-- CHOOSE CASTLIB -- -- -- © May 2003, OpenSpark Interactive Ltd -- -- ----------------------------------------------------------------------- -- Use this behavior on any button to swap in an external castLib in -- place of a given cast. This is useful for skinning an application -- or for creating localized versions. -- -- TIP: Give the member that this behavior is to be dropped on the -- same name as the castLib to be used. Do not include ".cst", ".cxt" -- or ".cct" in the member name. -- -- XTRAS: May require FileIO Xtra at author time and if not, will -- require FileXtra4 at runtime. ---------------------------------------------------------------------- property castNumber property castFile property castGlobal -- EVENT HANDLER -- on mouseUp(me) me.mSwapCastLib() end mouseUp -- PRIVATE METHODS -- on mSwapCastLib(me) -------------------------------------------------- -- SENT BY mouseUp() -- ACTION: Swaps in the selected castLib file, if it is available, -- and if so, sets the chosen global if required. -------------------------------------------------------------------- tCastFile = me.mGetAbsolutePath(castFile) if not tCastFile then -- The expected castLib file is missing exit end if castLib(castNumber).fileName = tCastFile if castLib(castNumber).fileName = tCastFile then -- The cast swap was successful if castGlobal <> "" then -- Set the chosen global to the name of the cast file, without -- folder path or extension tGlobal = symbol(castGlobal) tValue = me.mGetCastName(castFile) if (the globals)[tGlobal] <> tValue then (the globals)[tGlobal] = tValue -- Prompt any sprites to re-initialize sendAllSprites(#beginSprite) end if end if end if end mSwapCastLib on mGetAbsolutePath(me, aFilePath) ----------------------------------- -- CALLED by mSwapCastLib() if castFile does not start with "@" -- INPUT: should be a relative file path string -- OUTPUT: The absolute path to the file, taking the moviePath as -- the starting point, or 0 if the file is not found -------------------------------------------------------------------- -- Remove the "@\" relative path indicator if there is one if (aFilePath starts "@") then delete aFilePath.char[1..2] -- "@:", "@\" or "@/" end if -- Remove any cast or movie extension, in preparation for testing -- all cast or movie extensions in turn tDelimiter = the itemDelimiter the itemDelimiter = "." case (the last item of aFilePath) of "cst", "cxt", "cct": delete the last item of aFilePath -- tType = #cast --"dir", "dxr", "dcr": -- delete the last item of aFilePath -- tType = #movie end case -- Ensure that the folder path (if any) is in the correct format for -- this platform aFilePath = me.mConvertToPlatform(aFilePath) -- Convert the relative path into an absolute one, using the same -- rules as the built-in "@..." conversion tPath = the moviePath tPathDelimiter = the last char of tPath the itemDelimiter = tPathDelimiter delete the last char of tPath tCount = aFilePath.item.count repeat with i = 1 to tCount tFolder = aFilePath.item[i] if tFolder = "" then delete the last item of tPath else put tPathDelimiter&tFolder after tPath end if end repeat the itemDelimiter = tDelimiter -- Check for files with all relevant cast or movie extensions... tFileXtra = xtra("FileXtra4").new() -- case tType of -- #cast: tFilePath = tPath&".cst" if not tFileXtra.fx_FileExists(tFilePath) then tFilePath = tPath&".cxt" if not tFileXtra.fx_FileExists(tFilePath) then tFilePath = tPath&".cct" end if end if -- #movie: -- tFilePath = tPath&".dir" -- if not tFileXtra.fx_FileExists(tFilePath) then -- tFilePath = tPath&".dxr" -- if not tFileXtra.fx_FileExists(tFilePath) then -- tFilePath = tPath&".dcr" -- end if -- end if -- -- otherwise: -- tFilePath = tPath -- end case -- ... and that the expected file exists if not tFileXtra.fx_FileExists(tFilePath) then -- The expected file is missing tFilePath = 0 end if return tFilePath end mGetAbsolutePath on mGetCastName(me, aCastFile) --------------------------------------- -- CALLED by mSwapCastLib() if castGlobal is not "" -- INPUT: will be a string which may include a folder -- path and a cast extension -- OUTPUT: the raw file name -------------------------------------------------------------------- tDelimiter = the itemDelimiter -- Remove any cast extension the itemDelimiter = "." case (the last item of aCastFile) of "cst", "cxt", "cct": delete the last item of aCastFile end case -- Remove any Windows folder path the itemDelimiter = "\" aCastFile = the last item of aCastFile -- Remove any Mac folder path the itemDelimiter = ":" aCastFile = the last item of aCastFile the itemDelimiter = tDelimiter return aCastFile end mGetCastName on mConvertToPlatform(me, aFilePath) --------------------------------- -- CALLED by mGetCastFile() if castFile does not start with "@" -- INPUT: will be a string which may include a folder -- path -- ACTION: Converts any ":" characters to "\" on Windows and vice- -- versa on Macintosh -- OUTPUT: a platform-specific relative file path -------------------------------------------------------------------- if the platform starts "Win" then -- Mac or web to Win aFilePath = ReplaceAll(aFilePath, ":", "\") return ReplaceAll(aFilePath, "/", "\") else -- Win or web to Mac aFilePath = ReplaceAll(aFilePath, "\", ":") return ReplaceAll(aFilePath, "/", ":") end if end mConvertToPlatform -- GETPDL HELPERS -- on mSelectCast(me, aPropList) ---------------------------------------- -- CALLED by getPropertyDescriptionList() if the Shift key is down -- INPUT: will be a property list with the format: -- [#comment: , -- #format: #string, -- #default: ] -- ACTION: Displays a FileIO displayOpen() dialog to allow the user -- to choose an unprotected external castLib or to Cancel -- and maintain the current choice. If a castLib is chosen, -- a #range property is added ta aPropList and the .default -- property is altered as follows: -- [#comment: , -- #format: #string, -- #range: [], -- #default: ] -------------------------------------------------------------------- tFileIO = xtra("fileIO").new() if voidP(tFileIO) then exit end if if the platform starts "Mac" then tFilterMask = "MC85MC08MC07MC97" -- .cst Director 6 through DMX else tFilterMask = "Director casts,*.c*t" end if tFileIO.setFilterMask(tFilterMask) tCastLib = tFileIO.displayOpen() put tCastLib case tCastLib of VOID, "": -- User cancelled otherwise -- A new castLib was chosen: find the relative path to it tCastLib = me.mGetRelativePathTo(tCastLib) -- Use a range list in the getPropertyDescriptionList() dialog -- so that the previous value is overridden. aPropList[#range] = [tCastLib] aPropList.default = tCastLib end case end mSelectCast on mGetRelativePathTo(me, aFilePath) --------------------------------- -- CALLED BY mSelectCast() -- INPUT: will be a string file path -- ACTION: Calculates the relative path to , by comparing -- it with the moviePath of the current movie. -- OUTPUT: a string with the format "@\\chosenFile.ext" -------------------------------------------------------------------- -- Create a copy of aFilePath so that it can be altered tFilePath = aFilePath tMoviePath = the moviePath tDelimiter = the itemDelimiter tPathDelimiter = the last char of the applicationPath the itemDelimiter = tPathDelimiter repeat while TRUE -- Delete volumes and folders until the file paths diverge if tMoviePath.item[1] <> tFilePath.item[1] then exit repeat end if delete tMoviePath.item[1] delete tFilePath.item[1] end repeat if tFilePath = aFilePath then -- The two paths diverged from the outset: different volumes tRelativePath = aFilePath else -- Move up the folder hierarchy to where the paths diverge... tRelativePath = "@" tDeep = tMoviePath.item.count repeat while tDeep tRelativePath = tRelativePath&tPathDelimiter tDeep = tDeep - 1 end repeat -- ...and then down to the chosen file tRelativePath = tRelativePath&tFilePath end if the itemDelimiter = tDelimiter return tRelativePath end mGetRelativePathTo on mGetCastList(me) -------------------------------------------------- -- CALLED BY getPropertyDescriptionList() -- OUTPUT: Returns a list of external cast names in the format -- " - " -- The first item in the list will oorrespond to the current -- value of castNumber for this behavior -------------------------------------------------------------------- tCastList = [] tCount = the number of castLibs repeat with i = 2 to tCount if stringP(castLib(i).fileName) then -- This is an external castLib tCastList.append(me.mGetCastString(i)) end if end repeat -- Check for the current value of this behavior tCurrentCast = me.mGetCurrentSpriteData(#castNumber) tCastString = me.mGetCastString(tCurrentCast) if stringP(tCastString) then -- Place the current value at the beginning of the list as default tCastList.deleteOne(tCastString) tCastList.addAt(1, tCastString) end if return tCastList end mGetCastList on mGetCastString(me, aCastNumber) ----------------------------------- -- CALLED BY mGetCastList() -- INPUT: will be an integer castLibNum or a string -- OUTPUT: Returns a string with the format: -- " - " -------------------------------------------------------------------- if stringP(aCastNumber) then -- The behavior has just been dropped on the sprite and it has -- adopted as the default value the string representing the first -- external cast. The string is already the intended output value. return aCastNumber end if if aCastNumber then tCastString = aCastNumber&" - "&castLib(aCastNumber).name else tCastString = 0 end if return tCastString end mGetCastString on mGetCurrentSpriteData(me, aPropertyName)--------------------------- -- CALLED BY mGetCastList() -- INPUT: should be a symbol -- ACTION: Reads in the value of aPropertyName in the scriptList -- for this behavior -- OUTPUT: Returns a string with the format: -- ": " -------------------------------------------------------------------- if not the currentSpriteNum then -- The script is simply being recompiled return 0 end if -- Determine the name of this behavior tScriptName = string(me) -- "(script "Script Name")" tScriptName = tScriptName.char[10..tScriptName.char.count-2] -- Identify the behavior initialisers for this behavior tBehaviorList = sprite(the currentSpriteNum).scriptList i = tBehaviorList.count() repeat while i tBehaviorData = tBehaviorList[i] tBehaviorMember = tBehaviorData[1] if tBehaviorMember.name = tScriptName then -- This is the current behavior tBehaviorData = value(tBehaviorData[2]) if ilk(tBehaviorData) = #propList then return tBehaviorData[aPropertyName] end if end if i = i - 1 end repeat end mGetCurrentSpriteData -- UTILITY HANDLER (could be in a Movie Script) -- on ReplaceAll(aString, aSubString, aReplacement) --------------------- -- INPUT: is the main string to search in -- is a string which may appear in -- is a string which is to replace all -- occurrences of in -- OUTPUT: returns an updated version of where all -- occurrences of have been replaced by -- -------------------------------------------------------------------- if aSubString = "" then return aString end if tTreatedString = "" tLengthAdjust = the number of chars of aSubString - 1 repeat while TRUE tOffset = offset(aSubString, aString) if tOffset then if tOffset - 1 then put chars(aString, 1, (tOffset - 1)) after tTreatedString end if put aReplacement after tTreatedString delete char 1 to (tOffset + tLengthAdjust) of aString else -- there are no more occurrences put aString after tTreatedString return tTreatedString end if end repeat end ReplaceAll -- BEHAVIOR PARAMETERS AND DESCRIPTION -- on isOKToAttach(me, aSpriteType) return aSpriteType = #graphic end isOKToAttach on getPropertyDescriptionList(me) tPropertyList = [:] tCastList = me.mGetCastList() if not tCastList.count then tCastList = ["< No external castLibs available >"] end if tFileData = [ \ #comment: \ "(For a Choose File... dialog, hold down SHIFT) Swap the file", \ #format: #string, \ #default: "Alternative CastLib" \ ] tPropertyList[ \ #castFile] = tFileData if the currentSpriteNum then if the shiftDown then -- Show a FileIO displayOpen() dialog to allow the user to -- choose a castLib tCurrentCast = me.mSelectCast(tFileData) else tFileData.default = sprite(the currentSpriteNum).member.name end if end if tPropertyList[ \ #castNumber] = [ \ #comment: "into castLib", \ #format: #integer, \ #range: tCastList, \ #default: tCastList[3] \ ] tPropertyList[ \ #castGlobal] = [ \ #comment: "Global to set when castLib is changed", \ #format: #string, \ #default: "gUserLanguage" \ ] return tPropertyList end getPropertyDescriptionList