소스 검색

Made bone handling for actual Bone2D a special case. Make custom bones appear like a custom (less important) option now.

Juan Linietsky 7 년 전
부모
커밋
bf561c4946
5개의 변경된 파일186개의 추가작업 그리고 36개의 파일을 삭제
  1. 61 0
      editor/icons/icon_bone_2_d.svg
  2. 89 33
      editor/plugins/canvas_item_editor_plugin.cpp
  3. 17 3
      editor/plugins/canvas_item_editor_plugin.h
  4. 15 0
      scene/2d/skeleton_2d.cpp
  5. 4 0
      scene/2d/skeleton_2d.h

+ 61 - 0
editor/icons/icon_bone_2_d.svg

@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="16"
+   height="16"
+   version="1.1"
+   viewBox="0 0 16 16"
+   id="svg6"
+   sodipodi:docname="icon_bone_2d.svg"
+   inkscape:version="0.92.3 (2405546, 2018-03-11)">
+  <metadata
+     id="metadata12">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs10" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="836"
+     inkscape:window-height="480"
+     id="namedview8"
+     showgrid="false"
+     inkscape:zoom="14.75"
+     inkscape:cx="8"
+     inkscape:cy="8"
+     inkscape:window-x="67"
+     inkscape:window-y="27"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg6" />
+  <g
+     transform="translate(0 -1036.4)"
+     id="g4"
+     style="fill:#a5b7f3;fill-opacity:1">
+    <path
+       d="m10.478 1037.4a2.4664 2.4663 0 0 0 -1.7804 0.7205 2.4664 2.4663 0 0 0 -0.31408 3.1041l-3.559 3.5608a2.4664 2.4663 0 0 0 -3.1023 0.3121 2.4664 2.4663 0 0 0 0 3.4876 2.4664 2.4663 0 0 0 1.397 0.6955 2.4664 2.4663 0 0 0 0.69561 1.397 2.4664 2.4663 0 0 0 3.4877 0 2.4664 2.4663 0 0 0 0.31408 -3.1041l3.5609-3.5608a2.4664 2.4663 0 0 0 3.1004 -0.3102 2.4664 2.4663 0 0 0 0 -3.4875 2.4664 2.4663 0 0 0 -1.397 -0.6974 2.4664 2.4663 0 0 0 -0.69561 -1.3971 2.4664 2.4663 0 0 0 -1.7072 -0.7205z"
+       fill="#fc9c9c"
+       id="path2"
+       style="fill:#a5b7f3;fill-opacity:1" />
+  </g>
+</svg>

+ 89 - 33
editor/plugins/canvas_item_editor_plugin.cpp

@@ -44,6 +44,7 @@
 #include "scene/2d/particles_2d.h"
 #include "scene/2d/polygon_2d.h"
 #include "scene/2d/screen_button.h"
+#include "scene/2d/skeleton_2d.h"
 #include "scene/2d/sprite.h"
 #include "scene/gui/grid_container.h"
 #include "scene/gui/nine_patch_rect.h"
@@ -2590,27 +2591,27 @@ void CanvasItemEditor::_draw_bones() {
 		Color bone_selected_color = EditorSettings::get_singleton()->get("editors/2d/bone_selected_color");
 		int bone_outline_size = EditorSettings::get_singleton()->get("editors/2d/bone_outline_size");
 
-		for (Map<ObjectID, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
+		for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
 
 			E->get().from = Vector2();
 			E->get().to = Vector2();
 
-			Node2D *n2d = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key()));
-			if (!n2d)
-				continue;
+			Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key().from));
+			Node2D *to_node = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key().to));
 
-			if (!n2d->get_parent())
+			if (!from_node)
 				continue;
 
-			CanvasItem *pi = n2d->get_parent_item();
-
-			Node2D *pn2d = Object::cast_to<Node2D>(n2d->get_parent());
-
-			if (!pn2d)
+			if (!to_node && E->get().length == 0)
 				continue;
 
-			Vector2 from = transform.xform(pn2d->get_global_position());
-			Vector2 to = transform.xform(n2d->get_global_position());
+			Vector2 from = transform.xform(from_node->get_global_position());
+			Vector2 to;
+
+			if (to_node)
+				to = transform.xform(to_node->get_global_position());
+			else
+				to = transform.xform(from_node->get_global_transform().xform(Vector2(E->get().length, 0)));
 
 			E->get().from = from;
 			E->get().to = to;
@@ -2635,7 +2636,7 @@ void CanvasItemEditor::_draw_bones() {
 			bone_shape_outline.push_back(from + rel * 0.2 - relt - reltn * bone_outline_size);
 
 			Vector<Color> colors;
-			if (pi->has_meta("_edit_ik_")) {
+			if (from_node->has_meta("_edit_ik_")) {
 
 				colors.push_back(bone_ik_color);
 				colors.push_back(bone_ik_color);
@@ -2649,7 +2650,8 @@ void CanvasItemEditor::_draw_bones() {
 			}
 
 			Vector<Color> outline_colors;
-			if (editor_selection->is_selected(pi)) {
+
+			if (editor_selection->is_selected(from_node)) {
 				outline_colors.push_back(bone_selected_color);
 				outline_colors.push_back(bone_selected_color);
 				outline_colors.push_back(bone_selected_color);
@@ -2790,26 +2792,71 @@ void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p
 	}
 }
 
-void CanvasItemEditor::_build_bones_list(Node *p_node) {
-	ERR_FAIL_COND(!p_node);
+bool CanvasItemEditor::_build_bones_list(Node *p_node) {
+	ERR_FAIL_COND_V(!p_node, false);
+
+	bool has_child_bones = false;
 
 	for (int i = 0; i < p_node->get_child_count(); i++) {
-		_build_bones_list(p_node->get_child(i));
+		if (_build_bones_list(p_node->get_child(i))) {
+			has_child_bones = true;
+		}
 	}
 
 	CanvasItem *c = Object::cast_to<CanvasItem>(p_node);
-	if (c && c->is_visible_in_tree()) {
-		if (c->has_meta("_edit_bone_")) {
+	if (!c)
+		return false;
+
+	CanvasItem *p = c->get_parent_item();
+	if (!p)
+		return false;
+
+	if (!p->is_visible())
+		return false;
+
+	if (Object::cast_to<Bone2D>(c)) {
+
+		if (Object::cast_to<Bone2D>(p)) {
+			BoneKey bk;
+			bk.from = p->get_instance_id();
+			bk.to = c->get_instance_id();
+			if (!bone_list.has(bk)) {
+				BoneList b;
+				b.length = 0;
+				bone_list[bk] = b;
+			}
+
+			bone_list[bk].last_pass = bone_last_frame;
+		}
 
-			ObjectID id = c->get_instance_id();
-			if (!bone_list.has(id)) {
-				BoneList bone;
-				bone_list[id] = bone;
+		if (!has_child_bones) {
+			BoneKey bk;
+			bk.from = c->get_instance_id();
+			bk.to = 0;
+			if (!bone_list.has(bk)) {
+				BoneList b;
+				b.length = 0;
+				bone_list[bk] = b;
 			}
+			bone_list[bk].last_pass = bone_last_frame;
+		}
 
-			bone_list[id].last_pass = bone_last_frame;
+		return true;
+	}
+	if (c->has_meta("_edit_bone_")) {
+
+		BoneKey bk;
+		bk.from = c->get_parent()->get_instance_id();
+		bk.to = c->get_instance_id();
+		if (!bone_list.has(bk)) {
+			BoneList b;
+			b.length = 0;
+			bone_list[bk] = b;
 		}
+		bone_list[bk].last_pass = bone_last_frame;
 	}
+
+	return false;
 }
 
 void CanvasItemEditor::_draw_viewport() {
@@ -2936,9 +2983,9 @@ void CanvasItemEditor::_notification(int p_what) {
 		// Show / Hide the layout button
 		presets_menu->set_visible(nb_control > 0 && nb_control == selection.size());
 
-		for (Map<ObjectID, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
+		for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
 
-			Object *b = ObjectDB::get_instance(E->key());
+			Object *b = ObjectDB::get_instance(E->key().from);
 			if (!b) {
 
 				viewport->update();
@@ -2950,9 +2997,18 @@ void CanvasItemEditor::_notification(int p_what) {
 				continue;
 			}
 
-			if (b2->get_global_transform() != E->get().xform) {
+			Transform2D global_xform = b2->get_global_transform();
+
+			if (global_xform != E->get().xform) {
+
+				E->get().xform = global_xform;
+				viewport->update();
+			}
+
+			Bone2D *bone = Object::cast_to<Bone2D>(b);
+			if (bone && bone->get_default_length() != E->get().length) {
 
-				E->get().xform = b2->get_global_transform();
+				E->get().length = bone->get_default_length();
 				viewport->update();
 			}
 		}
@@ -3088,8 +3144,8 @@ void CanvasItemEditor::_update_scrollbars() {
 		_build_bones_list(editor->get_edited_scene());
 	}
 
-	List<Map<ObjectID, BoneList>::Element *> bone_to_erase;
-	for (Map<ObjectID, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
+	List<Map<BoneKey, BoneList>::Element *> bone_to_erase;
+	for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
 		if (E->get().last_pass != bone_last_frame) {
 			bone_to_erase.push_back(E);
 		}
@@ -4248,13 +4304,13 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
 
 	p = skeleton_menu->get_popup();
 	p->set_hide_on_checkable_item_selection(false);
-	p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bones"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B), SKELETON_MAKE_BONES);
-	p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Bones")), SKELETON_CLEAR_BONES);
-	p->add_separator();
 	p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES);
 	p->add_separator();
 	p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN);
 	p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN);
+	p->add_separator();
+	p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Custom Bone(s) from Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B), SKELETON_MAKE_BONES);
+	p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Custom Bones")), SKELETON_CLEAR_BONES);
 	p->connect("id_pressed", this, "_popup_callback");
 
 	hb->add_child(memnew(VSeparator));

+ 17 - 3
editor/plugins/canvas_item_editor_plugin.h

@@ -264,12 +264,26 @@ class CanvasItemEditor : public VBoxContainer {
 	struct BoneList {
 
 		Transform2D xform;
+		float length;
+		uint64_t last_pass;
 		Vector2 from;
 		Vector2 to;
-		uint64_t last_pass;
 	};
+
 	uint64_t bone_last_frame;
-	Map<ObjectID, BoneList> bone_list;
+
+	struct BoneKey {
+		ObjectID from;
+		ObjectID to;
+		_FORCE_INLINE_ bool operator<(const BoneKey &p_key) const {
+			if (from == p_key.from)
+				return to < p_key.to;
+			else
+				return from < p_key.from;
+		}
+	};
+
+	Map<BoneKey, BoneList> bone_list;
 
 	struct PoseClipboard {
 		Vector2 pos;
@@ -366,7 +380,7 @@ class CanvasItemEditor : public VBoxContainer {
 	void _selection_menu_hide();
 
 	UndoRedo *undo_redo;
-	void _build_bones_list(Node *p_node);
+	bool _build_bones_list(Node *p_node);
 
 	List<CanvasItem *> _get_edited_canvas_items(bool retreive_locked = false, bool remove_canvas_item_if_parent_in_selection = true);
 	Rect2 _get_encompassing_rect_from_list(List<CanvasItem *> p_list);

+ 15 - 0
scene/2d/skeleton_2d.cpp

@@ -56,7 +56,11 @@ void Bone2D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_skeleton_rest"), &Bone2D::get_skeleton_rest);
 	ClassDB::bind_method(D_METHOD("get_index_in_skeleton"), &Bone2D::get_index_in_skeleton);
 
+	ClassDB::bind_method(D_METHOD("set_default_length", "default_length"), &Bone2D::set_default_length);
+	ClassDB::bind_method(D_METHOD("get_default_length"), &Bone2D::get_default_length);
+
 	ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D,"rest"),"set_rest","get_rest");
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"default_length",PROPERTY_HINT_RANGE,"1,1024,1"),"set_default_length","get_default_length");
 }
 
 void Bone2D::set_rest(const Transform2D &p_rest) {
@@ -84,6 +88,16 @@ void Bone2D::apply_rest() {
 	set_transform(rest);
 }
 
+void Bone2D::set_default_length(float p_length) {
+
+	default_length=p_length;
+
+}
+
+float Bone2D::get_default_length() const {
+	return default_length;
+}
+
 int Bone2D::get_index_in_skeleton() const {
 	ERR_FAIL_COND_V(!skeleton,-1);
 	skeleton->_update_bone_setup();
@@ -118,6 +132,7 @@ Bone2D::Bone2D() {
 	skeleton = NULL;
 	parent_bone = NULL;
 	skeleton_index=-1;
+	default_length=16;
 	set_notify_local_transform(true);
 	//this is a clever hack so the bone knows no rest has been set yet, allowing to show an error.
 	for(int i=0;i<3;i++) {

+ 4 - 0
scene/2d/skeleton_2d.h

@@ -11,6 +11,7 @@ class Bone2D : public Node2D {
 	Bone2D *parent_bone;
 	Skeleton2D *skeleton;
 	Transform2D rest;
+	float default_length;
 
 friend class Skeleton2D;
 	int skeleton_index;
@@ -27,6 +28,9 @@ public:
 
 	String get_configuration_warning() const;
 
+	void set_default_length(float p_length);
+	float get_default_length() const;
+
 	int get_index_in_skeleton() const;
 
 	Bone2D();