From fa19fc70f59c6e183ceb22c68b4999b0e607cdb7 Mon Sep 17 00:00:00 2001 From: eitanbariboa Date: Sat, 22 Jun 2024 13:59:44 +0300 Subject: [PATCH] First init --- .gitattributes | 2 + README.md | 97 ++++++++++++- SearchIcon.jpg | Bin 0 -> 17814 bytes SearchIcon.jpg.import | 34 +++++ .../Examples/FindMainScene/FindMainScene.tscn | 40 ++++++ .../FindMainScene/findMainSceneExample.gd | 7 + .../Examples/FindNodeByType/ClassA.gd | 6 + .../Examples/FindNodeByType/ClassB.gd | 5 + .../FindNodeByType/SearchNodeByType.tscn | 45 ++++++ .../FindNodeByType/findNodeExample.gd | 37 +++++ addons/SearchByNode/SearchByNode.gd | 131 ++++++++++++++++++ project.godot | 19 +++ 12 files changed, 421 insertions(+), 2 deletions(-) create mode 100644 .gitattributes create mode 100644 SearchIcon.jpg create mode 100644 SearchIcon.jpg.import create mode 100644 addons/SearchByNode/Examples/FindMainScene/FindMainScene.tscn create mode 100644 addons/SearchByNode/Examples/FindMainScene/findMainSceneExample.gd create mode 100644 addons/SearchByNode/Examples/FindNodeByType/ClassA.gd create mode 100644 addons/SearchByNode/Examples/FindNodeByType/ClassB.gd create mode 100644 addons/SearchByNode/Examples/FindNodeByType/SearchNodeByType.tscn create mode 100644 addons/SearchByNode/Examples/FindNodeByType/findNodeExample.gd create mode 100644 addons/SearchByNode/SearchByNode.gd create mode 100644 project.godot diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/README.md b/README.md index c320c41..4f66ab6 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,95 @@ -# SearchByNode -A godot tool that provides a convenient way to find nodes in your scene tree by type, visibility, (including within sub-viewports or specific parent nodes) +## SearchByNode 🔍 + +This Godot tool provides a simple and efficient way to search and retrieve nodes within your scene tree (including within sub-viewports or specific parent nodes) based on their type and visibility. It's particularly useful for finding specific nodes without manually traversing the hierarchy. + +### Features + +- Find a single node by type (e.g., `Control`, `Node2D`, custom class). +- Find all nodes of a specific type. +- Option to search for active (visible) nodes only. +- Ability to limit the search to a specific sub-viewport. +- Find nodes within a specific parent node. + +### Installation + +1. **Download/Clone the GitHub repo:** Get the `SearchByNode.gd` script from the repository. +2. **Enable Autoload:** + - In your Godot project, go to **Project -> Project Settings -> AutoLoad**. + - Click "Add" and select the `SearchByNode.gd` script. + - Give it a name (e.g., "SearchByNode") in the AutoLoad settings. +3. **Use `SearchByNode` in your scripts:** Now you can access the `SearchByNode` functions directly in any of your project's scripts. + +### Usage + +#### Finding Nodes + +```gdscript +# Find the first active node of type ClassB +var objB_one : ClassB = SearchByNode.findNodeByType(ClassB) +if objB_one: + print(objB_one.nameObj) + +# Find all active nodes of type ClassA +var classA_array : Array[ClassA] +classA_array.assign(SearchByNode.findNodesByType(ClassA)) +for objA_all : ClassA in classA_array: + print(objA_all.nameObj) + +# Find the first active ClassA node within 'self' node +var objA_innerOne : ClassA = SearchByNode.findInnerNodeInNode(ClassA,self) +if objA_innerOne: + print(objA_innerOne.nameObj) + +# Find all active ClassA nodes within 'self' node +var innerClassA_array : Array[ClassA] +innerClassA_array.assign(SearchByNode.findInnerNodesInNode(ClassA,self)) +for objA_inner_all : ClassA in innerClassA_array: + print(objA_inner_all.nameObj) +``` + +#### Finding the Main Scene of a Viewport + +```gdscript +# Get the main scene of the viewport that 'self' belongs to +var main_scene = SearchByNode.get_main_scene_of_viewport(self) +print(main_scene.name) +``` + +### Parameters + +- **_type:** The type of node to search for (e.g., `ClassB`, `Control`, `Node`). +- **_active_only:** (Optional) If `true`, only visible nodes will be returned. Defaults to `true`. +- **mainSubViewPort:** (Optional) The `SubViewport` to limit the search within. Defaults to `null` (searches the entire scene). +- **parentObject:** The parent node to search within. + +### Examples + +**1. Finding a specific UI element:** + +```gdscript +# Find the "StartButton" button +var start_button : Button = SearchByNode.findNodeByType(Button, true, null) +``` + +**2. Finding all enemies in a level:** + +```gdscript +# Find all active "Enemy" nodes within the "Level" sub-viewport +for enemy : Enemy in SearchByNode.findNodesByType(Enemy,true,level): + print(enemy.name) +``` +### Additional Examples + +For more detailed examples and practical use cases, check out the **example scenes** included in this repository. +You can load and run these scenes in Godot to see `SearchByNode` in action. +Feel free to experiment and adapt the examples to fit your specific needs. + +### Notes + +- The script assumes you are passing valid types and nodes as arguments. +- The `_active_only` parameter relies on the `is_visible_in_tree()` method, which might not be suitable for all scenarios (for example when looking for inactive objects also). +- The `get_main_scene_of_viewport()` function is useful when working with nested viewports. + +### License + +This asset is provided under the [MIT License](LICENSE.md). diff --git a/SearchIcon.jpg b/SearchIcon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3dbc7e5de6d301c1fa9c1c62641ff56092cffd44 GIT binary patch literal 17814 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 literal 0 HcmV?d00001 diff --git a/SearchIcon.jpg.import b/SearchIcon.jpg.import new file mode 100644 index 0000000..742200c --- /dev/null +++ b/SearchIcon.jpg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d00s7ogckc22v" +path="res://.godot/imported/SearchIcon.jpg-6ef744b2619a0876b32ad2e3cbd0171f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://SearchIcon.jpg" +dest_files=["res://.godot/imported/SearchIcon.jpg-6ef744b2619a0876b32ad2e3cbd0171f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/SearchByNode/Examples/FindMainScene/FindMainScene.tscn b/addons/SearchByNode/Examples/FindMainScene/FindMainScene.tscn new file mode 100644 index 0000000..7ac660a --- /dev/null +++ b/addons/SearchByNode/Examples/FindMainScene/FindMainScene.tscn @@ -0,0 +1,40 @@ +[gd_scene load_steps=2 format=3 uid="uid://b3y3anla8qv17"] + +[ext_resource type="Script" path="res://addons/SearchByNode/Examples/FindMainScene/findMainSceneExample.gd" id="1_53184"] + +[node name="MainScene" type="Node2D"] + +[node name="Obj1" type="Node2D" parent="."] + +[node name="Obj2" type="Node" parent="."] +script = ExtResource("1_53184") + +[node name="Obj3" type="Node3D" parent="."] + +[node name="SubViewport" type="SubViewport" parent="."] + +[node name="SubMainScene" type="Node" parent="SubViewport"] + +[node name="subObj1" type="Node2D" parent="SubViewport/SubMainScene"] + +[node name="subObj2" type="Node2D" parent="SubViewport/SubMainScene"] +script = ExtResource("1_53184") + +[node name="subObj3" type="Node2D" parent="SubViewport/SubMainScene"] + +[node name="SubSubMainScene" type="Node3D" parent="SubViewport/SubMainScene"] + +[node name="subObj1" type="Node2D" parent="SubViewport/SubMainScene/SubSubMainScene"] + +[node name="subObj2" type="Node2D" parent="SubViewport/SubMainScene/SubSubMainScene"] +script = ExtResource("1_53184") + +[node name="subObj3" type="Node2D" parent="SubViewport/SubMainScene/SubSubMainScene"] + +[node name="SubMainScene2" type="Node2D" parent="SubViewport"] + +[node name="subObj1" type="Node2D" parent="SubViewport/SubMainScene2"] + +[node name="subObj2" type="Node2D" parent="SubViewport/SubMainScene2"] + +[node name="subObj3" type="Node2D" parent="SubViewport/SubMainScene2"] diff --git a/addons/SearchByNode/Examples/FindMainScene/findMainSceneExample.gd b/addons/SearchByNode/Examples/FindMainScene/findMainSceneExample.gd new file mode 100644 index 0000000..fb0beb8 --- /dev/null +++ b/addons/SearchByNode/Examples/FindMainScene/findMainSceneExample.gd @@ -0,0 +1,7 @@ +extends Node + + +func _ready() -> void: + print(SearchByNode.get_main_scene_of_viewport(self).name) # will return current MainScene of a specific viewport + #print(self.get_viewport().name) # will return viewport but not the MainScene or subMainScenes + #print(get_tree().current_scene.name) # Will always return the currentScene "MainScene" diff --git a/addons/SearchByNode/Examples/FindNodeByType/ClassA.gd b/addons/SearchByNode/Examples/FindNodeByType/ClassA.gd new file mode 100644 index 0000000..df2f7f6 --- /dev/null +++ b/addons/SearchByNode/Examples/FindNodeByType/ClassA.gd @@ -0,0 +1,6 @@ +extends Node +class_name ClassA + + +@export var nameObj : String = "" +@export var someInt : int = 3 diff --git a/addons/SearchByNode/Examples/FindNodeByType/ClassB.gd b/addons/SearchByNode/Examples/FindNodeByType/ClassB.gd new file mode 100644 index 0000000..6c50f69 --- /dev/null +++ b/addons/SearchByNode/Examples/FindNodeByType/ClassB.gd @@ -0,0 +1,5 @@ +extends Node2D +class_name ClassB + +@export var nameObj : String = "" +@export var someInt : int = 3 diff --git a/addons/SearchByNode/Examples/FindNodeByType/SearchNodeByType.tscn b/addons/SearchByNode/Examples/FindNodeByType/SearchNodeByType.tscn new file mode 100644 index 0000000..b677868 --- /dev/null +++ b/addons/SearchByNode/Examples/FindNodeByType/SearchNodeByType.tscn @@ -0,0 +1,45 @@ +[gd_scene load_steps=4 format=3 uid="uid://cysdm8cjpgygq"] + +[ext_resource type="Script" path="res://addons/SearchByNode/Examples/FindNodeByType/findNodeExample.gd" id="1_42tc7"] +[ext_resource type="Script" path="res://addons/SearchByNode/Examples/FindNodeByType/ClassA.gd" id="2_ysxnj"] +[ext_resource type="Script" path="res://addons/SearchByNode/Examples/FindNodeByType/ClassB.gd" id="3_8wveg"] + +[node name="MainScene" type="Node2D"] + +[node name="ClassAObj1" type="Node2D" parent="."] +script = ExtResource("2_ysxnj") +nameObj = "ObjA1" + +[node name="ClassAObj2" type="Node2D" parent="."] +script = ExtResource("2_ysxnj") +nameObj = "ObjA2" + +[node name="ClassAObj4" type="Node2D" parent="ClassAObj2"] +script = ExtResource("2_ysxnj") +nameObj = "ObjA4" + +[node name="ClassAObj3 NotVisible" type="Node2D" parent="."] +visible = false +script = ExtResource("2_ysxnj") +nameObj = "ObjA3 Not visible" + +[node name="ClassBObj1" type="Node2D" parent="."] +script = ExtResource("3_8wveg") +nameObj = "ObjB1" + +[node name="SomeObj" type="Node3D" parent="."] + +[node name="SearchExample" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 +script = ExtResource("1_42tc7") + +[node name="InnerClassAObj5" type="Node2D" parent="SearchExample"] +script = ExtResource("2_ysxnj") +nameObj = "InnerObjA5" + +[node name="InnerInnerClassAObj6" type="Node2D" parent="SearchExample/InnerClassAObj5"] +script = ExtResource("2_ysxnj") +nameObj = "InnerInnerObjA6" diff --git a/addons/SearchByNode/Examples/FindNodeByType/findNodeExample.gd b/addons/SearchByNode/Examples/FindNodeByType/findNodeExample.gd new file mode 100644 index 0000000..3299ba5 --- /dev/null +++ b/addons/SearchByNode/Examples/FindNodeByType/findNodeExample.gd @@ -0,0 +1,37 @@ +extends Control + + +func _ready() -> void: + print("----------Find one ClassB Visible Node-------------------") + var objB_one : ClassB = SearchByNode.findNodeByType(ClassB,true) + if objB_one: + print(objB_one.nameObj) + + print("----------Find all ClassA Visible only Nodes-------------------") + var classA_array : Array[ClassA] + classA_array.assign(SearchByNode.findNodesByType(ClassA,true)) + for objA_all : ClassA in classA_array: + print(objA_all.nameObj) + + print("----------Find all ClassA Visible and not Visible Nodes-------------------") + var classA_array_all_visiibility : Array[ClassA] + classA_array_all_visiibility.assign(SearchByNode.findNodesByType(ClassA,false)) + for objA_all : ClassA in classA_array_all_visiibility: + print(objA_all.nameObj) + + + + print("----------Find one InnerNode Visible Node-------------------") + var objA_innerOne : ClassA = SearchByNode.findInnerNodeInNode(ClassA,self) + if objA_innerOne: + print(objA_innerOne.nameObj) + print("----------Find all inner nodes of type ClassA Visible-------------------") + var innerClassA_array : Array[ClassA] + innerClassA_array.assign(SearchByNode.findInnerNodesInNode(ClassA,self)) + for objA_inner_all : ClassA in innerClassA_array: + print(objA_inner_all.nameObj) + + + + #SearchByNode.findNodeByType(ClassA.new(),true) # Do not use it like this as it will produce Error + #SearchByObject.findNodeByType(null,true) # Do not use it like this as it will produce Error diff --git a/addons/SearchByNode/SearchByNode.gd b/addons/SearchByNode/SearchByNode.gd new file mode 100644 index 0000000..9293549 --- /dev/null +++ b/addons/SearchByNode/SearchByNode.gd @@ -0,0 +1,131 @@ +extends Node + + + +""" +Finds node by a given type and returns it. (can search for an Object like Control,Node or even a Class) +_active_only = true default, if sets to true than will return only visible object +mainSubViewPort = null default, if you want to get objects only inside a subviewport (acting like current scene) +""" +## Finds node by a given type and returns it. +func findNodeByType(_type : Object,_active_only : bool = true,mainSubViewPort : SubViewport = null) -> Object: + if not _check_cast_class(_type): + push_error("Don't send an instantiated or null object ") + return null + else: + var main_scene_node : Object = get_tree().current_scene + if mainSubViewPort: + main_scene_node = mainSubViewPort + if main_scene_node: + listOfAllNodesInParent.clear() + _findByType(main_scene_node,_type) + for child in listOfAllNodesInParent: + if _active_only: + if (child as CanvasItem).is_visible_in_tree() == _active_only : + return child + else: + return child + return null + + + + +""" +Finds all nodes by a given type and returns it. (can search for an Object like Control,Node or even a Class) +_active_only = true default, if sets to true than will return only visible objects +mainSubViewPort = null default, if you want to get objects only inside a subviewport (acting like current scene) +""" +## Finds all nodes by a given type and returns it. +func findNodesByType(_type : RefCounted , _active_only : bool = true,mainSubViewPort : SubViewport = null) -> Array[Object]: + var listOfAllNodes: Array[Object] = [] + if not _check_cast_class(_type): + push_error("Don't send an instantiated or null object ") + return listOfAllNodes + else: + var main_scene_node : Object = get_tree().current_scene + if mainSubViewPort: + main_scene_node = mainSubViewPort + if main_scene_node: + listOfAllNodesInParent.clear() + _findByType(main_scene_node,_type) + for child in listOfAllNodesInParent: + if _active_only: + if (child as CanvasItem).is_visible_in_tree() == _active_only: + listOfAllNodes.append(child) + else: + listOfAllNodes.append(child) + return listOfAllNodes + +## Get Node inside a node like if a character has a rigidbody, it will get it. +func findInnerNodeInNode(_type : Object, parentObject : Object, _active_only : bool = true) -> Object: + if not _check_cast_class(_type): + push_error("Don't send an instantiated or null object ") + return null + elif not parentObject: + print("Parent Object is null") + else: + listOfAllNodesInParent.clear() + _findByType(parentObject,_type) + for child in listOfAllNodesInParent: + if _active_only: + if (child as CanvasItem).is_visible_in_tree() == _active_only: + return child + else: + return child + return null + + +## Get Nodes inside a node If there are multinodes that needs to be controlled inside a parent +func findInnerNodesInNode(_type : Object, parentObject : Object , _active_only : bool = true) -> Array[Object]: + var listOfAllNodes: Array[Object] = [] + if not _check_cast_class(_type): + push_error("Don't send an instantiated or null object in Type ") + return listOfAllNodes + elif not parentObject: + print("Parent Object is null") + else: + listOfAllNodesInParent.clear() + _findByType(parentObject,_type) + for child in listOfAllNodesInParent: + if _active_only: + if (child as CanvasItem).is_visible_in_tree() == _active_only : + listOfAllNodes.append(child) + else: + listOfAllNodes.append(child) + return listOfAllNodes + + +var listOfAllNodesInParent : Array[Node] = [] +func _findByType(parent : Node, type) -> void: + for child : Node in parent.get_children(): + if is_instance_of(child, type): + listOfAllNodesInParent.append(child) + if child.get_children().size()>0: + _findByType(child,type) + return + +''' +When working with several scenes you don't always want to get all objects of all scenes +but you want to get Object for a specific scene. +''' +##Gets the Main of the current scene instead of going to Tree (Usefull if you use SubViewPorts) +func get_main_scene_of_viewport(obj : Object): + if not obj: + return null + if is_instance_of(obj.get_parent(),Viewport): ## we found the parent that is a viewport so we return the obj + return obj + else: + return get_main_scene_of_viewport(obj.get_parent()) + + + +## Checks cast class +func _check_cast_class(castClass : Object) -> bool: + if typeof(castClass) == Variant.Type.TYPE_NIL: + return false + var properties: Array = castClass.get_property_list() + for property in properties: + ## Making sure this is a ref object and not an real object + if(property.name == "RefCounted"): + return true + return false diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..c514905 --- /dev/null +++ b/project.godot @@ -0,0 +1,19 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="SearchByNode" +run/main_scene="res://addons/SearchByNode/Examples/FindNodeByType/SearchNodeByType.tscn" +config/features=PackedStringArray("4.3", "Forward Plus") + +[autoload] + +SearchByNode="*res://addons/SearchByNode/SearchByNode.gd"