Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
# BoneEditor
# BoneGizmo

Plugin for Godot Engine
Simple Gizmo so you can edit bone transforms easily.

# How to use:
Append the node "BoneGizmo" to your scene
Select the node and change the exposed variables "Skeleton Path" as a string path to the Skeleton Node.
Change the exposed variable "Edit Bone" as a string name of the bone you want to edit. (Listed in the Skeleton node)
## How to use:

1. Enable plugin.
2. Add a BoneGizmo node to your scene.
3. Select BoneGizmo in scene tree and ensure it's properties points to a valid
Skeleton node and an optional AnimationPlayer node.
4. When you select a BoneGizmo node
- The BoneGizmo dock enables and loads up the selected BoneGizmo.
- You can then search for a bone. A highlighted bone is a selected bone.
- Bone filters are persisted via metadata for you to continue your work at
another time.
5. Hit *Run Gizmo* in the BoneGizmo dock.
6. Translate, rotate, and scale your selected bone.

## Caveats

You should disable *Run Gizmo* when an animation is playing.

BoneGizmo nodes will remain in your scene tree.
8 changes: 0 additions & 8 deletions addons/bone_gizmo.gd

This file was deleted.

43 changes: 43 additions & 0 deletions addons/bone_gizmo/bone_finder.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
tool
extends VBoxContainer

signal bone_selected(this, name, id)

onready var _bone_list: ItemList = $bone_list as ItemList
onready var _filter_edit: LineEdit = find_node('filter') as LineEdit

var _skel: Skeleton

var filter := '' setget set_filter,get_filter
func get_filter() -> String: return filter
func set_filter(new_val: String):
filter = new_val
_filter_edit.text = filter
refresh_bone_list()

func set_skeleton(skeleton: Skeleton):
if skeleton == null:
_bone_list.clear()
_skel = null
return
if _skel != skeleton:
_skel = skeleton
refresh_bone_list()

func refresh_bone_list():
if _skel == null:
return
_bone_list.clear()
for id in _skel.get_bone_count():
var name = _skel.get_bone_name(id)
if filter == "" or name.findn(filter) > -1:
_bone_list.add_item(name)
_bone_list.set_item_metadata(_bone_list.get_item_count() - 1, {name = name, id = id})

func _on_filter_text_changed(new_text: String) -> void:
filter = new_text
refresh_bone_list()

func _on_bone_list_item_selected(index: int) -> void:
var meta = _bone_list.get_item_metadata(index)
emit_signal("bone_selected", self, meta.name, meta.id)
37 changes: 37 additions & 0 deletions addons/bone_gizmo/bone_finder.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[gd_scene load_steps=2 format=2]

[ext_resource path="res://addons/bone_gizmo/bone_finder.gd" type="Script" id=1]

[node name="bone_finder" type="VBoxContainer"]
anchor_right = 1.0
anchor_bottom = 1.0
size_flags_horizontal = 3
size_flags_vertical = 3
script = ExtResource( 1 )

[node name="HBoxContainer" type="HBoxContainer" parent="."]
margin_right = 1024.0
margin_bottom = 24.0
size_flags_horizontal = 3

[node name="Label" type="Label" parent="HBoxContainer"]
margin_top = 5.0
margin_right = 37.0
margin_bottom = 19.0
text = "Filter:"

[node name="filter" type="LineEdit" parent="HBoxContainer"]
margin_left = 41.0
margin_right = 1024.0
margin_bottom = 24.0
size_flags_horizontal = 3
caret_blink = true

[node name="bone_list" type="ItemList" parent="."]
margin_top = 28.0
margin_right = 1024.0
margin_bottom = 600.0
size_flags_horizontal = 3
size_flags_vertical = 3
[connection signal="text_changed" from="HBoxContainer/filter" to="." method="_on_filter_text_changed"]
[connection signal="item_selected" from="bone_list" to="." method="_on_bone_list_item_selected"]
86 changes: 86 additions & 0 deletions addons/bone_gizmo/bone_gizmo.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
tool
extends Spatial

signal path_changed(what)

# All paths are must be relative to the node (BoneGizmo)
export(NodePath) var skeleton_path = @"../Skeleton" setget set_skeleton_path
func set_skeleton_path(new_val):
if new_val == skeleton_path:
return
skeleton_path = new_val
emit_signal("path_changed", "skeleton")

export(NodePath) var animation_path = @"../AnimationPlayer" setget set_animation_path
func set_animation_path(new_val):
if new_val == animation_path:
return
animation_path = new_val
emit_signal("path_changed", "animation")

var running: bool setget set_running,get_running
func get_running() -> bool: return running
func set_running(new_val: bool) -> void:
if new_val and not running:
global_transform = get_skeleton().get_bone_global_pose(get_edit_bone_index())
set_process(true)
elif not new_val:
set_process(false)
running = new_val

var edit_bone_filter setget set_edit_bone_filter,get_edit_bone_filter
func get_edit_bone_filter():
return get_meta("edit_bone_filter") if has_meta("edit_bone_filter") else ""
func set_edit_bone_filter(new_val):
set_meta("edit_bone_filter", new_val)

var edit_bone = ""
var allowed_to_run = false

func _ready():
set_running(false)

func _process(delta):
var skeleton = get_skeleton()
var bone_index = get_edit_bone_index()
skeleton.set_bone_global_pose(bone_index, global_transform)

func reset() -> void:
transform = Transform()

func can_run() -> bool:
return allowed_to_run and (get_skeleton() != null) and (get_edit_bone_index() != -1)

func get_animation_player() -> AnimationPlayer:
return get_node(animation_path) as AnimationPlayer

func get_skeleton() -> Skeleton:
return get_node(skeleton_path) as Skeleton

func get_edit_bone_index() -> int:
return get_skeleton().find_bone(edit_bone)

func create_tracks():
var skel = get_skeleton()
var anim_player = get_animation_player()
var anim = anim_player.get_animation(anim_player.assigned_animation)
for i in skel.get_bone_count():
anim.add_track(Animation.TYPE_TRANSFORM,i)
anim.track_set_path(i,skeleton_path + ":" + skel.get_bone_name(i))

# This will override all the bone poses in the track with the current ones
func insert_key():
var skel = get_skeleton()
var anim_player = get_animation_player()
var anim = anim_player.get_animation(anim_player.assigned_animation)
for i in skel.get_bone_count():
var bone_name = skel.get_bone_name(i)
var bone_pose = skel.get_bone_pose(i)
var bone_track = anim.find_track(NodePath(skel.name + ':' + bone_name))
anim.transform_track_insert_key(
bone_track,
anim_player.current_animation_position,
bone_pose.origin,
Quat(bone_pose.basis),
bone_pose.basis.get_scale()
)
File renamed without changes
64 changes: 64 additions & 0 deletions addons/bone_gizmo/dock.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
tool
extends Control

onready var bone_finder = find_node('bone_finder')
onready var run_gizmo_button = find_node('RunGizmo')

var gizmo setget set_gizmo,get_gizmo
func get_gizmo(): return gizmo
func set_gizmo(new_val):
if is_instance_valid(gizmo):
gizmo.running = false
gizmo.disconnect("path_changed", self, "_on_gizmo_path_changed")

gizmo = new_val
if gizmo == null:
$Disabled.visible = true
run_gizmo_button.pressed = false
bone_finder.set_skeleton(null)
bone_finder.set_filter('')
else:
$Disabled.visible = false
bone_finder.set_skeleton(gizmo.get_skeleton())
bone_finder.set_filter(gizmo.edit_bone_filter)
run_gizmo_button.pressed = gizmo.can_run()
gizmo.running = gizmo.can_run()
gizmo.connect("path_changed", self, "_on_gizmo_path_changed")

func _on_gizmo_path_changed(what):
if what == "skeleton":
bone_finder.set_skeleton(gizmo.get_skeleton())
gizmo.running = gizmo.can_run()

func _on_ResetGizmo_pressed():
gizmo.reset()
print("BoneGizmo reset transform")

func _on_RunGizmo_toggled(button_pressed):
gizmo.allowed_to_run = button_pressed
gizmo.running = gizmo.can_run()
print("BoneGizmo running: ", gizmo.running)

func _on_CreateTracks_pressed():
if check_anim_track_operation():
gizmo.create_tracks()

func _on_InsertKey_pressed():
if check_anim_track_operation():
gizmo.insert_key()

func check_anim_track_operation() -> bool:
var passed = true
if gizmo.get_skeleton() == null:
print("BoneGizmo Invalid skeleton path")
passed = false
if gizmo.get_animation_player() == null:
print("BoneGizmo Invalid animation path")
passed = false
return passed

func _on_bone_finder_bone_selected(this, name, id) -> void:
gizmo.running = false
gizmo.edit_bone = name
gizmo.edit_bone_filter = this.filter
gizmo.running = gizmo.can_run()
Loading