Browse Source

Urho3D Editor: Spawn on selected node in Spawn Editor

Vladimir 10 years ago
parent
commit
bf34fc8afb
2 changed files with 102 additions and 4 deletions
  1. 88 4
      bin/Data/Scripts/Editor/EditorSpawn.as
  2. 14 0
      bin/Data/UI/EditorSpawnWindow.xml

+ 88 - 4
bin/Data/Scripts/Editor/EditorSpawn.as

@@ -21,7 +21,7 @@ uint spawnCount = 1;
 float spawnRadius = 0;
 bool useNormal = true;
 bool alignToAABBBottom = true;
-
+bool spawnOnSelection = false;
 uint numberSpawnedObjects = 1;
 Array<String> spawnedObjectsNames;
 
@@ -61,6 +61,8 @@ void CreateSpawnEditor()
     useNormalToggle.checked = useNormal;
     CheckBox@ alignToAABBBottomToggle = spawnWindow.GetChild("AlignToAABBBottom", true);
     alignToAABBBottomToggle.checked = alignToAABBBottom;
+    CheckBox@ spawnOnSelectionToggle = spawnWindow.GetChild("SpawnOnSelected", true);
+    spawnOnSelectionToggle.checked = spawnOnSelection;    
 
     numberSpawnedObjectsEdit = spawnWindow.GetChild("NumberSpawnedObjects", true);
     numberSpawnedObjectsEdit.text = String(numberSpawnedObjects);
@@ -82,6 +84,7 @@ void CreateSpawnEditor()
     SubscribeToEvent(spawnCountEdit, "TextChanged", "EditSpawnCount");
     SubscribeToEvent(useNormalToggle, "Toggled", "ToggleUseNormal");
     SubscribeToEvent(alignToAABBBottomToggle, "Toggled", "ToggleAlignToAABBBottom");
+    SubscribeToEvent(spawnOnSelectionToggle, "Toggled", "ToggleSpawnOnSelected");
     SubscribeToEvent(numberSpawnedObjectsEdit, "TextFinished", "UpdateNumberSpawnedObjects");
     SubscribeToEvent(spawnWindow.GetChild("SetSpawnMode", true), "Released", "SetSpawnMode");
     RefreshPickedObjects();
@@ -152,6 +155,11 @@ void ToggleAlignToAABBBottom(StringHash eventType, VariantMap& eventData)
     alignToAABBBottom = cast<CheckBox>(eventData["Element"].GetPtr()).checked;
 }
 
+void ToggleSpawnOnSelected(StringHash eventType, VariantMap& eventData)
+{
+    spawnOnSelection = cast<CheckBox>(eventData["Element"].GetPtr()).checked;
+}
+
 void UpdateNumberSpawnedObjects(StringHash eventType, VariantMap& eventData)
 {
     LineEdit@ edit = eventData["Element"].GetPtr();
@@ -333,6 +341,69 @@ bool GetSpawnPosition(const Ray&in cameraRay, float maxDistance, Vector3&out pos
     return allowNoHit;
 }
 
+bool GetSpawnPositionOnNode(const Ray&in cameraRay, float maxDistance, Vector3&out position, Vector3&out normal, Node@ node, float randomRadius = 0.0,
+    bool allowNoHit = true)
+{
+    if (pickMode < PICK_RIGIDBODIES && editorScene.octree !is null)
+    {
+        Array<RayQueryResult> results = editorScene.octree.Raycast(cameraRay, RAY_TRIANGLE, maxDistance, DRAWABLE_GEOMETRY, 0x7fffffff);
+        
+        if (!results.empty)
+        {
+            RayQueryResult result = results[0];
+
+            for(int i=0; i<results.length; i++)
+            {
+                if (results[i].node.id == node.id)
+                {
+                    result = results[i];
+                    break;
+                }
+            }
+
+            if (randomRadius > 0)
+            {
+                Vector3 basePosition = RandomizeSpawnPosition(result.position, randomRadius);
+                basePosition.y += randomRadius;
+                Array<RayQueryResult> randomResults = editorScene.octree.Raycast(Ray(basePosition, Vector3(0, -1, 0)), RAY_TRIANGLE, randomRadius * 2.0, DRAWABLE_GEOMETRY, 0x7fffffff);
+
+                if (randomResults.length == 0)
+                {
+                    position = result.position;
+                    normal = result.normal;
+                    return true;
+                }
+
+                result = randomResults[0];
+
+                // find node in results
+                for(int i=0; i<randomResults.length; i++)
+                {
+                    if (randomResults[i].node.id == node.id)
+                    {
+                        result = randomResults[i];
+                        break;
+                    }
+                }
+
+                position = result.position;
+                normal = result.normal;
+                return true;
+            }
+            else
+            {
+                position = result.position;
+                normal = result.normal;
+                return true;
+            }
+        }
+    }
+
+    position = cameraRay.origin + cameraRay.direction * maxDistance;
+    normal = Vector3(0, 1, 0);
+    return allowNoHit;
+}
+
 Vector3 RandomizeSpawnPosition(const Vector3&in position, float randomRadius)
 {
     float angle = Random() * 360.0;
@@ -342,16 +413,29 @@ Vector3 RandomizeSpawnPosition(const Vector3&in position, float randomRadius)
 
 void SpawnObject()
 {
+    Node@ selectedNode = null;
+    
+    if (spawnOnSelection)
+    if (selectedNodes.length > 0)
+        selectedNode = selectedNodes[0];
+        
     if (spawnedObjectsNames.length == 0)
         return;
+        
     IntRect view = activeViewport.viewport.rect;
-
+    
     for (uint i = 0; i < spawnCount; ++i)
     {
         Ray cameraRay = GetActiveViewportCameraRay();
-
         Vector3 position, normal;
-        if (GetSpawnPosition(cameraRay, camera.farClip, position, normal, spawnRadius, false))
+        bool result = false;
+        
+        if (spawnOnSelection && selectedNode != null)
+            result = GetSpawnPositionOnNode(cameraRay, camera.farClip, position, normal, selectedNode, spawnRadius, false);
+        else
+            result = GetSpawnPosition(cameraRay, camera.farClip, position, normal, spawnRadius, false);        
+        
+        if (result)
             PlaceObject(position, normal);
     }
 }

+ 14 - 0
bin/Data/UI/EditorSpawnWindow.xml

@@ -228,6 +228,20 @@
 						<attribute name="Text" value="Align to AABB bottom" />
 					</element>
 				</element>
+				<element style="ListRow">
+					<attribute name="Min Size" value="200 17" />
+					<attribute name="Layout Spacing" value="8" />
+					<element type="CheckBox">
+						<attribute name="Name" value="SpawnOnSelected" />
+					</element>
+					<element type="Text">
+						<attribute name="Top Left Color" value="0.85 0.85 0.85 1" />
+						<attribute name="Top Right Color" value="0.85 0.85 0.85 1" />
+						<attribute name="Bottom Left Color" value="0.85 0.85 0.85 1" />
+						<attribute name="Bottom Right Color" value="0.85 0.85 0.85 1" />
+						<attribute name="Text" value="Spawn on selected node" />
+					</element>
+				</element>
 				<element style="ListRow">
 					<attribute name="Min Size" value="220 17" />
 					<attribute name="Layout Spacing" value="20" />