diff --git a/binaries/data/mods/public/gui/common/global.xml b/binaries/data/mods/public/gui/common/global.xml index 5f32aa2e62..945a45a37e 100644 --- a/binaries/data/mods/public/gui/common/global.xml +++ b/binaries/data/mods/public/gui/common/global.xml @@ -28,8 +28,8 @@ size="5 5 200 35" z="199" > - . - */ - -#include "precompiled.h" -#include "Scheduler.h" - -int simulationTime; -int frameCount; - -CScheduler::CScheduler() -{ - m_nextTaskId = 1; -} - -int CScheduler::PushTime( int delay, const CStrW& fragment, JSObject* operateOn ) -{ - timeScript.push( SDispatchObjectScript( m_nextTaskId, fragment, simulationTime + delay, operateOn ) ); - return m_nextTaskId++; -} - -int CScheduler::PushFrame( int delay, const CStrW& fragment, JSObject* operateOn ) -{ - frameScript.push( SDispatchObjectScript( m_nextTaskId, fragment, frameCount + delay, operateOn ) ); - return m_nextTaskId++; -} - -int CScheduler::PushInterval( int first, int interval, const CStrW& fragment, JSObject* operateOn, int id ) -{ - if( !id ) - id = m_nextTaskId++; - timeScript.push( SDispatchObjectScript( id, fragment, simulationTime + first, operateOn, interval ) ); - return id++; -} - -int CScheduler::PushTime( int delay, JSFunction* script, JSObject* operateOn ) -{ - timeFunction.push( SDispatchObjectFunction( m_nextTaskId, script, simulationTime + delay, operateOn ) ); - return m_nextTaskId++; -} - -int CScheduler::PushFrame( int delay, JSFunction* script, JSObject* operateOn ) -{ - frameFunction.push( SDispatchObjectFunction( m_nextTaskId, script, frameCount + delay, operateOn ) ); - return m_nextTaskId++; -} - -int CScheduler::PushInterval( int first, int interval, JSFunction* function, JSObject* operateOn, int id ) -{ - if( !id ) - id = m_nextTaskId++; - timeFunction.push( SDispatchObjectFunction( id, function, simulationTime + first, operateOn, interval ) ); - return id++; -} - -void CScheduler::PushProgressTimer( CJSProgressTimer* progressTimer ) -{ - progressTimers.push_back( progressTimer ); -} - -void CScheduler::CancelTask( int id ) -{ - tasksToCancel.insert( id ); -} - -void CScheduler::Update(int simElapsed) -{ - simulationTime += simElapsed; - frameCount++; - jsval rval; - - while( !timeScript.empty() ) - { - SDispatchObjectScript top = timeScript.top(); - if( top.deliveryTime > simulationTime ) - break; - timeScript.pop(); - m_abortInterval = false; - - if( tasksToCancel.find( top.id ) != tasksToCancel.end() ) - { - tasksToCancel.erase( top.id ); - continue; - } - - g_ScriptingHost.ExecuteScript( top.script, L"timer", top.operateOn ); - if( top.isRecurrent && !m_abortInterval ) - PushInterval( top.delay, top.delay, top.script, top.operateOn, top.id ); - } - while( !frameScript.empty() ) - { - SDispatchObjectScript top = frameScript.top(); - if( top.deliveryTime > frameCount ) - break; - frameScript.pop(); - - if( tasksToCancel.find( top.id ) != tasksToCancel.end() ) - { - tasksToCancel.erase( top.id ); - continue; - } - - g_ScriptingHost.ExecuteScript( top.script, L"timer", top.operateOn ); - } - while( !timeFunction.empty() ) - { - SDispatchObjectFunction top = timeFunction.top(); - if( top.deliveryTime > simulationTime ) - break; - timeFunction.pop(); - m_abortInterval = false; - - if( tasksToCancel.find( top.id ) != tasksToCancel.end() ) - { - tasksToCancel.erase( top.id ); - continue; - } - - JS_CallFunction( g_ScriptingHost.getContext(), top.operateOn, top.function, 0, NULL, &rval ); - - if( top.isRecurrent && !m_abortInterval ) - PushInterval( top.delay, top.delay, top.function, top.operateOn, top.id ); - } - while( !frameFunction.empty() ) - { - SDispatchObjectFunction top = frameFunction.top(); - if( top.deliveryTime > frameCount ) - break; - frameFunction.pop(); - - if( tasksToCancel.find( top.id ) != tasksToCancel.end() ) - { - tasksToCancel.erase( top.id ); - continue; - } - - JS_CallFunction( g_ScriptingHost.getContext(), top.operateOn, top.function, 0, NULL, &rval ); - } - - std::list::iterator it; - for( it = progressTimers.begin(); it != progressTimers.end(); it++ ) - { - (*it)->m_Current += (*it)->m_Increment * simElapsed; - if( (*it)->m_Current >= (*it)->m_Max ) - { - (*it)->m_Current = (*it)->m_Max; - if( (*it)->m_Callback ) - JS_CallFunction( g_ScriptingHost.GetContext(), (*it)->m_OperateOn, (*it)->m_Callback, 0, NULL, &rval ); - it = progressTimers.erase( it ); - } - } -} - -CJSProgressTimer::CJSProgressTimer( double Max, double Increment, JSFunction* Callback, JSObject* OperateOn ) -{ - m_Max = Max; m_Increment = Increment; m_Callback = Callback; m_OperateOn = OperateOn; m_Current = 0.0; -} - -void CJSProgressTimer::ScriptingInit() -{ - AddProperty( L"max", &CJSProgressTimer::m_Max ); - AddProperty( L"current", &CJSProgressTimer::m_Current ); - AddProperty( L"increment", &CJSProgressTimer::m_Increment ); - - CJSObject::ScriptingInit( "ProgressTimer", Construct, 2 ); -} - -JSBool CJSProgressTimer::Construct( JSContext* cx, JSObject* UNUSED(obj), uintN argc, jsval* argv, jsval* rval ) -{ - debug_assert( argc >= 2 ); - double max = ToPrimitive( argv[0] ); - double increment = ToPrimitive( argv[1] ); - JSFunction* callback_fn = NULL; - JSObject* scope_obj = NULL; - if( argc >= 3 ) - { - callback_fn = JS_ValueToFunction( cx, argv[2] ); - if( ( argc >= 4 ) && JSVAL_IS_OBJECT( argv[3] ) ) - { - scope_obj = JSVAL_TO_OBJECT( argv[3] ); - } - else - { - // Attempt to determine object to operate on automatically. - - // SpiderMonkey docs say the 'this' parameter of the calling - // function is in argv[-2]. Do I believe them? One way to find out. - scope_obj = JSVAL_TO_OBJECT( argv[-2] ); - } - } - CJSProgressTimer* timer = new CJSProgressTimer( max, increment, callback_fn, scope_obj ); - timer->m_EngineOwned = false; - - g_Scheduler.PushProgressTimer( timer ); - - *rval = OBJECT_TO_JSVAL( timer->GetScript() ); - return( JS_TRUE ); -} diff --git a/source/scripting/Scheduler.h b/source/scripting/Scheduler.h deleted file mode 100644 index 7dccb4c217..0000000000 --- a/source/scripting/Scheduler.h +++ /dev/null @@ -1,113 +0,0 @@ -/* Copyright (C) 2009 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * 0 A.D. is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with 0 A.D. If not, see . - */ - -// Scheduler.h -// -// Message scheduler -// - -#ifndef INCLUDED_SCHEDULER -#define INCLUDED_SCHEDULER - -#include -#include -#include - -#include "ps/Singleton.h" -#include "ps/CStr.h" -#include "scripting/ScriptableObject.h" - -class CJSProgressTimer; - -// Message, destination and delivery time information. -struct SDispatchObject -{ - int id; - int deliveryTime; - bool isRecurrent; int delay; - SDispatchObject( int _id, const int _deliveryTime ) - : id(_id), deliveryTime( _deliveryTime ), isRecurrent( false ) {} - SDispatchObject( int _id, const int _deliveryTime, const int _recurrence ) - : id(_id), deliveryTime( _deliveryTime ), isRecurrent( true ), delay( _recurrence ) {} - inline bool operator<( const SDispatchObject& compare ) const - { - return( deliveryTime > compare.deliveryTime ); - } -}; - -struct SDispatchObjectScript : public SDispatchObject -{ - CStrW script; - JSObject* operateOn; - inline SDispatchObjectScript( int _id, const CStrW& _script, - const int _deliveryTime, JSObject* _operateOn = NULL ) - : SDispatchObject( _id, _deliveryTime ), script( _script ), operateOn( _operateOn ) {} - inline SDispatchObjectScript( int _id, const CStrW& _script, - const int _deliveryTime, JSObject* _operateOn, const int recurrence ) - : SDispatchObject( _id, _deliveryTime, recurrence ), script( _script ), operateOn( _operateOn ) {} -}; - -struct SDispatchObjectFunction : public SDispatchObject -{ - JSFunction* function; - JSObject* operateOn; - inline SDispatchObjectFunction( int _id, JSFunction* _function, - const int _deliveryTime, JSObject* _operateOn = NULL ) - : SDispatchObject( _id, _deliveryTime ), function( _function ), operateOn( _operateOn ) {} - inline SDispatchObjectFunction( int _id, JSFunction* _function, - const int _deliveryTime, JSObject* _operateOn, const int recurrence ) - : SDispatchObject( _id, _deliveryTime, recurrence ), function( _function ), operateOn( _operateOn ) {} -}; - -struct CScheduler : public Singleton -{ - std::priority_queue timeScript, frameScript; - std::priority_queue timeFunction, frameFunction; - std::list progressTimers; - int m_nextTaskId; - bool m_abortInterval; - STL_HASH_SET tasksToCancel; - - CScheduler(); - int PushTime( int delay, const CStrW& fragment, JSObject* operateOn = NULL ); - int PushFrame( int delay, const CStrW& fragment, JSObject* operateOn = NULL ); - int PushInterval( int first, int interval, const CStrW& fragment, JSObject* operateOn = NULL, int id = 0 ); - int PushTime( int delay, JSFunction* function, JSObject* operateOn = NULL ); - int PushFrame( int delay, JSFunction* function, JSObject* operateOn = NULL ); - int PushInterval( int first, int interval, JSFunction* function, JSObject* operateOn = NULL, int id = 0 ); - void PushProgressTimer( CJSProgressTimer* progressTimer ); - void CancelTask( int id ); - void Update(int elapsedSimulationTime); -}; - -#define g_Scheduler CScheduler::GetSingleton() - -class CJSProgressTimer : public CJSObject -{ - friend struct CScheduler; - double m_Max, m_Current, m_Increment; - JSFunction* m_Callback; - JSObject* m_OperateOn; - CJSProgressTimer( double Max, double Increment, JSFunction* Callback, JSObject* OperateOn ); - static JSBool Construct( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval ); -public: - static void ScriptingInit(); -}; - -extern const int ORDER_DELAY; - -#endif diff --git a/source/scripting/ScriptGlue.cpp b/source/scripting/ScriptGlue.cpp index 22921b1e0a..3af0eb87bb 100644 --- a/source/scripting/ScriptGlue.cpp +++ b/source/scripting/ScriptGlue.cpp @@ -25,7 +25,6 @@ #include "ScriptGlue.h" #include "JSConversions.h" -#include "Scheduler.h" #include "ScriptableComplex.inl" @@ -112,169 +111,8 @@ JSBool WriteLog(JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval) // Timer //----------------------------------------------------------------------------- -// Request a callback be executed after the specified delay. -// params: callback [fragment or function], delay in milliseconds [int] -// returns: -// notes: -// - Scripts and functions registered this way are called on the first -// simulation frame after the specified period has elapsed. If this causes -// multiple segments of code to be executed in the same frame, -// relative timing is maintained. Delays of 0 milliseconds cause code to be -// executed on the following simulation frame. If more than one script or -// function is scheduled to execute in the same millisecond, the order of -// execution is undefined. Code is scheduled in simulation time, and is -// therefore suspended while the game is paused or frozen. Granularity of -// timing is also limited to 1/(Simulation frame rate); currently 100ms. -// The called function or script executes in the same scope as the -// code that called SetTimeout (amongst other things, the -// 'this' reference is usually maintained) -JSBool SetTimeout( JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval ) -{ - JSU_REQUIRE_PARAM_RANGE(2, 3); - - int delay; - try - { - delay = ToPrimitive( argv[1] ); - } - catch( PSERROR_Scripting_ConversionFailed ) - { - JS_ReportError( cx, "Invalid timer parameters" ); - return( JS_TRUE ); - } - - JSObject* scope; - if( argc == 3 ) - { - if( !JSVAL_IS_OBJECT( argv[2] ) ) - { - JS_ReportError( cx, "Invalid timer parameters" ); - return( JS_TRUE ); - } - scope = JSVAL_TO_OBJECT( argv[2] ); - } - else - { - scope = JS_GetScopeChain( cx ); - } - - switch( JS_TypeOfValue( cx, argv[0] ) ) - { - case JSTYPE_STRING: - { - CStrW fragment = g_ScriptingHost.ValueToUCString( argv[0] ); - int id = g_Scheduler.PushTime( delay, fragment, scope ); - *rval = INT_TO_JSVAL( id ); - return( JS_TRUE ); - } - case JSTYPE_FUNCTION: - { - JSFunction* fn = JS_ValueToFunction( cx, argv[0] ); - int id = g_Scheduler.PushTime( delay, fn, scope ); - *rval = INT_TO_JSVAL( id ); - return( JS_TRUE ); - } - default: - JS_ReportError( cx, "Invalid timer script" ); - return( JS_TRUE ); - } -} - -// Request a callback be executed periodically. -// params: callback [fragment or function], initial delay in ms [int], period in ms [int] -// OR callback [fragment or function], period in ms [int] (initial delay = period) -// returns: -// notes: -// - SetTimeout's notes apply here as well. -JSBool SetInterval( JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval ) -{ - JSU_REQUIRE_PARAM_RANGE(2, 3); - - int first, interval; - try - { - first = ToPrimitive( argv[1] ); - if( argc == 3 ) - { - // toDo, first, interval - interval = ToPrimitive( argv[2] ); - } - else - { - // toDo, interval (first = interval) - interval = first; - } - } - catch( PSERROR_Scripting_ConversionFailed ) - { - JS_ReportError( cx, "Invalid timer parameters" ); - return( JS_TRUE ); - } - - switch( JS_TypeOfValue( cx, argv[0] ) ) - { - case JSTYPE_STRING: - { - CStrW fragment = g_ScriptingHost.ValueToUCString( argv[0] ); - int id = g_Scheduler.PushInterval( first, interval, fragment, JS_GetScopeChain( cx ) ); - *rval = INT_TO_JSVAL( id ); - return( JS_TRUE ); - } - case JSTYPE_FUNCTION: - { - JSFunction* fn = JS_ValueToFunction( cx, argv[0] ); - int id = g_Scheduler.PushInterval( first, interval, fn, JS_GetScopeChain( cx ) ); - *rval = INT_TO_JSVAL( id ); - return( JS_TRUE ); - } - default: - JS_ReportError( cx, "Invalid timer script" ); - return( JS_TRUE ); - } -} - -// Cause all periodic functions registered via SetInterval to -// no longer be called. -// params: -// returns: -// notes: -// - Execution continues until the end of the triggered function or -// script fragment, but is not triggered again. -JSBool CancelInterval( JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval ) -{ - JSU_REQUIRE_NO_PARAMS(); - - g_Scheduler.m_abortInterval = true; - return( JS_TRUE ); -} - -// Cause the scheduled task (timeout or interval) with the given ID to -// no longer be called. -// params: -// returns: -// notes: -// - Execution continues until the end of the triggered function or -// script fragment, but is not triggered again. -JSBool CancelTimer( JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval ) -{ - JSU_REQUIRE_PARAMS(1); - - try - { - int id = ToPrimitive( argv[0] ); - g_Scheduler.CancelTask( id ); - } - catch( PSERROR_Scripting_ConversionFailed ) - { - JS_ReportError( cx, "Invalid ID parameter" ); - return( JS_TRUE ); - } - - return( JS_TRUE ); -} - -//Set the simulation rate scalar-time becomes time * SimRate. -//Params: rate [float] : sets SimRate +// Set the simulation rate scalar-time becomes time * SimRate. +// Params: rate [float] : sets SimRate JSBool SetSimRate(JSContext* cx, JSObject*, uintN argc, jsval* argv, jsval* rval) { JSU_REQUIRE_PARAMS(1); @@ -856,10 +694,6 @@ JSFunctionSpec ScriptFunctionTable[] = JS_FUNC("toggleSky", ToggleSky, 0) // Timer - JS_FUNC("setTimeout", SetTimeout, 2) - JS_FUNC("setInterval", SetInterval, 2) - JS_FUNC("cancelInterval", CancelInterval, 0) - JS_FUNC("cancelTimer", CancelTimer, 0) JS_FUNC("setSimRate", SetSimRate, 1) // Profiling diff --git a/source/scripting/ScriptingHost.cpp b/source/scripting/ScriptingHost.cpp index 6c1ed6f591..078cc38485 100644 --- a/source/scripting/ScriptingHost.cpp +++ b/source/scripting/ScriptingHost.cpp @@ -54,6 +54,8 @@ ScriptingHost::ScriptingHost() if(!m_Context) throw PSERROR_Scripting_SetupFailed(); + // JS_SetGCZeal(m_Context, 2); + JS_SetErrorReporter(m_Context, ScriptingHost::ErrorReporter); JS_BeginRequest(m_Context);