Open chucklepie opened 3 years ago
Here's the GDScript equivalent that seems to be what's needed for toggling this in the meantime:
get_tree().set_debug_collisions_hint(p_toggled_setting)
var root_node : Node = get_tree().get_root()
var queue_stack : Array = []
queue_stack.push_back(root_node)
# Traverse tree to call update methods where available.
while not queue_stack.empty():
var node : Node = queue_stack.pop_back()
if is_instance_valid(node):
if node.has_method("update"):
#warning-ignore:unsafe_method_access
node.update()
var children_count : int = node.get_child_count()
for child_index in range(0, children_count):
queue_stack.push_back(node.get_child(child_index))
Here's the GDScript equivalent that seems to be what's needed for toggling this in the meantime:
Thank you for this, I long ago reluctantly accepted that this was impossible. My workaround has been to have the option always enabled, then add every single CollisionShape/Polygon to a group called "Debug" and toggle the visibility of all nodes in that group on a certain key press. It worked but was really prone to human forgetfulness :P
Your implementation is made for Godot 3 I assume, since it didn't work for me in 4.0.2. Here is a Godot 4 compatible version that toggles whatever the current state is:
func toggle_collision_shape_visibility() -> void:
var tree := get_tree()
tree.debug_collisions_hint = not tree.debug_collisions_hint
# Traverse tree to call queue_redraw on instances of
# CollisionShape2D and CollisionPolygon2D.
var node_stack: Array[Node] = [tree.get_root()]
while not node_stack.is_empty():
var node: Node = node_stack.pop_back()
if is_instance_valid(node):
if node is CollisionShape2D or node is CollisionPolygon2D:
node.queue_redraw()
node_stack.append_array(node.get_children())
update
was renamed to queue_redraw
and I removed the nested loop (though it probably doesn't make much of a difference unless you have a node with a crazy number of children). Instead of checking for the existence of the method, I check the type of the node, since the only nodes that should require a redraw are CollisionShape/Polygon2D whereas queue_redraw
is present in all CanvasItems.
Not sure how it works in 3D, but I assume you would just also check for the corresponding 3D types.
This is probably not the cleanest possible, but since the above solution wasn't working for TileMap in Godot 4 and using queue_redraw
on a TileMap didn't work either, I modified it slightly to add
if node is TileMap:
node.collision_visibility_mode = TileMap.VISIBILITY_MODE_FORCE_HIDE
node.collision_visibility_mode = TileMap.VISIBILITY_MODE_DEFAULT
basically setting VISIBILITY_MODE_FORCE_HIDE
to make it update, then setting VISIBILITY_MODE_DEFAULT
mode again to make it depend on whatever was set before.
There's probably a way to do this in one step, but I haven't looked into TileMaps all that much. So here's what seems to work fine for me right now in total:
func toggle_collision_shape_visibility() -> void:
var tree := get_tree()
tree.debug_collisions_hint = not tree.debug_collisions_hint
# Traverse tree to call queue_redraw on instances of
# CollisionShape2D and CollisionPolygon2D.
var node_stack: Array[Node] = [tree.get_root()]
while not node_stack.is_empty():
var node: Node = node_stack.pop_back()
if is_instance_valid(node):
if node is CollisionShape2D or node is CollisionPolygon2D:
node.queue_redraw()
if node is TileMap:
node.collision_visibility_mode = TileMap.VISIBILITY_MODE_FORCE_HIDE
node.collision_visibility_mode = TileMap.VISIBILITY_MODE_DEFAULT
node_stack.append_array(node.get_children())
The debug options (visible collision shapes, paths, nav, avoidance) should just be options available on SubViewport nodes under the 'Debug Draw' drop down. Never understood why these weren't exposed there, and now we have detachable windows, super useful for having actual/debug scenes side by side.
The debug options (visible collision shapes, paths, nav, avoidance) should just be options available on SubViewport nodes under the 'Debug Draw' drop down. Never understood why these weren't exposed there, and now we have detachable windows, super useful for having actual/debug scenes side by side.
Making debug drawing visible on specific viewports only via SubViewport properties is a lot of work, as the engine would need to keep track of visibility layers for the debug meshes.
My current workaround kinda works for 3D:
var show_debug_collisions_hint: bool:
set(visible):
print("Set show_debug_collisions_hint: ", visible)
var tree: SceneTree = get_tree()
# https://github.com/godotengine/godot-proposals/issues/2072
tree.debug_collisions_hint = visible
# Traverse tree to call toggle collision visibility
var node_stack: Array[Node] = [tree.get_root()]
while not node_stack.is_empty():
var node: Node = node_stack.pop_back()
if is_instance_valid(node):
if node is CollisionShape2D \
or node is CollisionPolygon2D \
or node is CollisionObject2D:
# queue_redraw on instances of
node.queue_redraw()
elif node is TileMap:
# use visibility mode to force redraw
node.collision_visibility_mode = TileMap.VISIBILITY_MODE_FORCE_HIDE
node.collision_visibility_mode = TileMap.VISIBILITY_MODE_DEFAULT
elif node is RayCast3D \
or node is CollisionShape3D \
or node is CollisionPolygon3D \
or node is CollisionObject3D \
or node is GPUParticlesCollision3D \
or node is GPUParticlesCollisionBox3D \
or node is GPUParticlesCollisionHeightField3D \
or node is GPUParticlesCollisionSDF3D \
or node is GPUParticlesCollisionSphere3D:
# remove and re-add the node to the tree to force a redraw
# https://github.com/godotengine/godot/blob/26b1fd0d842fa3c2f090ead47e8ea7cd2d6515e1/scene/3d/collision_object_3d.cpp#L39
var parent: Node = node.get_parent()
if parent:
parent.remove_child(node)
parent.add_child(node)
node_stack.append_array(node.get_children())
get:
return get_tree().debug_collisions_hint
I would love to be able to set it on specific nodes only and at runtime.
For 3D. should be?
var parent: Node = node.get_parent()
if parent:
parent.set_block_signal(true)
parent.remove_child(node)
parent.add_child(node)
parent.set_block_signal(false)
Describe the project you are working on
rhino simulator
Describe the problem or limitation you are having in your project
Debugging collision problems is difficult and you don't always know when they occur or how to easily get back to that point or recreate it upon enabling collision shapes and restarting the code. Lesser, but similarly, when you have collisions on it makes the screen very cluttered and there are many times when you want to turn collision shapes off as you want to test something else while still running the code.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
I presume there is a reason for this omissions, but you cannot enable/disable collision shapes from the Debug menu when the code is running.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
When the menu item is clicked in debug it informs the remote window to turn on collisions
Is there a reason why this should be core and not an add-on in the asset library?
It's basic debugging aid.