71 entries in Development

Transform Presets

Save and restore transformations as presets to objects such as cameras, IK handles, etc.

Saturday, May 17th, 2008

Transform Presets is a pretty simple plugin – it allows you to store multiple transformations of an object (and it’s target, if there is one) in a list, to call up when you like.

You apply it to any object, and it adds a custom rollout to the base object, with a small interface that you can use when the object is selected.

I built it for fun in response to a thread on CGTalk.

Screenshots

Here it is working on a target camera. Note both the camera and target are transformed.

And here it is working with an IK handle. Note the swivel angle is updated as well as the transform.

Download and installation

Download TransformPresets.mzp and then drag the .mzp file onto one of your 3dsmax viewports, which will install the script in the correct directory. Then you can add the script to a toolbar / quad by going to:

  • Customize > Customize User Interface…
  • Then look under the Animation Tools category for Transform Presets

Particle Visualizer and Papervision3D Exporter

A script to visualize particle motion and export particle and camera data to Flash's Papervision 3D

Saturday, May 10th, 2008

Papervision 3D is the latest in 3D development for the Adobe Flash platform. It supports a variety of methods for creating 3D content, from basic primitives, to import via the Collada file format. However, being XML-based, Collada files are pretty huge – getting a 300 frame, 150 particle animation into Flash was creating files that were about 22MB!

After trying various approaches to get animation data from 3dsmax to Flash, Good Technology got in contact with me to write an exporter in Max Script for their latest Papervision job for the Audi RS6 microsite.

The plugin has 2 main functions:

  • Visualize particle motion before export
  • Export particle and camera data from max’s Z-up coordinate system to Papervision’s Y-up coordinate system

More information and screengrabs are available on my portfolio site.

Screenshot

Interface

As with all interfaces I write for 3dsmax, I do my best to provide as much feedback as possible. Note:

  • Group titles are updated with the latest information
  • Dropdowns have an update button
  • Tasks have multiple customization options
  • Progress bars and dialog preferences come as standard

Download

This plugin is not available for download, however please contact me if you wish to discuss custom Papervision3D or any other development.

Time Stamper

A struct to make light work of timing tasks, benchmarking, etc

Friday, May 9th, 2008

This struct basically makes timing things much easier by packaging a few useful methods together.

Now, instead of writing and retrieving timestamp variables, and formatting strings to the listener, you simply call struct methods such as start(), end(), and print(), or see a report of the process with getReport().

Example Code

Create a new Time Stamper, assigning a task name:

ts = timeStamper "Testing"

Time something, and alert the results in a messagebox:

ts.start()
-- your code here
ts.alert()

Benchmark a series of tests, and print the results to the listener when completed:

for i = 1 to 10 do (
        ts.start()
        -- your code here
        ts.end()
)
ts.print average:true
-- Average processing time for 'Testing' was 24.6162 seconds, based on 10 timed sessions.

Methods

Starting and stopping

  • start() – start timing. Returns start time
  • end() – end timing. Returns last timing duration
  • reset() – reset all timing data

Getting results in English

  • print average: difference: – end timing and print results to listener
  • prompt average: difference: – end timing and prompt results to notification area
  • alert average: difference: – end timing and alert the results in a messagebox

For the above methods, the following keyword arguments can be supplied:

  • average – returns the average result of all the timed tests since the TimeStamper was instantiated or last reset
  • difference – returns the comparative difference between another TimeStamper, in English, e.g.“Test 1′ was 2.58 times quicker than ‘Test 2′”

Getting results as numbers

  • getLast() – gets the last single timed session (alias for duration property)
  • getTotal() – gets the total of all timed sessions
  • getAverage() – gets the average of all timed sessions
  • getDifference difference: average: – Returns a 3-element array representing how much quicker one time stamper is than another.

The array’s elements are ordered like so:

  1. – how many times quicker the quickest Time Stamper was
  2. – the task name of the quicker time stamper
  3. – the task name of the slower time stamper

Getting results as an Excel-compatible report

  • getReport columns: step: output: – gets all timed sessions as a customizable report

The step property defines how many iterations to average/total values for, and defaults to 10.

The columns property can take any of the following name values:

  • #index – the numeric index of the row, e.g. 1, 2, 3
  • #step – the current step, e.g. 1, 11, 21
  • #stepaverage – the average of all measurements from the current step
  • #steptotal – the total of all the measurements from the current step
  • #slower – how much slower the current step was than the fastest step
  • #quicker – how much quicker the current step was than the slowest step
  • #total – the cumulative total from all measurements so far

The output property defines where the generate report will be output to. Values can be:

  • No value – the report will be returned as a string
  • “path/to/file.txt” – a file path. If the file exists it will be overwritten, if not it will be created
  • #window – a new script window
  • – a reference to a windowstream
  • – a reference to a stringstream

Download a report that was built using calls to getReport() in Excel 2007 or in Excel 2003

Properties

  • duration – the duration of the last timed session
  • durations – an array of all timed sessions
  • task – the name of the current timed task

Demo and case study

Check out a case study and download a demo script here:

Download

Download TimeStamper.ms.

Progress Bar Updater

A struct to simply and easily update a progress bar by providing just start and end values, and calling update()

Thursday, May 1st, 2008

Updating a progress bar is fairly simple in conceptual terms, but it always takes a slightly different bit of code to do it right:

  • What if the sequence is backwards?
  • What if you’re incrementing in units of 2, or 3, or 10?
  • How big is the progress jump?

It makes sense to abstract the process and stick it in a struct. The progressBarUpdater does just that, and really is as simple as:

  1. Create a struct instance
  2. Initialize it with a reference to a progress bar, and the known start and end values of the calculation
  3. Call update() for each loop iteration.

In code, starting with a 2-line initialization, it looks like this:

pbu = progressBarUpdater()
pbu.init pb1 startValue endValue

And to update the progress bar, this is the only command you need to place in the loop:

pbu.update()

The pbUpdater struct already knows everything it needs to know, so it’s just one call.

Download

Download progressBarUpdater.ms.

UI Manager

Save and load rollout settings, such as size, position, control states, items, etc to a preferences file

Thursday, May 1st, 2008

A struct containing methods to save and load rollout settings, such as size, position, control states, items, etc
to a preferences file, as well as methods to accomplish UI control tasks for example keeping one spinner higher or lower
than another when editing ranges.

Usage

To manage a rollout or dialog, you simply:

  1. create a struct instance
  2. initialize it with a reference to a rollout
  3. Manage the rollout by calling the struct’s methods

In code, that’s as easy as this:

ui = uiManager()
ui.initialize roTools
ui.loadPosition()

All settings are saved to an .ini file named after the rollout title, so in this case, an ini file named “Tools.ini” would be saved to your max installation’s /plugcfg folder.

Methods

This is a work in progress, and will be updated from time to time with new methods.

Dialog functions

  • savePosition - save the dialog position
  • loadPosition - load the dialog position
  • saveSize - save the dialog size
  • loadSize - restore the dialog size

Rollout functions

  • autoSizeFloater - resize the floater to exactly the size of all open rollouts
  • toggleRollout - set one or several rollouts open
  • loadRolloutStates - save all rolled-up / down states (not yet implemented)
  • saveRolloutStates - load all rolled-up / down states (not yet implemented)

Control functions

  • updateSpinnerPair - ensure that spinners react as a pair, eg one can never go higher than the other
  • moveListboxItem – move selected Listbox items up or down, and have them remain selected
  • moveMultiListboxItems – move multiple MultiListbox selections up or down, and have them remain selected
  • getValue - abstract function to get a control’s value (not yet implimented)
  • setValue - abstract function to set a controls’s value (not yet implimented)

Preference functions (WIP)

  • saveValue - save a control’s value
  • loadValue - load a control’s value
  • saveAllValues - save all controls’ values
  • loadAllValues - load all controls’ values

Downloads

Download uiManager0.52.ms. Place in your scripts/startup directory, or just include the file when you need it.

These example files will get you started:

  • Preferences functionality – save and restore a dialog’s position when re-running a script
  • Floater functionality – open only selected rollouts, and automatically resize when opening rollouts

Flash “PHPLoadVars” class

Natively send complex / multidimensional variables from Flash to PHP with this extended LoadVars class

Thursday, February 28th, 2008

I was pitching in on a forum thread Send an object to a php script the other day and some chap wanted to send complex objects to PHP using LoadVars. “Can’t be done!” was the reply.

Oh yeah? Well if PHP can deserialize array variables from HTML forms, I don’t see why we can’t do the same with Flash.

Well it took about 15 minutes to work up a rough proof-of-concept that worked for GETs only, but it got me thinking to do something nice with:

  • a proper class
  • that works with POST (so you can send BIG objects!)
  • and has a recursive serialization routine (so you just give it any nested data-structure, and it chews through all of it)

PHPLoadVars (also works with Ruby)

Well it couldn’t be simpler, really. Just create a new PHPLoadVars object, ask it to serialize your data, and send:

var data :Object      = {data:[1,2,{sub_object:{name:'Dave',age:33,gender:'male'}},3,4,5]}
var lv   :LoadVars    = new PHPLoadVars();
lv.serialize(data)
lv.send('process.php')

Then PHP receives the complex variables natively like so (a quick print_r($_POST); shows the results):

Array
(
    [data] => Array
        (
            [0] => 1
            [1] => 2
            [2] => Array
                (
                    [sub_object] => Array
                        (
                            [gender] => male
                            [age] => 33
                            [name] => Dave
                        )

                )

            [3] => 3
            [4] => 4
            [5] => 5
        )

)

Just to be absolutely clear – this result isn’t manually de-serialized, or run through any processing routines – PHP automatically reads in data serialized using square brackets (which is how things were serialized in Flash) as numeric or associative arrays, so your data is literally ready to go as soon as the headers have been processed!

And you can make your data-structure as deep as you like…

Could it be any easier!? No. It couldn’t! Not even XML is this easy!

Download

Download the class file, sample .fla, and a basic PHP file to echo the variables to screen.

LoadPHPVars.zip

jQuery Favelet

Add jQuery functionality to any browsable web page

Saturday, February 23rd, 2008

Any developer worth his salt knows about Firebug and its JavaScript console. I use it all the time to tinker with web pages, test stuff out and debug my own pages.

But sometimes, if I’m *cough* hacking *cough cough* someone else’s page, I need the added power of jQuery! But what if the page doesn’t have it?

Simple – load jQuery from a remote source manually through a javascript: call.

Save Favelet

Just drag the link below to your Links toolbar, then click it on any page to jQuery-enable it.

Add jQuery to page

Test it out!

Save the Favelet and click on it (or just click the link above), then: animate page.

Simple!

Wordpress “Page Redirect” template

Have any page in the Wordpress "Pages" list invisibly redirect to a static page or other url

Wednesday, February 20th, 2008

The very nature of Wordpress demands that you work within it’s infrastructure in order to maintain flexibility. Sometimes, though, the structure of your pages demand that you need to operate outside of this constraint.

This template lets you specify a single URL as the page content, then as the page loads, the template automatically redirects the page to this new location.

Usage

Once you’ve uploaded the template-redirect.php file to your themes… sub-directory, i.e. wp-content/themes/theme_name/

1 – Create a new Page in your Wordpress control panel

2 – In the Page Content panel, just enter the URL (or local path) you want to redirect to:

3 – Set the Page Template dropdown to “Page Redirect”:

That’s it!

Note that in Wordpress 2.7 and later, you will need to do a little additional setup work to display the page template dropdown (don’t ask me why).

See this link for further details.

Examples

Examples of URLS might be:

  • category/flowers (a relative link to the permalink for “flowers”)
  • ../page.html (a page outside of a Wordpress subfolder (the WP folder being /blog/) but still in your site)
  • http://www.davestewart.co.uk/resources/ (a page on a completely different site)

The “Latest developments…” page in my sidebar automatically redirects to /category/development/ – or in other words, the archive for my “Development” category, as my home page is not the standard “last-post first” format.

Download

template-redirect.zip

jQuery “Highlight” plugin

Highlight a form field’s parent tag (or any other selector) as you tab into it.

Tuesday, February 12th, 2008

Highlight increases usability by highlighting elements as you interact with the page.

Its primary use is for forms, but it can also be used for tables, lists, or any element you specify. It can also be used to toggle elements on and off, for example, table rows.

Examples uses:

  • Form-filling can be made clearer by highlighting the element around a control as you tab into it
  • Table rows can be made more visible as you pass the mouse over them, or click them
  • Elements can be toggled as you click them

Code example

Because of the defaults, basic usage can be as simple as:

$('form').highlight();

The method signature for Highlight is:

$(selector).highlight(parentSelector, highlightClass, startEvent, endEvent);

Demo

View the Highlight demo which has examples for forms, tables, and lists.

Download

  • jquery.highlight.js
  • jquery.highlight.pack.js

jQuery “Populate” plugin

Populate a form or an element's child elements using a JSON object.

Tuesday, February 12th, 2008

I don’t like mixing HTML and PHP when I build my forms. Instead I like to keep my HTML completely clean, then if a form needs to be pre-filled (for example retrieving a bunch of database results), get JavaScript to fill it in for me after the page has loaded.

This plugin supports full PHP naming and deep data structures, as well as checkbox arrays, other non-standard UI controls, and even standard HTML elements such as labels or divs.

The plugin can be used as part of your AJAX toolkit, or for separating server-side code from HTML by populating a form after the page has loaded eg:

$('form').populate({text:'text', radio:1})

and not inline as the page is processed, such as:



You can also populate non-form controls such as

s, by specifiying the id and an identifying attribute (defaults to id):

$('div').populate({'text-1':'text', 'text-2':'More text'})

This can be useful when you want to show the results of a database call, but don’t want the text to be editable.

Instructions and demos

View the jQuery Populate demo for a view a full set of instructions and a working demo, with examples of populating:

  • a simple form, using string variable types for textfields, radiobuttons, dropdowns and checkboxes
  • a complex form, using array variable types for checkbox arrays and multi-list boxes
  • a hierarchical form, using hierarchical JSON data

Update 29th November 2009

Thanks to everyone who spotted bugs and contributed their comments. The following features are added / bugs are now squished:

  • Now populates standard HTML elements within forms
  • Is now case-sensitive for element value comparisons (keith, 5030SDEC, Mark Croxton)
  • Now skips function references and undefined elements (Henning, Found-a-Bug)
  • Fixed debug trace for missing elements (Found-a-Bug)

Download

JavaScript

  • Populate (no compression) 4.6k
  • Populate (packer compression) 1.6k

PHP

Demo files

  • Populate standalone demos

Fixed debug trace for missing elements (Found-a-Bug)

Now skips function references and undefined elements (Henning, Found-a-Bug)

Now populates standard HTML elements

Is now case-insensitive for element value comparisons (keith, 5030SDEC, Mark Croxton)