From 55d7d842bbe2bea202c6df1289d7f8f9a5e9e501 Mon Sep 17 00:00:00 2001 From: James Date: Mon, 10 Apr 2023 10:10:30 -0400 Subject: [PATCH 1/3] Add search methods to SceneGraph --- .../mundus/commons/scene3d/GameObject.java | 68 +++++++ .../mundus/commons/scene3d/SceneGraph.java | 42 ++++ .../mundus/commons/utils/LightUtils.java | 2 + .../mundus/commons/SceneGraphTest.java | 187 ++++++++++++++++++ .../mundus/commons/test/SceneGraphTest.java | 52 ----- 5 files changed, 299 insertions(+), 52 deletions(-) create mode 100644 commons/src/test/com/mbrlabs/mundus/commons/SceneGraphTest.java delete mode 100644 commons/src/test/com/mbrlabs/mundus/commons/test/SceneGraphTest.java diff --git a/commons/src/main/com/mbrlabs/mundus/commons/scene3d/GameObject.java b/commons/src/main/com/mbrlabs/mundus/commons/scene3d/GameObject.java index 90bb39ee6..89393653f 100644 --- a/commons/src/main/com/mbrlabs/mundus/commons/scene3d/GameObject.java +++ b/commons/src/main/com/mbrlabs/mundus/commons/scene3d/GameObject.java @@ -300,6 +300,74 @@ public void isComponentAddable(Component component) throws InvalidComponentExcep } } + /** + * Returns the first child GameObject matching the name. + * + * @param name the GameObject name to search for + * @return the first GameObject found or null if not found + */ + public GameObject findChildByName(String name) { + for (GameObject go : this) { + if (go.name.equals(name)) { + return go; + } + } + + return null; + } + + /** + * Returns an Array of all child GameObjects matching the name. + * + * @param name the GameObject name to search for + * @return Array of all matching GameObjects + */ + public Array findChildrenByName(String name) { + Array objects = new Array<>(); + for (GameObject go : this) { + if (go.name.equals(name)) { + objects.add(go); + } + } + + return objects; + } + + /** + * Returns an Array of all child GameObjects that have the given Component.Type + * + * @param type the Component Type to search for + * @return Array of all matching GameObjects + */ + public Array findChildrenByComponent(Component.Type type) { + Array objects = new Array<>(); + for (GameObject go : this) { + Component component = go.findComponentByType(type); + if (component != null) { + objects.add(go); + } + } + + return objects; + } + + /** + * Returns an Array of all child GameObjects that have the given Tag + * + * @param tag the string tag to search for + * @return Array of all matching GameObjects + */ + public Array findChildrenByTag(String tag) { + Array objects = new Array<>(); + for (GameObject go : this) { + if (go.tags != null && go.tags.contains(tag, false)) { + objects.add(go); + } + } + + return objects; + } + @Override public void addChild(GameObject child) { super.addChild(child); diff --git a/commons/src/main/com/mbrlabs/mundus/commons/scene3d/SceneGraph.java b/commons/src/main/com/mbrlabs/mundus/commons/scene3d/SceneGraph.java index dba1eae5f..bb22e1292 100644 --- a/commons/src/main/com/mbrlabs/mundus/commons/scene3d/SceneGraph.java +++ b/commons/src/main/com/mbrlabs/mundus/commons/scene3d/SceneGraph.java @@ -153,6 +153,48 @@ private int getNextId() { return maxId + 1; } + /** + * Returns the first GameObject in the scene matching the name. + * + * @param name the GameObject name to search for + * @return the first GameObject found or null if not found + */ + public GameObject findByName(String name) { + return root.findChildByName(name); + } + + /** + * Returns an Array of all GameObjects in the scene matching the name. + * Traversing the scene can be expensive, cache these results if you need them often. + * + * @param name the GameObject name to search for + * @return Array of all matching GameObjects + */ + public Array findAllByName(String name) { + return root.findChildrenByName(name); + } + + /** + * Returns an Array of all GameObjects in the scene that have the given Component.Type + * Traversing the scene can be expensive, cache these results if you need them often. + * + * @param type the Component Type to search for + * @return Array of all matching GameObjects + */ + public Array findAllByComponent(Component.Type type) { + return root.findChildrenByComponent(type); + } + + /** + * Returns an Array of all scene GameObjects that have the given Tag + * + * @param tag the string tag to search for + * @return Array of all matching GameObjects + */ + public Array findAllByTag(String tag) { + return root.findChildrenByTag(tag); + } + public GameObject getRoot() { return root; } diff --git a/commons/src/main/com/mbrlabs/mundus/commons/utils/LightUtils.java b/commons/src/main/com/mbrlabs/mundus/commons/utils/LightUtils.java index add8225bd..63a989386 100644 --- a/commons/src/main/com/mbrlabs/mundus/commons/utils/LightUtils.java +++ b/commons/src/main/com/mbrlabs/mundus/commons/utils/LightUtils.java @@ -21,6 +21,8 @@ public class LightUtils { */ public static DirectionalLight getDirectionalLight(Environment env) { DirectionalLightsAttribute dirLightAttribs = env.get(DirectionalLightsAttribute.class, DirectionalLightsAttribute.Type); + if (dirLightAttribs == null) return null; + Array dirLights = dirLightAttribs.lights; if (dirLights != null && dirLights.size > 0) { return dirLights.first(); diff --git a/commons/src/test/com/mbrlabs/mundus/commons/SceneGraphTest.java b/commons/src/test/com/mbrlabs/mundus/commons/SceneGraphTest.java new file mode 100644 index 000000000..9975192c4 --- /dev/null +++ b/commons/src/test/com/mbrlabs/mundus/commons/SceneGraphTest.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2016. See AUTHORS file. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mbrlabs.mundus.commons; + +import com.badlogic.gdx.utils.Array; +import com.mbrlabs.mundus.commons.env.MundusEnvironment; +import com.mbrlabs.mundus.commons.scene3d.GameObject; +import com.mbrlabs.mundus.commons.scene3d.InvalidComponentException; +import com.mbrlabs.mundus.commons.scene3d.Node; +import com.mbrlabs.mundus.commons.scene3d.SceneGraph; +import com.mbrlabs.mundus.commons.scene3d.SimpleNode; + +import com.mbrlabs.mundus.commons.scene3d.components.Component; +import com.mbrlabs.mundus.commons.scene3d.components.ModelComponent; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +/** + * @author Marcus Brummer + * @version 21-06-2016 + */ +public class SceneGraphTest { + + @Test + public void basicParenting() { + Node root = new SimpleNode<>(0); + Assert.assertNull(root.getChildren()); + + SimpleNode c0 = new SimpleNode<>(1); + root.addChild(c0); + Assert.assertEquals(1, root.getChildren().size); + Assert.assertSame(root.getChildren().first(), c0); + Assert.assertSame(root, c0.getParent()); + + SimpleNode c1 = new SimpleNode<>(2); + root.addChild(c1); + Assert.assertEquals(2, root.getChildren().size); + Assert.assertSame(root, c0.getParent()); + + c0.remove(); + Assert.assertEquals(1, root.getChildren().size); + Assert.assertNull(c0.getParent()); + } + + @Test + public void gameObjectFindByName() { + SceneGraph sceneGraph = new SceneGraph(null); + + // The GO to search for + String searchName = "SearchName"; + GameObject searchObject = new GameObject(sceneGraph, searchName, -1); + + // Parent GO + GameObject parent = new GameObject(sceneGraph, "Parent", -1); + parent.addChild(searchObject); + + sceneGraph.addGameObject(parent); + + GameObject result = sceneGraph.findByName(searchName); + Assert.assertNotNull(result); + Assert.assertEquals(searchName, result.name); + } + + @Test + public void gameObjectsFindByName() { + SceneGraph sceneGraph = new SceneGraph(null); + + // The GO's to search for + String searchName = "SearchName"; + GameObject searchObject = new GameObject(sceneGraph, searchName, -1); + GameObject searchObjectTwo = new GameObject(sceneGraph, searchName, -1); + + // Parent GO + GameObject parent = new GameObject(sceneGraph, "Parent", -1); + parent.addChild(searchObject); + parent.addChild(searchObjectTwo); + + sceneGraph.addGameObject(parent); + + Array result = sceneGraph.findAllByName(searchName); + Assert.assertEquals(2, result.size); + Assert.assertEquals(searchObject, result.get(0)); + Assert.assertEquals(searchObjectTwo, result.get(1)); + } + + @Test + public void gameObjectsHierarchyFindByName() { + SceneGraph sceneGraph = new SceneGraph(null); + + // The GO's to search for + String searchName = "SearchName"; + + int expectedResult = 0; + + // Parent GO + GameObject parent = new GameObject(sceneGraph, "Parent", -1); + GameObject currentParent = parent; + + // Create a hierarchy of Parent->Child GO's to search through + for (int i = 0; i < 4; i++) { + GameObject searchObject = new GameObject(sceneGraph, searchName, -1); + GameObject nonSearchObject = new GameObject(sceneGraph, "OtherObject", -1); + currentParent.addChild(searchObject); + currentParent.addChild(nonSearchObject); + + // each iteration, current child becomes next parent + // variate which one is parent to complicate scenegraph more + currentParent = i % 2 == 0 ? searchObject : nonSearchObject; + expectedResult++; + } + + int parentCount = 0; + // Add the top level parent multiple times just add complexity to scenegraph + for (int i = 0; i < 4; i++) { + sceneGraph.addGameObject(parent); + parentCount++; + } + + Array result = sceneGraph.findAllByName(searchName); + Assert.assertEquals(expectedResult * parentCount, result.size); + } + + @Test + public void gameObjectsFindByComponent() throws InvalidComponentException { + Scene mock = Mockito.mock(Scene.class); + mock.environment = new MundusEnvironment(); + + SceneGraph sceneGraph = new SceneGraph(null); + sceneGraph.scene = mock; + + // The GO's to search for + String searchName = "SearchName"; + GameObject searchObject = new GameObject(sceneGraph, searchName, -1); + GameObject searchObjectTwo = new GameObject(sceneGraph, searchName, -1); + + searchObject.addComponent(new ModelComponent(searchObject)); + searchObjectTwo.addComponent(new ModelComponent(searchObjectTwo)); + + // Parent GO + GameObject parent = new GameObject(sceneGraph, "Parent", -1); + parent.addChild(searchObject); + parent.addChild(searchObjectTwo); + + sceneGraph.addGameObject(parent); + + Array result = sceneGraph.findAllByComponent(Component.Type.MODEL); + Assert.assertEquals(2, result.size); + Assert.assertEquals(searchObject, result.get(0)); + Assert.assertEquals(searchObjectTwo, result.get(1)); + } + + @Test + public void gameObjectFindByTag() { + SceneGraph sceneGraph = new SceneGraph(null); + + // The GO to search for + String searchTag = "SearchTag"; + GameObject searchObject = new GameObject(sceneGraph, "search", -1); + searchObject.addTag(searchTag); + + // Parent GO + GameObject parent = new GameObject(sceneGraph, "Parent", -1); + parent.addChild(searchObject); + + sceneGraph.addGameObject(parent); + + Array result = sceneGraph.findAllByTag(searchTag); + Assert.assertEquals(1, result.size); + Assert.assertEquals(searchTag, result.first().getTags().first()); + } + +} diff --git a/commons/src/test/com/mbrlabs/mundus/commons/test/SceneGraphTest.java b/commons/src/test/com/mbrlabs/mundus/commons/test/SceneGraphTest.java deleted file mode 100644 index c8e2b6043..000000000 --- a/commons/src/test/com/mbrlabs/mundus/commons/test/SceneGraphTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2016. See AUTHORS file. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.mbrlabs.mundus.commons.test; - -import com.mbrlabs.mundus.commons.scene3d.Node; -import com.mbrlabs.mundus.commons.scene3d.SimpleNode; - -import org.junit.Assert; -import org.junit.Test; - -/** - * @author Marcus Brummer - * @version 21-06-2016 - */ -public class SceneGraphTest { - - @Test - public void basicParenting() { - Node root = new SimpleNode<>(0); - Assert.assertNull(root.getChildren()); - - SimpleNode c0 = new SimpleNode<>(1); - root.addChild(c0); - Assert.assertEquals(1, root.getChildren().size); - Assert.assertSame(root.getChildren().first(), c0); - Assert.assertSame(root, c0.getParent()); - - SimpleNode c1 = new SimpleNode<>(2); - root.addChild(c1); - Assert.assertEquals(2, root.getChildren().size); - Assert.assertSame(root, c0.getParent()); - - c0.remove(); - Assert.assertEquals(1, root.getChildren().size); - Assert.assertNull(c0.getParent()); - } - -} From b312fa152394eb083773413cc3cc830756c698f8 Mon Sep 17 00:00:00 2001 From: James Date: Mon, 10 Apr 2023 10:17:54 -0400 Subject: [PATCH 2/3] Update CHANGES --- gdx-runtime/CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/gdx-runtime/CHANGES b/gdx-runtime/CHANGES index 3490bd677..86bb22b4b 100644 --- a/gdx-runtime/CHANGES +++ b/gdx-runtime/CHANGES @@ -4,6 +4,7 @@ - Add render event handling - Change scene camera to be base camera class - Add active boolean to Skybox class to toggle rendering +- Added new convenience methods to SceneGraph and GameObject for searching for GameObjects [0.4.0] ~ 10/12/2022 - [BREAKING CHANGE] The loadScene method for the runtime has changed. A ModelBatch is no longer required to be passed in. From 4912ee608c5cc4ef252c8cf025dc86abd46a1d53 Mon Sep 17 00:00:00 2001 From: James Date: Mon, 10 Apr 2023 10:22:01 -0400 Subject: [PATCH 3/3] Update Comment --- .../src/main/com/mbrlabs/mundus/commons/scene3d/SceneGraph.java | 1 + 1 file changed, 1 insertion(+) diff --git a/commons/src/main/com/mbrlabs/mundus/commons/scene3d/SceneGraph.java b/commons/src/main/com/mbrlabs/mundus/commons/scene3d/SceneGraph.java index bb22e1292..7c74b66ca 100644 --- a/commons/src/main/com/mbrlabs/mundus/commons/scene3d/SceneGraph.java +++ b/commons/src/main/com/mbrlabs/mundus/commons/scene3d/SceneGraph.java @@ -187,6 +187,7 @@ public Array findAllByComponent(Component.Type type) { /** * Returns an Array of all scene GameObjects that have the given Tag + * Traversing the scene can be expensive, cache these results if you need them often. * * @param tag the string tag to search for * @return Array of all matching GameObjects