Godot Version
4.5 Stable
Question
Hello,
I am currently creating a tool script that takes a mesh and prepares it for further use.
On a button press it takes a glb mesh and then precesses it (creating, removing and moving files). This works fine. The problem is when i restart the engine it gives naming conflics:
The nodes shown here are just a small protion of the nodes being handles. But only these give naming conflics.
Then most of the nodes are deleted and some higher in the scene hierarchy are renamed.
The expected behaviour would be that the nodes and their properties stay saved when i reload the engine.
Code:
@tool
class_name Limb extends Node3D
@export_category(“Actions”)
@export var generate: bool = false : set = _on_btn_generate
@export var clear: bool = false : set = _on_btn_clear
@export_category(“Data”)
@export var mesh: PackedScene
@export var item_data: ItemData
@export_category(“References”)
@export var root_attachment: Node3D
@export var physics_skeleton: Skeleton3D
@export var animation_skeleton: Skeleton3D
@export var target_anim_player: AnimationPlayer
@export var physics_root_bone: PhysicalBone3D
@export_category(“Bone Settings”)
spring stuff
@export var linear_spring_stiffness: float = 400.0
@export var linear_spring_damping: float = 40.0
@export var max_linear_force: float = 9999.0
@export var angular_spring_stiffness: float = 1000.0
@export var angular_spring_damping: float = 80.0
@export var max_angular_force: float = 9999.0
@onready var attachments_container: Node3D = $AttachmentPoints
var physics_bones: Array[PhysicalBone3D] =
var physics_simulator: PhysicalBoneSimulator3D
var current_delta: float
var ragdoll_mode: bool = false
const SPEED: float = 50
const DAMPING: float = 0.9
func _on_btn_generate(value: bool) → void:
if value == false:
return
await get_tree().process_frame
generate_structure()
generate = false # Reset switch
func _on_btn_clear(value: bool) → void:
if value == false:
return
_clear_all_generated_nodes()
clear = false
func generate_structure() → void:
# If not inside tree the wait
if not is_inside_tree():
await ready
if not mesh:
printerr(self.name, ": No mesh assigned!")
return
print("Owner. ", get_tree().edited_scene_root)
var old_mesh_1 = get_node_or_null("PhysicsMesh")
free_and_clean_node(old_mesh_1)
var old_mesh_2 = get_node_or_null("TargetMesh")
free_and_clean_node(old_mesh_2)
var old_attachment_points = get_node_or_null("AttachmentPoints")
free_and_clean_node(old_attachment_points)
if not mesh:
return
attachments_container = Node3D.new()
add_child(attachments_container)
attachments_container.owner = get_tree().edited_scene_root
attachments_container.name = "AttachmentPoints"
var instance_1 = mesh.instantiate()
instance_1.name = "PhysicsMesh" # Name setzen für das Aufräumen später
add_child(instance_1)
instance_1.owner = get_tree().edited_scene_root
var instance_2 = mesh.instantiate()
instance_2.name = "TargetMesh"
add_child(instance_2)
instance_2.owner = get_tree().edited_scene_root
if Engine.is_editor_hint():
var tree_root = get_tree().edited_scene_root
if tree_root:
_make_all_children_local(instance_1, tree_root)
_make_all_children_local(instance_2, tree_root)
instance_1.find_child("AnimationPlayer").queue_free()
physics_skeleton = instance_1.find_child("Skeleton3D",true, false)
if physics_skeleton:
var physical_bone_simulator: PhysicalBoneSimulator3D = PhysicalBoneSimulator3D.new()
physical_bone_simulator.name = "PhysicalBoneSimulator3D"
physics_skeleton.add_child(physical_bone_simulator)
physical_bone_simulator.owner = tree_root
setup_physical_bone_coll(physics_skeleton,
physical_bone_simulator)
var i2_children = instance_2.find_child("Skeleton3D").find_children("*", "",true)
for child in i2_children:
child.queue_free()
# Adding the Variables
animation_skeleton = instance_2.find_child("Skeleton3D",true, false)
target_anim_player = instance_2.find_child("AnimationPlayer", true)
#physics_root_bone =
func setup_physical_bone_coll(skeleton:Skeleton3D, physical_bone_simulator: PhysicalBoneSimulator3D)->void:
for i in range(skeleton.get_bone_count() -1, -1, -1):
var physics_bone: PhysicalBone3D = PhysicalBone3D.new()
physics_bone.bone_name = skeleton.get_bone_name(i)
physical_bone_simulator.add_child(physics_bone)
physics_bone.owner = get_tree().edited_scene_root
physics_bone.name = skeleton.find_children(“*”, “BoneAttachment3D”, true)[0 - i + skeleton.get_bone_count() -1].name
skeleton.find_children("*", "CollisionShape3D", true)[0].reparent(physics_bone)
for bone_attachemnet in skeleton.find_children("*", "BoneAttachment3D", true):
bone_attachemnet.get_child(0).queue_free()
bone_attachemnet.queue_free()
func _make_all_children_local(node: Node, new_owner: Node) → void:
for child in node.get_children():
child.owner = new_owner
_make_all_children_local(child, new_owner)
func _clear_owner_recursive(node: Node) → void:
node.owner = null
for child in node.get_children():
_clear_owner_recursive(child)
func _clear_all_generated_nodes() → void:
var names_to_remove = [“PhysicsMesh”, “TargetMesh”, “AttachmentPoints”]
for n_name in names_to_remove:
var node = get_node_or_null(n_name)
free_and_clean_node(node)
func free_and_clean_node(node: Node) → void:
if not node:
return
_clear_owner_recursive(node)
node.name = "TRASH_" + str(node.get_instance_id())
if node.get_parent():
node.get_parent().remove_child(node)
node.queue_free()
