Browse Source

Some renames. CollisionGroup -> CollisionLayer, Scene::GetNodeByID() -> GetNode(), Ray::Distance() -> HitDistance().
Moved all hit distance tests to Ray.
Tundra scene physics import.

Lasse Öörni 14 years ago
parent
commit
3f7fffbf49
40 changed files with 389 additions and 304 deletions
  1. 5 0
      Bin/CoreData/Materials/DefaultGrey.xml
  2. 136 49
      Bin/Data/Scripts/Editor/EditorImport.as
  3. 3 3
      Bin/Data/Scripts/Editor/EditorNodeWindow.as
  4. 6 6
      Bin/Data/Scripts/Editor/EditorSceneWindow.as
  5. 3 3
      Bin/Data/Scripts/NinjaSnowWar.as
  6. 1 1
      Bin/Data/Scripts/NinjaSnowWar/GameObject.as
  7. 1 1
      Bin/Data/Scripts/NinjaSnowWar/Ninja.as
  8. 2 2
      Bin/Data/Scripts/NinjaSnowWar/Potion.as
  9. 1 1
      Bin/Data/Scripts/NinjaSnowWar/SnowBall.as
  10. 1 1
      Bin/Data/Scripts/NinjaSnowWar/SnowCrate.as
  11. 5 5
      Bin/Data/Scripts/TestScene.as
  12. 1 1
      Docs/Reference.dox
  13. 18 18
      Docs/ScriptAPI.dox
  14. 3 3
      Engine/Engine/APITemplates.h
  15. 6 5
      Engine/Engine/MathAPI.cpp
  16. 2 2
      Engine/Engine/PhysicsAPI.cpp
  17. 2 2
      Engine/Engine/SceneAPI.cpp
  18. 4 4
      Engine/Graphics/AnimatedModel.cpp
  19. 1 1
      Engine/Graphics/Geometry.cpp
  20. 2 2
      Engine/Graphics/Octree.cpp
  21. 2 2
      Engine/Graphics/StaticModel.cpp
  22. 0 79
      Engine/Math/BoundingBox.cpp
  23. 0 3
      Engine/Math/BoundingBox.h
  24. 0 13
      Engine/Math/Plane.h
  25. 123 4
      Engine/Math/Ray.cpp
  26. 14 4
      Engine/Math/Ray.h
  27. 0 28
      Engine/Math/Sphere.cpp
  28. 0 3
      Engine/Math/Sphere.h
  29. 13 13
      Engine/Network/Connection.cpp
  30. 5 5
      Engine/Physics/CollisionShape.cpp
  31. 3 3
      Engine/Physics/CollisionShape.h
  32. 2 2
      Engine/Physics/Joint.cpp
  33. 1 0
      Engine/Physics/PhysicsWorld.cpp
  34. 2 2
      Engine/Scene/Component.cpp
  35. 4 4
      Engine/Scene/Component.h
  36. 3 14
      Engine/Scene/Node.cpp
  37. 4 6
      Engine/Scene/Node.h
  38. 2 2
      Engine/Scene/Scene.cpp
  39. 3 2
      Engine/Scene/Scene.h
  40. 5 5
      Tools/AssetImporter/AssetImporter.cpp

+ 5 - 0
Bin/CoreData/Materials/DefaultGrey.xml

@@ -0,0 +1,5 @@
+<material>
+    <technique name="Techniques/NoTexture.xml" />
+    <parameter name="MatDiffColor" value="0.5 0.5 0.5 1" />
+    <parameter name="MatSpecProperties" value="0.5 16" />
+</material>

+ 136 - 49
Bin/Data/Scripts/Editor/EditorImport.as

@@ -77,7 +77,6 @@ void ImportScene(const String&in fileName)
     }
     }
 }
 }
 
 
-
 void ImportTundraScene(const String&in fileName)
 void ImportTundraScene(const String&in fileName)
 {
 {
     fileSystem.CreateDir(sceneResourcePath + "Materials");
     fileSystem.CreateDir(sceneResourcePath + "Materials");
@@ -97,21 +96,27 @@ void ImportTundraScene(const String&in fileName)
 
 
     // Clear old scene, then create a zone and a directional light first
     // Clear old scene, then create a zone and a directional light first
     CreateScene();
     CreateScene();
+    
+    // Set standard gravity
+    editorScene.physicsWorld.gravity = Vector3(0, -9.81, 0);
 
 
+    // Create zone & global light
     Node@ zoneNode = editorScene.CreateChild("Zone", useLocalIDs ? LOCAL : REPLICATED);
     Node@ zoneNode = editorScene.CreateChild("Zone", useLocalIDs ? LOCAL : REPLICATED);
     Zone@ zone = zoneNode.CreateComponent("Zone");
     Zone@ zone = zoneNode.CreateComponent("Zone");
+    zone.boundingBox = BoundingBox(-1000, 1000);
+    zone.ambientColor = Color(0.5, 0.5, 0.5);
+    zone.fogColor = Color(0.5, 0.7, 1.0);
+    zone.fogStart = 100.0;
+    zone.fogEnd = 500.0;
+
     Node@ lightNode = editorScene.CreateChild("GlobalLight", useLocalIDs ? LOCAL : REPLICATED);
     Node@ lightNode = editorScene.CreateChild("GlobalLight", useLocalIDs ? LOCAL : REPLICATED);
     Light@ light = lightNode.CreateComponent("Light");
     Light@ light = lightNode.CreateComponent("Light");
     lightNode.rotation = Quaternion(60, 30, 0);
     lightNode.rotation = Quaternion(60, 30, 0);
     light.lightType = LIGHT_DIRECTIONAL;
     light.lightType = LIGHT_DIRECTIONAL;
     light.castShadows = true;
     light.castShadows = true;
     light.shadowCascade = CascadeParameters(3, 0.95, 0.2, 1000000);
     light.shadowCascade = CascadeParameters(3, 0.95, 0.2, 1000000);
-    zone.boundingBox = BoundingBox(-1000, 1000);
-    zone.ambientColor = Color(0.5, 0.5, 0.5);
-    zone.fogColor = Color(0.5, 0.7, 1.0);
-    zone.fogStart = 100.0;
-    zone.fogEnd = 500.0;
 
 
+    // Loop through scene entities
     while (!entityElem.isNull)
     while (!entityElem.isNull)
     {
     {
         String nodeName;
         String nodeName;
@@ -126,6 +131,15 @@ void ImportTundraScene(const String&in fileName)
         bool castShadows = false;
         bool castShadows = false;
         float drawDistance = 0;
         float drawDistance = 0;
         Array<String> materialNames;
         Array<String> materialNames;
+        
+        int shapeType = -1;
+        float mass = 0.0f;
+        Vector3 bodySize;
+        bool phantom = false;
+        bool kinematic = false;
+        uint collisionLayer;
+        uint collisionMask;
+        String collisionMeshName;
 
 
         XMLElement compElem = entityElem.GetChild("component");
         XMLElement compElem = entityElem.GetChild("component");
         while (!compElem.isNull)
         while (!compElem.isNull)
@@ -158,49 +172,37 @@ void ImportTundraScene(const String&in fileName)
                 scale = GetVector3FromStrings(coords, 6);
                 scale = GetVector3FromStrings(coords, 6);
                 parentName = GetComponentAttribute(compElem, "Parent entity ref");
                 parentName = GetComponentAttribute(compElem, "Parent entity ref");
             }
             }
-            
+            if (compType == "EC_RigidBody")
+            {
+                shapeType = GetComponentAttribute(compElem, "Shape type").ToInt();
+                mass = GetComponentAttribute(compElem, "Mass").ToFloat();
+                bodySize = GetComponentAttribute(compElem, "Size").ToVector3();
+                collisionMeshName = GetComponentAttribute(compElem, "Collision mesh ref");
+                phantom = GetComponentAttribute(compElem, "Phantom").ToBool();
+                kinematic = GetComponentAttribute(compElem, "Kinematic").ToBool();
+                collisionLayer = GetComponentAttribute(compElem, "Collision Layer").ToInt();
+                collisionMask = GetComponentAttribute(compElem, "Collision Mask").ToInt();
+                ProcessRef(collisionMeshName);
+            }
+
             compElem = compElem.GetNext("component");
             compElem = compElem.GetNext("component");
         }
         }
 
 
-        // For now we are only interested of meshes
-        if (!meshName.empty)
+        // If collision mesh not specified for the rigid body, assume same as the visible mesh
+        if ((shapeType == 4 || shapeType == 6) && collisionMeshName.Trimmed().empty)
+            collisionMeshName = meshName;
+
+        if (!meshName.empty || shapeType >= 0)
         {
         {
             for (uint i = 0; i < materialNames.length; ++i)
             for (uint i = 0; i < materialNames.length; ++i)
-            {
-                bool found = false;
-                for (uint j = 0; j < convertedMaterials.length; ++j)
-                {
-                    if (convertedMaterials[j] == materialNames[i])
-                    {
-                        found = true;
-                        break;
-                    }                    
-                }
-    
-                if (!found)
-                {
-                    ConvertMaterial(materialNames[i], filePath);
-                    convertedMaterials.Push(materialNames[i]);
-                }
-            }
-    
-            bool found = false;
-            for (uint i = 0; i < convertedMeshes.length; ++i)
-            {
-                if (convertedMeshes[i] == meshName)
-                {
-                    found = true;
-                    break;
-                }
-            }
-            if (!found)
-                ConvertModel(meshName, filePath);
-    
+                ConvertMaterial(materialNames[i], filePath, convertedMaterials);
+            
+            ConvertModel(meshName, filePath, convertedMeshes);
+            ConvertModel(collisionMeshName, filePath, convertedMeshes);
+
             Node@ newNode = editorScene.CreateChild(nodeName, useLocalIDs ? LOCAL : REPLICATED);
             Node@ newNode = editorScene.CreateChild(nodeName, useLocalIDs ? LOCAL : REPLICATED);
-            StaticModel@ model = newNode.CreateComponent("StaticModel");
 
 
             // Calculate final transform in an Ogre-like fashion
             // Calculate final transform in an Ogre-like fashion
-            /// \todo Tundra 2.0 supports entity parenting. It is not yet taken into account
             Quaternion quat = GetTransformQuaternion(rot);
             Quaternion quat = GetTransformQuaternion(rot);
             Quaternion meshQuat = GetTransformQuaternion(meshRot);
             Quaternion meshQuat = GetTransformQuaternion(meshRot);
             Quaternion finalQuat = quat * meshQuat;
             Quaternion finalQuat = quat * meshQuat;
@@ -208,12 +210,75 @@ void ImportTundraScene(const String&in fileName)
             Vector3 finalPos = pos + quat * (scale * meshPos);
             Vector3 finalPos = pos + quat * (scale * meshPos);
 
 
             newNode.SetTransform(finalPos, finalQuat, finalScale);
             newNode.SetTransform(finalPos, finalQuat, finalScale);
-            model.model = cache.GetResource("Model", "Models/" + meshName.Replaced(".mesh", ".mdl"));
-            model.drawDistance = drawDistance;
-            model.castShadows = castShadows;
-            for (uint i = 0; i < materialNames.length; ++i)
-                model.materials[i] = cache.GetResource("Material", "Materials/" + materialNames[i].Replaced(".material", ".xml"));
+
+            // Create model
+            if (!meshName.empty)
+            {
+                StaticModel@ model = newNode.CreateComponent("StaticModel");
+                model.model = cache.GetResource("Model", "Models/" + meshName.Replaced(".mesh", ".mdl"));
+                model.drawDistance = drawDistance;
+                model.castShadows = castShadows;
+                // Set default grey material to match Tundra defaults
+                model.material = cache.GetResource("Material", "Materials/DefaultGrey.xml");
+                // Then try to assign the actual materials
+                for (uint i = 0; i < materialNames.length; ++i)
+                {
+                    Material@ mat = cache.GetResource("Material", "Materials/" + materialNames[i].Replaced(".material", ".xml"));
+                    if (mat !is null)
+                        model.materials[i] = mat;
+                }
+            }
+            
+            // Create collision shape
+            if (shapeType >= 0)
+            {
+                // If mesh has scaling, undo it for the collision shape
+                bodySize.x /= meshScale.x;
+                bodySize.y /= meshScale.y;
+                bodySize.z /= meshScale.z;
+
+                CollisionShape@ shape = newNode.CreateComponent("CollisionShape");
+                switch (shapeType)
+                {
+                case 0:
+                    shape.SetBox(bodySize);
+                    break;
+
+                case 1:
+                    shape.SetSphere(bodySize.x * 0.5);
+                    break;
+
+                case 2:
+                    shape.SetCylinder(bodySize.x * 0.5, bodySize.y, Vector3(0, 0, 0), Quaternion(90, 0, 0));
+                    break;
+
+                case 3:
+                    shape.SetCapsule(bodySize.x * 0.5, bodySize.y - bodySize.x, Vector3(0, 0, 0), Quaternion(90, 0, 0));
+                    break;
+                    
+                case 4:
+                    shape.SetTriangleMesh(cache.GetResource("Model", "Models/" + collisionMeshName.Replaced(".mesh", ".mdl")), 0, bodySize);
+                    break;
+                    
+                case 6:
+                    shape.SetConvexHull(cache.GetResource("Model", "Models/" + collisionMeshName.Replaced(".mesh", ".mdl")), 0.1, 0, bodySize);
+                    break;
+                }
                 
                 
+                shape.collisionLayer = collisionLayer;
+                shape.collisionMask = collisionMask;
+                shape.phantom = phantom;
+
+                // Create rigid body if the object should be dynamic or kinematic
+                if (mass > 0.0)
+                {
+                    RigidBody@ body = newNode.CreateComponent("RigidBody");
+                    //if (kinematic)
+                    //    mass = 0.0;
+                    body.mass = mass;
+                }
+            }
+
             // Store pending parent assignment if necessary
             // Store pending parent assignment if necessary
             if (!parentName.empty)
             if (!parentName.empty)
             {
             {
@@ -230,7 +295,7 @@ void ImportTundraScene(const String&in fileName)
     // Process any parent assignments now
     // Process any parent assignments now
     for (uint i = 0; i < parentAssignments.length; ++i)
     for (uint i = 0; i < parentAssignments.length; ++i)
     {
     {
-        Node@ childNode = editorScene.GetNodeByID(parentAssignments[i].childID);
+        Node@ childNode = editorScene.GetNode(parentAssignments[i].childID);
         Node@ parentNode = editorScene.GetChild(parentAssignments[i].parentName, true);
         Node@ parentNode = editorScene.GetChild(parentAssignments[i].parentName, true);
         if (childNode !is null && parentNode !is null)
         if (childNode !is null && parentNode !is null)
             childNode.parent = parentNode;
             childNode.parent = parentNode;
@@ -276,8 +341,17 @@ void ProcessRef(String& ref)
         ref = ref.Substring(7);
         ref = ref.Substring(7);
 }
 }
 
 
-void ConvertModel(const String&in modelName, const String&in filePath)
+void ConvertModel(const String&in modelName, const String&in filePath, Array<String>@ convertedModels)
 {
 {
+    if (modelName.Trimmed().empty)
+        return;
+
+    for (uint i = 0; i < convertedModels.length; ++i)
+    {
+        if (convertedModels[i] == modelName)
+            return;
+    }
+
     // Convert .mesh to .mesh.xml
     // Convert .mesh to .mesh.xml
     String cmdLine = "ogrexmlconverter.exe \"" + filePath + modelName + "\" \"" + filePath + modelName + ".xml\"";
     String cmdLine = "ogrexmlconverter.exe \"" + filePath + modelName + "\" \"" + filePath + modelName + ".xml\"";
     fileSystem.SystemCommand(cmdLine.Replaced('/', '\\'));
     fileSystem.SystemCommand(cmdLine.Replaced('/', '\\'));
@@ -288,10 +362,21 @@ void ConvertModel(const String&in modelName, const String&in filePath)
     args.Push("\"" + sceneResourcePath + "Models/" + modelName.Replaced(".mesh", ".mdl") + "\"");
     args.Push("\"" + sceneResourcePath + "Models/" + modelName.Replaced(".mesh", ".mdl") + "\"");
     args.Push("-a");
     args.Push("-a");
     fileSystem.SystemRun(fileSystem.programDir + "OgreImporter.exe", args);
     fileSystem.SystemRun(fileSystem.programDir + "OgreImporter.exe", args);
+    
+    convertedModels.Push(modelName);
 }
 }
 
 
-void ConvertMaterial(const String&in materialName, const String&in filePath)
+void ConvertMaterial(const String&in materialName, const String&in filePath, Array<String>@ convertedMaterials)
 {
 {
+    if (materialName.Trimmed().empty)
+        return;
+
+    for (uint i = 0; i < convertedMaterials.length; ++i)
+    {
+        if (convertedMaterials[i] == materialName)
+            return;
+    }
+
     String fileName = filePath + materialName;
     String fileName = filePath + materialName;
     String outFileName = sceneResourcePath + "Materials/" + GetFileName(materialName) + ".xml";
     String outFileName = sceneResourcePath + "Materials/" + GetFileName(materialName) + ".xml";
 
 
@@ -341,4 +426,6 @@ void ConvertMaterial(const String&in materialName, const String&in filePath)
     
     
         fileSystem.Copy(filePath + textureName, sceneResourcePath + "Textures/" + textureName);
         fileSystem.Copy(filePath + textureName, sceneResourcePath + "Textures/" + textureName);
     }
     }
+    
+    convertedMaterials.Push(materialName);
 }
 }

+ 3 - 3
Bin/Data/Scripts/Editor/EditorNodeWindow.as

@@ -319,9 +319,9 @@ void SetAttributeEditorID(UIElement@ attrEdit, Serializable@ serializable)
 Serializable@ GetAttributeEditorTarget(UIElement@ attrEdit)
 Serializable@ GetAttributeEditorTarget(UIElement@ attrEdit)
 {
 {
     if (attrEdit.vars.Contains("NodeID"))
     if (attrEdit.vars.Contains("NodeID"))
-        return editorScene.GetNodeByID(attrEdit.vars["NodeID"].GetUInt());
+        return editorScene.GetNode(attrEdit.vars["NodeID"].GetUInt());
     else if (attrEdit.vars.Contains("ComponentID"))
     else if (attrEdit.vars.Contains("ComponentID"))
-        return editorScene.GetComponentByID(attrEdit.vars["ComponentID"].GetUInt());
+        return editorScene.GetComponent(attrEdit.vars["ComponentID"].GetUInt());
     else
     else
         return null;
         return null;
 }
 }
@@ -866,7 +866,7 @@ void PickResourceDone(StringHash eventType, VariantMap& eventData)
         return;
         return;
     }
     }
 
 
-    Component@ target = editorScene.GetComponentByID(resourcePickID);
+    Component@ target = editorScene.GetComponent(resourcePickID);
     if (target is null || resourcePicker is null)
     if (target is null || resourcePicker is null)
         return;
         return;
 
 

+ 6 - 6
Bin/Data/Scripts/Editor/EditorSceneWindow.as

@@ -280,7 +280,7 @@ Node@ GetListNode(uint index)
     if (item is null)
     if (item is null)
         return null;
         return null;
 
 
-    return editorScene.GetNodeByID(item.vars["NodeID"].GetUInt());
+    return editorScene.GetNode(item.vars["NodeID"].GetUInt());
 }
 }
 
 
 Component@ GetListComponent(uint index)
 Component@ GetListComponent(uint index)
@@ -298,7 +298,7 @@ Component@ GetListComponent(UIElement@ item)
     if (item.vars["Type"].GetInt() != ITEM_COMPONENT)
     if (item.vars["Type"].GetInt() != ITEM_COMPONENT)
         return null;
         return null;
 
 
-    return editorScene.GetComponentByID(item.vars["ComponentID"].GetUInt());
+    return editorScene.GetComponent(item.vars["ComponentID"].GetUInt());
 }
 }
 
 
 uint GetComponentListIndex(Component@ component)
 uint GetComponentListIndex(Component@ component)
@@ -493,8 +493,8 @@ void HandleDragDropFinish(StringHash eventType, VariantMap& eventData)
     if (!accept)
     if (!accept)
         return;
         return;
 
 
-    Node@ sourceNode = editorScene.GetNodeByID(source.vars["NodeID"].GetUInt());
-    Node@ targetNode = editorScene.GetNodeByID(target.vars["NodeID"].GetUInt());
+    Node@ sourceNode = editorScene.GetNode(source.vars["NodeID"].GetUInt());
+    Node@ targetNode = editorScene.GetNode(target.vars["NodeID"].GetUInt());
 
 
     // If target is null, parent to scene
     // If target is null, parent to scene
     if (targetNode is null)
     if (targetNode is null)
@@ -542,9 +542,9 @@ bool TestSceneWindowElements(UIElement@ source, UIElement@ target)
     Node@ sourceNode;
     Node@ sourceNode;
     Node@ targetNode;
     Node@ targetNode;
     if (source.vars.Contains("NodeID"))
     if (source.vars.Contains("NodeID"))
-        sourceNode = editorScene.GetNodeByID(source.vars["NodeID"].GetUInt());
+        sourceNode = editorScene.GetNode(source.vars["NodeID"].GetUInt());
     if (target.vars.Contains("NodeID"))
     if (target.vars.Contains("NodeID"))
-        editorScene.GetNodeByID(target.vars["NodeID"].GetUInt());
+        editorScene.GetNode(target.vars["NodeID"].GetUInt());
 
 
     if (sourceNode is null)
     if (sourceNode is null)
         return false;
         return false;

+ 3 - 3
Bin/Data/Scripts/NinjaSnowWar.as

@@ -164,7 +164,7 @@ void InitScene()
     staticModel.material = cache.GetResource("Material", "Materials/Snow.xml");
     staticModel.material = cache.GetResource("Material", "Materials/Snow.xml");
     CollisionShape@ shape = staticNode.CreateComponent("CollisionShape");
     CollisionShape@ shape = staticNode.CreateComponent("CollisionShape");
     shape.SetTriangleMesh(cache.GetResource("Model", "Models/Level.mdl"), 0);
     shape.SetTriangleMesh(cache.GetResource("Model", "Models/Level.mdl"), 0);
-    shape.collisionGroup = 2;
+    shape.collisionLayer = 2;
     shape.collisionMask = 3;
     shape.collisionMask = 3;
 
 
     Node@ skyNode = gameScene.CreateChild("Sky");
     Node@ skyNode = gameScene.CreateChild("Sky");
@@ -563,7 +563,7 @@ int FindPlayerIndex(uint nodeID)
 Node@ FindPlayerNode(int playerIndex)
 Node@ FindPlayerNode(int playerIndex)
 {
 {
     if (playerIndex >= 0 && playerIndex < int(players.length))
     if (playerIndex >= 0 && playerIndex < int(players.length))
-        return gameScene.GetNodeByID(players[playerIndex].nodeID);
+        return gameScene.GetNode(players[playerIndex].nodeID);
     else
     else
         return null;
         return null;
 }
 }
@@ -573,7 +573,7 @@ Node@ FindOwnNode()
     if (singlePlayer)
     if (singlePlayer)
         return gameScene.GetChild("Player", true);
         return gameScene.GetChild("Player", true);
     else
     else
-        return gameScene.GetNodeByID(clientNodeID);
+        return gameScene.GetNode(clientNodeID);
 }
 }
 
 
 bool CheckHiscore(int playerIndex)
 bool CheckHiscore(int playerIndex)

+ 1 - 1
Bin/Data/Scripts/NinjaSnowWar/GameObject.as

@@ -135,7 +135,7 @@ class GameObject : ScriptObject
         CollisionShape@ otherShape = eventData["OtherShape"].GetCollisionShape();
         CollisionShape@ otherShape = eventData["OtherShape"].GetCollisionShape();
 
 
         // If the other collision shape belongs to static geometry, perform world collision
         // If the other collision shape belongs to static geometry, perform world collision
-        if (otherShape.collisionGroup == 2)
+        if (otherShape.collisionLayer == 2)
             WorldCollision(eventData);
             WorldCollision(eventData);
 
 
         // If the other node is scripted, perform object-to-object collision
         // If the other node is scripted, perform object-to-object collision

+ 1 - 1
Bin/Data/Scripts/NinjaSnowWar/Ninja.as

@@ -85,7 +85,7 @@ class Ninja : GameObject
         // Create collision shape
         // Create collision shape
         CollisionShape@ shape = node.CreateComponent("CollisionShape");
         CollisionShape@ shape = node.CreateComponent("CollisionShape");
         shape.SetCapsule(35, 110, Vector3(), Quaternion(90, 0, 0));
         shape.SetCapsule(35, 110, Vector3(), Quaternion(90, 0, 0));
-        shape.collisionGroup = 1;
+        shape.collisionLayer = 1;
         shape.collisionMask = 3;
         shape.collisionMask = 3;
         shape.friction = ninjaFriction;
         shape.friction = ninjaFriction;
 
 

+ 2 - 2
Bin/Data/Scripts/NinjaSnowWar/Potion.as

@@ -18,7 +18,7 @@ class Potion : GameObject
     {
     {
         SubscribeToEvent("NodeCollision", "HandleNodeCollision");
         SubscribeToEvent("NodeCollision", "HandleNodeCollision");
     }
     }
-    
+
     void Create(const Vector3&in position, const Quaternion&in rotation)
     void Create(const Vector3&in position, const Quaternion&in rotation)
     {
     {
         node.position = position;
         node.position = position;
@@ -40,7 +40,7 @@ class Potion : GameObject
         // Create collision shape
         // Create collision shape
         CollisionShape@ shape = node.CreateComponent("CollisionShape");
         CollisionShape@ shape = node.CreateComponent("CollisionShape");
         shape.SetBox(Vector3(20, 40, 20));
         shape.SetBox(Vector3(20, 40, 20));
-        shape.collisionGroup = 1;
+        shape.collisionLayer = 1;
         shape.collisionMask = 3;
         shape.collisionMask = 3;
         shape.friction = potionFriction;
         shape.friction = potionFriction;
 
 

+ 1 - 1
Bin/Data/Scripts/NinjaSnowWar/SnowBall.as

@@ -46,7 +46,7 @@ class SnowBall : GameObject
         // Create collision shape. Create as local to avoid divergent simulation by the client
         // Create collision shape. Create as local to avoid divergent simulation by the client
         CollisionShape@ shape = node.CreateComponent("CollisionShape", LOCAL);
         CollisionShape@ shape = node.CreateComponent("CollisionShape", LOCAL);
         shape.SetBox(Vector3(15, 15, 15));
         shape.SetBox(Vector3(15, 15, 15));
-        shape.collisionGroup = 1;
+        shape.collisionLayer = 1;
         shape.collisionMask = 3;
         shape.collisionMask = 3;
         shape.friction = snowballFriction;
         shape.friction = snowballFriction;
 
 

+ 1 - 1
Bin/Data/Scripts/NinjaSnowWar/SnowCrate.as

@@ -39,7 +39,7 @@ class SnowCrate : GameObject
         // Create collision shape
         // Create collision shape
         CollisionShape@ shape = node.CreateComponent("CollisionShape");
         CollisionShape@ shape = node.CreateComponent("CollisionShape");
         shape.SetBox(Vector3(80, 80, 80));
         shape.SetBox(Vector3(80, 80, 80));
-        shape.collisionGroup = 2;
+        shape.collisionLayer = 2;
         shape.collisionMask = 3;
         shape.collisionMask = 3;
         shape.friction = snowcrateFriction;
         shape.friction = snowcrateFriction;
 
 

+ 5 - 5
Bin/Data/Scripts/TestScene.as

@@ -134,7 +134,7 @@ void InitScene()
 
 
         CollisionShape@ shape = objectNode.CreateComponent("CollisionShape");
         CollisionShape@ shape = objectNode.CreateComponent("CollisionShape");
         shape.SetBox(Vector3(2.0, 2.0, 2.0));
         shape.SetBox(Vector3(2.0, 2.0, 2.0));
-        shape.collisionGroup = 2;
+        shape.collisionLayer = 2;
         shape.collisionMask = 1;
         shape.collisionMask = 1;
     }
     }
 
 
@@ -150,7 +150,7 @@ void InitScene()
 
 
         CollisionShape@ shape = objectNode.CreateComponent("CollisionShape");
         CollisionShape@ shape = objectNode.CreateComponent("CollisionShape");
         shape.SetBox(Vector3(2.0, 2.0, 2.0));
         shape.SetBox(Vector3(2.0, 2.0, 2.0));
-        shape.collisionGroup = 2;
+        shape.collisionLayer = 2;
         shape.collisionMask = 1;
         shape.collisionMask = 1;
     }
     }
 
 
@@ -168,7 +168,7 @@ void InitScene()
 
 
         CollisionShape@ shape = objectNode.CreateComponent("CollisionShape");
         CollisionShape@ shape = objectNode.CreateComponent("CollisionShape");
         shape.SetBox(Vector3(2.0, 2.0, 2.0));
         shape.SetBox(Vector3(2.0, 2.0, 2.0));
-        shape.collisionGroup = 2;
+        shape.collisionLayer = 2;
         shape.collisionMask = 1;
         shape.collisionMask = 1;
     }
     }
 
 
@@ -186,7 +186,7 @@ void InitScene()
 
 
         CollisionShape@ shape = objectNode.CreateComponent("CollisionShape");
         CollisionShape@ shape = objectNode.CreateComponent("CollisionShape");
         shape.SetTriangleMesh(cache.GetResource("Model", "Models/Mushroom.mdl"), 0);
         shape.SetTriangleMesh(cache.GetResource("Model", "Models/Mushroom.mdl"), 0);
-        shape.collisionGroup = 2;
+        shape.collisionLayer = 2;
         shape.collisionMask = 1;
         shape.collisionMask = 1;
     }
     }
 
 
@@ -414,7 +414,7 @@ void HandleSpawnBox(StringHash eventType, VariantMap& eventData)
     CollisionShape@ shape = newNode.CreateComponent("CollisionShape");
     CollisionShape@ shape = newNode.CreateComponent("CollisionShape");
     shape.SetBox(Vector3(2, 2, 2));
     shape.SetBox(Vector3(2, 2, 2));
     shape.friction = 1.0;
     shape.friction = 1.0;
-    shape.collisionGroup = 1;
+    shape.collisionLayer = 1;
     shape.collisionMask = 3;
     shape.collisionMask = 3;
 
 
     RigidBody@ body = newNode.CreateComponent("RigidBody");
     RigidBody@ body = newNode.CreateComponent("RigidBody");

+ 1 - 1
Docs/Reference.dox

@@ -723,7 +723,7 @@ The other physics components are:
 
 
 Triangle meshes, convex hulls and heightfields are created by specifying a Model resource.
 Triangle meshes, convex hulls and heightfields are created by specifying a Model resource.
 
 
-Several collision shapes may exist in the same scene node to create compound shapes. An offset position and rotation relative to the node's transform can be specified for each. The shape (instead of RigidBody) also contains collision behaviour parameters: which other objects to collide with (see \ref CollisionShape::SetCollisionGroup "SetCollisionGroup()" and \ref CollisionShape::SetCollisionMask "SetCollisionMask()"), the friction coefficient, and the bounce coefficient.
+Several collision shapes may exist in the same scene node to create compound shapes. An offset position and rotation relative to the node's transform can be specified for each. The shape (instead of RigidBody) also contains collision behaviour parameters: which other objects to collide with (see \ref CollisionShape::SetCollisionLayer "SetCollisionLayer()" and \ref CollisionShape::SetCollisionMask "SetCollisionMask()"), the friction coefficient, and the bounce coefficient.
 
 
 Note that static physics objects such as unmoving level geometry should not have RigidBody components at all.
 Note that static physics objects such as unmoving level geometry should not have RigidBody components at all.
 
 

+ 18 - 18
Docs/ScriptAPI.dox

@@ -342,17 +342,6 @@ Properties:<br>
 - float z
 - float z
 
 
 
 
-Ray
-
-Methods:<br>
-- void Define(const Vector3&, const Vector3&)
-- float Distance(const Vector3&, const Vector3&, const Vector3&) const
-
-Properties:<br>
-- Vector3 origin
-- Vector3 direction
-
-
 Rect
 Rect
 
 
 Methods:<br>
 Methods:<br>
@@ -386,7 +375,6 @@ Methods:<br>
 - Intersection IsInside(const Vector3&) const
 - Intersection IsInside(const Vector3&) const
 - Intersection IsInside(const Sphere&) const
 - Intersection IsInside(const Sphere&) const
 - Intersection IsInside(const BoundingBox&) const
 - Intersection IsInside(const BoundingBox&) const
-- float Distance(const Ray&) const
 
 
 Properties:<br>
 Properties:<br>
 - Vector3 center (readonly)
 - Vector3 center (readonly)
@@ -410,7 +398,6 @@ Methods:<br>
 - Intersection IsInside(const Vector3&) const
 - Intersection IsInside(const Vector3&) const
 - Intersection IsInside(const Sphere&) const
 - Intersection IsInside(const Sphere&) const
 - Intersection IsInside(const BoundingBox&) const
 - Intersection IsInside(const BoundingBox&) const
-- float Distance(const Ray&) const
 
 
 Properties:<br>
 Properties:<br>
 - Vector3 center
 - Vector3 center
@@ -430,6 +417,19 @@ Properties:<br>
 - bool defined
 - bool defined
 
 
 
 
+Ray
+
+Methods:<br>
+- void Define(const Vector3&, const Vector3&)
+- float HitDistance(const Sphere&) const
+- float HitDistance(const BoundingBox&) const
+- float HitDistance(const Vector3&, const Vector3&, const Vector3&) const
+
+Properties:<br>
+- Vector3 origin
+- Vector3 direction
+
+
 Color
 Color
 
 
 Methods:<br>
 Methods:<br>
@@ -1053,7 +1053,7 @@ Methods:<br>
 - Node@[]@ GetChildrenWithScript(const String&, bool arg1 = false) const
 - Node@[]@ GetChildrenWithScript(const String&, bool arg1 = false) const
 - Node@ GetChild(const String&, bool arg1 = false) const
 - Node@ GetChild(const String&, bool arg1 = false) const
 - Component@[]@ GetComponents(const String&) const
 - Component@[]@ GetComponents(const String&) const
-- Component@ GetComponent(const String&, uint arg1 = 0) const
+- Component@ GetComponent(const String&) const
 - bool HasComponent(const String&) const
 - bool HasComponent(const String&) const
 - ScriptObject@ CreateScriptObject(ScriptFile@, const String&, CreateMode arg2 = REPLICATED)
 - ScriptObject@ CreateScriptObject(ScriptFile@, const String&, CreateMode arg2 = REPLICATED)
 - ScriptObject@ CreateScriptObject(const String&, const String&, CreateMode arg2 = REPLICATED)
 - ScriptObject@ CreateScriptObject(const String&, const String&, CreateMode arg2 = REPLICATED)
@@ -1131,7 +1131,7 @@ Methods:<br>
 - Node@[]@ GetChildrenWithScript(const String&, bool arg1 = false) const
 - Node@[]@ GetChildrenWithScript(const String&, bool arg1 = false) const
 - Node@ GetChild(const String&, bool arg1 = false) const
 - Node@ GetChild(const String&, bool arg1 = false) const
 - Component@[]@ GetComponents(const String&) const
 - Component@[]@ GetComponents(const String&) const
-- Component@ GetComponent(const String&, uint arg1 = 0) const
+- Component@ GetComponent(const String&) const
 - bool HasComponent(const String&) const
 - bool HasComponent(const String&) const
 - bool LoadXML(File@)
 - bool LoadXML(File@)
 - bool SaveXML(File@)
 - bool SaveXML(File@)
@@ -1144,8 +1144,8 @@ Methods:<br>
 - void RegisterVar(const String&)
 - void RegisterVar(const String&)
 - void UnregisterVar(const String&)
 - void UnregisterVar(const String&)
 - void UnregisterAllVars(const String&)
 - void UnregisterAllVars(const String&)
-- Component@ GetComponentByID(uint)
-- Node@ GetNodeByID(uint)
+- Component@ GetComponent(uint)
+- Node@ GetNode(uint)
 - const String& GetVarName(ShortStringHash) const
 - const String& GetVarName(ShortStringHash) const
 - void Update(float)
 - void Update(float)
 
 
@@ -3624,7 +3624,7 @@ Properties:<br>
 - ShapeType shapeType (readonly)
 - ShapeType shapeType (readonly)
 - Vector3& position
 - Vector3& position
 - Quaternion& rotation
 - Quaternion& rotation
-- uint collisionGroup
+- uint collisionLayer
 - uint collisionMask
 - uint collisionMask
 - float friction
 - float friction
 - float bounce
 - float bounce

+ 3 - 3
Engine/Engine/APITemplates.h

@@ -399,9 +399,9 @@ static Component* NodeGetComponent(unsigned index, Node* ptr)
         return components[index];
         return components[index];
 }
 }
 
 
-static Component* NodeGetComponentWithTypeAndIndex(const String& typeName, unsigned index, Node* ptr)
+static Component* NodeGetComponentWithType(const String& typeName, Node* ptr)
 {
 {
-    return ptr->GetComponent(ShortStringHash(typeName), index);
+    return ptr->GetComponent(ShortStringHash(typeName));
 }
 }
 
 
 static CScriptArray* NodeGetComponentsWithType(const String& typeName, Node* ptr)
 static CScriptArray* NodeGetComponentsWithType(const String& typeName, Node* ptr)
@@ -516,7 +516,7 @@ template <class T> void RegisterNode(asIScriptEngine* engine, const char* classN
     engine->RegisterObjectMethod(className, "Array<Node@>@ GetChildrenWithScript(const String&in, bool recursive = false) const", asFUNCTION(NodeGetChildrenWithClassName), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod(className, "Array<Node@>@ GetChildrenWithScript(const String&in, bool recursive = false) const", asFUNCTION(NodeGetChildrenWithClassName), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod(className, "Node@+ GetChild(const String&in, bool recursive = false) const", asMETHODPR(T, GetChild, (const String&, bool) const, Node*), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "Node@+ GetChild(const String&in, bool recursive = false) const", asMETHODPR(T, GetChild, (const String&, bool) const, Node*), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "Array<Component@>@ GetComponents(const String&in) const", asFUNCTION(NodeGetComponentsWithType), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod(className, "Array<Component@>@ GetComponents(const String&in) const", asFUNCTION(NodeGetComponentsWithType), asCALL_CDECL_OBJLAST);
-    engine->RegisterObjectMethod(className, "Component@+ GetComponent(const String&in, uint index = 0) const", asFUNCTION(NodeGetComponentWithTypeAndIndex), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod(className, "Component@+ GetComponent(const String&in) const", asFUNCTION(NodeGetComponentWithType), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod(className, "bool HasComponent(const String&in) const", asFUNCTION(NodeHasComponent), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod(className, "bool HasComponent(const String&in) const", asFUNCTION(NodeHasComponent), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod(className, "void set_position(const Vector3&in)", asMETHOD(T, SetPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_position(const Vector3&in)", asMETHOD(T, SetPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "const Vector3& get_position() const", asMETHOD(T, GetPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "const Vector3& get_position() const", asMETHOD(T, GetPosition), asCALL_THISCALL);

+ 6 - 5
Engine/Engine/MathAPI.cpp

@@ -24,6 +24,7 @@
 #include "Precompiled.h"
 #include "Precompiled.h"
 #include "Color.h"
 #include "Color.h"
 #include "Frustum.h"
 #include "Frustum.h"
+#include "Ray.h"
 
 
 #include <angelscript.h>
 #include <angelscript.h>
 
 
@@ -404,7 +405,9 @@ static void RegisterRay(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Ray", "Ray& opAssign(const Ray&in)", asMETHOD(Ray, operator =), asCALL_THISCALL);
     engine->RegisterObjectMethod("Ray", "Ray& opAssign(const Ray&in)", asMETHOD(Ray, operator =), asCALL_THISCALL);
     engine->RegisterObjectMethod("Ray", "bool opEquals(const Ray&in) const", asMETHOD(Ray, operator ==), asCALL_THISCALL);
     engine->RegisterObjectMethod("Ray", "bool opEquals(const Ray&in) const", asMETHOD(Ray, operator ==), asCALL_THISCALL);
     engine->RegisterObjectMethod("Ray", "void Define(const Vector3&in, const Vector3&in)", asMETHOD(Ray, Define), asCALL_THISCALL);
     engine->RegisterObjectMethod("Ray", "void Define(const Vector3&in, const Vector3&in)", asMETHOD(Ray, Define), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Ray", "float Distance(const Vector3&in, const Vector3&in, const Vector3&in) const", asMETHODPR(Ray, Distance, (const Vector3&, const Vector3&, const Vector3&) const, float), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Ray", "float HitDistance(const Sphere&in) const", asMETHODPR(Ray, HitDistance, (const Sphere&) const, float), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Ray", "float HitDistance(const BoundingBox&in) const", asMETHODPR(Ray, HitDistance, (const BoundingBox&) const, float), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Ray", "float HitDistance(const Vector3&in, const Vector3&in, const Vector3&in) const", asMETHODPR(Ray, HitDistance, (const Vector3&, const Vector3&, const Vector3&) const, float), asCALL_THISCALL);
     engine->RegisterObjectProperty("Ray", "Vector3 origin", offsetof(Ray, origin_));
     engine->RegisterObjectProperty("Ray", "Vector3 origin", offsetof(Ray, origin_));
     engine->RegisterObjectProperty("Ray", "Vector3 direction", offsetof(Ray, direction_));
     engine->RegisterObjectProperty("Ray", "Vector3 direction", offsetof(Ray, direction_));
 }
 }
@@ -538,7 +541,6 @@ static void RegisterVolumes(asIScriptEngine* engine)
     engine->RegisterObjectMethod("BoundingBox", "Intersection IsInside(const Vector3&in) const", asMETHODPR(BoundingBox, IsInside, (const Vector3&) const, Intersection), asCALL_THISCALL);
     engine->RegisterObjectMethod("BoundingBox", "Intersection IsInside(const Vector3&in) const", asMETHODPR(BoundingBox, IsInside, (const Vector3&) const, Intersection), asCALL_THISCALL);
     engine->RegisterObjectMethod("BoundingBox", "Intersection IsInside(const Sphere&in) const", asMETHODPR(BoundingBox, IsInside, (const Sphere&) const, Intersection), asCALL_THISCALL);
     engine->RegisterObjectMethod("BoundingBox", "Intersection IsInside(const Sphere&in) const", asMETHODPR(BoundingBox, IsInside, (const Sphere&) const, Intersection), asCALL_THISCALL);
     engine->RegisterObjectMethod("BoundingBox", "Intersection IsInside(const BoundingBox&in) const", asMETHODPR(BoundingBox, IsInside, (const BoundingBox&) const, Intersection), asCALL_THISCALL);
     engine->RegisterObjectMethod("BoundingBox", "Intersection IsInside(const BoundingBox&in) const", asMETHODPR(BoundingBox, IsInside, (const BoundingBox&) const, Intersection), asCALL_THISCALL);
-    engine->RegisterObjectMethod("BoundingBox", "float Distance(const Ray&in) const", asMETHOD(BoundingBox, Distance), asCALL_THISCALL);
     engine->RegisterObjectMethod("BoundingBox", "Vector3 get_center() const", asMETHOD(BoundingBox, Center), asCALL_THISCALL);
     engine->RegisterObjectMethod("BoundingBox", "Vector3 get_center() const", asMETHOD(BoundingBox, Center), asCALL_THISCALL);
     engine->RegisterObjectMethod("BoundingBox", "Vector3 get_size() const", asMETHOD(BoundingBox, Size), asCALL_THISCALL);
     engine->RegisterObjectMethod("BoundingBox", "Vector3 get_size() const", asMETHOD(BoundingBox, Size), asCALL_THISCALL);
     engine->RegisterObjectMethod("BoundingBox", "Vector3 get_halfSize() const", asMETHOD(BoundingBox, HalfSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("BoundingBox", "Vector3 get_halfSize() const", asMETHOD(BoundingBox, HalfSize), asCALL_THISCALL);
@@ -561,7 +563,6 @@ static void RegisterVolumes(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Sphere", "Intersection IsInside(const Vector3&in) const", asMETHODPR(Sphere, IsInside, (const Vector3&) const, Intersection), asCALL_THISCALL);
     engine->RegisterObjectMethod("Sphere", "Intersection IsInside(const Vector3&in) const", asMETHODPR(Sphere, IsInside, (const Vector3&) const, Intersection), asCALL_THISCALL);
     engine->RegisterObjectMethod("Sphere", "Intersection IsInside(const Sphere&in) const", asMETHODPR(Sphere, IsInside, (const Sphere&) const, Intersection), asCALL_THISCALL);
     engine->RegisterObjectMethod("Sphere", "Intersection IsInside(const Sphere&in) const", asMETHODPR(Sphere, IsInside, (const Sphere&) const, Intersection), asCALL_THISCALL);
     engine->RegisterObjectMethod("Sphere", "Intersection IsInside(const BoundingBox&in) const", asMETHODPR(Sphere, IsInside, (const BoundingBox&) const, Intersection), asCALL_THISCALL);
     engine->RegisterObjectMethod("Sphere", "Intersection IsInside(const BoundingBox&in) const", asMETHODPR(Sphere, IsInside, (const BoundingBox&) const, Intersection), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Sphere", "float Distance(const Ray&in) const", asMETHOD(Sphere, Distance), asCALL_THISCALL);
     engine->RegisterObjectProperty("Sphere", "Vector3 center", offsetof(Sphere, center_));
     engine->RegisterObjectProperty("Sphere", "Vector3 center", offsetof(Sphere, center_));
     engine->RegisterObjectProperty("Sphere", "float radius", offsetof(Sphere, radius_));
     engine->RegisterObjectProperty("Sphere", "float radius", offsetof(Sphere, radius_));
     engine->RegisterObjectProperty("Sphere", "bool defined", offsetof(Sphere, defined_));
     engine->RegisterObjectProperty("Sphere", "bool defined", offsetof(Sphere, defined_));
@@ -628,10 +629,10 @@ void RegisterMathAPI(asIScriptEngine* engine)
     RegisterVector3(engine);
     RegisterVector3(engine);
     RegisterVector4(engine);
     RegisterVector4(engine);
     RegisterQuaternion(engine);
     RegisterQuaternion(engine);
-    RegisterRay(engine);
     RegisterRect(engine);
     RegisterRect(engine);
     RegisterVolumes(engine);
     RegisterVolumes(engine);
+    RegisterRay(engine);
     RegisterColor(engine);
     RegisterColor(engine);
     
     
-    /// \todo Register Matrix types
+    /// \todo Register matrix types
 }
 }

+ 2 - 2
Engine/Engine/PhysicsAPI.cpp

@@ -89,8 +89,8 @@ static void RegisterCollisionShape(asIScriptEngine* engine)
     engine->RegisterObjectMethod("CollisionShape", "const Vector3& get_position() const", asMETHOD(CollisionShape, GetPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "const Vector3& get_position() const", asMETHOD(CollisionShape, GetPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "void set_rotation(const Quaternion&in)", asMETHOD(CollisionShape, SetRotation), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "void set_rotation(const Quaternion&in)", asMETHOD(CollisionShape, SetRotation), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "const Quaternion& get_rotation() const", asMETHOD(CollisionShape, GetRotation), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "const Quaternion& get_rotation() const", asMETHOD(CollisionShape, GetRotation), asCALL_THISCALL);
-    engine->RegisterObjectMethod("CollisionShape", "void set_collisionGroup(uint)", asMETHOD(CollisionShape, SetCollisionGroup), asCALL_THISCALL);
-    engine->RegisterObjectMethod("CollisionShape", "uint get_collisionGroup() const", asMETHOD(CollisionShape, GetCollisionGroup), asCALL_THISCALL);
+    engine->RegisterObjectMethod("CollisionShape", "void set_collisionLayer(uint)", asMETHOD(CollisionShape, SetCollisionLayer), asCALL_THISCALL);
+    engine->RegisterObjectMethod("CollisionShape", "uint get_collisionLayer() const", asMETHOD(CollisionShape, GetCollisionLayer), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "void set_collisionMask(uint)", asMETHOD(CollisionShape, SetCollisionMask), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "void set_collisionMask(uint)", asMETHOD(CollisionShape, SetCollisionMask), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "uint get_collisionMask() const", asMETHOD(CollisionShape, GetCollisionMask), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "uint get_collisionMask() const", asMETHOD(CollisionShape, GetCollisionMask), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "void set_friction(float)", asMETHOD(CollisionShape, SetFriction), asCALL_THISCALL);
     engine->RegisterObjectMethod("CollisionShape", "void set_friction(float)", asMETHOD(CollisionShape, SetFriction), asCALL_THISCALL);

+ 2 - 2
Engine/Engine/SceneAPI.cpp

@@ -119,8 +119,8 @@ static void RegisterScene(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Scene", "void RegisterVar(const String&in)", asMETHOD(Scene, RegisterVar), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void RegisterVar(const String&in)", asMETHOD(Scene, RegisterVar), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void UnregisterVar(const String&in)", asMETHOD(Scene, UnregisterVar), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void UnregisterVar(const String&in)", asMETHOD(Scene, UnregisterVar), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void UnregisterAllVars(const String&in)", asMETHOD(Scene, UnregisterAllVars), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void UnregisterAllVars(const String&in)", asMETHOD(Scene, UnregisterAllVars), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Scene", "Component@+ GetComponentByID(uint)", asMETHOD(Scene, GetComponentByID), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Scene", "Node@+ GetNodeByID(uint)", asMETHOD(Scene, GetNodeByID), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Scene", "Component@+ GetComponent(uint)", asMETHODPR(Scene, GetComponent, (unsigned) const, Component*), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Scene", "Node@+ GetNode(uint)", asMETHOD(Scene, GetNode), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "const String& GetVarName(ShortStringHash) const", asMETHOD(Scene, GetVarName), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "const String& GetVarName(ShortStringHash) const", asMETHOD(Scene, GetVarName), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void Update(float)", asMETHOD(Scene, Update), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void Update(float)", asMETHOD(Scene, Update), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void set_active(bool)", asMETHOD(Scene, SetActive), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void set_active(bool)", asMETHOD(Scene, SetActive), asCALL_THISCALL);

+ 4 - 4
Engine/Graphics/AnimatedModel.cpp

@@ -130,7 +130,7 @@ void AnimatedModel::ProcessRayQuery(RayOctreeQuery& query, float initialDistance
             // Do an initial crude test using the bone's AABB
             // Do an initial crude test using the bone's AABB
             const BoundingBox& box = bone.boundingBox_;
             const BoundingBox& box = bone.boundingBox_;
             const Matrix3x4& transform = bone.node_->GetWorldTransform();
             const Matrix3x4& transform = bone.node_->GetWorldTransform();
-            float distance = box.Transformed(transform).Distance(query.ray_);
+            float distance = query.ray_.HitDistance(box.Transformed(transform));
             if (distance < query.maxDistance_)
             if (distance < query.maxDistance_)
             {
             {
                 if (level == RAY_AABB)
                 if (level == RAY_AABB)
@@ -147,7 +147,7 @@ void AnimatedModel::ProcessRayQuery(RayOctreeQuery& query, float initialDistance
                     // Follow with an OBB test if required
                     // Follow with an OBB test if required
                     Matrix3x4 inverse = transform.Inverse();
                     Matrix3x4 inverse = transform.Inverse();
                     Ray localRay(inverse * query.ray_.origin_, inverse * Vector4(query.ray_.direction_, 0.0f));
                     Ray localRay(inverse * query.ray_.origin_, inverse * Vector4(query.ray_.direction_, 0.0f));
-                    distance = box.Distance(localRay);
+                    distance = localRay.HitDistance(box);
                     if (distance < query.maxDistance_)
                     if (distance < query.maxDistance_)
                     {
                     {
                         RayQueryResult result;
                         RayQueryResult result;
@@ -164,7 +164,7 @@ void AnimatedModel::ProcessRayQuery(RayOctreeQuery& query, float initialDistance
         {
         {
             boneSphere.center_ = bone.node_->GetWorldPosition();
             boneSphere.center_ = bone.node_->GetWorldPosition();
             boneSphere.radius_ = bone.radius_;
             boneSphere.radius_ = bone.radius_;
-            float distance = boneSphere.Distance(query.ray_);
+            float distance = query.ray_.HitDistance(boneSphere);
             if (distance < query.maxDistance_)
             if (distance < query.maxDistance_)
             {
             {
                 RayQueryResult result;
                 RayQueryResult result;
@@ -709,7 +709,7 @@ void AnimatedModel::OnNodeSet(Node* node)
     Drawable::OnNodeSet(node);
     Drawable::OnNodeSet(node);
     
     
     // If this AnimatedModel is the first in the node, it is the master which controls animation & morphs
     // If this AnimatedModel is the first in the node, it is the master which controls animation & morphs
-    isMaster_ = GetComponent<AnimatedModel>(0) == this;
+    isMaster_ = GetComponent<AnimatedModel>() == this;
 }
 }
 
 
 void AnimatedModel::OnMarkedDirty(Node* node)
 void AnimatedModel::OnMarkedDirty(Node* node)

+ 1 - 1
Engine/Graphics/Geometry.cpp

@@ -224,7 +224,7 @@ float Geometry::GetDistance(const Ray& ray)
     if (!rawIndexData_ || !rawVertexData_ || !indexBuffer_)
     if (!rawIndexData_ || !rawVertexData_ || !indexBuffer_)
         return M_INFINITY;
         return M_INFINITY;
     
     
-    return ray.Distance(rawVertexData_.Get(), 3 * sizeof(float), rawIndexData_.Get(), indexBuffer_->GetIndexSize(), indexStart_, indexCount_);
+    return ray.HitDistance(rawVertexData_.Get(), 3 * sizeof(float), rawIndexData_.Get(), indexBuffer_->GetIndexSize(), indexStart_, indexCount_);
 }
 }
 
 
 void Geometry::GetPositionBufferIndex()
 void Geometry::GetPositionBufferIndex()

+ 2 - 2
Engine/Graphics/Octree.cpp

@@ -205,7 +205,7 @@ void Octant::GetDrawablesInternal(RayOctreeQuery& query) const
     if (!numDrawables_)
     if (!numDrawables_)
         return;
         return;
     
     
-    float octantDist = cullingBox_.Distance(query.ray_);
+    float octantDist = query.ray_.HitDistance(cullingBox_);
     if (octantDist >= query.maxDistance_)
     if (octantDist >= query.maxDistance_)
         return;
         return;
     
     
@@ -219,7 +219,7 @@ void Octant::GetDrawablesInternal(RayOctreeQuery& query) const
             !drawable->GetCastShadows()))
             !drawable->GetCastShadows()))
             continue;
             continue;
         
         
-        float drawableDist = drawable->GetWorldBoundingBox().Distance(query.ray_);
+        float drawableDist = query.ray_.HitDistance(drawable->GetWorldBoundingBox());
         // The drawable will possibly do more accurate collision testing, then store the result(s)
         // The drawable will possibly do more accurate collision testing, then store the result(s)
         if (drawableDist < query.maxDistance_)
         if (drawableDist < query.maxDistance_)
             drawable->ProcessRayQuery(query, drawableDist);
             drawable->ProcessRayQuery(query, drawableDist);

+ 2 - 2
Engine/Graphics/StaticModel.cpp

@@ -91,7 +91,7 @@ void StaticModel::ProcessRayQuery(RayOctreeQuery& query, float initialDistance)
         {
         {
             Matrix3x4 inverse(GetWorldTransform().Inverse());
             Matrix3x4 inverse(GetWorldTransform().Inverse());
             Ray localRay(inverse * query.ray_.origin_, inverse * Vector4(query.ray_.direction_, 0.0f));
             Ray localRay(inverse * query.ray_.origin_, inverse * Vector4(query.ray_.direction_, 0.0f));
-            float distance = boundingBox_.Distance(localRay);
+            float distance = localRay.HitDistance(boundingBox_);
             if (distance < query.maxDistance_)
             if (distance < query.maxDistance_)
             {
             {
                 RayQueryResult result;
                 RayQueryResult result;
@@ -108,7 +108,7 @@ void StaticModel::ProcessRayQuery(RayOctreeQuery& query, float initialDistance)
             // Do a pretest using the OBB
             // Do a pretest using the OBB
             Matrix3x4 inverse(GetWorldTransform().Inverse());
             Matrix3x4 inverse(GetWorldTransform().Inverse());
             Ray localRay(inverse * query.ray_.origin_, inverse * Vector4(query.ray_.direction_, 0.0f));
             Ray localRay(inverse * query.ray_.origin_, inverse * Vector4(query.ray_.direction_, 0.0f));
-            float distance = boundingBox_.Distance(localRay);
+            float distance = localRay.HitDistance(boundingBox_);
             if (distance < query.maxDistance_)
             if (distance < query.maxDistance_)
             {
             {
                 // Then the actual test using triangle geometry
                 // Then the actual test using triangle geometry

+ 0 - 79
Engine/Math/BoundingBox.cpp

@@ -280,82 +280,3 @@ Intersection BoundingBox::IsInsideFast(const Sphere& sphere) const
     else
     else
         return INSIDE;
         return INSIDE;
 }
 }
-
-float BoundingBox::Distance(const Ray& ray) const
-{
-    // If undefined, no hit (infinite distance)
-    if (!defined_)
-        return M_INFINITY;
-    
-    // Check for ray origin being inside the box
-    if (IsInside(ray.origin_))
-        return 0.0f;
-    
-    float dist = M_INFINITY;
-    
-    // Check for intersecting in the X-direction
-    if (ray.origin_.x_ < min_.x_ && ray.direction_.x_ > 0.0f)
-    {
-        float x = (min_.x_ - ray.origin_.x_) / ray.direction_.x_;
-        if (x < dist)
-        {
-            Vector3 point = ray.origin_ + x * ray.direction_;
-            if (point.y_ >= min_.y_ && point.y_ <= max_.y_ && point.z_ >= min_.z_ && point.z_ <= max_.z_)
-                dist = x;
-        }
-    }
-    if (ray.origin_.x_ > max_.x_ && ray.direction_.x_ < 0.0f)
-    {
-        float x = (max_.x_ - ray.origin_.x_) / ray.direction_.x_;
-        if (x < dist)
-        {
-            Vector3 point = ray.origin_ + x * ray.direction_;
-            if (point.y_ >= min_.y_ && point.y_ <= max_.y_ && point.z_ >= min_.z_ && point.z_ <= max_.z_)
-                dist = x;
-        }
-    }
-    // Check for intersecting in the Y-direction
-    if (ray.origin_.y_ < min_.y_ && ray.direction_.y_ > 0.0f)
-    {
-        float x = (min_.y_ - ray.origin_.y_) / ray.direction_.y_;
-        if (x < dist)
-        {
-            Vector3 point = ray.origin_ + x * ray.direction_;
-            if (point.x_ >= min_.x_ && point.x_ <= max_.x_ && point.z_ >= min_.z_ && point.z_ <= max_.z_)
-                dist = x;
-        }
-    }
-    if (ray.origin_.y_ > max_.y_ && ray.direction_.y_ < 0.0f)
-    {
-        float x = (max_.y_ - ray.origin_.y_) / ray.direction_.y_;
-        if (x < dist)
-        {
-            Vector3 point = ray.origin_ + x * ray.direction_;
-            if (point.x_ >= min_.x_ && point.x_ <= max_.x_ && point.z_ >= min_.z_ && point.z_ <= max_.z_)
-                dist = x;
-        }
-    }
-    // Check for intersecting in the Z-direction
-    if (ray.origin_.z_ < min_.z_ && ray.direction_.z_ > 0.0f)
-    {
-        float x = (min_.z_ - ray.origin_.z_) / ray.direction_.z_;
-        if (x < dist)
-        {
-            Vector3 point = ray.origin_ + x * ray.direction_;
-            if (point.x_ >= min_.x_ && point.x_ <= max_.x_ && point.y_ >= min_.y_ && point.y_ <= max_.y_)
-                dist = x;
-        }
-    }
-    if (ray.origin_.z_ > max_.z_ && ray.direction_.z_ < 0.0f)
-    {
-        float x = (max_.z_ - ray.origin_.z_) / ray.direction_.z_;
-        if (x < dist)
-        {
-            Vector3 point = ray.origin_ + x * ray.direction_;
-            if (point.x_ >= min_.x_ && point.x_ <= max_.x_ && point.y_ >= min_.y_ && point.y_ <= max_.y_)
-                dist = x;
-        }
-    }
-    
-    return dist;
-}

+ 0 - 3
Engine/Math/BoundingBox.h

@@ -30,7 +30,6 @@ class Frustum;
 class Matrix3;
 class Matrix3;
 class Matrix4;
 class Matrix4;
 class Matrix3x4;
 class Matrix3x4;
-class Ray;
 class Sphere;
 class Sphere;
 
 
 /// Three-dimensional axis-aligned bounding box.
 /// Three-dimensional axis-aligned bounding box.
@@ -243,8 +242,6 @@ public:
     Intersection IsInside(const Sphere& sphere) const;
     Intersection IsInside(const Sphere& sphere) const;
     /// Test if a sphere is (partially) inside or outside.
     /// Test if a sphere is (partially) inside or outside.
     Intersection IsInsideFast(const Sphere& sphere) const;
     Intersection IsInsideFast(const Sphere& sphere) const;
-    /// Return ray hit distance, or infinity if no hit.
-    float Distance(const Ray& ray) const;
     
     
     /// Minimum vector.
     /// Minimum vector.
     Vector3 min_;
     Vector3 min_;

+ 0 - 13
Engine/Math/Plane.h

@@ -23,11 +23,8 @@
 
 
 #pragma once
 #pragma once
 
 
-#include "Ray.h"
 #include "Vector3.h"
 #include "Vector3.h"
 
 
-class Ray;
-
 /// Surface in three-dimensional space.
 /// Surface in three-dimensional space.
 class Plane
 class Plane
 {
 {
@@ -87,16 +84,6 @@ public:
         return absNormal_.DotProduct(absPoint);
         return absNormal_.DotProduct(absPoint);
     }
     }
     
     
-    /// Return ray hit distance, or infinity if no hit.
-    float Distance(const Ray& ray) const
-    {
-        float d = normal_.DotProduct(ray.direction_);
-        if (fabsf(d) >= M_EPSILON)
-            return (-normal_.DotProduct(ray.origin_) + intercept_) / d;
-        else
-            return M_INFINITY;
-    }
-    
     /// Plane normal.
     /// Plane normal.
     Vector3 normal_;
     Vector3 normal_;
     /// Plane absolute normal.
     /// Plane absolute normal.

+ 123 - 4
Engine/Math/Ray.cpp

@@ -22,7 +22,10 @@
 //
 //
 
 
 #include "Precompiled.h"
 #include "Precompiled.h"
+#include "BoundingBox.h"
+#include "Plane.h"
 #include "Ray.h"
 #include "Ray.h"
+#include "Sphere.h"
 
 
 Vector3 Ray::Project(const Vector3& point) const
 Vector3 Ray::Project(const Vector3& point) const
 {
 {
@@ -30,7 +33,123 @@ Vector3 Ray::Project(const Vector3& point) const
     return origin_ + offset.DotProduct(direction_) * direction_;
     return origin_ + offset.DotProduct(direction_) * direction_;
 }
 }
 
 
-float Ray::Distance(const Vector3& v0, const Vector3& v1, const Vector3& v2) const
+float Ray::HitDistance(const Plane& plane) const
+{
+    float d = plane.normal_.DotProduct(direction_);
+    if (fabsf(d) >= M_EPSILON)
+        return (-plane.normal_.DotProduct(origin_) + plane.intercept_) / d;
+    else
+        return M_INFINITY;
+}
+
+float Ray::HitDistance(const Sphere& sphere) const
+{
+    Vector3 centeredOrigin = origin_ - sphere.center_;
+    float squaredRadius = sphere.radius_ * sphere.radius_;
+    
+    // Check if ray originates inside the sphere
+    if (centeredOrigin.LengthSquared() <= squaredRadius)
+        return 0.0f;
+    
+    // Calculate intersection by quadratic equation
+    float a = direction_.DotProduct(direction_);
+    float b = 2.0f * centeredOrigin.DotProduct(direction_);
+    float c = centeredOrigin.DotProduct(centeredOrigin) - squaredRadius;
+    float d = b * b - 4.0f * a * c;
+    
+    // No solution
+    if (d < 0.0f)
+        return M_INFINITY;
+    
+    // Get the nearer solution
+    float dSqrt = sqrtf(d);
+    float dist = (-b - dSqrt) / (2.0f * a);
+    if (dist >= 0.0f)
+        return dist;
+    else
+        return (-b + dSqrt) / (2.0f * a);
+}
+
+float Ray::HitDistance(const BoundingBox& box) const
+{
+    // If undefined, no hit (infinite distance)
+    if (!box.defined_)
+        return M_INFINITY;
+    
+    // Check for ray origin being inside the box
+    if (box.IsInside(origin_))
+        return 0.0f;
+    
+    float dist = M_INFINITY;
+    
+    // Check for intersecting in the X-direction
+    if (origin_.x_ < box.min_.x_ && direction_.x_ > 0.0f)
+    {
+        float x = (box.min_.x_ - origin_.x_) / direction_.x_;
+        if (x < dist)
+        {
+            Vector3 point = origin_ + x * direction_;
+            if (point.y_ >= box.min_.y_ && point.y_ <= box.max_.y_ && point.z_ >= box.min_.z_ && point.z_ <= box.max_.z_)
+                dist = x;
+        }
+    }
+    if (origin_.x_ > box.max_.x_ && direction_.x_ < 0.0f)
+    {
+        float x = (box.max_.x_ - origin_.x_) / direction_.x_;
+        if (x < dist)
+        {
+            Vector3 point = origin_ + x * direction_;
+            if (point.y_ >= box.min_.y_ && point.y_ <= box.max_.y_ && point.z_ >= box.min_.z_ && point.z_ <= box.max_.z_)
+                dist = x;
+        }
+    }
+    // Check for intersecting in the Y-direction
+    if (origin_.y_ < box.min_.y_ && direction_.y_ > 0.0f)
+    {
+        float x = (box.min_.y_ - origin_.y_) / direction_.y_;
+        if (x < dist)
+        {
+            Vector3 point = origin_ + x * direction_;
+            if (point.x_ >= box.min_.x_ && point.x_ <= box.max_.x_ && point.z_ >= box.min_.z_ && point.z_ <= box.max_.z_)
+                dist = x;
+        }
+    }
+    if (origin_.y_ > box.max_.y_ && direction_.y_ < 0.0f)
+    {
+        float x = (box.max_.y_ - origin_.y_) / direction_.y_;
+        if (x < dist)
+        {
+            Vector3 point = origin_ + x * direction_;
+            if (point.x_ >= box.min_.x_ && point.x_ <= box.max_.x_ && point.z_ >= box.min_.z_ && point.z_ <= box.max_.z_)
+                dist = x;
+        }
+    }
+    // Check for intersecting in the Z-direction
+    if (origin_.z_ < box.min_.z_ && direction_.z_ > 0.0f)
+    {
+        float x = (box.min_.z_ - origin_.z_) / direction_.z_;
+        if (x < dist)
+        {
+            Vector3 point = origin_ + x * direction_;
+            if (point.x_ >= box.min_.x_ && point.x_ <= box.max_.x_ && point.y_ >= box.min_.y_ && point.y_ <= box.max_.y_)
+                dist = x;
+        }
+    }
+    if (origin_.z_ > box.max_.z_ && direction_.z_ < 0.0f)
+    {
+        float x = (box.max_.z_ - origin_.z_) / direction_.z_;
+        if (x < dist)
+        {
+            Vector3 point = origin_ + x * direction_;
+            if (point.x_ >= box.min_.x_ && point.x_ <= box.max_.x_ && point.y_ >= box.min_.y_ && point.y_ <= box.max_.y_)
+                dist = x;
+        }
+    }
+    
+    return dist;
+}
+
+float Ray::HitDistance(const Vector3& v0, const Vector3& v1, const Vector3& v2) const
 {
 {
     // Based on Fast, Minimum Storage Ray/Triangle Intersection by Möller & Trumbore
     // Based on Fast, Minimum Storage Ray/Triangle Intersection by Möller & Trumbore
     // http://www.graphics.cornell.edu/pubs/1997/MT97.pdf
     // http://www.graphics.cornell.edu/pubs/1997/MT97.pdf
@@ -61,7 +180,7 @@ float Ray::Distance(const Vector3& v0, const Vector3& v1, const Vector3& v2) con
     return M_INFINITY;
     return M_INFINITY;
 }
 }
 
 
-float Ray::Distance(const void* vertexData, unsigned vertexSize, const void* indexData, unsigned indexSize, unsigned indexStart, unsigned indexCount) const
+float Ray::HitDistance(const void* vertexData, unsigned vertexSize, const void* indexData, unsigned indexSize, unsigned indexStart, unsigned indexCount) const
 {
 {
     float nearest = M_INFINITY;
     float nearest = M_INFINITY;
     const unsigned char* vertices = (const unsigned char*)vertexData;
     const unsigned char* vertices = (const unsigned char*)vertexData;
@@ -76,7 +195,7 @@ float Ray::Distance(const void* vertexData, unsigned vertexSize, const void* ind
             const Vector3& v0 = *((const Vector3*)(&vertices[indices[i] * vertexSize]));
             const Vector3& v0 = *((const Vector3*)(&vertices[indices[i] * vertexSize]));
             const Vector3& v1 = *((const Vector3*)(&vertices[indices[i + 1] * vertexSize]));
             const Vector3& v1 = *((const Vector3*)(&vertices[indices[i + 1] * vertexSize]));
             const Vector3& v2 = *((const Vector3*)(&vertices[indices[i + 2] * vertexSize]));
             const Vector3& v2 = *((const Vector3*)(&vertices[indices[i + 2] * vertexSize]));
-            nearest = Min(nearest, Distance(v0, v1, v2));
+            nearest = Min(nearest, HitDistance(v0, v1, v2));
         }
         }
     }
     }
     // 32-bit indices
     // 32-bit indices
@@ -89,7 +208,7 @@ float Ray::Distance(const void* vertexData, unsigned vertexSize, const void* ind
             const Vector3& v0 = *((const Vector3*)(&vertices[indices[i] * vertexSize]));
             const Vector3& v0 = *((const Vector3*)(&vertices[indices[i] * vertexSize]));
             const Vector3& v1 = *((const Vector3*)(&vertices[indices[i + 1] * vertexSize]));
             const Vector3& v1 = *((const Vector3*)(&vertices[indices[i + 1] * vertexSize]));
             const Vector3& v2 = *((const Vector3*)(&vertices[indices[i + 2] * vertexSize]));
             const Vector3& v2 = *((const Vector3*)(&vertices[indices[i + 2] * vertexSize]));
-            nearest = Min(nearest, Distance(v0, v1, v2));
+            nearest = Min(nearest, HitDistance(v0, v1, v2));
         }
         }
     }
     }
     
     

+ 14 - 4
Engine/Math/Ray.h

@@ -25,6 +25,10 @@
 
 
 #include "Vector3.h"
 #include "Vector3.h"
 
 
+class BoundingBox;
+class Plane;
+class Sphere;
+
 /// Infinite straight line in three-dimensional space.
 /// Infinite straight line in three-dimensional space.
 class Ray
 class Ray
 {
 {
@@ -70,10 +74,16 @@ public:
     
     
     /// Project a point on the ray.
     /// Project a point on the ray.
     Vector3 Project(const Vector3& point) const;
     Vector3 Project(const Vector3& point) const;
-    /// Return minimum distance to a triangle, or infinity if no hit.
-    float Distance(const Vector3& v0, const Vector3& v1, const Vector3& v2) const;
-    /// Return minimum distance to a triangle mesh defined by vertex and index data.
-    float Distance(const void* vertexData, unsigned vertexSize, const void* indexData, unsigned indexSize, unsigned indexStart, unsigned indexCount) const;
+    /// Return hit distance to a plane, or infinity if no hit.
+    float HitDistance(const Plane& plane) const;
+    /// Return hit distance to a sphere, or infinity if no hit.
+    float HitDistance(const Sphere& sphere) const;
+    /// Return hit distance to a bounding box, or infinity if no hit.
+    float HitDistance(const BoundingBox& box) const;
+    /// Return hit distance to a triangle, or infinity if no hit.
+    float HitDistance(const Vector3& v0, const Vector3& v1, const Vector3& v2) const;
+    /// Return hit distance to a triangle mesh defined by vertex and index data, or infinity if no hit.
+    float HitDistance(const void* vertexData, unsigned vertexSize, const void* indexData, unsigned indexSize, unsigned indexStart, unsigned indexCount) const;
     
     
     /// Ray origin.
     /// Ray origin.
     Vector3 origin_;
     Vector3 origin_;

+ 0 - 28
Engine/Math/Sphere.cpp

@@ -235,31 +235,3 @@ Intersection Sphere::IsInsideFast(const BoundingBox& box) const
     else
     else
         return INSIDE;
         return INSIDE;
 }
 }
-
-float Sphere::Distance(const Ray& ray) const
-{
-    Vector3 centeredOrigin = ray.origin_ - center_;
-    float squaredRadius = radius_ * radius_;
-    
-    // Check if ray originates inside the sphere
-    if (centeredOrigin.LengthSquared() <= squaredRadius)
-        return 0.0f;
-    
-    // Calculate intersection by quadratic equation
-    float a = ray.direction_.DotProduct(ray.direction_);
-    float b = 2.0f * centeredOrigin.DotProduct(ray.direction_);
-    float c = centeredOrigin.DotProduct(centeredOrigin) - squaredRadius;
-    float d = b * b - 4.0f * a * c;
-    
-    // No solution
-    if (d < 0.0f)
-        return M_INFINITY;
-    
-    // Get the nearer solution
-    float dSqrt = sqrtf(d);
-    float dist = (-b - dSqrt) / (2.0f * a);
-    if (dist >= 0.0f)
-        return dist;
-    else
-        return (-b + dSqrt) / (2.0f * a);
-}

+ 0 - 3
Engine/Math/Sphere.h

@@ -27,7 +27,6 @@
 
 
 class BoundingBox;
 class BoundingBox;
 class Frustum;
 class Frustum;
-class Ray;
 
 
 /// %Sphere in three-dimensional space.
 /// %Sphere in three-dimensional space.
 class Sphere
 class Sphere
@@ -153,8 +152,6 @@ public:
     Intersection IsInside(const BoundingBox& box) const;
     Intersection IsInside(const BoundingBox& box) const;
     /// Test if a bounding box is (partially) inside or outside.
     /// Test if a bounding box is (partially) inside or outside.
     Intersection IsInsideFast(const BoundingBox& box) const;
     Intersection IsInsideFast(const BoundingBox& box) const;
-    /// Return distance to a ray, or infinity if no intersection.
-    float Distance(const Ray& ray) const;
     
     
     /// Sphere center.
     /// Sphere center.
     Vector3 center_;
     Vector3 center_;

+ 13 - 13
Engine/Network/Connection.cpp

@@ -344,7 +344,7 @@ void Connection::ProcessPendingLatestData()
     for (HashMap<unsigned, PODVector<unsigned char> >::Iterator i = nodeLatestData_.Begin(); i != nodeLatestData_.End();)
     for (HashMap<unsigned, PODVector<unsigned char> >::Iterator i = nodeLatestData_.Begin(); i != nodeLatestData_.End();)
     {
     {
         HashMap<unsigned, PODVector<unsigned char> >::Iterator current = i++;
         HashMap<unsigned, PODVector<unsigned char> >::Iterator current = i++;
-        Node* node = scene_->GetNodeByID(current->first_);
+        Node* node = scene_->GetNode(current->first_);
         if (node)
         if (node)
         {
         {
             MemoryBuffer msg(current->second_);
             MemoryBuffer msg(current->second_);
@@ -358,7 +358,7 @@ void Connection::ProcessPendingLatestData()
     for (HashMap<unsigned, PODVector<unsigned char> >::Iterator i = componentLatestData_.Begin(); i != componentLatestData_.End();)
     for (HashMap<unsigned, PODVector<unsigned char> >::Iterator i = componentLatestData_.Begin(); i != componentLatestData_.End();)
     {
     {
         HashMap<unsigned, PODVector<unsigned char> >::Iterator current = i++;
         HashMap<unsigned, PODVector<unsigned char> >::Iterator current = i++;
-        Component* component = scene_->GetComponentByID(current->first_);
+        Component* component = scene_->GetComponent(current->first_);
         if (component)
         if (component)
         {
         {
             MemoryBuffer msg(current->second_);
             MemoryBuffer msg(current->second_);
@@ -497,7 +497,7 @@ void Connection::ProcessSceneUpdate(int msgID, MemoryBuffer& msg)
         {
         {
             unsigned nodeID = msg.ReadNetID();
             unsigned nodeID = msg.ReadNetID();
             // In case of the root node (scene), it should already exist. Do not create in that case
             // In case of the root node (scene), it should already exist. Do not create in that case
-            Node* node = scene_->GetNodeByID(nodeID);
+            Node* node = scene_->GetNode(nodeID);
             if (!node)
             if (!node)
             {
             {
                 // Add initially to the root level. May be moved as we receive the parent attribute
                 // Add initially to the root level. May be moved as we receive the parent attribute
@@ -532,7 +532,7 @@ void Connection::ProcessSceneUpdate(int msgID, MemoryBuffer& msg)
                 unsigned componentID = msg.ReadNetID();
                 unsigned componentID = msg.ReadNetID();
                 
                 
                 // Check if the component by this ID and type already exists in this node
                 // Check if the component by this ID and type already exists in this node
-                Component* component = scene_->GetComponentByID(componentID);
+                Component* component = scene_->GetComponent(componentID);
                 if (!component || component->GetType() != type || component->GetNode() != node)
                 if (!component || component->GetType() != type || component->GetNode() != node)
                 {
                 {
                     if (component)
                     if (component)
@@ -557,7 +557,7 @@ void Connection::ProcessSceneUpdate(int msgID, MemoryBuffer& msg)
     case MSG_NODEDELTAUPDATE:
     case MSG_NODEDELTAUPDATE:
         {
         {
             unsigned nodeID = msg.ReadNetID();
             unsigned nodeID = msg.ReadNetID();
-            Node* node = scene_->GetNodeByID(nodeID);
+            Node* node = scene_->GetNode(nodeID);
             if (node)
             if (node)
             {
             {
                 node->ReadDeltaUpdate(msg, deltaUpdateBits_);
                 node->ReadDeltaUpdate(msg, deltaUpdateBits_);
@@ -580,7 +580,7 @@ void Connection::ProcessSceneUpdate(int msgID, MemoryBuffer& msg)
     case MSG_NODELATESTDATA:
     case MSG_NODELATESTDATA:
         {
         {
             unsigned nodeID = msg.ReadNetID();
             unsigned nodeID = msg.ReadNetID();
-            Node* node = scene_->GetNodeByID(nodeID);
+            Node* node = scene_->GetNode(nodeID);
             if (node)
             if (node)
                 node->ReadLatestDataUpdate(msg);
                 node->ReadLatestDataUpdate(msg);
             else
             else
@@ -596,7 +596,7 @@ void Connection::ProcessSceneUpdate(int msgID, MemoryBuffer& msg)
     case MSG_REMOVENODE:
     case MSG_REMOVENODE:
         {
         {
             unsigned nodeID = msg.ReadNetID();
             unsigned nodeID = msg.ReadNetID();
-            Node* node = scene_->GetNodeByID(nodeID);
+            Node* node = scene_->GetNode(nodeID);
             if (node)
             if (node)
                 node->Remove();
                 node->Remove();
             nodeLatestData_.Erase(nodeID);
             nodeLatestData_.Erase(nodeID);
@@ -606,14 +606,14 @@ void Connection::ProcessSceneUpdate(int msgID, MemoryBuffer& msg)
     case MSG_CREATECOMPONENT:
     case MSG_CREATECOMPONENT:
         {
         {
             unsigned nodeID = msg.ReadNetID();
             unsigned nodeID = msg.ReadNetID();
-            Node* node = scene_->GetNodeByID(nodeID);
+            Node* node = scene_->GetNode(nodeID);
             if (node)
             if (node)
             {
             {
                 ShortStringHash type = msg.ReadShortStringHash();
                 ShortStringHash type = msg.ReadShortStringHash();
                 unsigned componentID = msg.ReadNetID();
                 unsigned componentID = msg.ReadNetID();
                 
                 
                 // Check if the component by this ID and type already exists in this node
                 // Check if the component by this ID and type already exists in this node
-                Component* component = scene_->GetComponentByID(componentID);
+                Component* component = scene_->GetComponent(componentID);
                 if (!component || component->GetType() != type || component->GetNode() != node)
                 if (!component || component->GetType() != type || component->GetNode() != node)
                 {
                 {
                     if (component)
                     if (component)
@@ -640,7 +640,7 @@ void Connection::ProcessSceneUpdate(int msgID, MemoryBuffer& msg)
     case MSG_COMPONENTDELTAUPDATE:
     case MSG_COMPONENTDELTAUPDATE:
         {
         {
             unsigned componentID = msg.ReadNetID();
             unsigned componentID = msg.ReadNetID();
-            Component* component = scene_->GetComponentByID(componentID);
+            Component* component = scene_->GetComponent(componentID);
             if (component)
             if (component)
             {
             {
                 component->ReadDeltaUpdate(msg, deltaUpdateBits_);
                 component->ReadDeltaUpdate(msg, deltaUpdateBits_);
@@ -654,7 +654,7 @@ void Connection::ProcessSceneUpdate(int msgID, MemoryBuffer& msg)
     case MSG_COMPONENTLATESTDATA:
     case MSG_COMPONENTLATESTDATA:
         {
         {
             unsigned componentID = msg.ReadNetID();
             unsigned componentID = msg.ReadNetID();
-            Component* component = scene_->GetComponentByID(componentID);
+            Component* component = scene_->GetComponent(componentID);
             if (component)
             if (component)
             {
             {
                 component->ReadLatestDataUpdate(msg);
                 component->ReadLatestDataUpdate(msg);
@@ -673,7 +673,7 @@ void Connection::ProcessSceneUpdate(int msgID, MemoryBuffer& msg)
     case MSG_REMOVECOMPONENT:
     case MSG_REMOVECOMPONENT:
         {
         {
             unsigned componentID = msg.ReadNetID();
             unsigned componentID = msg.ReadNetID();
-            Component* component = scene_->GetComponentByID(componentID);
+            Component* component = scene_->GetComponent(componentID);
             if (component)
             if (component)
                 component->Remove();
                 component->Remove();
             componentLatestData_.Erase(componentID);
             componentLatestData_.Erase(componentID);
@@ -925,7 +925,7 @@ void Connection::ProcessRemoteEvent(int msgID, MemoryBuffer& msg)
         }
         }
         
         
         VariantMap eventData = msg.ReadVariantMap();
         VariantMap eventData = msg.ReadVariantMap();
-        Node* receiver = scene_->GetNodeByID(nodeID);
+        Node* receiver = scene_->GetNode(nodeID);
         if (!receiver)
         if (!receiver)
         {
         {
             LOGWARNING("Missing receiver for remote node event, discarding");
             LOGWARNING("Missing receiver for remote node event, discarding");

+ 5 - 5
Engine/Physics/CollisionShape.cpp

@@ -307,7 +307,7 @@ CollisionShape::CollisionShape(Context* context) :
     position_(Vector3::ZERO),
     position_(Vector3::ZERO),
     rotation_(Quaternion::IDENTITY),
     rotation_(Quaternion::IDENTITY),
     geometryScale_(Vector3::UNITY),
     geometryScale_(Vector3::UNITY),
-    collisionGroup_(M_MAX_UNSIGNED),
+    collisionLayer_(M_MAX_UNSIGNED),
     collisionMask_(M_MAX_UNSIGNED),
     collisionMask_(M_MAX_UNSIGNED),
     friction_(DEFAULT_FRICTION),
     friction_(DEFAULT_FRICTION),
     bounce_(DEFAULT_BOUNCE),
     bounce_(DEFAULT_BOUNCE),
@@ -334,7 +334,7 @@ void CollisionShape::RegisterObject(Context* context)
     ATTRIBUTE(CollisionShape, VAR_FLOAT, "Hull Thickness", thickness_, 0.0f, AM_DEFAULT);
     ATTRIBUTE(CollisionShape, VAR_FLOAT, "Hull Thickness", thickness_, 0.0f, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(CollisionShape, VAR_FLOAT, "Friction", GetFriction, SetFriction, float, DEFAULT_FRICTION, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(CollisionShape, VAR_FLOAT, "Friction", GetFriction, SetFriction, float, DEFAULT_FRICTION, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(CollisionShape, VAR_FLOAT, "Bounce", GetBounce, SetBounce, float, DEFAULT_BOUNCE, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(CollisionShape, VAR_FLOAT, "Bounce", GetBounce, SetBounce, float, DEFAULT_BOUNCE, AM_DEFAULT);
-    ACCESSOR_ATTRIBUTE(CollisionShape, VAR_INT, "Collision Group", GetCollisionGroup, SetCollisionGroup, unsigned, M_MAX_UNSIGNED, AM_DEFAULT);
+    ACCESSOR_ATTRIBUTE(CollisionShape, VAR_INT, "Collision Group", GetCollisionLayer, SetCollisionLayer, unsigned, M_MAX_UNSIGNED, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(CollisionShape, VAR_INT, "Collision Mask", GetCollisionMask, SetCollisionMask, unsigned, M_MAX_UNSIGNED, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(CollisionShape, VAR_INT, "Collision Mask", GetCollisionMask, SetCollisionMask, unsigned, M_MAX_UNSIGNED, AM_DEFAULT);
     ATTRIBUTE(CollisionShape, VAR_BOOL, "Is Phantom", phantom_, false, AM_DEFAULT);
     ATTRIBUTE(CollisionShape, VAR_BOOL, "Is Phantom", phantom_, false, AM_DEFAULT);
 }
 }
@@ -511,9 +511,9 @@ void CollisionShape::SetTransform(const Vector3& position, const Quaternion& rot
     UpdateTransform();
     UpdateTransform();
 }
 }
 
 
-void CollisionShape::SetCollisionGroup(unsigned group)
+void CollisionShape::SetCollisionLayer(unsigned group)
 {
 {
-    collisionGroup_ = group;
+    collisionLayer_ = group;
     if (geometry_)
     if (geometry_)
         dGeomSetCategoryBits(geometry_, group);
         dGeomSetCategoryBits(geometry_, group);
 }
 }
@@ -923,7 +923,7 @@ void CollisionShape::CreateGeometry()
     // Set collision group and mask & userdata
     // Set collision group and mask & userdata
     if (geometry_)
     if (geometry_)
     {
     {
-        dGeomSetCategoryBits(geometry_, collisionGroup_);
+        dGeomSetCategoryBits(geometry_, collisionLayer_);
         dGeomSetCollideBits(geometry_, collisionMask_);
         dGeomSetCollideBits(geometry_, collisionMask_);
         dGeomSetData(geometry_, this);
         dGeomSetData(geometry_, this);
     }
     }

+ 3 - 3
Engine/Physics/CollisionShape.h

@@ -127,7 +127,7 @@ public:
     /// %Set offset transform.
     /// %Set offset transform.
     void SetTransform(const Vector3& position, const Quaternion& rotation);
     void SetTransform(const Vector3& position, const Quaternion& rotation);
     /// %Set collision group bits.
     /// %Set collision group bits.
-    void SetCollisionGroup(unsigned group);
+    void SetCollisionLayer(unsigned group);
     /// %Set collision mask bits.
     /// %Set collision mask bits.
     void SetCollisionMask(unsigned mask);
     void SetCollisionMask(unsigned mask);
     /// %Set friction coefficient.
     /// %Set friction coefficient.
@@ -158,7 +158,7 @@ public:
     /// Return rotation.
     /// Return rotation.
     const Quaternion& GetRotation() const { return rotation_; }
     const Quaternion& GetRotation() const { return rotation_; }
     /// Return collision group bits.
     /// Return collision group bits.
-    unsigned GetCollisionGroup() const { return collisionGroup_; }
+    unsigned GetCollisionLayer() const { return collisionLayer_; }
     /// Return collision mask bits.
     /// Return collision mask bits.
     unsigned GetCollisionMask() const { return collisionMask_; }
     unsigned GetCollisionMask() const { return collisionMask_; }
     /// Return friction coefficient.
     /// Return friction coefficient.
@@ -215,7 +215,7 @@ private:
     /// Scene node scale used to create the geometry.
     /// Scene node scale used to create the geometry.
     Vector3 geometryScale_;
     Vector3 geometryScale_;
     /// Collision group bits.
     /// Collision group bits.
-    unsigned collisionGroup_;
+    unsigned collisionLayer_;
     /// Collision mask bits.
     /// Collision mask bits.
     unsigned collisionMask_;
     unsigned collisionMask_;
     /// Friction coefficient.
     /// Friction coefficient.

+ 2 - 2
Engine/Physics/Joint.cpp

@@ -260,14 +260,14 @@ Vector3 Joint::GetAxis() const
 void Joint::SetBodyAAttr(int value)
 void Joint::SetBodyAAttr(int value)
 {
 {
     Scene* scene = node_ ? node_->GetScene() : 0;
     Scene* scene = node_ ? node_->GetScene() : 0;
-    bodyA_ = scene ? dynamic_cast<RigidBody*>(scene->GetComponentByID(value)) : (RigidBody*)0;
+    bodyA_ = scene ? dynamic_cast<RigidBody*>(scene->GetComponent(value)) : (RigidBody*)0;
     recreateJoint_ = true;
     recreateJoint_ = true;
 }
 }
 
 
 void Joint::SetBodyBAttr(int value)
 void Joint::SetBodyBAttr(int value)
 {
 {
     Scene* scene = node_ ? node_->GetScene() : 0;
     Scene* scene = node_ ? node_->GetScene() : 0;
-    bodyB_ = scene ? dynamic_cast<RigidBody*>(scene->GetComponentByID(value)) : (RigidBody*)0;
+    bodyB_ = scene ? dynamic_cast<RigidBody*>(scene->GetComponent(value)) : (RigidBody*)0;
     recreateJoint_ = true;
     recreateJoint_ = true;
 }
 }
 
 

+ 1 - 0
Engine/Physics/PhysicsWorld.cpp

@@ -32,6 +32,7 @@
 #include "PhysicsWorld.h"
 #include "PhysicsWorld.h"
 #include "ProcessUtils.h"
 #include "ProcessUtils.h"
 #include "Profiler.h"
 #include "Profiler.h"
+#include "Ray.h"
 #include "RigidBody.h"
 #include "RigidBody.h"
 #include "Scene.h"
 #include "Scene.h"
 #include "SceneEvents.h"
 #include "SceneEvents.h"

+ 2 - 2
Engine/Scene/Component.cpp

@@ -61,9 +61,9 @@ bool Component::HasComponent(ShortStringHash type) const
     return node_ ? node_->HasComponent(type) : false;
     return node_ ? node_->HasComponent(type) : false;
 }
 }
 
 
-Component* Component::GetComponent(ShortStringHash type, unsigned index) const
+Component* Component::GetComponent(ShortStringHash type) const
 {
 {
-    return node_ ? node_->GetComponent(type, index) : 0;
+    return node_ ? node_->GetComponent(type) : 0;
 }
 }
 
 
 void Component::GetComponents(PODVector<Component*>& dest, ShortStringHash type) const
 void Component::GetComponents(PODVector<Component*>& dest, ShortStringHash type) const

+ 4 - 4
Engine/Scene/Component.h

@@ -67,12 +67,12 @@ public:
     
     
     /// Return components in the same scene node by type.
     /// Return components in the same scene node by type.
     void GetComponents(PODVector<Component*>& dest, ShortStringHash type) const;
     void GetComponents(PODVector<Component*>& dest, ShortStringHash type) const;
-    /// Return component in the same scene node by type. The optional index allows to specify which component, if there are several.
-    Component* GetComponent(ShortStringHash type, unsigned index = 0) const;
+    /// Return component in the same scene node by type. If there are several, returns the first.
+    Component* GetComponent(ShortStringHash type) const;
     /// Return whether the same scene node has a specific component.
     /// Return whether the same scene node has a specific component.
     bool HasComponent(ShortStringHash type) const;
     bool HasComponent(ShortStringHash type) const;
     /// Template version of returning a component in the same scene node by type.
     /// Template version of returning a component in the same scene node by type.
-    template <class T> T* GetComponent(unsigned index = 0) const;
+    template <class T> T* GetComponent() const;
     /// Template version of returning components in the same scene node by type.
     /// Template version of returning components in the same scene node by type.
     template <class T> void GetComponents(PODVector<T*>& dest) const;
     template <class T> void GetComponents(PODVector<T*>& dest) const;
     
     
@@ -88,5 +88,5 @@ protected:
     Node* node_;
     Node* node_;
 };
 };
 
 
-template <class T> T* Component::GetComponent(unsigned index) const { return static_cast<T*>(GetComponent(T::GetTypeStatic(), index)); }
+template <class T> T* Component::GetComponent() const { return static_cast<T*>(GetComponent(T::GetTypeStatic())); }
 template <class T> void Component::GetComponents(PODVector<T*>& dest) const { GetComponents(reinterpret_cast<PODVector<Component*>&>(dest), T::GetTypeStatic()); }
 template <class T> void Component::GetComponents(PODVector<T*>& dest) const { GetComponents(reinterpret_cast<PODVector<Component*>&>(dest), T::GetTypeStatic()); }

+ 3 - 14
Engine/Scene/Node.cpp

@@ -699,24 +699,13 @@ bool Node::HasComponent(ShortStringHash type) const
     return false;
     return false;
 }
 }
 
 
-Component* Node::GetComponent(unsigned index) const
+Component* Node::GetComponent(ShortStringHash type) const
 {
 {
-    return index < components_.Size() ? components_[index].Get() : 0;
-}
-
-Component* Node::GetComponent(ShortStringHash type, unsigned index) const
-{
-    unsigned cmpIndex = 0;
     for (Vector<SharedPtr<Component> >::ConstIterator i = components_.Begin(); i != components_.End(); ++i)
     for (Vector<SharedPtr<Component> >::ConstIterator i = components_.Begin(); i != components_.End(); ++i)
     {
     {
         if ((*i)->GetType() == type)
         if ((*i)->GetType() == type)
-        {
-            if (cmpIndex == index)
-                return *i;
-            ++cmpIndex;
-        }
+            return *i;
     }
     }
-    
     return 0;
     return 0;
 }
 }
 
 
@@ -767,7 +756,7 @@ void Node::SetNetParentAttr(const PODVector<unsigned char>& value)
     }
     }
     
     
     unsigned baseNodeID = buf.ReadNetID();
     unsigned baseNodeID = buf.ReadNetID();
-    Node* baseNode = scene->GetNodeByID(baseNodeID);
+    Node* baseNode = scene->GetNode(baseNodeID);
     if (!baseNode)
     if (!baseNode)
     {
     {
         LOGWARNING("Failed to find parent node " + String(baseNodeID));
         LOGWARNING("Failed to find parent node " + String(baseNodeID));

+ 4 - 6
Engine/Scene/Node.h

@@ -253,10 +253,8 @@ public:
     const Vector<SharedPtr<Component> >& GetComponents() const { return components_; }
     const Vector<SharedPtr<Component> >& GetComponents() const { return components_; }
     /// Return all components of type.
     /// Return all components of type.
     void GetComponents(PODVector<Component*>& dest, ShortStringHash type) const;
     void GetComponents(PODVector<Component*>& dest, ShortStringHash type) const;
-    /// Return component by index.
-    Component* GetComponent(unsigned index) const;
-    /// Return component by type. The optional index allows to specify which component, if there are several.
-    Component* GetComponent(ShortStringHash type, unsigned index = 0) const;
+    /// Return component by type. If there are several, returns the first.
+    Component* GetComponent(ShortStringHash type) const;
     /// Return whether has a specific component.
     /// Return whether has a specific component.
     bool HasComponent(ShortStringHash type) const;
     bool HasComponent(ShortStringHash type) const;
     /// Return listener components.
     /// Return listener components.
@@ -268,7 +266,7 @@ public:
     /// Template version of returning child nodes with a specific component.
     /// Template version of returning child nodes with a specific component.
     template <class T> void GetChildrenWithComponent(PODVector<Node*>& dest, bool recursive = false) const;
     template <class T> void GetChildrenWithComponent(PODVector<Node*>& dest, bool recursive = false) const;
     /// Template version of returning a component by type.
     /// Template version of returning a component by type.
-    template <class T> T* GetComponent(unsigned index = 0) const;
+    template <class T> T* GetComponent() const;
     /// Template version of returning all components of type.
     /// Template version of returning all components of type.
     template <class T> void GetComponents(PODVector<T*>& dest) const;
     template <class T> void GetComponents(PODVector<T*>& dest) const;
     /// Template version of checking whether has a specific component.
     /// Template version of checking whether has a specific component.
@@ -357,6 +355,6 @@ private:
 template <class T> T* Node::CreateComponent(CreateMode mode) { return static_cast<T*>(CreateComponent(T::GetTypeStatic(), mode)); }
 template <class T> T* Node::CreateComponent(CreateMode mode) { return static_cast<T*>(CreateComponent(T::GetTypeStatic(), mode)); }
 template <class T> T* Node::GetOrCreateComponent(CreateMode mode) { return static_cast<T*>(GetOrCreateComponent(T::GetTypeStatic(), mode)); }
 template <class T> T* Node::GetOrCreateComponent(CreateMode mode) { return static_cast<T*>(GetOrCreateComponent(T::GetTypeStatic(), mode)); }
 template <class T> void Node::GetChildrenWithComponent(PODVector<Node*>& dest, bool recursive) const { GetChildrenWithComponent(dest, T::GetTypeStatic(), recursive); }
 template <class T> void Node::GetChildrenWithComponent(PODVector<Node*>& dest, bool recursive) const { GetChildrenWithComponent(dest, T::GetTypeStatic(), recursive); }
-template <class T> T* Node::GetComponent(unsigned index) const { return static_cast<T*>(GetComponent(T::GetTypeStatic(), index)); }
+template <class T> T* Node::GetComponent() const { return static_cast<T*>(GetComponent(T::GetTypeStatic())); }
 template <class T> void Node::GetComponents(PODVector<T*>& dest) const { GetComponents(reinterpret_cast<PODVector<Component*>&>(dest), T::GetTypeStatic()); }
 template <class T> void Node::GetComponents(PODVector<T*>& dest) const { GetComponents(reinterpret_cast<PODVector<Component*>&>(dest), T::GetTypeStatic()); }
 template <class T> bool Node::HasComponent() const { return HasComponent(T::GetTypeStatic()); }
 template <class T> bool Node::HasComponent() const { return HasComponent(T::GetTypeStatic()); }

+ 2 - 2
Engine/Scene/Scene.cpp

@@ -323,7 +323,7 @@ void Scene::UnregisterAllVars()
     varNames_.Clear();
     varNames_.Clear();
 }
 }
 
 
-Node* Scene::GetNodeByID(unsigned id) const
+Node* Scene::GetNode(unsigned id) const
 {
 {
     Map<unsigned, Node*>::ConstIterator i = allNodes_.Find(id);
     Map<unsigned, Node*>::ConstIterator i = allNodes_.Find(id);
     if (i != allNodes_.End())
     if (i != allNodes_.End())
@@ -332,7 +332,7 @@ Node* Scene::GetNodeByID(unsigned id) const
         return 0;
         return 0;
 }
 }
 
 
-Component* Scene::GetComponentByID(unsigned id) const
+Component* Scene::GetComponent(unsigned id) const
 {
 {
     Map<unsigned, Component*>::ConstIterator i = allComponents_.Find(id);
     Map<unsigned, Component*>::ConstIterator i = allComponents_.Find(id);
     if (i != allComponents_.End())
     if (i != allComponents_.End())

+ 3 - 2
Engine/Scene/Scene.h

@@ -54,6 +54,7 @@ class Scene : public Node
 {
 {
     OBJECT(Scene);
     OBJECT(Scene);
     
     
+    using Node::GetComponent;
     using Node::SaveXML;
     using Node::SaveXML;
     
     
 public:
 public:
@@ -103,9 +104,9 @@ public:
     void UnregisterAllVars();
     void UnregisterAllVars();
     
     
     /// Return node from the whole scene by ID, or null if not found.
     /// Return node from the whole scene by ID, or null if not found.
-    Node* GetNodeByID(unsigned id) const;
+    Node* GetNode(unsigned id) const;
     /// Return component from the whole scene by ID, or null if not found.
     /// Return component from the whole scene by ID, or null if not found.
-    Component* GetComponentByID(unsigned id) const;
+    Component* GetComponent(unsigned id) const;
     /// Return active flag.
     /// Return active flag.
     bool IsActive() const { return active_; }
     bool IsActive() const { return active_; }
     /// Return asynchronous loading flag.
     /// Return asynchronous loading flag.

+ 5 - 5
Tools/AssetImporter/AssetImporter.cpp

@@ -149,7 +149,7 @@ void WriteVertex(float*& dest, aiMesh* mesh, unsigned index, unsigned elementMas
     Vector<PODVector<float> >& blendWeights);
     Vector<PODVector<float> >& blendWeights);
 unsigned GetElementMask(aiMesh* mesh);
 unsigned GetElementMask(aiMesh* mesh);
 
 
-aiNode* FindNode(const String& name, aiNode* rootNode, bool caseSensitive = true);
+aiNode* GetNode(const String& name, aiNode* rootNode, bool caseSensitive = true);
 aiMatrix4x4 GetDerivedTransform(aiNode* node, aiNode* rootNode);
 aiMatrix4x4 GetDerivedTransform(aiNode* node, aiNode* rootNode);
 aiMatrix4x4 GetDerivedTransform(aiMatrix4x4 transform, aiNode* node, aiNode* rootNode);
 aiMatrix4x4 GetDerivedTransform(aiMatrix4x4 transform, aiNode* node, aiNode* rootNode);
 aiMatrix4x4 GetMeshBakingTransform(aiNode* meshNode, aiNode* modelRootNode);
 aiMatrix4x4 GetMeshBakingTransform(aiNode* meshNode, aiNode* modelRootNode);
@@ -327,7 +327,7 @@ void Run(const Vector<String>& arguments)
         rootNode_ = scene_->mRootNode;
         rootNode_ = scene_->mRootNode;
         if (!rootNodeName.Empty())
         if (!rootNodeName.Empty())
         {
         {
-            rootNode_ = FindNode(rootNodeName, rootNode_, false);
+            rootNode_ = GetNode(rootNodeName, rootNode_, false);
             if (!rootNode_)
             if (!rootNode_)
                 ErrorExit("Could not find scene node " + rootNodeName);
                 ErrorExit("Could not find scene node " + rootNodeName);
         }
         }
@@ -491,7 +491,7 @@ void CollectBones(OutModel& model)
         {
         {
             aiBone* bone = mesh->mBones[j];
             aiBone* bone = mesh->mBones[j];
             String boneName(FromAIString(bone->mName));
             String boneName(FromAIString(bone->mName));
-            aiNode* boneNode = FindNode(boneName, scene_->mRootNode, true);
+            aiNode* boneNode = GetNode(boneName, scene_->mRootNode, true);
             if (!boneNode)
             if (!boneNode)
                 ErrorExit("Could not find scene node for bone " + boneName);
                 ErrorExit("Could not find scene node for bone " + boneName);
             necessary.Insert(boneNode);
             necessary.Insert(boneNode);
@@ -1571,7 +1571,7 @@ unsigned GetElementMask(aiMesh* mesh)
     return elementMask;
     return elementMask;
 }
 }
 
 
-aiNode* FindNode(const String& name, aiNode* rootNode, bool caseSensitive)
+aiNode* GetNode(const String& name, aiNode* rootNode, bool caseSensitive)
 {
 {
     if (!rootNode)
     if (!rootNode)
         return 0;
         return 0;
@@ -1579,7 +1579,7 @@ aiNode* FindNode(const String& name, aiNode* rootNode, bool caseSensitive)
         return rootNode;
         return rootNode;
     for (unsigned i = 0; i < rootNode->mNumChildren; ++i)
     for (unsigned i = 0; i < rootNode->mNumChildren; ++i)
     {
     {
-        aiNode* found = FindNode(name, rootNode->mChildren[i], caseSensitive);
+        aiNode* found = GetNode(name, rootNode->mChildren[i], caseSensitive);
         if (found)
         if (found)
             return found;
             return found;
     }
     }