00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "scriptingengine.h"
00021
00022 #include "scriptingasset.h"
00023 #include "scriptingcomponent.h"
00024
00025 #include <QtScript>
00026
00027
00028 void qtscript_initialize_com_trolltech_qt_gui_bindings( QScriptValue& );
00029 namespace GluonEngine
00030 {
00031 class ScriptingEngine::Private
00032 {
00033 public:
00034 Private()
00035 {
00036 DEBUG_FUNC_NAME
00037 DEBUG_TEXT2( "Available extensions: %1", engine->availableExtensions().join( ", " ) );
00038 engine = new QScriptEngine();
00039 engine->importExtension( "jsmoke.qtcore" );
00040 engine->importExtension( "jsmoke.qtgui" );
00041 engine->importExtension( "jsmoke.qtopengl" );
00042
00043 qScriptRegisterMetaType( engine, gluonObjectToScriptValue, gluonObjectFromScriptValue );
00044 qScriptRegisterMetaType( engine, gameObjectToScriptValue, gameObjectFromScriptValue );
00045
00046 DEBUG_TEXT2( "Imported extensions: %1", engine->importedExtensions().join( ", " ) );
00047
00048 QScriptValue extensionObject = engine->globalObject();
00049 qtscript_initialize_com_trolltech_qt_gui_bindings( extensionObject );
00050 }
00051
00052 QScriptEngine* engine;
00053
00054
00055
00056 QHash<const ScriptingAsset*, QString> classNames;
00057
00058 QHash<const ScriptingAsset*, QScriptValue> scriptInstances;
00059
00060
00061
00062 QString script;
00063 void buildScript();
00064 };
00065 }
00066
00067 using namespace GluonEngine;
00068
00069 template<> GLUON_ENGINE_EXPORT ScriptingEngine* GluonCore::Singleton<ScriptingEngine>::m_instance = 0;
00070
00071 ScriptingEngine::ScriptingEngine( QObject* parent )
00072 : d( new Private() )
00073 {
00074 Q_UNUSED( parent )
00075 }
00076
00077 ScriptingEngine::~ScriptingEngine()
00078 {
00079 delete d;
00080 }
00081
00082 QScriptSyntaxCheckResult
00083 ScriptingEngine::registerAsset( const ScriptingAsset* asset )
00084 {
00085 DEBUG_BLOCK
00086
00087
00088
00089 if( !asset )
00090 {
00091 DEBUG_TEXT( "Asset is empty" );
00092 return d->engine->checkSyntax( QString( ')' ) );
00093 }
00094
00095 if( d->classNames.contains( asset ) )
00096 {
00097 DEBUG_TEXT( "Asset is already registered" );
00098 return d->engine->checkSyntax( QString( '}' ) );
00099 }
00100
00101
00102 QScriptSyntaxCheckResult result = d->engine->checkSyntax( asset->data()->text() );
00103 if( result.state() == QScriptSyntaxCheckResult::Valid )
00104 {
00105
00106 QString className( asset->fullyQualifiedName().replace( ' ', QString() ).replace( '/', '_' ) );
00107
00108 d->classNames.insert( asset, className );
00109
00110 d->buildScript();
00111 }
00112
00113 return result;
00114 }
00115
00116 void
00117 ScriptingEngine::Private::buildScript()
00118 {
00119 script.clear();
00120
00121 QHash<const ScriptingAsset*, QString>::const_iterator i;
00122 for( i = classNames.constBegin(); i != classNames.constEnd(); ++i )
00123 {
00124
00125 QString tmpScript = QString( "function %2(){\n%1}\n" ).arg( i.key()->data()->text() ).arg( i.value() );
00126 scriptInstances.insert( i.key(), engine->evaluate( tmpScript, i.key()->file().toLocalFile(), 0 ) );
00128 }
00129 }
00130
00131 bool
00132 ScriptingEngine::unregisterAsset( const ScriptingAsset* asset ) const
00133 {
00134 if( !asset )
00135 return false;
00136 if( !d->classNames.contains( asset ) )
00137 return false;
00138
00139 d->classNames.remove( asset );
00140 d->scriptInstances.remove( asset );
00141 d->buildScript();
00142
00143 return true;
00144 }
00145
00146 bool
00147 ScriptingEngine::isRegistered( const ScriptingAsset* asset ) const
00148 {
00149 return d->classNames.contains( asset );
00150 }
00151
00152 QScriptValue
00153 ScriptingEngine::instantiateClass( const ScriptingAsset* asset ) const
00154 {
00155 DEBUG_BLOCK
00156
00157 if( d->scriptInstances.contains( asset ) )
00158 {
00159
00160 QScriptValue val = d->engine->globalObject().property( d->classNames[asset] );
00161
00162 QScriptValue instance = val.construct();
00163 if( d->engine->hasUncaughtException() )
00164 {
00165 DEBUG_TEXT2( "Exception on class instantiation: %1", d->engine->uncaughtExceptionBacktrace().join( " --> " ) );
00166 }
00167
00168 return instance;
00169 }
00170
00171 return QScriptValue();
00172 }
00173
00174 QScriptValue
00175 ScriptingEngine::instantiateClass( const QString& className ) const
00176 {
00177 DEBUG_BLOCK
00178 QScriptValue val = d->engine->globalObject().property( className );
00179
00180 QScriptValue instance = val.construct();
00181 if( d->engine->hasUncaughtException() )
00182 {
00183 DEBUG_TEXT2( "Exception on class instantiation: %1", d->engine->uncaughtExceptionBacktrace().join( " --> " ) );
00184 }
00185
00186 return instance;
00187 }
00188
00189 QString
00190 ScriptingEngine::className( const ScriptingAsset* asset ) const
00191 {
00192 return d->classNames.value( asset );
00193 }
00194
00195 QScriptEngine *
00196 ScriptingEngine::scriptEngine() const
00197 {
00198 return instance()->d->engine;
00199 }
00200
00201 QScriptValue gluonObjectToScriptValue( QScriptEngine* engine, GluonCore::GluonObject* const &in )
00202 {
00203 return engine->newQObject( in );
00204 }
00205
00206 void gluonObjectFromScriptValue( const QScriptValue& object, GluonCore::GluonObject* &out )
00207 {
00208 out = qobject_cast<GluonCore::GluonObject*>( object.toQObject() );
00209 }
00210
00211 QScriptValue gameObjectToScriptValue( QScriptEngine* engine, GluonEngine::GameObject* const &in )
00212 {
00213 return engine->newQObject( in );
00214 }
00215
00216 void gameObjectFromScriptValue( const QScriptValue& object, GluonEngine::GameObject* &out )
00217 {
00218 out = qobject_cast<GluonEngine::GameObject*>( object.toQObject() );
00219 }
00220
00221 #include "scriptingengine.moc"