-- PRIMARY EVENT BROKER -- -- Movie Script -- -- © September 2005, OpenSpark Interactive Ltd -- -- ---------------------------------------------------------------------- -- This Broker script allows you to modify the primary event handlers: -- * the mouseDownScript -- * the mouseUpScript -- * the keyDownScript -- * the keyUpScript -- -- These player properties can contain code which is executed before -- the appropriate events are sent to the sprites, member scripts or -- the movie. By default, the event will be passed on. To prevent -- any other code from being executed, you should add the command... -- -- stopEvent -- -- ... to the primary event handler. -- -- You may want to intercept all use of the mouse buttons or the -- keyboard temporarily or on a more permanent basis. Examples: -- -- Watching for a mouse click outside a custom menu -- ------------------------------------------------ -- -- the mouseDownScript = "if the clickOn <> 27 then closeMenu" -- -- Hijacking a particular key -- -------------------------- -- -- the keyDownScript = ¬ -- "if the key = RETURN then"&RETURN&¬ -- alert ""E&"Don't touch the RETURN key""E&RETURN&¬ -- " stopEvent"&RETURN&¬ -- "end if" -- -- If you need to override the current settings for a given primary -- event handler, then you'll find this script useful. -- PUBLIC METHODS -- ============== -- -- Primary_RegisterCode() -- Register code snippets then refer to those snippets using the -- appropriate symbol. -- -- Primary_AddCode() -- Add a pre-registered code snippet to a given primary event handler -- -- Primary_RemoveCode() -- Remove a code snippet previously added to the given primary event -- handler by Primary_AddCode() -- -- Primary_Set() -- Replace the entire primary event handler with the given code -- string. You can _Set() a primary event handler to its current -- value in order to create a backup before you use _AddCode() or -- _RemoveCode() to modify it. You can later restore the backup. -- -- Primary_Restore() -- Restore the event handler to the state it was in before the last -- Primary_Set() call. Any modifications since the last _Set() call -- will be lost. You can use symbols to define particular restore -- steps. _Set() and _Restore() calls should be balanced; you should -- take care not to _Restore() a given primary event handler more often -- than you _Set() it. If you name restore steps using symbols, then -- -- TIP: You could use the _Set() and _Restore() methods to set up a -- series of actions that the user must perform. As each action is -- performed correctly, a previous version of the primary event -- handler is restored, thus defining the next action to be performed. ---------------------------------------------------------------------- -- PUBLIC METHODS -- on Primary_RegisterCode(aSymbol, aCodeString, aHandler) -------------- -- INPUT: should be a symbol which uniquely identifies -- a code string -- should be a string of executable Lingo code -- may be #mouseDown | #mouseUp | #keyDown | -- #keyUp, in which case the code string will be added to -- the appropriate primary event handler -- ACTION: Registers the code string with this script, so that -- future calls to Primary_AddCode can add the code to a -- chosen primary event handler, and Primary_DeleteCode can -- remove the code from the handler later. Note that no -- test is made to check whether the code string can be -- executed without provoking a script error. -- OUTPUT: Returns 0 (no error) or an error symbol -------------------------------------------------------------------- vBroker = mPrimary_GetBroker() return vBroker.mPrimary_RegisterCode(aSymbol, aCodeString, aHandler) end Primary_RegisterCode on Primary_AddCode(aHandler, aCodeSymbol) ---------------------------- -- INPUT: should be #mouseDown | #mouseUp | #keyDown | -- #keyUp -- should be a symbol previously registered -- using Primary_RegisterCode() -- ACTION: Adds the code string previously registered with -- aCodeSymbol to the given primary event handler -- OUTPUT: Returns 0 (no error) or an error symbol -------------------------------------------------------------------- vBroker = mPrimary_GetBroker() return vBroker.mPrimary_AddCode(aHandler, aCodeSymbol) end Primary_AddCode on Primary_RemoveCode(aHandler, aCodeSymbol) ------------------------- -- INPUT: should be #mouseDown | #mouseUp | #keyDown | -- #keyUp -- should be a symbol previously registered -- using Primary_RegisterCode() -- ACTION: Removes the code string associated with aCodeSymbol to -- the given primary event handler -- OUTPUT: Returns 0 (no error) or an error symbol -------------------------------------------------------------------- vBroker = mPrimary_GetBroker() return vBroker.mPrimary_RemoveCode(aHandler, aCodeSymbol) end Primary_RemoveCode on Primary_Set(aHandler, aCodeString, aStepSymbol) ------------------- -- INPUT: should be #mouseDown | #mouseUp | #keyDown | -- #keyUp -- should be a string of executable Lingo code -- ACTION: Replaces the current primary event handler with the given -- code string. The current primary handler is stored in -- pRestoreList so that it can be restored later. -- OUTPUT: Return 0 (no error) or an error symbol -------------------------------------------------------------------- vBroker = mPrimary_GetBroker() return vBroker.mPrimary_Set(aHandler, aCodeString, aStepSymbol) end Primary_Set on Primary_Restore(aHandler, aStepSymbol) ---------------------------- -- INPUT: should be #mouseDown | #mouseUp | #keyDown | -- #keyUp -- ACTION: Replaces the current primary event handler with the value -- it had before the most recent Primary_Set() cgll. -- OUTPUT: Return 0 (no error) or an error symbol -------------------------------------------------------------------- vBroker = mPrimary_GetBroker() return vBroker.mPrimary_Restore(aHandler, aStepSymbol) end Primary_Restore -- ================================================================ -- -- SCRIPT PROPERTY AND METHOD -- property broker on mPrimary_GetBroker() ---------------------------------------------- -- SOURCE: Called by all Public Methods except XtraInfo() -- ACTION: Creates an instance of this script, if none exists, and -- stores it as the .broker property of the script itself. -- OUTPUT: Returns a pointer to the .broker instance -------------------------------------------------------------------- vScript = script("Primary Event Broker") -- HARD-CODED script name vBroker = vScript.broker if voidP(vBroker) then vBroker = vScript.new() -- implicit handler vBroker.mPrimary_Initialize() vScript.broker = vBroker end if return vBroker end mPrimary_GetBroker -- ================================================================ -- -- PRIVATE PROPERTIES AND METHODS -- property pCodeList -- [: , ...] property pRestoreList -- [: [list of strings], ...] on mPrimary_Initialize(me) ------------------------------------------- -- SOURCE: Sent by mPrimary_GetBroker() -- ACTION: -------------------------------------------------------------------- pCodeList = [:] pRestoreList = [:] end mPrimary_Initialize -- ================================================================ -- -- PRIVATE METHODS on mPrimary_RegisterCode(me, aCodeSymbol, aCodeString, aHandler) ----- -- INPUT: should be a symbol which uniquely identifies -- a code string -- should be a string of executable Lingo code -- may be #mouseDown | #mouseUp | #keyDown | -- #keyUp, in which case the code string will be added to -- the appropriate primary event handler -- ACTION: Registers the code string with this script, so that -- future calls to Primary_AddCode can add the code to a -- chosen primary event handler, and Primary_RemoveCode can -- remove the code from the handler later. Note that no -- test is made to check whether the code string can be -- executed without provoking a script error. -- OUTPUT: Returns 0 (no error) or an error symbol -------------------------------------------------------------------- if not symbolP(aCodeSymbol) then return #symbolExpected else if not stringP(aCodeString) then return #stringExpected end if -- Delete any leading or trailing whitespace vCount = the number of words of aCodeString aCodeString = word 1 to vCount of aCodeString vExistingCode = pCodeList[aCodeSymbol] if stringP(vExistingCode) then -- This code symbol is already defined if vExistingCode = aCodeString then -- There is no need to re-register the code string... if symbolP(aHandler) then -- ... but we might need to add it to the event handler return me.mPrimary_AddCode(aHandler, aCodeSymbol) else return 0 end if else -- The new code string is different. Remove the existing code -- from the event handler before we adopt the new version. me.mPrimary_RemoveCode(aHandler, aCodeSymbol) end if end if pCodeList[aCodeSymbol] = aCodeString if symbolP(aHandler) then vError = me.mPrimary_AddCode(aHandler, aCodeSymbol) else vError = 0 end if return vError end mPrimary_RegisterCode on mPrimary_AddCode(me, aHandler, aCodeSymbol) ----------------------- -- INPUT: should be #mouseDown | #mouseUp | #keyDown | -- #keyUp -- should be a symbol previously registered -- using Primary_RegisterCode() -- ACTION: Adds the code string previously registered with -- aCodeSymbol to the given primary event handler -- OUTPUT: Returns 0 (no error) or an error symbol -------------------------------------------------------------------- -- Check aHandler case aHandler of #mouseDown: vEventHandler = the mouseDownScript #mouseUp: vEventHandler = the mouseUpScript #keyDown: vEventHandler = the keyDownScript #keyUp: vEventHandler = the keyUpScript otherwise: return #unknownEvent end case -- Check aCodeSymbol vCodeString = pCodeList[aCodeSymbol] if not stringP(vCodeString) then return #unknownCode end if -- Check if the code is already in the primary event handler _ = RETURN vOffset = offset(_&vCodeString&_, _&vEventHandler&_) if vOffset then -- The event handler already contains the given code extract return 0 end if -- If we get here, we need to add the code to the event handler if vEventHandler = "" then vEventHandler = vCodeString else put _&vCodeString after vEventHandler end if -- Update the event handler case aHandler of #mouseDown: the mouseDownScript = vEventHandler #mouseUp: the mouseUpScript = vEventHandler #keyDown: the keyDownScript = vEventHandler #keyUp: the keyUpScript = vEventHandler end case return 0 end mPrimary_AddCode on mPrimary_RemoveCode(me, aHandler, aCodeSymbol) -------------------- -- INPUT: should be #mouseDown | #mouseUp | #keyDown | -- #keyUp -- should be a symbol previously registered -- using Primary_RegisterCode() -- ACTION: Removes the code string associated with aCodeSymbol to -- the given primary event handler -- OUTPUT: Returns 0 (no error) or an error symbol -------------------------------------------------------------------- -- Check aHandler case aHandler of #mouseDown: vEventHandler = the mouseDownScript #mouseUp: vEventHandler = the mouseUpScript #keyDown: vEventHandler = the keyDownScript #keyUp: vEventHandler = the keyUpScript otherwise: return #unknownEvent end case -- Check aCodeSymbol vCodeString = pCodeList[aCodeSymbol] if not stringP(vCodeString) then return #unknownCode end if -- Check if the code is already in the primary event handler _ = RETURN vOffset = offset(_&vCodeString&_, _&vEventHandler&_) if not vOffset then -- The given code extract does not appear in the event handler return 0 end if -- If we get here, we need to remove the code to the event handler if vEventHandler = vCodeString then vEventHandler = "" else vChunk = char 1 to vOffset of vEventHandler vStart = the number of lines of vChunk vEnd = vStart + the number of lines of vCodeString - 1 end if -- Update the event handler case aHandler of #mouseDown: the mouseDownScript = vEventHandler #mouseUp: the mouseUpScript = vEventHandler #keyDown: the keyDownScript = vEventHandler #keyUp: the keyUpScript = vEventHandler end case return 0 end mPrimary_RemoveCode on mPrimary_Set(me, aHandler, aCodeString, aStepSymbol) -------------- -- INPUT: should be #mouseDown | #mouseUp | #keyDown | -- #keyUp -- should be a string of executable Lingo code -- may be a symbol. If not, an arbitrary -- integer will be used as the key for the saved version of -- the given primary event handler. -- ACTION: Replaces the current primary event handler with the given -- code string. The current primary handler is stored in -- pRestoreList so that it can be restored later. -- OUTPUT: Return 0 (no error) or an error symbol -------------------------------------------------------------------- -- Check aCodeString if not stringP(aCodeString) then return #stringExpected end if vList = pRestoreList[aHandler] if ilk(vList) <> #list then vList = [:] pRestoreList[aHandler] = vList end if if not symbolP(aStepSymbol) then -- Use the index number to save the current event handler aStepSymbol = vList.count() + 1 end if -- Check aHandler case aHandler of #mouseDown: vList.addProp(aStepSymbol, the mouseDownScript) #mouseUp: vList.addProp(aStepSymbol, the mouseUpScript) #keyDown: vList.addProp(aStepSymbol, the keyDownScript) #keyUp: vList.addProp(aStepSymbol, the keyUpScript) otherwise: return #unknownEvent end case -- Update the event handler case aHandler of #mouseDown: the mouseDownScript = aCodeString #mouseUp: the mouseUpScript = aCodeString #keyDown: the keyDownScript = aCodeString #keyUp: the keyUpScript = aCodeString end case return 0 end mPrimary_Set on mPrimary_Restore(me, aHandler, aStepSymbol) ----------------------- -- INPUT: should be #mouseDown | #mouseUp | #keyDown | -- #keyUp -- may be a symbol previously used to define -- a restore step in Primary_Set. If so, all steps added -- since the most recent use of aStep will be deleted. If -- it is any other value other than 0 or VOID, then only -- unnamed steps will be restored. -- ACTION: Replaces the current primary event handler with the value -- it had before the most recent Primary_Set() call. -- OUTPUT: Return 0 (no error) or an error symbol -------------------------------------------------------------------- if not symbolP(aHandler) then return #symbolExpected end if vList = pRestoreList[aHandler] if ilk(vList) <> #propList then -- Primary_Set has never been called... or aHandler is invalid return #setNotCalled end if i = vList.count if not i then return #nothingToRestore end if if symbolP(aStepSymbol) then -- We are restoring back to the last use of the given symbol vCount = i repeat while i vProp = vList.getPropAt(i) if vProp = aStepSymbol then exit repeat end if i = i - 1 end repeat if i then -- Restore back to the given step, deleting all later restore -- steps j = vCount - 1 repeat while j vList.deleteAt(i + j) j = j - 1 end repeat else return #symbolNotFound end if else if not aStepSymbol or integerP(vList.getPropAt(i)) then -- This step is not named, or we're not concerned whether it is -- named or not: continue else -- aStepSymbol is not VOID and the next restore step is named. -- Don't restore. return #stepIsNamed end if vEventHandler = vList.getLast() -- faster than vList[i] -- Restore the primary event handler case aHandler of #mouseDown: the mouseDownScript = vEventHandler #mouseUp: the mouseUpScript = vEventHandler #keyDown: the keyDownScript = vEventHandler #keyUp: the keyUpScript = vEventHandler otherwise: return #unknownEvent end case -- The primary event handler was successfully restored. We can now -- safely remove the restored value vList.deleteAt(i) return 0 end mPrimary_Restore --34567890123456789012345678901234567890123456789012345678901234567890