Browse Source

Moved NinjaSnowWar audio initialization to script for quick verification of the script API.
Added possibility to transmit a VariantMap of custom login data when connecting to a server.
Added isClient() and isServer() functions to the script API.
ScriptFile::execute() borrows the ScriptEngine's immediate context automatically if a null context is specified.
Changed AngelScript x86 function calls to use EMMS instead of FNINIT to clear the floating point stack, to not affect the floating point control word.
Updated documentation.

Lasse Öörni 15 years ago
parent
commit
ad9edd8e72

+ 15 - 0
Bin/Data/Scripts/NinjaSnowWar.as

@@ -0,0 +1,15 @@
+void initAudio()
+{
+    // Do a very basic test of scripting functionality by setting up sound & music in script
+    
+    // Lower mastervolumes slightly
+    audio.setMasterGain(CHANNEL_MASTER, 0.75f);
+    audio.setMasterGain(CHANNEL_MUSIC, 0.75f);
+
+    // Play music only in singleplayer, otherwise there will be cacophony if testing on same machine
+    if ((!isServer()) && (!isClient()))
+    {
+        Song@ song = cache.getResource("XM", "Music/NinjaGods.xm");
+        song.play(0);
+    }
+}

+ 3 - 1
Engine/Engine/Client.cpp

@@ -94,7 +94,7 @@ void Client::setMaxPredictionTime(float time)
     mMaxPredictionTime = max(time, 0.0f);
     mMaxPredictionTime = max(time, 0.0f);
 }
 }
 
 
-bool Client::connect(const std::string& address, unsigned short port, const std::string& userName)
+bool Client::connect(const std::string& address, unsigned short port, const std::string& userName, const VariantMap& loginData)
 {
 {
     disconnect();
     disconnect();
     
     
@@ -105,6 +105,7 @@ bool Client::connect(const std::string& address, unsigned short port, const std:
     mServerConnection = new Connection(peer);
     mServerConnection = new Connection(peer);
     mFrameNumber = 1;
     mFrameNumber = 1;
     mPendingUserName = userName;
     mPendingUserName = userName;
+    mPendingLoginData = loginData;
     return true;
     return true;
 }
 }
 
 
@@ -325,6 +326,7 @@ void Client::handleChallenge(VectorBuffer& packet)
     replyPacket.writeUByte(MSG_IDENTITY);
     replyPacket.writeUByte(MSG_IDENTITY);
     replyPacket.writeUInt(mServerConnection->getResponse());
     replyPacket.writeUInt(mServerConnection->getResponse());
     replyPacket.writeString(mPendingUserName);
     replyPacket.writeString(mPendingUserName);
+    replyPacket.writeVariantMap(mPendingLoginData);
     mServerConnection->sendReliable(replyPacket);
     mServerConnection->sendReliable(replyPacket);
     mServerConnection->updateResponse();
     mServerConnection->updateResponse();
 }
 }

+ 4 - 1
Engine/Engine/Client.h

@@ -131,7 +131,8 @@ public:
     //! Set maximum amount of client-side prediction
     //! Set maximum amount of client-side prediction
     void setMaxPredictionTime(float time);
     void setMaxPredictionTime(float time);
     //! Connect to a server
     //! Connect to a server
-    bool connect(const std::string& address, unsigned short port, const std::string& userName = std::string());
+    bool connect(const std::string& address, unsigned short port, const std::string& userName = std::string(), const VariantMap&
+        loginData = VariantMap());
     //! Disconnect from a server
     //! Disconnect from a server
     void disconnect();
     void disconnect();
     //! Set client controls to be sent over the network
     //! Set client controls to be sent over the network
@@ -237,6 +238,8 @@ private:
     std::set<std::string> mPendingDownloads;
     std::set<std::string> mPendingDownloads;
     //! Username to send to the server
     //! Username to send to the server
     std::string mPendingUserName;
     std::string mPendingUserName;
+    //! Extra login data to send to the server
+    VariantMap mPendingLoginData;
 };
 };
 
 
 //! Return Client instance
 //! Return Client instance

+ 10 - 12
Engine/Engine/Connection.cpp

@@ -50,6 +50,8 @@ Connection::Connection(Peer* peer) :
     mJoinState(JS_NOTINSCENE),
     mJoinState(JS_NOTINSCENE),
     mPosition(Vector3::sZero)
     mPosition(Vector3::sZero)
 {
 {
+    if (!peer)
+        EXCEPTION("Null networking peer");
 }
 }
 
 
 Connection::~Connection()
 Connection::~Connection()
@@ -81,15 +83,13 @@ bool Connection::receiveUnreliable(VectorBuffer& packet)
 void Connection::disconnect()
 void Connection::disconnect()
 {
 {
     leftScene();
     leftScene();
-    if (mPeer)
-        mPeer->disconnect();
+    mPeer->disconnect();
 }
 }
 
 
 void Connection::forceDisconnect()
 void Connection::forceDisconnect()
 {
 {
     leftScene();
     leftScene();
-    if (mPeer)
-        mPeer->forceDisconnect();
+    mPeer->forceDisconnect();
 }
 }
 
 
 void Connection::setUserName(const std::string& userName)
 void Connection::setUserName(const std::string& userName)
@@ -299,19 +299,17 @@ bool Connection::isConnected() const
 
 
 void Connection::send(const VectorBuffer& packet, bool reliable)
 void Connection::send(const VectorBuffer& packet, bool reliable)
 {
 {
-    if ((packet.getSize()) && (mPeer) && (mPeer->getConnectionState() == CS_CONNECTED))
+    if ((packet.getSize()) && (mPeer->getConnectionState() == CS_CONNECTED))
         mPeer->send(packet, reliable ? CHN_RELIABLE : CHN_UNRELIABLE, reliable);
         mPeer->send(packet, reliable ? CHN_RELIABLE : CHN_UNRELIABLE, reliable);
 }
 }
 
 
 bool Connection::receive(VectorBuffer& packet, bool reliable)
 bool Connection::receive(VectorBuffer& packet, bool reliable)
 {
 {
-    if (mPeer)
+    if (mPeer->getConnectionState() == CS_CONNECTED)
+        return mPeer->receive(packet, reliable ? CHN_RELIABLE : CHN_UNRELIABLE);
+    else
     {
     {
-        if (mPeer->getConnectionState() == CS_CONNECTED)
-            return mPeer->receive(packet, reliable ? CHN_RELIABLE : CHN_UNRELIABLE);
-        else
-            mPeer->flushPackets();
+        mPeer->flushPackets();
+        return false;
     }
     }
-    
-    return false;
 }
 }

+ 3 - 2
Engine/Engine/ProtocolEvents.h

@@ -30,8 +30,9 @@
 DEFINE_EVENT(EVENT_CLIENTIDENTITY, ClientIdentity)
 DEFINE_EVENT(EVENT_CLIENTIDENTITY, ClientIdentity)
 {
 {
     EVENT_PARAM(P_CONNECTION, Connection);      // Connection pointer
     EVENT_PARAM(P_CONNECTION, Connection);      // Connection pointer
-    EVENT_PARAM(P_PACKET, Packet);              // Buffer
-    EVENT_PARAM(P_AUTHORIZE, Authorize);        // bool
+    EVENT_PARAM(P_USERNAME, UserName);          // string
+    EVENT_PARAM(P_AUTHORIZE, Authorize);        // bool (set false to deny access)
+    // Extra login data may exist if sent by the client
 }
 }
 
 
 //! (Server) Client has joined a scene
 //! (Server) Client has joined a scene

+ 25 - 1
Engine/Engine/RegisterEngine.cpp

@@ -155,6 +155,21 @@ static void DestructSceneInfo(SceneInfo* ptr)
     ptr->~SceneInfo();
     ptr->~SceneInfo();
 }
 }
 
 
+static bool ClientConnectAddress(const std::string& address, unsigned short port, Client* ptr)
+{
+    return ptr->connect(address, port);
+}
+
+static bool ClientConnectAddressUserName(const std::string& address, unsigned short port, const std::string& userName, Client* ptr)
+{
+    return ptr->connect(address, port, userName);
+}
+
+static bool IsClient()
+{
+    return getClient() != 0;
+}
+
 static void registerClient(asIScriptEngine* engine)
 static void registerClient(asIScriptEngine* engine)
 {
 {
     engine->RegisterObjectType("SceneInfo", sizeof(SceneInfo), asOBJ_VALUE | asOBJ_APP_CLASS_CDA);
     engine->RegisterObjectType("SceneInfo", sizeof(SceneInfo), asOBJ_VALUE | asOBJ_APP_CLASS_CDA);
@@ -172,7 +187,9 @@ static void registerClient(asIScriptEngine* engine)
     engine->RegisterObjectBehaviour("Client", asBEHAVE_RELEASE, "void f()", asMETHOD(Client, releaseRef), asCALL_THISCALL);
     engine->RegisterObjectBehaviour("Client", asBEHAVE_RELEASE, "void f()", asMETHOD(Client, releaseRef), asCALL_THISCALL);
     engine->RegisterObjectMethod("Client", "void setScene(Scene@+)", asMETHOD(Client, setScene), asCALL_THISCALL);
     engine->RegisterObjectMethod("Client", "void setScene(Scene@+)", asMETHOD(Client, setScene), asCALL_THISCALL);
     engine->RegisterObjectMethod("Client", "void setMaxPredictionTime(float)", asMETHOD(Client, setMaxPredictionTime), asCALL_THISCALL);
     engine->RegisterObjectMethod("Client", "void setMaxPredictionTime(float)", asMETHOD(Client, setMaxPredictionTime), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Client", "bool connect(const string& in, uint16, const string& in)", asMETHOD(Client, connect), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Client", "bool connect(const string& in, uint16)", asFUNCTION(ClientConnectAddress), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Client", "bool connect(const string& in, uint16, const string& in)", asFUNCTION(ClientConnectAddressUserName), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Client", "bool connect(const string& in, uint16, const string& in, const VariantMap& in)", asMETHOD(Client, connect), asCALL_THISCALL);
     engine->RegisterObjectMethod("Client", "void disconnect()", asMETHOD(Client, disconnect), asCALL_THISCALL);
     engine->RegisterObjectMethod("Client", "void disconnect()", asMETHOD(Client, disconnect), asCALL_THISCALL);
     engine->RegisterObjectMethod("Client", "void setControls(const Controls& in)", asMETHOD(Client, setControls), asCALL_THISCALL);
     engine->RegisterObjectMethod("Client", "void setControls(const Controls& in)", asMETHOD(Client, setControls), asCALL_THISCALL);
     engine->RegisterObjectMethod("Client", "void setPosition(const Vector3& in)", asMETHOD(Client, setPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("Client", "void setPosition(const Vector3& in)", asMETHOD(Client, setPosition), asCALL_THISCALL);
@@ -190,6 +207,7 @@ static void registerClient(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Client", "string getFileTransferStatus() const", asMETHOD(Client, getFileTransferStatus), asCALL_THISCALL);
     engine->RegisterObjectMethod("Client", "string getFileTransferStatus() const", asMETHOD(Client, getFileTransferStatus), asCALL_THISCALL);
     engine->RegisterObjectMethod("Client", "const SceneInfo& getSceneInfo() const", asMETHOD(Client, getSceneInfo), asCALL_THISCALL);
     engine->RegisterObjectMethod("Client", "const SceneInfo& getSceneInfo() const", asMETHOD(Client, getSceneInfo), asCALL_THISCALL);
     
     
+    engine->RegisterGlobalFunction("bool isClient()", asFUNCTION(IsClient), asCALL_CDECL);
     engine->RegisterGlobalFunction("Client@+ getClient()", asFUNCTION(getClient), asCALL_CDECL);
     engine->RegisterGlobalFunction("Client@+ getClient()", asFUNCTION(getClient), asCALL_CDECL);
     engine->RegisterGlobalFunction("Client@+ get_client()", asFUNCTION(getClient), asCALL_CDECL);
     engine->RegisterGlobalFunction("Client@+ get_client()", asFUNCTION(getClient), asCALL_CDECL);
 }
 }
@@ -212,6 +230,11 @@ static CScriptArray* ServerGetConnections(Server* ptr)
     return vectorToHandleArray<Connection*>(result, "array<Connection@>");
     return vectorToHandleArray<Connection*>(result, "array<Connection@>");
 }
 }
 
 
+static bool IsServer()
+{
+    return getServer() != 0;
+}
+
 static void registerServer(asIScriptEngine* engine)
 static void registerServer(asIScriptEngine* engine)
 {
 {
     engine->RegisterObjectType("Server", 0, asOBJ_REF);
     engine->RegisterObjectType("Server", 0, asOBJ_REF);
@@ -233,6 +256,7 @@ static void registerServer(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Server", "array<Scene@>@ getScenes() const", asFUNCTION(ServerGetScenes), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Server", "array<Scene@>@ getScenes() const", asFUNCTION(ServerGetScenes), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Server", "array<Connection@>@ getConnections() const", asFUNCTION(ServerGetConnections), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Server", "array<Connection@>@ getConnections() const", asFUNCTION(ServerGetConnections), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Server", "uint getNumUsersInScene(Scene@+) const", asMETHOD(Server, getNumUsersInScene), asCALL_THISCALL);
     engine->RegisterObjectMethod("Server", "uint getNumUsersInScene(Scene@+) const", asMETHOD(Server, getNumUsersInScene), asCALL_THISCALL);
+    engine->RegisterGlobalFunction("bool isServer()", asFUNCTION(IsServer), asCALL_CDECL);
     engine->RegisterGlobalFunction("Server@+ getServer()", asFUNCTION(getServer), asCALL_CDECL);
     engine->RegisterGlobalFunction("Server@+ getServer()", asFUNCTION(getServer), asCALL_CDECL);
     engine->RegisterGlobalFunction("Server@+ get_server()", asFUNCTION(getServer), asCALL_CDECL);
     engine->RegisterGlobalFunction("Server@+ get_server()", asFUNCTION(getServer), asCALL_CDECL);
 }
 }

+ 7 - 3
Engine/Engine/Server.cpp

@@ -367,6 +367,7 @@ bool Server::handleIdentity(Connection* connection, VectorBuffer& packet)
 {
 {
     // Set initial username
     // Set initial username
     std::string userName = packet.readString();
     std::string userName = packet.readString();
+    VariantMap loginData = packet.readVariantMap();
     if (userName.empty())
     if (userName.empty())
         userName = "user" + toString(random(999));
         userName = "user" + toString(random(999));
     connection->setUserName(userName);
     connection->setUserName(userName);
@@ -374,15 +375,18 @@ bool Server::handleIdentity(Connection* connection, VectorBuffer& packet)
     // Send identity event and check if any event handler denies access
     // Send identity event and check if any event handler denies access
     using namespace ClientIdentity;
     using namespace ClientIdentity;
     
     
-    VariantMap eventData;
+    // Initialize eventdata with the logindata received
+    VariantMap eventData = loginData;
     eventData[P_CONNECTION] = (void*)connection;
     eventData[P_CONNECTION] = (void*)connection;
-    eventData[P_PACKET] = packet.getBuffer();
+    eventData[P_USERNAME] = userName;
     eventData[P_AUTHORIZE] = true;
     eventData[P_AUTHORIZE] = true;
     sendEvent(EVENT_CLIENTIDENTITY, eventData);
     sendEvent(EVENT_CLIENTIDENTITY, eventData);
     
     
     if (!eventData[P_AUTHORIZE].getBool())
     if (!eventData[P_AUTHORIZE].getBool())
     {
     {
-        disconnect(connection, false, "Disconnecting unauthorized client");
+        Peer* peer = connection->getPeer();
+        disconnect(connection, false, "Disconnecting unauthorized client from " + peer->getAddress() + ":" +
+            toString(peer->getPort()));
         return false;
         return false;
     }
     }
     
     

+ 4 - 1
Engine/Physics/RigidBody.cpp

@@ -800,6 +800,8 @@ bool RigidBody::isActive() const
 
 
 void RigidBody::drawDebugGeometry(DebugRenderer* debug)
 void RigidBody::drawDebugGeometry(DebugRenderer* debug)
 {
 {
+    //_controlfp( _PC_24, MCW_PC );
+
     Color color;
     Color color;
     if (!isActive())
     if (!isActive())
         color = Color(0.0f, 1.0f, 0.0f);
         color = Color(0.0f, 1.0f, 0.0f);
@@ -860,6 +862,7 @@ void RigidBody::drawDebugGeometry(DebugRenderer* debug)
                 for (unsigned i = 0; i < 360; i += 45)
                 for (unsigned i = 0; i < 360; i += 45)
                 {
                 {
                     unsigned j = i + 45;
                     unsigned j = i + 45;
+                    
                     float a = radius * sinf(i * M_DEGTORAD);
                     float a = radius * sinf(i * M_DEGTORAD);
                     float b = radius * cosf(i * M_DEGTORAD);
                     float b = radius * cosf(i * M_DEGTORAD);
                     float c = radius * sinf(j * M_DEGTORAD);
                     float c = radius * sinf(j * M_DEGTORAD);
@@ -878,7 +881,7 @@ void RigidBody::drawDebugGeometry(DebugRenderer* debug)
                         end = transform * Vector3(a, b, -0.5f * length);
                         end = transform * Vector3(a, b, -0.5f * length);
                         debug->addLine(start, end, color);
                         debug->addLine(start, end, color);
                     }
                     }
-                    if (b >= 0.0f)
+                    if (b > -M_EPSILON)
                     {
                     {
                         start = transform * Vector3(a, 0.0f, b + 0.5f * length);
                         start = transform * Vector3(a, 0.0f, b + 0.5f * length);
                         end = transform * Vector3(c, 0.0f, d + 0.5f * length);
                         end = transform * Vector3(c, 0.0f, d + 0.5f * length);

+ 12 - 3
Engine/Script/ScriptFile.cpp

@@ -99,9 +99,12 @@ bool ScriptFile::execute(asIScriptFunction* function, asIScriptContext* context,
 {
 {
     PROFILE(Script_Execute);
     PROFILE(Script_Execute);
     
     
-    if ((!mCompiled) || (!context) || (!function))
+    if ((!mCompiled) || (!function))
         return false;
         return false;
     
     
+    if (!context)
+        context = mScriptEngine->getImmediateContext();
+    
     if (context->GetState() != asEXECUTION_ACTIVE)
     if (context->GetState() != asEXECUTION_ACTIVE)
     {
     {
         if (context->Prepare(function->GetId()) < 0)
         if (context->Prepare(function->GetId()) < 0)
@@ -156,9 +159,12 @@ bool ScriptFile::execute(asIScriptObject* object, asIScriptFunction* method, asI
 {
 {
     PROFILE(Script_Execute);
     PROFILE(Script_Execute);
     
     
-    if ((!mCompiled) || (!context) || (!object) || (!method))
+    if ((!mCompiled) || (!object) || (!method))
         return false;
         return false;
     
     
+    if (!context)
+        context = mScriptEngine->getImmediateContext();
+    
     if (context->GetState() != asEXECUTION_ACTIVE)
     if (context->GetState() != asEXECUTION_ACTIVE)
     {
     {
         if (context->Prepare(method->GetId()) < 0)
         if (context->Prepare(method->GetId()) < 0)
@@ -202,9 +208,12 @@ asIScriptObject* ScriptFile::createObject(const std::string& className, asIScrip
 {
 {
     PROFILE(Script_CreateObject);
     PROFILE(Script_CreateObject);
     
     
-    if ((!isCompiled()) || (!context))
+    if (!isCompiled())
         return 0;
         return 0;
     
     
+    if (!context)
+        context = mScriptEngine->getImmediateContext();
+    
     asIScriptEngine* engine = mScriptEngine->getAngelScriptEngine();
     asIScriptEngine* engine = mScriptEngine->getAngelScriptEngine();
     asIObjectType *type = engine->GetObjectTypeById(mScriptModule->GetTypeIdByDecl(className.c_str()));
     asIObjectType *type = engine->GetObjectTypeById(mScriptModule->GetTypeIdByDecl(className.c_str()));
     if (!type)
     if (!type)

+ 10 - 10
Engine/Script/ScriptFile.h

@@ -50,16 +50,16 @@ public:
     //! Load resource
     //! Load resource
     virtual void load(Deserializer& source, ResourceCache* cache = 0);
     virtual void load(Deserializer& source, ResourceCache* cache = 0);
     
     
-    //! Query for a function by declaration and execute if found
-    bool execute(const std::string& declaration, asIScriptContext* context, const std::vector<Variant>& parameters = std::vector<Variant>());
-    //! Execute a function
-    bool execute(asIScriptFunction* function, asIScriptContext* context, const std::vector<Variant>& parameters = std::vector<Variant>());
-    //! Query for an object method by declaration and execute if found
-    bool execute(asIScriptObject* object, const std::string& declaration, asIScriptContext* context, const std::vector<Variant>& parameters = std::vector<Variant>());
-    //! Execute an object method
-    bool execute(asIScriptObject* object, asIScriptFunction* method, asIScriptContext* context, const std::vector<Variant>& parameters = std::vector<Variant>());
-    //! Create a script object
-    asIScriptObject* createObject(const std::string& className, asIScriptContext* context);
+    //! Query for a function by declaration and execute if found. If context is null, use the immediate context
+    bool execute(const std::string& declaration, asIScriptContext* context = 0, const std::vector<Variant>& parameters = std::vector<Variant>());
+    //! Execute a function. If context is null, use the immediate context
+    bool execute(asIScriptFunction* function, asIScriptContext* context = 0, const std::vector<Variant>& parameters = std::vector<Variant>());
+    //! Query for an object method by declaration and execute if found. If context is null, use the immediate context
+    bool execute(asIScriptObject* object, const std::string& declaration, asIScriptContext* context = 0, const std::vector<Variant>& parameters = std::vector<Variant>());
+    //! Execute an object method. If context is null, use the immediate context
+    bool execute(asIScriptObject* object, asIScriptFunction* method, asIScriptContext* context = 0, const std::vector<Variant>& parameters = std::vector<Variant>());
+    //! Create a script object. If context is null, use the immediate context
+    asIScriptObject* createObject(const std::string& className, asIScriptContext* context = 0);
     
     
     //! Return script engine
     //! Return script engine
     ScriptEngine* getScriptEngine() const { return mScriptEngine; }
     ScriptEngine* getScriptEngine() const { return mScriptEngine; }

+ 4 - 13
Examples/NinjaSnowWar/Game.cpp

@@ -197,6 +197,7 @@ void Game::init()
     
     
     // Run server in headless mode
     // Run server in headless mode
     mEngine = new Engine(logName, runServer);
     mEngine = new Engine(logName, runServer);
+    mEngine->createScriptEngine();
     if (runServer)
     if (runServer)
         openConsoleWindow();
         openConsoleWindow();
     
     
@@ -234,19 +235,9 @@ void Game::init()
     if (runClient)
     if (runClient)
         mClient = mEngine->createClient(downloadDir);
         mClient = mEngine->createClient(downloadDir);
     
     
-    // Lower mastervolumes slightly
-    Audio* audio = mEngine->getAudio();
-    if (audio)
-    {
-        audio->setMasterGain(CHANNEL_MASTER, 0.75f);
-        audio->setMasterGain(CHANNEL_MUSIC, 0.75f);
-        // Play music only in singleplayer, otherwise there will be cacophony if testing on same machine
-        if ((!mClient) && (!mServer))
-        {
-            mSong = mCache->getResource<XM>("Music/NinjaGods.xm");
-            mSong->play();
-        }
-    }
+    // Execute sound setup in script to verify that the script interface works
+    ScriptFile* script = mCache->getResource<ScriptFile>("Scripts/NinjaSnowWar.as");
+    script->execute("void initAudio()");
     
     
     setupOptions();
     setupOptions();
     createOverlays();
     createOverlays();

+ 4 - 4
Readme.txt

@@ -54,10 +54,10 @@ Documentation
 For documentation, see the Urho3D wiki:
 For documentation, see the Urho3D wiki:
 http://code.google.com/p/urho3d/wiki/Urho3D
 http://code.google.com/p/urho3d/wiki/Urho3D
 
 
-Urho3D classes have also been sparsely documented using Doxygen notation. Use 
-the Doxyfile in the root directory to build the documentation, which will be 
-created into the "Docs" subdirectory. Doxygen is available at:
-http://www.doxygen.org/
+Urho3D classes have also been sparsely documented using Doxygen notation. To
+generate documentation into the "Docs" subdirectory, open the Doxyfile in the
+root directory with doxywizard and click "Run doxygen" from the "Run" tab. 
+Get Doxygen from http://www.doxygen.org
 
 
 
 
 Building
 Building

+ 37 - 18
ThirdParty/AngelScript/source/as_callfunc_x86.cpp

@@ -28,6 +28,7 @@
    [email protected]
    [email protected]
 */
 */
 
 
+// Modified by Lasse Öörni for Urho3D
 
 
 //
 //
 // as_callfunc_x86.cpp
 // as_callfunc_x86.cpp
@@ -371,7 +372,8 @@ void NOINLINE CallCDeclFunction(const asDWORD *args, int paramSize, size_t func)
 	    push ecx
 	    push ecx
 
 
 		// Clear the FPU stack, in case the called function doesn't do it by itself
 		// Clear the FPU stack, in case the called function doesn't do it by itself
-		fninit
+		// Urho3D: modified to use EMMS instead to not modify the floating point control word
+		emms
 
 
 		// Copy arguments from script
 		// Copy arguments from script
 		// stack to application stack
 		// stack to application stack
@@ -405,8 +407,9 @@ endcopy:
     UNUSED_VAR(paramSize);
     UNUSED_VAR(paramSize);
     UNUSED_VAR(func);
     UNUSED_VAR(func);
 
 
+	// Urho3D: modified to use EMMS instead to not modify the floating point control word
 	asm("pushl %ecx           \n"
 	asm("pushl %ecx           \n"
-	    "fninit               \n"
+		"emms                 \n"
 
 
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
@@ -454,7 +457,8 @@ void NOINLINE CallCDeclFunctionObjLast(const void *obj, const asDWORD *args, int
 	    push ecx
 	    push ecx
 
 
 		// Clear the FPU stack, in case the called function doesn't do it by itself
 		// Clear the FPU stack, in case the called function doesn't do it by itself
-		fninit
+		// Urho3D: modified to use EMMS instead to not modify the floating point control word
+		emms
 
 
 		// Push the object pointer as the last argument to the function
 		// Push the object pointer as the last argument to the function
 		push obj
 		push obj
@@ -493,8 +497,9 @@ endcopy:
     UNUSED_VAR(paramSize);
     UNUSED_VAR(paramSize);
     UNUSED_VAR(func);
     UNUSED_VAR(func);
 
 
+	// Urho3D: modified to use EMMS instead to not modify the floating point control word
 	asm("pushl %ecx           \n"
 	asm("pushl %ecx           \n"
-	    "fninit               \n"
+		"emms                 \n"
 
 
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
@@ -544,7 +549,8 @@ void NOINLINE CallCDeclFunctionObjFirst(const void *obj, const asDWORD *args, in
 	    push ecx
 	    push ecx
 
 
 		// Clear the FPU stack, in case the called function doesn't do it by itself
 		// Clear the FPU stack, in case the called function doesn't do it by itself
-		fninit
+		// Urho3D: modified to use EMMS instead to not modify the floating point control word
+		emms
 
 
 		// Copy arguments from script
 		// Copy arguments from script
 		// stack to application stack
 		// stack to application stack
@@ -583,8 +589,9 @@ endcopy:
     UNUSED_VAR(paramSize);
     UNUSED_VAR(paramSize);
     UNUSED_VAR(func);
     UNUSED_VAR(func);
 
 
+	// Urho3D: modified to use EMMS instead to not modify the floating point control word
 	asm("pushl %ecx           \n"
 	asm("pushl %ecx           \n"
-	    "fninit               \n"
+		"emms                 \n"
 
 
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
@@ -634,7 +641,8 @@ void NOINLINE CallCDeclFunctionRetByRefObjFirst_impl(const void *obj, const asDW
 	    push ecx
 	    push ecx
 
 
 		// Clear the FPU stack, in case the called function doesn't do it by itself
 		// Clear the FPU stack, in case the called function doesn't do it by itself
-		fninit
+		// Urho3D: modified to use EMMS instead to not modify the floating point control word
+		emms
 
 
 		// Copy arguments from script
 		// Copy arguments from script
 		// stack to application stack
 		// stack to application stack
@@ -682,8 +690,9 @@ endcopy:
     UNUSED_VAR(func);
     UNUSED_VAR(func);
     UNUSED_VAR(retPtr);
     UNUSED_VAR(retPtr);
 
 
+	// Urho3D: modified to use EMMS instead to not modify the floating point control word
 	asm("pushl %ecx           \n"
 	asm("pushl %ecx           \n"
-	    "fninit               \n"
+		"emms                 \n"
 
 
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
@@ -737,7 +746,8 @@ void NOINLINE CallCDeclFunctionRetByRef_impl(const asDWORD *args, int paramSize,
 	    push ecx
 	    push ecx
 
 
 		// Clear the FPU stack, in case the called function doesn't do it by itself
 		// Clear the FPU stack, in case the called function doesn't do it by itself
-		fninit
+		// Urho3D: modified to use EMMS instead to not modify the floating point control word
+		emms
 
 
 		// Copy arguments from script
 		// Copy arguments from script
 		// stack to application stack
 		// stack to application stack
@@ -779,8 +789,9 @@ endcopy:
     UNUSED_VAR(func);
     UNUSED_VAR(func);
     UNUSED_VAR(retPtr);
     UNUSED_VAR(retPtr);
 
 
+	// Urho3D: modified to use EMMS instead to not modify the floating point control word
 	asm("pushl %ecx           \n"
 	asm("pushl %ecx           \n"
-	    "fninit               \n"
+		"emms                 \n"
 
 
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
@@ -831,7 +842,8 @@ void NOINLINE CallCDeclFunctionRetByRefObjLast_impl(const void *obj, const asDWO
 	    push ecx
 	    push ecx
 
 
 		// Clear the FPU stack, in case the called function doesn't do it by itself
 		// Clear the FPU stack, in case the called function doesn't do it by itself
-		fninit
+		// Urho3D: modified to use EMMS instead to not modify the floating point control word
+		emms
 
 
 		push obj
 		push obj
 
 
@@ -877,8 +889,9 @@ endcopy:
     UNUSED_VAR(func);
     UNUSED_VAR(func);
     UNUSED_VAR(retPtr);
     UNUSED_VAR(retPtr);
 
 
+	// Urho3D: modified to use EMMS instead to not modify the floating point control word
 	asm("pushl %ecx           \n"
 	asm("pushl %ecx           \n"
-	    "fninit               \n"
+		"emms                 \n"
 
 
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
@@ -932,7 +945,8 @@ void NOINLINE CallSTDCallFunction(const asDWORD *args, int paramSize, size_t fun
 	    push ecx
 	    push ecx
 
 
 		// Clear the FPU stack, in case the called function doesn't do it by itself
 		// Clear the FPU stack, in case the called function doesn't do it by itself
-		fninit
+		// Urho3D: modified to use EMMS instead to not modify the floating point control word
+		emms
 
 
 		// Copy arguments from script
 		// Copy arguments from script
 		// stack to application stack
 		// stack to application stack
@@ -965,8 +979,9 @@ endcopy:
     UNUSED_VAR(paramSize);
     UNUSED_VAR(paramSize);
     UNUSED_VAR(func);
     UNUSED_VAR(func);
 
 
+	// Urho3D: modified to use EMMS instead to not modify the floating point control word
 	asm("pushl %ecx           \n"
 	asm("pushl %ecx           \n"
-	    "fninit               \n"
+		"emms                 \n"
 
 
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
@@ -1014,7 +1029,8 @@ void NOINLINE CallThisCallFunction(const void *obj, const asDWORD *args, int par
 	    push ecx
 	    push ecx
 
 
 		// Clear the FPU stack, in case the called function doesn't do it by itself
 		// Clear the FPU stack, in case the called function doesn't do it by itself
-		fninit
+		// Urho3D: modified to use EMMS instead to not modify the floating point control word
+		emms
 
 
 		// Copy arguments from script
 		// Copy arguments from script
 		// stack to application stack
 		// stack to application stack
@@ -1063,8 +1079,9 @@ endcopy:
     UNUSED_VAR(paramSize);
     UNUSED_VAR(paramSize);
     UNUSED_VAR(func);
     UNUSED_VAR(func);
 
 
+	// Urho3D: modified to use EMMS instead to not modify the floating point control word
 	asm("pushl %ecx           \n"
 	asm("pushl %ecx           \n"
-	    "fninit               \n"
+		"emms                 \n"
 
 
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
@@ -1115,7 +1132,8 @@ void NOINLINE CallThisCallFunctionRetByRef_impl(const void *obj, const asDWORD *
 	    push ecx
 	    push ecx
 
 
 		// Clear the FPU stack, in case the called function doesn't do it by itself
 		// Clear the FPU stack, in case the called function doesn't do it by itself
-		fninit
+		// Urho3D: modified to use EMMS instead to not modify the floating point control word
+		emms
 
 
 		// Copy arguments from script
 		// Copy arguments from script
 		// stack to application stack
 		// stack to application stack
@@ -1173,8 +1191,9 @@ endcopy:
     UNUSED_VAR(func);
     UNUSED_VAR(func);
     UNUSED_VAR(retPtr);
     UNUSED_VAR(retPtr);
 
 
+	// Urho3D: modified to use EMMS instead to not modify the floating point control word
 	asm("pushl %ecx           \n"
 	asm("pushl %ecx           \n"
-	    "fninit               \n"
+		"emms                 \n"
 
 
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need
 		// It is assumed that when entering this function, the stack pointer is already aligned, so we need