virtual void ProcessEvent( Event &event ) { Element *elem = event.GetTargetElement(); UI_ScriptDocument *document = dynamic_cast<UI_ScriptDocument *>( elem->GetOwnerDocument() ); if( !document || document->IsLoading() ) { return; } if( UI_Main::Get()->debugOn() ) { Com_Printf( "ScriptEventCaller: Event %s, target %s, func %s\n", event.GetType().CString(), event.GetTargetElement()->GetTagName().CString(), funcPtr.getName() ); } if( funcPtr.isValid() ) { event.AddReference(); try { asIScriptContext *context = as->getContext(); // the context may actually be NULL after AS shutdown if( context ) { funcPtr.setContext( context ); funcPtr( NULL, &event ); } } catch( ASBind::Exception & ) { Com_Printf( S_COLOR_RED "ScriptEventListener: Failed to call function %s\n", funcPtr.getName() ); } } else { Com_Printf( S_COLOR_RED "ScriptEventListener: Not gonna call invalid function %s\n", funcPtr.getName() ); } }
virtual void ProcessEvent( Event &event ) { if( !target ) { return; } if( released ) { // the function pointer has been released, but // we're hanging around, waiting for shutdown or GC return; } Element *elem = event.GetTargetElement(); if( elem->GetOwnerDocument() != target->GetOwnerDocument() ) { // make sure the event originated from the same document as the original target return; } UI_ScriptDocument *document = dynamic_cast<UI_ScriptDocument *>(elem->GetOwnerDocument()); if( !document || document->IsLoading() ) { return; } fetchFunctionPtr( document->GetModule() ); // push elem and event as parameters to the internal function // and call it if( UI_Main::Get()->debugOn() ) { Com_Printf( "ScriptEventListener: Event %s, target %s, script %s\n", event.GetType().CString(), event.GetTargetElement()->GetTagName().CString(), script.CString() ); } if( funcPtr.isValid() ) { target->AddReference(); event.AddReference(); try { asIScriptContext *context = asmodule->getContext(); // the context may actually be NULL after AS shutdown if( context ) { funcPtr.setContext( context ); funcPtr( target, &event ); } } catch( ASBind::Exception & ) { Com_Printf( S_COLOR_RED "ScriptEventListener: Failed to call function %s %s\n", funcName.CString(), script.CString() ); } } else { Com_Printf( S_COLOR_RED "ScriptEventListener: Not gonna call invalid function %s %s\n", funcName.CString(), script.CString() ); } }
virtual void ProcessEvent( Event &event ) { if( released ) { // the function pointer has been released, but // we're hanging around, waiting for shutdown or GC return; } // onloads cant be called within building process if( /* event.GetType() == "load" && */ asmodule->isBuilding() ) { // TODO: we should eliminate chain to DocumentLoader like this, so move // event postponing somewhere else UI_Main::Get()->getDocumentLoader()->postponeOnload( this, event ); return; } Element *elem = event.GetTargetElement(); fetchFunctionPtr( elem->GetOwnerDocument()->GetSourceURL() ); // push elem and event as parameters to the internal function // and call it if( UI_Main::Get()->debugOn() ) { Com_Printf( "ScriptEventListener: Event %s, target %s, script %s\n", event.GetType().CString(), event.GetTargetElement()->GetTagName().CString(), script.CString() ); } if( funcPtr.isValid() ) { elem->AddReference(); event.AddReference(); try { asIScriptContext *context = asmodule->getContext(); // the context may actually be NULL after AS shutdown if( context ) { funcPtr.setContext( context ); funcPtr( elem, &event ); } } catch( ASBind::Exception & ) { Com_Printf( S_COLOR_RED "ScriptEventListener: Failed to call function %s %s\n", funcName.CString(), script.CString() ); } } else { Com_Printf( S_COLOR_RED "ScriptEventListener: Not gonna call invalid function %s %s\n", funcName.CString(), script.CString() ); } }
ScriptEventCaller( ASInterface *as, asIScriptFunction *func ) : as( as ) { funcPtr = ASBind::CreateFunctionPtr( func, funcPtr ); if( !funcPtr.isValid() ) { Com_Printf( S_COLOR_YELLOW "WARNING: ScriptEventCaller::CreateFunctionPtr failed with %s\n", func ? func->GetDeclaration() : "NULL" ); return; } }
void fetchFunctionPtr( const String &document_name ) { if( loaded ) { return; } loaded = true; asIScriptModule *module = asmodule->getModule( document_name.CString() ); assert( module != NULL ); if( module == NULL ) { Com_Printf( S_COLOR_YELLOW "WARNING: ScriptEventListener unable to find module %s\n", document_name.CString() ); } // check direct function-name if( script[0] == '$' ) funcName = script.Substring( 1 ); else { // compile inline code funcName = createFunctionName( uniqueId ); String funcCode = createFunctionCode( uniqueId, script ); script = funcCode; asIScriptFunction *scriptFunc = NULL; if( !asmodule->addFunction( module, funcName.CString(), funcCode.CString(), &scriptFunc ) ) { Com_Printf( S_COLOR_YELLOW "WARNING: ScriptEventListener addFunction failed with %s %s\n", funcName.CString(), funcCode.CString() ); } else if( scriptFunc ) { // I think we only hit this scenario when we do smth like // elem.setInnerRML( '<button onclick="window.close();" />' ); funcPtr = ASBind::CreateFunctionPtr( scriptFunc, funcPtr ); funcPtr.addref(); scriptFunc->Release(); } return; } funcPtr = ASBind::CreateFunctionPtr( funcName.CString(), module, funcPtr ); if( !funcPtr.isValid() ) { Com_Printf( S_COLOR_YELLOW "WARNING: ScriptEventListener::fetchFunctionPtr failed with %s\n", funcName.CString() ); return; } funcPtr.addref(); }
void releaseFunctionPtr() { if( released ) { return; } released = true; funcPtr.release(); if( target ) { target->RemoveReference(); target = NULL; } }
virtual void ProcessEvent( Event &event ) { // onloads cant be called within building process if( /* event.GetType() == "load" && */ asmodule->isBuilding() ) { UI_Main::Get()->getDocumentLoader()->postponeOnload( this, event ); return; } Element *elem = event.GetTargetElement(); if( UI_Main::Get()->debugOn() ) { Com_Printf( "ScriptEventCaller: Event %s, target %s, func %s\n", event.GetType().CString(), event.GetTargetElement()->GetTagName().CString(), funcPtr.getName() ); } if( funcPtr.isValid() ) { elem->AddReference(); event.AddReference(); try { asIScriptContext *context = asmodule->getContext(); // the context may actually be NULL after AS shutdown if( context ) { funcPtr.setContext( context ); funcPtr( elem, &event ); } } catch( ASBind::Exception & ) { Com_Printf( S_COLOR_RED "ScriptEventListener: Failed to call function %s\n", funcPtr.getName() ); } } else { Com_Printf( S_COLOR_RED "ScriptEventListener: Not gonna call invalid function %s\n", funcPtr.getName() ); } }
virtual ~ScriptEventCaller() { funcPtr.release(); }
void releaseFunctionPtr() { released = true; funcPtr.release(); }