Undocumented Lingo
Contents
- 1 3D
- 1.1 generateOutlines() - font outlines from font members
- 1.2 #extruder property of a vector shape cast member
- 1.3 newTexture
- 1.4 member.userdata
- 1.5 supersample filters for antialiasing in Shockwave3D
- 1.6 Interface of a 3D cast member
- 1.7 Reference to a meshDeform modifier
- 1.8 Multiple texture coordinates for a newMesh()
- 1.9 Shader.elasticity
- 1.10 Particle Resource
- 1.11 Get/Set getRendererServices().pixelAspectRatio
- 1.12 Two Other Toon Modifiers
- 1.13 .fileSaveMode
- 1.14 .primitiveOrientation
- 2 Audio
- 3 Fonts
- 4 Imaging Lingo
- 5 Lists
- 6 Maths & Rects
- 7 Scripts
- 8 Strings & Text Members
- 9 System, Sprites, Cast, Members
- 9.1 the commandLine
- 9.2 the stageColor
- 9.3 stretch property of sprites
- 9.4 JavaScript Garbage Collection
- 9.5 blend property for window opacity (Win only)
- 9.6 closeRequest
- 9.7 the systemDate
- 9.8 the stage.name
- 9.9 Mouse Buttons Detected with KeyPressed
- 9.10 Multiple Instances of a MIAW
- 9.11 Pausing and Playing the Playhead
- 9.12 DispatchCommand
- 9.13 UIHelper Xtra
- 9.14 Seconds in the Date Object
- 9.15 The searchPathList Not Affected by clearGlobals
- 9.16 Mime Types for Shockwave
- 9.17 Create Filmloop With Lingo
- 9.18 importFileInto with castLib files
- 9.19 Number of Members and Casts
- 9.20 CompressedMedia
- 10 Vectors
- 11 Work in Progress
3D
generateOutlines() - font outlines from font members
With the undocumented method generateOutlines() you can create a vertex list from any given string using an imported font. This could be used in a vector member e.g.
- First we import the desired font into the cast.
- Now we call the font member method generateOutlines() with a string and get the vertex list:
-- Lingo-Syntax myVertexList = member("myFont").generateOutlines("Hello World")
Attention! The string provided to generateOutlines() must be a valid string with characters (not just spaces). Otherwise you'll get a script error! Note: vector shapes suffer from a maximum size of 2798.0499px width and height, and using generateOutlines() produces large vector shapes, thus the size of the string passed to it is very limited... however, you can do this:
-- Lingo-Syntax myVertexList = member("myFont").generateOutlines("Hello World") myVertexList = myVertexList / 2 -- divide the [#newCurve] item by 2 newCurve = [#newCurve] / 2 -- anywhere a [#newCurve] item is found in the vertexList, which in this case -- has been converted to [733] because of the division by 2, we change it back repeat while true newCurveItem = myVertexList.getOne(newCurve) if newCurveItem = 0 then exit repeat myVertexList[newCurveItem] = [#newCurve] end repeat
#extruder property of a vector shape cast member
It is possible to extrude vector shapes with the extrude3d command. But you have to build an extruder resource from a normal textmember, before you are able to apply the vertexList from the vector shape.
- create a text cast member
textMember = new(#text)
- initialize the member with any string
textMember.text = "a"
- extrude the text member's string into a 3D cast member
extruderResource = textMember.extrude3d(member("3D"))
- grab vertex list of vector shape cast member
tList = member("vector shape").vertexList
- update model resource
extruderResource.vertexList = tList
Now use that model resource as desired.
newTexture
newTexture() accepts an additional list like the one for copypixels(). Very useful for creating matte or transparent textures from image objects with no alpha color.
im=the stage.image wrld=member("3d") txtr=wrld.newTexture("MyNewTexture", #fromImageObject, im, [#bgcolor:rgb(255,255,255), #ink:36]) -- Note: see the entry on copypixels for the exact syntax/options of the list -- this example is just from the top of my head
member.userdata
Allows to store a list object with a 3D castmember which is persistent.
property pSprite property pMember on beginSprite me pSprite = sprite(me.spriteNum) pMember = pSprite.member -- create a property list to be stored in userData myPropList = [#name:"bla",#data1:1,#data2:2,#data3:3] -- create member's userData and add the above property list pMember.userData = myPropList -- create reference to existing userData property ud = pMember.userData -- add an item to the userData list ud.addProp(#age,22) -- change a property's value ud.setProp(#name,"blubb") -- check put pMember.userData end
---------------------------------------------------------------------- -- SAVE the movie, close Director, restart Director, reopen your movie -- Make sure, you've removed the above sprite behavior before playing the movie! ---------------------------------------------------------------------- put member(my3dWorld).userdata
No script objects, nor image objects can be saved though. Just static data. Can be very helpful nevertheless.
supersample filters for antialiasing in Shockwave3D
You can set the sampling mode for anti-aliasing with Lingo. This only works in #software rendering mode! Here is the list of available modes:
#superSample4x #superSample4xSoft #superSample9x #superSample9xSoft #superSample16x #superSample16xSoft Usage: sprite(1).antialiasingmode=#superSample4x
4, 9, 16 refer to the number of samples per pixel (2x2, 3x3, 4x4). The "soft" modes use a 4x4, 5x5, and 6x6 tent filter to provide a larger sampling area for blending the color samples. The non-soft modes simply average the color samples. This still works apparently as of Director 11. Great for doing hi-res 3D captures.
Interface of a 3D cast member
Usefull for xtras developpers, you may want to access the different interface of a 3D cast member.
For more information, see Director XDK, "Tips, Guidelines and Gotchas", end of page, "Getting the interface of an Xtra Asset for a cast Member".
There is 3 undocumented method:
member("3D").getMoaInterface() -- same as: member("3D").interface member("3D").getAssetCallback() member("3D").get3DCastMember()
Reference to a meshDeform modifier
Not an Undocumented method/property, but a little-tip to obtain direct access to "genDeform" modifier.
myModel.addModifier(#meshDeform) -- When you apply meshdeform modifier, you retrieve data like this: myModel.meshDeform.mesh[i].vertexlist[j] -- You could, also do it like this: t_genDeform = (myModel.meshDeform.list)[1] t_genDeform.mesh[i].vertexlist[j]
Multiple texture coordinates for a newMesh()
When you create a newMesh(), you could apply multiple texture coordinates.
myModelResource = my3DMember.newMesh( sResourceName, nFacesCount, nVerticesCount, nNormalsCount, nColorsCount, nCoordsCount, nLayersCount ) myModelResource.vertexList = myVerticesList myModelResource.normalList = myNormalsList myModelResource.colorList = myColorsList -- repeat with i = 1 to nLayersCount myModelResource.textureLayer[i].textureCoordinates = myCoordsPropList[i] end repeat -- repeat with i = 1 to nFacesCount myModelResource.face[i].vertices = myVerticesFaceList[i] myModelResource.face[i].normals = myNormalsFaceList[i] myModelResource.face[i].colors = myColorsFaceList[i] repeat with j = 1 to nLayersCount -- we must pass "j" to the textureCoordinates, (see Director XDK, "AccessPropRef" IMoaMmXValue Interface) myModelResource.face[i].textureLayer[j].textureCoordinates[j] = myCoordsFaceList[i] end repeat end repeat
Shader.elasticity
by default to 0.5
According to Intel:
"- This property retrieves/assigns an elasticity value. This is a single floating-point value. It has a range of 0.0f - 1.0f, where 0.0 represents extremely low elasticity and 1.0f represents high elasticity. Elasticity is a physics property that will apply to any object which uses this material. A low elasticity value will cause the object to dissipate energy during collisions with other objects. A high elasticity value will cause to preserve energy during collisions with other objects. a good analogy would be to compare a clay ball (low elasticity) to a billiard ball (high elasticity)." source W3D SDK:"IFXMaterialResource"
Particle Resource
3 undocumented properties for particle resource:
myParticleResource.upVector = vector(0,1,0) -- vector expected myParticleResource.useUpVector = TRUE -- boolean expected myParticleRecource.faceCamera = FALSE -- boolean expected
Get/Set getRendererServices().pixelAspectRatio
You can distort the image of the 3D viewport. Everything below 1 means a wider aspect ratio, anything bigger means a taller aspect ratio
-- get pixelAspectRatio put getRendererServices().pixelAspectRatio -- 1.000 -- set pixelAspectRatio getRendererServices().pixelAspectRatio = .85
Two Other Toon Modifiers
The toon modifier allows non-photorealistic rendering like in a cartoon. It is used on a per model basis. There are two additional undocumented toon modifiers, #toon1 and #toon2. These combine the normal toon rendering with either an newsprint or engraver shader. This is achieved by chaining multiple shaders together. The toon shader, for instance, is a combination of an inker and a or multiple standard shader. #toon1 and #toon2 just use newsprint or engraver shader instead of the standard one.
member("3d").model("yourModel").addModifier(#toon1) -- or member("3d").model("yourModel").addModifier(#toon2)
Credit goes to Ulla Gusenbauer for discovering them independently from Tom Higgins (former Director team member) who revealed their existence in an article on a now-defunct site.
.fileSaveMode
This is an undocumented property of 3D members. Its default value is #saveOriginal, which means that any Lingo changes to the 3D models in a member will not be saved in the member permanently. However, if you use #saveMarked, then any models that are cloned will also be saved in the member. If you use #saveScene setting, then changes to existing models will be saved, but not new models created. If you use #saveAll, then all changes to the models will be saved.
sprite(1).member.fileSaveMode = #saveAll
.primitiveOrientation
When you create a primitive in Shockwave3D, the default orientation for the model is #NegZForwardYUp, meaning that the primitive is pointing away from the default cam in a freshly created Shockwave3d world. When you create a Shockwave3D world programmatically, you are looking down the negative Z-axis, and the Y-axis is up.
The default camera is set up at vector (0,0,250), looking at the origin of the world:
mem = new(#shockwave3d) put mem.camera(1).transform.position -- vector( 0.0000, 0.0000, 250.0000 )
This actually causes a problem when you create a default plane primitive for instance, as the plane´s surface normals will be pointing away from the camera and thus cannot be seen (remember backface culling). You will have to rotate it around 180 degrees around the Y-axis in order to see it or to create a plane primitive with double sided geometry. In order to change this, several other symbols were implemented:
- #DefaultOrientation
- #NegZForwardYUp
- #ZForwardYUp
- #PreRelease
These symbols change the default orientation of new models which are created by Lingo. This is not a problem for box, sphere and particle primitives, and just a minor issue for cylinders. It does however apply to plane primitives for reasons explained above.
member("your3DWorld").primitiveOrientation=#ZForwardYUp
Any subsequently created model will now be created pointing down the Z-axis and the Y-axis up. This means that a newly created plane primitive will be facing the camera and thus can be seen right away.
Audio
#rateShift property of sound playback
Change the playback speed of your sound with the undocumented #rateShift property in the queue() method.
-- the value of #rateShift can be a float -- to change the rateShift you must stop() the sound -- the sound property sound(1).rateShift is read-only on shiftRate myValue sound(1).stop() sound(1).queue([#member: member("mySound"), #rateShift: myValue]) sound(1).play() put sound(1).rateShift end
-- message window shiftRate(1.5) --1.5000
- Note: 12 semitones is an octave.
Fonts
fontList() and outlineFontList()
- The undocumented method fontList() of the Font Xtra returns a list of all installed fonts. Works on PC and Mac.
- The undocumented method outLineFontList() of the Font Xtra returns a list of all installed fonts that can be embedded (imported) in Director because they contain the necessary "Outlines".
- These methods require the Font Asset Xtra
-- Lingo-Syntax on getAllFonts myFont = new(#font) myFontList = myFont.fontList() myFont.erase() put myFontList end on getAllOutlineFonts myFont = new(#font) myFontList = myFont.outlineFontList() myFont.erase() put myFontList end
// JavaScript-Syntax function getAllFonts() { var myFont = _movie.newMember(symbol("font")); var myFontList = myFont.fontList(); myFont.erase(); trace(myFontList); } // JavaScript-Syntax function getAllOutlineFonts() { var myFont = _movie.newMember(symbol("font")); var myFontList = myFont.outlineFontList(); myFont.erase(); trace(myFontList); }
generateOutlines() - generate font outlines from font members
With the undocumented method generateOutlines() you can create a vertex list from any given string using an imported font. This could be used in a vector member e.g.
- First we import the desired font into the cast.
- Now we call the font member method generateOutlines() with a string and get the vertex list:
-- Lingo-Syntax myVertexList = member("myFont").generateOutlines("Hello World")
Attention! The string provided to generateOutlines() must be a valid string with characters (not just spaces). Otherwise you'll get a script error! Note: vector shapes suffer from a maximum size of 2798.0499px width and height, and using generateOutlines() produces large vector shapes, thus the size of the string passed to it is very limited... however, you can do this:
-- Lingo-Syntax myVertexList = member("myFont").generateOutlines("Hello World") myVertexList = myVertexList / 2 -- divide the [#newCurve] item by 2 newCurve = [#newCurve] / 2 -- anywhere a [#newCurve] item is found in the vertexList, which in this case -- has been converted to [733] because of the division by 2, we change it back repeat while true newCurveItem = myVertexList.getOne(newCurve) if newCurveItem = 0 then exit repeat myVertexList[newCurveItem] = [#newCurve] end repeat
Undocumented Font Styles
Here's the list of all undocumented font styles for text members:
- #Boxed
- #DoubleUnderline
- #WordUnderline
- #DottedUnderline
- #HiddenText
- #StrikeOut
- #SuperScript
- #SubScript
- #AllCaps
- #AllLower
- #SmallCaps
- #Overline
-- text member named "text" member("text").fontStyle = [#DottedUnderline, #SmallCaps]
- Note: in D11+ only #DottedUnderline, #StrikeOut, #SuperScript and #SubScript work.
Imaging Lingo
floodFill()
Use this undocumented method to flood fill an area of a bitmap image with identical color value with a given color. Works a bit like the paint bucket.
-- Lingo-Syntax myImage.floodFill(xPoint,yPoint,rgb(myRed,myGreen,myBlue))
copyPixels() with undocumented #dither values
The copyPixels() method has two unocumented values for the "#dither" parameter. These additional values for #dither are 1215 and 1969 (see below details).
- Use [#dither:1215] - This uses a remapping algorithm that searches the palette for the closest color instead of using 5 bits of R, G and B to find a color. Good for very subtle palettes with lots of very similar colors.
- Use [#dither:1969) - This uses a high-quality dithering algorithm with better results than the regular dither, but a lot slower.
Using these parameters can strongly affect performance. Don't forget to test and reduce usage to a minimum.
-- Lingo-Syntax targetImage.copyPixels(sourceImage, targetRect, sourceRect, [#dither:1215])
image(x,y,depth,switch) - 4th parameter
The 4th parameter seems to activate/deactivate useAlpha.
-- Lingo-Syntax myImage = image(myWidth, myHeight, 32, true)
The 4th parameter can also be a symbol representing any of the built-in palettes: #systemWin, #systemMac, #rainbow, #web216, #metallic, #pastels, #vivid, #ntsc. It will only work on 8-bit images (ie. images consisting of 256 colours).
-- Lingo-Syntax myImage = image(myWidth, myHeight, 8, #metallic)
or you can use a custom palette member like so:
-- Lingo-Syntax myImage = image(myWidth, myHeight, 8) myImage.paletteRef = member("custom palette")
paletteRef of images
It is possible to set the palette used by an in-memory image (that may not be associated with any cast member), although the printed material and help file do not mention it.
img = image(640, 480, 8) img.paletteRef = member("my custom palette") img.copypixels(_movie.stage.image, rect(0, 0, 640, 480), rect(0, 0, 640, 480))
Image Equality Test
A fast method of doing a pixel based image equality test:
imagesEqual = (member(1).image = member(2).image) -- or directly with image objects imagesEqual = (image1 = image2)
Bitmap Image of Field Member
For field members you can't use member.image like you can for text members. Instead use member.picture. See below.
member("bitmap").picture = member("field").picture
hexString()
This color object function converts decimal rgb color values to hexadecimal strings.
mycolor = rgb( 51, 0, 204 ) put mycolor.hexString() -- "#3300CC"
Lists
deleteAll
l=[1,2,3] l.deleteAll() put l -- []
Filling a List With a Value
You can populate a list by setting some index in the list to any value:
myList = [] myList[10] = 5 put myList -- [0, 0, 0, 0, 0, 0, 0, 0, 0, 5]
Test If a List is Empty
To see if a list is empty it's up to 4x faster to test the count of the list instead of comparing the list to an empty list:
if count(someList) = 0 then nothing end if -- Not this: if someList = [] then nothing end if
Maths & Rects
min() and max() in lists
With the list methods min() und max() you can easily get the min or max value for integers, floats, and strings.
-- Lingo-Syntax myList = [10,5,3,17,52,26] put myList.min() -- 3 put myList.max() -- 52
Some other examples to illustate how min() and max() function on lists:
aList = ["Bob", "was", "here", "2008"] put aList.max() -- "was" put aList.min() -- "2008" -- mixing up types p1 = #zz p2 = #aa aList = [3, p1, p2, ["z", "aa", 2.91, 1, 3], "bar" ] put aList.min() -- ["z", "aa", 2.9100, 1, 3] put aList.max() -- #zz
Note: the methods do not perform a 'deep' search of nested lists. The last example demonstrates that symbols are sorted as strings, not by their integer value (the #aa symbol would have a higher integer value since it is made after the #zz symbol).
random() with 2 parameters
The method random() can be used with 2 parameters to draw random numbers from a given range. The following example draws a random number from the range of 3 to 17:
-- Lingo-Syntax put random(3,17)
Make sure that the second parameter is strictly superior to the first parameter. ... first parameter the lowest value, second parameter the highest value! If the second parameter is inferior or equal, such as random(100, 50) and random(100, 100), it is equivalent to random(100). Random(-12, 12) also work and so does random(-100, -50). Just make sure to put the smallest number first (and not random(-50, -100)!). i.e. -100 < -50
atan method with 2 parameters (atan2)
An undocumented option of the method atan() is to use 2 parameters, which equals the method "atan2" in other programming languages.
-- Lingo-Syntax myAngle = atan(y,x)
Get the Width and Height of a Rect
Director already has built-in methods for getting the width and height of a rect*:
-- the unnecessarily complicated way to get the width and height theRect = the desktopRectList[1].rect width = theRect.right - theRect.left height = theRect.bottom - theRect.top -- instead, use .width and .height which are methods of the rect property/data type the desktopRectList[1].rect.width the desktopRectList[1].rect.height window("stage").rect.width window("stage").rect.height
- caveat: the width and height values calculated from the rect are updated on a stage update (or Lingo equivalent: updateStage) so be aware of this limitation.
Using the Inflate() command (8.5 to MX2004)
Takes a rectangle and a width and height change, and returns a new rectangle inflated from the centre.
-- add 5 pixels to the height of the sprite sprite(1).rect = sprite(1).rect.inflate(0, 5) -- subtract 5 pixels from the width of the sprite sprite(1).rect = sprite(1).rect.inflate(-5, 0)
Scripts
the scriptExecutionStyle
In Director 10 (Director MX 2004), the syntax used for creating new objects was standardized. A new movie property, the scriptExecutionStyle, was introduced so that movies created in version 9 (MX) and earlier will still function correctly. By default, any movie last saved in a version of Director prior to MX 2004 will be set to use a value of 9.
see information here: http://www.director-online.com/dougwiki/index.php?title=Syntax_changes_in_Director_MX_2004
scriptSyntax property
Members have an undocumented scriptSyntax property, that can be read and set. Possible values are the symbols "#lingo" and "#javascript". New members have the default value "#lingo".
linkAs with filename parameter
linkAs() supports an optional parameter for specifying the target filename of the linked script file. If it's omitted, a save dialog box is presented.
member("main").linkAs("c:\main.ls")
Using prepareFrame and exitFrame in a Parent Script
This method can be used in a Parent script to provide access to the prepareFrame and exitFrame event handlers via a quirk with timeout objects.
-- frameProxy Script -- provides access to the prepareFrame and exitFrame event handlers -- using a timeout object quirk property pObjFrameProxy ----------------------------- -- Public Methods ----------------------------- on new me put "new instance of frameProxy script created." return me end on createFrameProxy me put "frame proxy initiated." pObjFrameProxy = timeout().new("frameProxy" & the milliseconds, the maxInteger, #frameProxyHandler, me) end on cleanup me put "clean up frameProxy timeout object." pObjFrameProxy.forget() end ----------------------------- -- Private Methods ----------------------------- on prepareFrame me put "prepareFrame! " & the milliseconds end -- the enterFrame handler will not work -- added for testing purposes only on enterFrame me put "enterFrame! " & the milliseconds end on exitFrame me put "exitFrame! " & the milliseconds end on frameProxyHandler me nothing end
Strings & Text Members
Delete Text Chunk Using Dot Syntax
Delete a text chunk in a member using dot syntax:
member("text").line[1].delete() member("text").char[1..4].delete()
Case Sensitive String Comparison
You can use lists to do case sensitive string comparisons.
put "Steve" = "steve" -- 1 put list("Steve") = list("steve") -- 0
Range and Ref of Text Member
You can determine the character range of a text chunk expression using the undocumented .range property:
put member(1).word[10].range -- [24, 28]
The somewhat obscure .ref property allows you to set a reference to a text chunk so it can be manipulated directly:
txtRef = member("text").line[2..3].ref put txtRef -- <Prop Ref 2 249760> put txtRef.range -- [74, 236] put txtRef.font -- "Arial" put txtRef.word[1] -- "The" txtRef.word[1].font = "Verdana" put txtRef.word[1].font -- Verdana
Note that the .ref property value gives you access to the defined chunk of text as if it was a text member in its own right. You can get and set .font, .fontstyle, .fontsize, .text, .word, .line, .char, etc.
Using the .selection and .selectedText Properties of a Text Member
When using member(“text”).selection the value of the start and end position of the insertion character (carat) is returned; the positions are the spaces between characters, starting at position 0. Thus, there are two systems of numbering - the first is base-0 and the second is base-1, ie. the insertion position starts at 0 and the character position starts at 1. There are two text member properties to consider: .selection and selectedText. Let's say I select the first to fourth characters in a text member. The text reads "This is a test". In the message window:
put member("text").selection -- [0,4] -- that's the insertion point (carat) position put member("text").selectedText -- <Prop Ref 1 3cb8eac> Instead, you can use: put member("text").selectedText.text -- "This" put member("text").selectedText.range -- [1,4] -- since the selectedText is a reference to the text chunk -- various chunk properties can be set: member("text").selectedText.fontStyle = [#bold] member("text").selectedText.font = "Tahoma" member("text").selectedText.fontSize = 18
The "byte" Chunk Expression
From the Director 7.02 release notes:
On double-byte systems such as Japanese, the "byte" chunk expression enables you to access individual bytes in multibyte characters.
For example, to find out the number of bytes in line 3, use this lingo:
put myTextMember.line[3].byte.count -- 19 -- use this Lingo to access the first byte of a multibyte character: put myTextMember.char[5].byte[1]
On Roman systems "byte" has the same meaning as "char".
System, Sprites, Cast, Members
the commandLine
With the undocumented property "the commandLine" you can get commandline parameters that had been defined when the projector was started (only Windows and OSX). Start Director in Windows with the following line ...
"C:\Program Files\Macromedia\Director MX 2004\Director.exe" myCommand
... you can now get the additional parameter inside Director:
-- Lingo-Syntax put the commandLine -- "myCommand"
If you drag and drop another file on top of a Director projector, you get the file´s name as the command line.
the stageColor
If you need to clear the stage of some anomalous graphical residue that remains from a sprite who's updating is not being handled by Director (ie. an activeX control, video or flash sprite on the stage) then you can try this (commonly called 'repainting'):
the stageColor = the stageColor
stretch property of sprites
If you import a new image into an existing sprite on runtime (e.g. by setting the filename property of the member), the new image will be stretched or squeezed into the sprite dimensions. This can be prevented with the stretch property set to FALSE.
-- Lingo-Syntax sprite("myImage").stretch = FALSE -- or TRUE
JavaScript Garbage Collection
Even in Director's (from Director MX 2004) JavaScript syntax, there's something undocumented for you guys.
The JavaScript Interpreter (SpiderMonkey) remembers everything, until 8MB of system memory are used. Then it starts to collect garbage. With the method gc() you can force garbage collection anytime.
// JavaScript-Syntax _system.gc();
blend property for window opacity (Win only)
With the undocumented blend property of the window object you can set the opacity for the whole projector window.
-- Lingo-Syntax myWindow = new window("Hello") myWindow.blend = 50
closeRequest
Developers wishing to use the exitLock property can capture a user's attempt to close the projector by using the following code:
on closeRequest -- statement(s) end
This new handler used with the exitLock setting is a great way to create a "Save dialog" routine if the user has not saved their work before exiting the program. The closeRequest handler was introduced in DMX2004.
the systemDate
the systemDate returns a date object with the current date and time.
put the systemDate -- date( 2008, 10, 6 )
You can get the various components of the date and time from the returned date object, eg.
sysDate = the systemDate put sysDate.month -- 10 put sysDate.day -- 6 put sysDate.year -- 2008 put sysDate.seconds -- 1084 hours = sysDate.seconds / 3600 minutes = (sysDate.seconds mod 3600) / 60 seconds = sysDate.seconds mod 60 -- dot syntax _movie.systemDate()
_system.date() is not the equivalent dot syntax method (but _system.date(stringOrInt) returns the same kind of date object but only the Int eg. 20081006 works across sytems; a string parameter eg. "10/6/2008" is dependent upon the regional settings of the computer it's running on so cannot be relied upon).
the stage.name
Allows a developer to store some piece of information. Not to be confused with the stage.title. It's important to note that one of the dot syntax equivalents is _movie.window("stage"), however, if you change the stage name then you MUST reference it by the new name. Dot syntax further confuses the issue as _movie.stage also references the stage, but changing the name of the stage using this syntax does not affect the association.
put _movie.window("stage").name -- "stage" _movie.stage.name = "test" put _movie.window("stage").name -- <throws a script error> put _movie.window("test").name -- "test" put _movie.stage.name -- "test" put _player.windowList -- [(window "test")]
Mouse Buttons Detected with KeyPressed
- Left Mouse Button – keyPressed(128)
- Right Mouse Button – keyPressed(129)
- Middle Mouse Button – keyPressed(130)
Using keyPressed for the middle button should work on all standard 3-button mice. It may not function on mice with more than three buttons. The keyPressed needs to be placed in an on mouseDown or a frame handler. For best results, use a frame handler.
on enterFrame if keyPressed(130) then alert("You pressed the middle button") end if end
Multiple Instances of a MIAW
To open up multiple instances of a MIAW you must set the .dir file to read-only. This can be done through either the Explorer window (PC), the File Browser window (mac) or through an Xtra such as BuddyAPI (Please note, that it is not necessary to do so on macOS, as one file can be opened more than once on macOS. Also note, that you cannot set the readonly property for windows on macOS, you will always need a windows OS to set the readonly property for a file for windows). As well, you need to give each window a custom instance name. One way to accomplish this is to append the milliseconds onto the end, ie.
-- no spaces allowed instanceName = "display_profile" & the milliseconds window().new(instanceName) -- assuming the file name is profile.dir -- leave out the extension, that way Director will -- look for profile.dir or profile.dxr window(instanceName).fileName = "profile" window().open(instanceName)
An example where you would use multiple instances of the same window is in a chat program where you have a private chat window popup to chat with another person. In this situation, it would be more useful to name the windows by the unique chatter and chattee names, eg. "codemonger_lisa369"
Pausing and Playing the Playhead
Even though they've been deprecated, these two oldies still work (tested in DMX2004).
-- to pause the playhead pause -- to play the playhead again continue
DispatchCommand
credit to: Valentin Schmidt, Pedja, Kraig - Thu, 27 Jan 2005 Direct-L
DispatchCommand() is a lingo method found in UIHelper.x32 xtra which works in DMX2004 or above. It permits lingo to send events to the authoring environment via a code value (0 - 65535) allowing interaction with any menu entry in Director.
Examples: General
dispatchCommand(4104) -- publish the movie with the last publish settings dispatchCommand(4101) -- saves the movie, dispatchCommand(4103) -- does a "Save and Compact" dispatchcommand(35334) -- Recompiles all scripts dispatchCommand(58370) -- clear the message window (bottom pane)
Examples: Open a script
castLib(1).selection = [[9, 9]] -- Select the script member in cast library dispatchCommand(9245) -- Open script window
(Although you do not need this specific example, as the UIHelper xtra has a dedicated method to open a scripteditor window. You can even specify the char where to scroll to. To do so use: activateScriptEditor <int memberNum>, <int castLibNum>, <int selectionStart>, <int selectionEnd>)
Although a definitive list of valid command codes was never published, work by the Director community (Valentin, Pedja, Kriag) provided several resources.
Known command numbers - Short list of known, useful and working commands.
Full menu command list - Lists all menu items and corresponding comand code, as extracted from the menu resource of Director.
Publish from the commandline - Example by Valentin Schmidt on how to publish from command line.
UIHelper Xtra
Seconds in the Date Object
The date object (including the systemDate), contains an undocumented property, seconds.
dateObj = the systemDate -- get today's date from the computer put dateObj.seconds -- 81290 dateObj = date(2009, 12, 1) put dateObj.seconds -- 0 -- the seconds are zero by default. It must be set. dateObj.seconds = 32000
The searchPathList Not Affected by clearGlobals
The _player.searchPathList is not affected by clearGlobals but can be passed from one movie to another after a 'go movie()' command. This means you can pass variables using the searchPathList without a clearGlobals affecting it. As well, even though it's meant for passing fully qualified paths, it will accept any datatype and will not throw an error.
global gTest gTest = "This is a test" _player.searchPathList = ["This is a test", 21, #customSymbol, [32, 45, 22, 8]] _global.clearGlobals() _global.showGlobals() -- Global Variables -- version = "10.1.1" put _player.searchPathList -- ["This is a test", 21, #customSymbol, [32, 45, 22, 8]]
Here are all the syntax forms of the searchPathList:
-- Dot Syntax for Lingo and Javascript _player.searchPathList _player.searchPaths -- Verbose Syntax the searchPathList the searchPaths
Mime Types for Shockwave
Make sure your server has the correct mime types for cct files set up. It's often the case that even though your server might serve dcr's correctly, it won't serve other formats in the shockwave family. Here's the full list of mime types for shockwave:
- application/x-director dir
- application/x-director dcr
- application/x-director dxr
- application/x-director cst
- application/x-director cct
- application/x-director cxt
- application/x-director w3d
- application/x-director swa
Link Resources:
- http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_16509
- http://director-online.com/forums/read.php?2,20039
Create Filmloop With Lingo
credit to: Brennan Young Sat, 6 Oct 2007 18:03:28 +0200 on Direct-L
mem = new(#filmloop) mem.media = the score -- yields a filmloop
The more alert amongst you will realize that you have to use ALL the score, and you are almost certainly using the score for something else, no?
One workaround is to use an offscreen MIAW with an empty score reserved for exactly this purpose, another is to store the 'proper' score in another filmloop while you're generating the LDM, then dump the cached filmloop back into the score when you're done.
the score = member("oldScoreStoredinFilmloop").media
Still another is to do everything except the LDM/filmloop generation with imaging lingo directly to the stage. (Ugh).
Like I said, it's ugly, but it's doable if you really need it.
I've also had success using filmloops containing a frame full of placeholders occupying as many channels as I think I'll need, then 'tell sprite...'. There are some issues with mouse/frame events, and editable text, but it is fairly robust otherwise.
importFileInto with castLib files
If you want to dynamically link a new castLib to your movie at runtime (without using an xtra like castXtra), you can use:
dummyMember.importFileInto("c:\test.cst")
This will link "c:\test.cst" as additional castLib. Be careful, the member in member slot dummyMember will be deleted, therefor you have to make sure to use an empty member slot, e.g. by creating a new member on the fly (that will be deleted again right away):
put _movie.castLib.count -- 1 new(#bitmap).importFileInto("c:\test.cst") put _movie.castLib.count -- 2 put _movie.castLib[2].name -- "test"
Number of Members and Casts
The verbose and dot syntax for getting both the number of members and number of castlibs.
This gets the number of members of the first cast:
-- verbose the number of members -- dot syntax castlib(1).member.count
This gets the number of members of a specific cast library:
-- verbose the number of members of castlib 1 the number of members of castlib "scripts" -- dot syntax castlib(2).member.count castlib("scripts").member.count
This gets the number of cast libraries in the movie:
-- verbose the number of castlibs -- dot syntax _movie.castlib.count
CompressedMedia
credit to: James Newton & Valentin Schmidt - Tue, 4 Sep 2007 Direct-L
Before you access the compressedMedia of the bitmap member, save the castLib in which it is stored. Also, you must use .importFileInto() instead of .fileName()
You can check if the compressedMedia is really compressed by comparing memberRef.media.length to memberRef.compressedMedia.length:
isCompressed = (memberRef.compressedMedia.length <> memberRef.media.length)
Vectors
Vector Shapes and Float Values
Although the vector points in a vertextList can contain floats, those values do not survive the process of saving the project; the floats are rounded to the nearest whole number. The only way to maintain the float precision is to store all vertexLists. Two methods of storage are: 1) In a field or text member, setting to the vectorShape member at runtime or 2) Store the values in the .comments property of the vector shape member itself.
mem = new(#vectorshape) mem.name = "vectorshape" mem.vertexList = [[#vertex: point(-66.6350, 37.8780), #handle1: point(-70.333, -36.1254), \ #handle2: point(-62.4209, 110.5532)], [#vertex: point(66.3000, -5.0066), \ #handle1: point(121.089, 56.1200), #handle2: point(11.7881, -66.4112)]] -- at this point, if you save the project, close it, -- and then open it back up again you will get this: put member("vectorshape").vertexList [[#vertex: point(-67, 38), #handle1: point(-70, -36), #handle2: point(-62, 111)], \ [#vertex: point(66, -5), #handle1: point(121, 56), #handle2: point(12, -66)]] -- a way around this might be to save the information during -- authoring to the little-used .comments property of the member member("vectorshape").comments = string(member("vectorshape").vertexList) -- then, to load it back in: member("vectorshape").vertexList = value(member("vectorshape").comments)
#extruder property of a vector shape cast member
It is possible to extrude vector shapes with the extrude3d command. But you have to build an extruder resource from a normal textmember, before you are able to apply the vertexList from the vector shape.
- create a text cast member
textMember = new(#text)
- initialize the member with any string
textMember.text = "a"
- extrude the text member's string into a 3D cast member
extruderResource = textMember.extrude3d(member("3D"))
- grab vertex list of vector shape cast member
tList = member("vector shape").vertexList
- update model resource
extruderResource.vertexList = tList
Now use that model resource as desired.
Typing Text in the Vector Shape Window
There is a special text entry mode in the vector editor of Director - open a vector window then type 'abc' (without the single quotes) and then start typing ... you get a sort-of plotter-style vector text...no font choice though – fairly useless for anything.
Work in Progress
Undoc'd Parameters in importFileInto()
-- Lingo-Syntax member("myImage").importFileInto(fileToImport, [#trimWhitespace: false, #remapImageToStage: false, #dither: true])
When #trimWhiteSpace is set to FALSE, any white pixels surrounding the non-white content of the image will be left intact. When #trimWhiteSpace is TRUE, white pixels surrounding the non-white image content are removed. The default is TRUE.
#remapImageToStage prevents the new member from inheriting the bit depth of the stage. If the image is 8-bit, this ensures that the palette (if it is valid) is also imported. This parameter addresses the problem, that importFileInto() always uses the current bit depth of the stage. With this you can set it to always use 32-bit, but there is no way to define a lower bit depth. So you cannot create an 8-bit member with this command. The default is TRUE.
#dither set to TRUE, the image is dithered to the closest colors of the current palette, rather than remapped to the current palette. Also, you can use the undocumented dither values, 1215 and 1969. The default is FALSE.