Last active
October 24, 2023 15:51
-
-
Save Shilo/c2a8cc05d131432f3b8c5f237acc413b to your computer and use it in GitHub Desktop.
Godot tool for auto syncing position and size of collision shape 3d with a target mesh instance 3d. (GDScript or C#)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@tool | |
class_name AutoCollisionShape3DGD extends CollisionShape3D | |
@export var mesh_instance_3d: MeshInstance3D | |
@export_group("Editor Auto Sync") | |
@export var auto_sync_position_editor: bool = true | |
@export var auto_sync_size_editor: bool = true | |
@export_group("Editor Gizmo [EXPERIMENTAL]") | |
@export var scale_to_shape: bool = false | |
@export var scale_sensitivity: float = 0.25 | |
@export_group("Runtime") | |
@export var destroy_script_in_runtime: bool = true | |
func _enter_tree(): | |
if destroy_script_in_runtime && !Engine.is_editor_hint(): | |
set_script(null) | |
func _process(_delta): | |
_process_auto_sync() | |
_process_gizmo() | |
func _process_auto_sync(): | |
if !mesh_instance_3d: | |
return | |
if !mesh_instance_3d.is_inside_tree(): | |
mesh_instance_3d = null | |
return | |
if auto_sync_position_editor: | |
global_position = mesh_instance_3d.global_position | |
if auto_sync_size_editor: | |
scale = Vector3.ONE | |
if shape && shape is BoxShape3D && mesh_instance_3d.mesh: | |
shape.size = mesh_instance_3d.mesh.get_aabb().size | |
if !_is_mesh_instance_ancestor(): | |
shape.size *= mesh_instance_3d.global_transform.basis | |
# TODO: handle rotation if not child of mesh instance | |
func _process_gizmo(): | |
if !scale_to_shape || !shape: | |
return | |
if scale != Vector3.ONE: | |
shape.size *= (scale - Vector3.ONE) * scale_sensitivity + Vector3.ONE | |
scale = Vector3.ONE | |
func _is_mesh_instance_ancestor() -> bool: | |
var parent = get_parent() | |
while parent: | |
if parent == mesh_instance_3d: | |
return true | |
parent = parent.get_parent() | |
return false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Godot; | |
[Tool, GlobalClass] | |
public partial class AutoCollisionShape3D : CollisionShape3D | |
{ | |
[Export] | |
public MeshInstance3D MeshInstance; | |
[ExportGroup("Editor Auto Sync")] | |
[Export] | |
public bool AutoSyncPositionEditor = true; | |
[Export] | |
public bool AutoSyncSizeEditor = true; | |
[ExportGroup("Editor Gizmo [EXPERIMENTAL]")] | |
[Export] | |
public bool ScaleToShape = false; | |
[Export] | |
public float ScaleSensitivity = 0.25f; | |
[ExportGroup("Runtime")] | |
[Export] | |
public bool DestroyScriptInRuntime = true; | |
public override void _EnterTree() | |
{ | |
if (DestroyScriptInRuntime && !Engine.IsEditorHint()) | |
SetScript(new Variant()); | |
} | |
public override void _Process(double delta) | |
{ | |
_ProcessAutoSync(); | |
_ProcessGizmo(); | |
} | |
private void _ProcessAutoSync() | |
{ | |
if (MeshInstance == null) | |
return; | |
if (!MeshInstance.IsInsideTree()) | |
{ | |
MeshInstance = null; | |
return; | |
} | |
if (AutoSyncPositionEditor) | |
GlobalPosition = MeshInstance.GlobalPosition; | |
if (AutoSyncSizeEditor) | |
{ | |
Scale = Vector3.One; | |
if (Shape != null && Shape is BoxShape3D && MeshInstance.Mesh != null) | |
{ | |
var boxShape = Shape as BoxShape3D; | |
boxShape.Size = MeshInstance.Mesh.GetAabb().Size; | |
if (!_IsMeshInstanceAncestor()) | |
{ | |
boxShape.Size *= MeshInstance.GlobalTransform.Basis; | |
// TODO: handle rotation if not child of mesh instance | |
} | |
} | |
} | |
} | |
private void _ProcessGizmo() | |
{ | |
if (!ScaleToShape || Shape == null) | |
return; | |
if (Scale != Vector3.One && Shape is BoxShape3D) | |
{ | |
(Shape as BoxShape3D).Size *= (Scale - Vector3.One) * ScaleSensitivity + Vector3.One; | |
Scale = Vector3.One; | |
} | |
} | |
private bool _IsMeshInstanceAncestor() | |
{ | |
Node parent = GetParent(); | |
while (parent != null) | |
{ | |
if (parent == MeshInstance) | |
return true; | |
parent = parent.GetParent(); | |
} | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment