March 03, 2006

3D Model Resources: Extruding Vector Shapes

At long last I'm back with another Friday dose of undocumented fun in Director and the Shockwave Player. This particular undocumented technique is one that allows you to create 3D model resources by extruding vector shape cast members. This is a bit of an involved process so it's a longer read than the other items I've posted, but I think it's worth it if you don't know of this already.


Built into all versions of Director and Shockwave since v8.5 is the capability to extrude text strings into model resources within a 3D cast member. Extruding of strings is really just an excercise in vector shape extrusion where the font and characters used determine the shape of the outline that is extruded. There is an undocumented property of #extruder model resource objects (those created via the extrude3d text cast member method) that allows you to update the vertex list of an extruded model resource to any desired shape. When you update the model resource's vertex list, all of the previously held properties relating to the extrusion are maintained (bevelDepth, bevelType, displayFace, smoothness, tunnelDepth). You can set these either before or after the extrusion and/or vertex list replacement.

There are in fact two means by which you can update the vertex list, one is to simply set the entire list equal to a new list, the second is to manually draw the needed outlines by using further undocumented commands. First I'll discuss how to go about getting an #extruder model resource, then I'll talk about the capability to simply set the resource's vertex list to a new value and finally I'll discuss how to go about drawing the outline manually.


Getting an #extruder model resource
We must create an #extruder model resource object, this is achieved by using the extrude3d text member method:

-- create a text cast member
tTextMember = new(#text)

-- initialize the member with any string
tTextMember.text = "a"

-- extrude the text member's string into a 3D cast member
tExtruderResource = textMember.extrude3d(member("3D")

The font and display settings of the text member are of no importance being as they only affect the outline to be extruded and we'll be providing our own outlines later.


Replacing the resource's vertex list
Now that we have an #extruder model resource we can simply push a new vertex list onto the resource via the resource's undocumented vertexList property. For example:

-- grab vertex list of vector shape cast member
tList = member("vector shape").vertexList

-- update model resource
tExtruderResource.vertexList = tList

I've experimented with this a bit but not extensively. I recall warnings that the winding order of vector shapes can be/is sometimes in reverse order resulting in objects not rendering correctly (their insides are pointing out). This can be repaired by walking your vector shape's vertex list and multiple all y-coordinate values by -1.


Drawing the new outlines manually
This technique is a bit more involved and is something that I've only tried once with minimal success (a portion of my troubles was most certainly due to errors on my part though). Once you've created an #extruder model resource you can then draw your outlines using the following undocumented commands: startCompositePath, startCompositeElement, startPath, moveTo, curveTo,lineTo, endPath, endCompositeElement, and endCompositePath. Here is a quick and rough definition of each command:

startCompositePath / endCompositePath
syntax: extruderResourceRef.startCompositePath()
syntax: extruderResourceRef.endCompositePath()
These commands start and end the creation of a composite path (a string is an example of a composite path); once you've created your #extruder resource, starting a composite path is the first thing you'll do and ending that composite path the last thing you'll do.

startCompositeElement / endCompositeElement
syntax: extruderResourceRef.startCompositeElement()
syntax: extruderResourceRef.endCompositeElement( point )
These commands start and end the creation of a composite element (a character is an example of a composite element); you must first create a composite path before creating composite elements; end a composite element to begin working on the next element. When using the endCompositeElement command you must provide a point value that offsets to the next composite element (character) to draw.

startPath / endPath
syntax: extruderResourceRef.startPath()
syntax: extruderResourceRef.endPath()
These commands start and end the creation of a path (the dot in an "i" is one path, the vertical bar another); you must first create a composite element before creating a path; end one path in order to be able to start another.

moveTo
syntax: extruderResourceRef.moveTo( point,#boolean )
After you have begun a path using the startPath command you can set the point at which you would like your new path to begin by using this command. The moveTo command also contains a second parameter in which you specify if the curve about to be drawn is on the inside (the center of an o) or the outisde (the outer ring of an o). Passing a value of TRUE results in an outside path while a value of FALSE results in an inside path.

curveTo
syntax: extruderResourceRef.curveTo( controlPt1,controlPt2,point )
After you have begun a path using the startPath command you can draw your next vertex by specifying its position and control hadles using this command. All parameters are #point values.

lineTo
syntax: extruderResourceRef.lineTo( point )
After you have begun a path using the startPath command you can draw your next vertex specifying just its position using this command. The parameter provided is a #point value.

Here is some code that you can copy and paste right into your message window in order to use the above commands to draw and extrude a vector box shape:

-- create text member
tTxt = new(#text)

-- member must have a string in order to extrude
tTxt.text = "a"

-- create 3D member
tMem = new(#shockwave3D)

-- extrude text member
tMR= tTxt.extrude3d(tMem)

-- create model using the #extruder resource
tM = tMem.newmodel("a",tMr)

-- place member on stage, verify that you see an
-- extruded letter "a", when done *remove*the*
-- sprite*from*the*stage*; I'll explain later

-- start the composite path
tMr.startCompositePath()

-- start a composite element
tMr.startCompositeElement()

-- start a path
tMr.startPath()

-- move initial vertex into place
tMr.moveto(point(0,0),TRUE)

-- make a line connection with second vertex
tMr.lineTo(point(25,25))

-- make a line connection with third vertex
tMr.lineTo(point(0,50))

-- make a line connection with the fourth vertex
tMr.lineTo(point(-25,25))

-- connect a line back to our initial point
tMr.lineTo(point(0,0))

-- end the path
tMr.endPath()

-- end the composite element
tMr.endCompositeElement(point(0,0))

-- end the composite path
tMr.endcompositepath()

-- place member back on stage, you should now see an
-- extruded square


Stability Warning
It should be noted that upon being told of this capability I was also sternly warned that I should not perform any of the above drawing routines while the cast member is actually being rendered. I haven't tested that rule (meaning I've always done this with the member not being rendered), do so at your own risk/benefit.


Disclaimer: I make no guarantees regarding validity or usefullness of the information contained in this post. This feature was left as undocumented, and therefore unsupported on purpose, it either wasn't fully developed and/or it wasn't fully tested. I suggest that you utilize this technique in experimental movies due to the potential risks involved. There is no guarantee that this undocumented feature will survive from release to release. Use this technique at your own risk!

Posted by thiggins at 02:14 PM

August 26, 2005

Generating Font Outlines

As most folks know fonts and text display is very much an outline/path driven routine and as such one might want to use a particular font and instead of showing it as text, they might simply want the vector outline for a particular string. Well, another one of Director's hidden gems is the ability to do just that using font cast members and their undocumented (and therefore untested!) generateOutlines() method.

If you have a font cast member present in your movie you generate a vertex list defining the outlines of a specified string using that font. This capability is provided via the undocumented generateOutlines cast member method. With this command you provide the desired string and the vertex list is returned, that list can then be applied as you wish, but an obvious candidate is to apply that vertex list to a vector shape cast member. Here's how you do it:

1. In a Director movie, insert a font from your system. This can be done using Insert > Media Element > Font... Please note that when doing this choose the font you want to use in order to create the vector outline of your string.

2. Once you have your font cast member, just call generateOutlines() as a method of that member and provide the string whose outline is to be generated and returned:

tVertexList = member("MyFont*").generateOutlines("Some String")

Note: you must provide a valid string with at least one non-space character or else a script error will occur.


The generateOutlines() method returns a vertex list that can be used for whatever purpose you desire, one simple method of using this list is to apply it as the vertex list for a vector shape cast member. For example:

member("MyVectorShape").vertexList = member("MyFont*").generateOutlines("Some String")


Have fun!


Disclaimer: I make no guarantees regarding validity or usefullness of the information contained in this post. This feature was left as undocumented, and therefore unsupported on purpose, it either wasn't fully developed and/or it wasn't fully tested. I suggest that you utilize this technique in experimental movies due to the potential risks involved. There is no guarantee that this undocumented feature will survive from release to release. Use this technique at your own risk!

Posted by thiggins at 02:51 PM

May 31, 2005

Transparent MIAWs

For many releases now Director has provided the ability to mask MIAWs (Movies In A Window) opened by projectors, but that ability has been limited to using 1-bit black and white masking images. The development and release of Director MX 2004 saw some excellent improvements to the MIAW feature, but what didn't make the cut was >1bit masking. In exploring what would be possible in this area there was one little feature left in the Windows player (sorry Mac folks) and as with all undoc'd abilities it's untested and therefore something you should use carefully. That one feature is the ability to set a window's blend... :)

Setting the Blend of a Window
This undocumented property is really simple, it's called 'blend' and it's a window property that takes a numerical value from zero to one hundred:

-- create a window and set its blend property
tWindow = new window("Foo")
tWindow.blend = 50

Done. Give it a go, but remember that this property is only active in Director MX 2004 on Windows, and as always heed the disclaimer below. Enjoy.

Disclaimer: I make no guarantees regarding validity or usefullness of the information contained in this post. This feature was left as undocumented, and therefore unsupported on purpose, it either wasn't fully developed and/or it wasn't fully tested. I suggest that you utilize this technique in experimental movies due to the potential risks involved. There is no guarantee that this undocumented feature will survive from release to release. Use this technique at your own risk!

Posted by thiggins at 11:11 AM | TrackBack

February 08, 2005

Getting a list of installed recordable fonts

Sorry, I missed last Friday's appointment to post up another undocumented gem, my apologies for the delay, read on...

Last week I dropped a hint about the undocumented fontList() method of Font cast members in Macromedia Director. Well, this week I want to extend that a bit further by discussing another undocumented Font member method, outlineFontList(). When called this method behaves similar to the fontList() method but instead of returning a list of all installed font names it returns a linear list containing the names of all recordable or insertable fonts.

Macromedia Director has long supported the ability to import Fonts as cast members in order to render text on a user's machine where that user doesn't have the needed font. In order to insert a font Macromedia Director's Font Xtras "record" or store the font's outlines within a font cast member for later use. Only outline fonts can be recorded and so often a given machine will have many fonts that can't be inserted/recorded into Macromedia Director. Normally the list of fonts that can be inserted is found by going to Insert > Media Element > Font..., but now using this method you can get the list of names through code as well.

Let's look at some code examples...

1. Create a font cast member
You can do this ahead of time by inserting a font using Insert>Media Element>Font..., or you can do it at run-time using code:

-- in Lingo
tFontMem = new(#font)
-- or
tFontMem = _movie.newMember(#font)

// in JavaScript syntax
var tFontMem = _movie.newMember( symbol("font") );


2. Call the outlineFontList() method off a font member reference
Once you have a reference to a valid font cast member you simply call the outlineFontList() method off that reference:

-- in Lingo
tFontList = tFontMem.outlineFontList()

// in JavaScript syntax
var tFontList = tFontMem.outlineFontList();

When called this method builds a Lingo linear list of strings, where each string in that list is the name of a system-installed font that is recordable or insertable as a cast member inside Macromedia Director.


Enjoy.


Disclaimer: I make no guarantees regarding validity or usefullness of the information contained in this post. This feature was left as undocumented, and therefore unsupported on purpose, it either wasn't fully developed and/or it wasn't fully tested. I suggest that you utilize this technique in experimental movies due to the potential risks involved. There is no guarantee that this undocumented feature will survive from release to release. Use this technique at your own risk!

Posted by thiggins at 11:41 AM

January 28, 2005

Getting a list of installed fonts

If you want to get a list of fonts that are installed on a computer at run-time using Lingo or JavaScript syntax, then you simply need to make use of the fontList() method for font cast members in Macromedia Director. It's really rather simple, here are the steps needed, including code examples.


1. Create a font cast member
You can do this ahead of time by inserting a font using Insert>Media Element>Font..., or you can do it at run-time using code:

-- in Lingo
tFontMem = new(#font)
-- or
tFontMem = _movie.newMember(#font)

// in JavaScript syntax
var tFontMem = _movie.newMember( symbol("font") );


2. Call the fontList() method off a font member reference
Once you have a reference to a valid font cast member you simply call the fontList() method off that reference:

-- in Lingo
tFontList = tFontMem.fontList()

// in JavaScript syntax
var tFontList = tFontMem.fontList();

When called this method builds a Lingo linear list of strings, where each string in that list is the name of a system-installed font. It's important to note that you're getting a list of _all_ installed fonts that can be used in your text and field cast members.


Stay tuned, next week I'll post about a variation on this theme that lets you get a list of the fonts that are insertable or "recordable" as font cast members as opposed to a list of each and every font that's installed.


Enjoy.


Disclaimer: I make no guarantees regarding validity or usefullness of the information contained in this post. This feature was left as undocumented, and therefore unsupported on purpose, it either wasn't fully developed and/or it wasn't fully tested. I suggest that you utilize this technique in experimental movies due to the potential risks involved. There is no guarantee that this undocumented feature will survive from release to release. Use this technique at your own risk!

Posted by thiggins at 02:30 PM

Gems from the Cave of Undocumented Features

Over the years there have been many bits of functionality put into Macromedia Director and/or the Shockwave Player that have never seen official and documented support. There are many reasons for features or functionality to fall into this catagory, an over-zealous development engineer having fun or features that turned out a wee bit buggy or even areas that were simply not tested well enough to get full and proper support. During my tenure at Macromedia I've had the pleasure of sharing some of these functional gems with the developer base and I'm hoping to set about doing that again, here, on my blog. But before doing so I need to make a few things clear to all interested parties:

1. I will be disabling comments on all posts made under the "Undocumented" catagory. I'm doing this to prevent any backlash comments regarding displeasure at these not being official features and to prevent folks from providing any further details that might not be appropriate for these posts. Sorry, but so it goes. Please note that comments are enabled for this post, but won't be for others. ;)

2. I will be providing a disclaimer in each and every post made under the "Undocumented" catagory so that the stance of these items is clear within the scope of the product as a whole.

3. If the posting of these items turns out to be problematic then they may be removed, I'm trying to post them here as a bit of a service to our customers and to enable others to have fun exploring them for what they might be good for.

4. Come back each Friday as I'm going to do my best to post a new undocumented tidbit at the end of each week.

So, let it begin...

Posted by thiggins at 02:04 PM