summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/dummy/rasterizer_dummy.h2
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp2
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h2
-rw-r--r--editor/editor_node.cpp2
-rw-r--r--editor/plugins/skeleton_2d_editor_plugin.cpp115
-rw-r--r--editor/plugins/skeleton_2d_editor_plugin.h55
-rw-r--r--scene/2d/canvas_item.cpp6
-rw-r--r--scene/2d/canvas_item.h2
-rw-r--r--scene/2d/mesh_instance_2d.cpp2
-rw-r--r--scene/2d/skeleton_2d.cpp210
-rw-r--r--scene/2d/skeleton_2d.h68
-rw-r--r--servers/visual/rasterizer.h6
-rw-r--r--servers/visual/visual_server_canvas.cpp19
-rw-r--r--servers/visual/visual_server_canvas.h7
-rw-r--r--servers/visual/visual_server_raster.h5
-rw-r--r--servers/visual/visual_server_wrap_mt.h5
-rw-r--r--servers/visual_server.h6
17 files changed, 488 insertions, 26 deletions
diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h
index 4a7b8fd3a4..5836f5a700 100644
--- a/drivers/dummy/rasterizer_dummy.h
+++ b/drivers/dummy/rasterizer_dummy.h
@@ -619,7 +619,7 @@ public:
void canvas_begin(){};
void canvas_end(){};
- void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light){};
+ void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light,const Transform2D& p_transform){};
void canvas_debug_viewport_shadows(Light *p_lights_with_shadow){};
void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache) {}
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index d4b6c8577e..85fd565f5b 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -1042,7 +1042,7 @@ void RasterizerCanvasGLES3::_copy_texscreen(const Rect2 &p_rect) {
glEnable(GL_BLEND);
}
-void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light) {
+void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_transform) {
Item *current_clip = NULL;
RasterizerStorageGLES3::Shader *shader_cache = NULL;
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index 9f1a9466f1..1dc17f98d5 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -129,7 +129,7 @@ public:
_FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip);
_FORCE_INLINE_ void _copy_texscreen(const Rect2 &p_rect);
- virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light);
+ virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_transform);
virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow);
virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, CameraMatrix *p_xform_cache);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index c584619931..8132575479 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -99,6 +99,7 @@
#include "editor/plugins/script_text_editor.h"
#include "editor/plugins/shader_editor_plugin.h"
#include "editor/plugins/shader_graph_editor_plugin.h"
+#include "editor/plugins/skeleton_2d_editor_plugin.h"
#include "editor/plugins/spatial_editor_plugin.h"
#include "editor/plugins/sprite_editor_plugin.h"
#include "editor/plugins/sprite_frames_editor_plugin.h"
@@ -5673,6 +5674,7 @@ EditorNode::EditorNode() {
add_editor_plugin(memnew(MeshLibraryEditorPlugin(this)));
add_editor_plugin(memnew(StyleBoxEditorPlugin(this)));
add_editor_plugin(memnew(SpriteEditorPlugin(this)));
+ add_editor_plugin(memnew(Skeleton2DEditorPlugin(this)));
add_editor_plugin(memnew(ParticlesEditorPlugin(this)));
add_editor_plugin(memnew(ResourcePreloaderEditorPlugin(this)));
add_editor_plugin(memnew(ItemListEditorPlugin(this)));
diff --git a/editor/plugins/skeleton_2d_editor_plugin.cpp b/editor/plugins/skeleton_2d_editor_plugin.cpp
new file mode 100644
index 0000000000..6bf94b95eb
--- /dev/null
+++ b/editor/plugins/skeleton_2d_editor_plugin.cpp
@@ -0,0 +1,115 @@
+#include "skeleton_2d_editor_plugin.h"
+
+#include "canvas_item_editor_plugin.h"
+#include "scene/2d/mesh_instance_2d.h"
+#include "scene/gui/box_container.h"
+#include "thirdparty/misc/clipper.hpp"
+
+void Skeleton2DEditor::_node_removed(Node *p_node) {
+
+ if (p_node == node) {
+ node = NULL;
+ options->hide();
+ }
+}
+
+void Skeleton2DEditor::edit(Skeleton2D *p_sprite) {
+
+ node = p_sprite;
+}
+
+void Skeleton2DEditor::_menu_option(int p_option) {
+
+ switch (p_option) {
+ case MENU_OPTION_MAKE_REST: {
+
+ if (node->get_bone_count() == 0) {
+ err_dialog->set_text(TTR("This skeleton has no bones, create some children Bone2D nodes."));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Create Rest Pose from Bones");
+ for (int i = 0; i < node->get_bone_count(); i++) {
+ Bone2D *bone = node->get_bone(i);
+ ur->add_do_method(bone, "set_rest", bone->get_transform());
+ ur->add_undo_method(bone, "set_rest", bone->get_rest());
+ }
+ ur->commit_action();
+
+ } break;
+ case MENU_OPTION_SET_REST: {
+ if (node->get_bone_count() == 0) {
+ err_dialog->set_text(TTR("This skeleton has no bones, create some children Bone2D nodes."));
+ err_dialog->popup_centered_minsize();
+ return;
+ }
+ UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Set Rest Pose to Bones");
+ for (int i = 0; i < node->get_bone_count(); i++) {
+ Bone2D *bone = node->get_bone(i);
+ ur->add_do_method(bone, "set_transform", bone->get_rest());
+ ur->add_undo_method(bone, "set_transform", bone->get_transform());
+ }
+ ur->commit_action();
+
+ } break;
+ }
+}
+
+void Skeleton2DEditor::_bind_methods() {
+
+ ClassDB::bind_method("_menu_option", &Skeleton2DEditor::_menu_option);
+}
+
+Skeleton2DEditor::Skeleton2DEditor() {
+
+ options = memnew(MenuButton);
+
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(options);
+
+ options->set_text(TTR("Skeleton2D"));
+ options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Skeleton2D", "EditorIcons"));
+
+ options->get_popup()->add_item(TTR("Make Rest Pose (From Bones)"), MENU_OPTION_MAKE_REST);
+ options->get_popup()->add_separator();
+ options->get_popup()->add_item(TTR("Set Bones to Rest Pose"), MENU_OPTION_SET_REST);
+
+ options->get_popup()->connect("id_pressed", this, "_menu_option");
+
+ err_dialog = memnew(AcceptDialog);
+ add_child(err_dialog);
+}
+
+void Skeleton2DEditorPlugin::edit(Object *p_object) {
+
+ sprite_editor->edit(Object::cast_to<Skeleton2D>(p_object));
+}
+
+bool Skeleton2DEditorPlugin::handles(Object *p_object) const {
+
+ return p_object->is_class("Skeleton2D");
+}
+
+void Skeleton2DEditorPlugin::make_visible(bool p_visible) {
+
+ if (p_visible) {
+ sprite_editor->options->show();
+ } else {
+
+ sprite_editor->options->hide();
+ sprite_editor->edit(NULL);
+ }
+}
+
+Skeleton2DEditorPlugin::Skeleton2DEditorPlugin(EditorNode *p_node) {
+
+ editor = p_node;
+ sprite_editor = memnew(Skeleton2DEditor);
+ editor->get_viewport()->add_child(sprite_editor);
+
+ //sprite_editor->options->hide();
+}
+
+Skeleton2DEditorPlugin::~Skeleton2DEditorPlugin() {
+}
diff --git a/editor/plugins/skeleton_2d_editor_plugin.h b/editor/plugins/skeleton_2d_editor_plugin.h
new file mode 100644
index 0000000000..bbe2a3a6f2
--- /dev/null
+++ b/editor/plugins/skeleton_2d_editor_plugin.h
@@ -0,0 +1,55 @@
+#ifndef SKELETON_2D_EDITOR_PLUGIN_H
+#define SKELETON_2D_EDITOR_PLUGIN_H
+
+#include "editor/editor_node.h"
+#include "editor/editor_plugin.h"
+#include "scene/2d/skeleton_2d.h"
+#include "scene/gui/spin_box.h"
+
+class Skeleton2DEditor : public Control {
+
+ GDCLASS(Skeleton2DEditor, Control);
+
+ enum Menu {
+ MENU_OPTION_MAKE_REST,
+ MENU_OPTION_SET_REST,
+ };
+
+ Skeleton2D *node;
+
+ MenuButton *options;
+ AcceptDialog *err_dialog;
+
+ void _menu_option(int p_option);
+
+ //void _create_uv_lines();
+ friend class Skeleton2DEditorPlugin;
+
+protected:
+ void _node_removed(Node *p_node);
+ static void _bind_methods();
+
+public:
+ void edit(Skeleton2D *p_sprite);
+ Skeleton2DEditor();
+};
+
+class Skeleton2DEditorPlugin : public EditorPlugin {
+
+ GDCLASS(Skeleton2DEditorPlugin, EditorPlugin);
+
+ Skeleton2DEditor *sprite_editor;
+ EditorNode *editor;
+
+public:
+ virtual String get_name() const { return "Skeleton2D"; }
+ bool has_main_screen() const { return false; }
+ virtual void edit(Object *p_object);
+ virtual bool handles(Object *p_object) const;
+ virtual void make_visible(bool p_visible);
+
+ Skeleton2DEditorPlugin(EditorNode *p_node);
+ ~Skeleton2DEditorPlugin();
+};
+
+#endif // SKELETON_2D_EDITOR_PLUGIN_H
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 8d7fce8cc4..5cca5705a0 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -779,13 +779,13 @@ void CanvasItem::draw_colored_polygon(const Vector<Point2> &p_points, const Colo
VisualServer::get_singleton()->canvas_item_add_polygon(canvas_item, p_points, colors, p_uvs, rid, rid_normal, p_antialiased);
}
-void CanvasItem::draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture> &p_texture, const Ref<Texture> &p_normal_map, RID p_skeleton) {
+void CanvasItem::draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture> &p_texture, const Ref<Texture> &p_normal_map) {
ERR_FAIL_COND(p_mesh.is_null());
RID texture_rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
RID normal_map_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID();
- VisualServer::get_singleton()->canvas_item_add_mesh(canvas_item, p_mesh->get_rid(), texture_rid, normal_map_rid, p_skeleton);
+ VisualServer::get_singleton()->canvas_item_add_mesh(canvas_item, p_mesh->get_rid(), texture_rid, normal_map_rid);
}
void CanvasItem::draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Texture> &p_texture, const Ref<Texture> &p_normal_map) {
@@ -1032,7 +1032,7 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_colored_polygon", "points", "color", "uvs", "texture", "normal_map", "antialiased"), &CanvasItem::draw_colored_polygon, DEFVAL(PoolVector2Array()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_string", "font", "position", "text", "modulate", "clip_w"), &CanvasItem::draw_string, DEFVAL(Color(1, 1, 1)), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("draw_char", "font", "position", "char", "next", "modulate"), &CanvasItem::draw_char, DEFVAL(Color(1, 1, 1)));
- ClassDB::bind_method(D_METHOD("draw_mesh", "mesh", "texture", "normal_map", "skeleton"), &CanvasItem::draw_mesh, DEFVAL(Ref<Texture>()), DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("draw_mesh", "mesh", "texture", "normal_map"), &CanvasItem::draw_mesh, DEFVAL(Ref<Texture>()));
ClassDB::bind_method(D_METHOD("draw_multimesh", "mesh", "texture", "normal_map"), &CanvasItem::draw_mesh, DEFVAL(Ref<Texture>()));
ClassDB::bind_method(D_METHOD("draw_set_transform", "position", "rotation", "scale"), &CanvasItem::draw_set_transform);
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index d0bf584b38..980fcb4109 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -283,7 +283,7 @@ public:
void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture> p_texture = Ref<Texture>(), const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_antialiased = false);
void draw_colored_polygon(const Vector<Point2> &p_points, const Color &p_color, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture> p_texture = Ref<Texture>(), const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_antialiased = false);
- void draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture> &p_texture, const Ref<Texture> &p_normal_map, RID p_skeleton);
+ void draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture> &p_texture, const Ref<Texture> &p_normal_map);
void draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Texture> &p_texture, const Ref<Texture> &p_normal_map);
void draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, const Color &p_modulate = Color(1, 1, 1), int p_clip_w = -1);
diff --git a/scene/2d/mesh_instance_2d.cpp b/scene/2d/mesh_instance_2d.cpp
index 184942663f..adbb227d0c 100644
--- a/scene/2d/mesh_instance_2d.cpp
+++ b/scene/2d/mesh_instance_2d.cpp
@@ -4,7 +4,7 @@ void MeshInstance2D::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
if (mesh.is_valid()) {
- draw_mesh(mesh, texture, normal_map, RID());
+ draw_mesh(mesh, texture, normal_map);
}
}
}
diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp
new file mode 100644
index 0000000000..705e82bcbb
--- /dev/null
+++ b/scene/2d/skeleton_2d.cpp
@@ -0,0 +1,210 @@
+#include "skeleton_2d.h"
+
+void Bone2D::_notification(int p_what) {
+
+ if (p_what == NOTIFICATION_ENTER_TREE) {
+ Node *parent = get_parent();
+ parent_bone = Object::cast_to<Bone2D>(parent);
+ skeleton = NULL;
+ while (parent) {
+ skeleton = Object::cast_to<Skeleton2D>(parent);
+ if (skeleton)
+ break;
+ if (!Object::cast_to<Bone2D>(parent))
+ break; //skeletons must be chained to Bone2Ds.
+ }
+
+ if (skeleton) {
+ Skeleton2D::Bone bone;
+ bone.bone = this;
+ skeleton->bones.push_back(bone);
+ skeleton->_make_bone_setup_dirty();
+ }
+ }
+ if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
+ if (skeleton) {
+ skeleton->_make_transform_dirty();
+ }
+ }
+
+ if (p_what == NOTIFICATION_EXIT_TREE) {
+ if (skeleton) {
+ for (int i = 0; i < skeleton->bones.size(); i++) {
+ if (skeleton->bones[i].bone == this) {
+ skeleton->bones.remove(i);
+ break;
+ }
+ }
+ skeleton->_make_bone_setup_dirty();
+ skeleton = NULL;
+ }
+ parent_bone = NULL;
+ }
+}
+void Bone2D::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_rest", "rest"), &Bone2D::set_rest);
+ ClassDB::bind_method(D_METHOD("get_rest"), &Bone2D::get_rest);
+ ClassDB::bind_method(D_METHOD("apply_rest"), &Bone2D::apply_rest);
+}
+
+void Bone2D::set_rest(const Transform2D &p_rest) {
+ rest = p_rest;
+ if (skeleton)
+ skeleton->_make_bone_setup_dirty();
+}
+
+Transform2D Bone2D::get_rest() const {
+ return rest;
+}
+
+Transform2D Bone2D::get_skeleton_rest() const {
+
+ if (parent_bone) {
+ return parent_bone->get_skeleton_rest() * rest;
+ } else {
+ return rest;
+ }
+}
+
+void Bone2D::apply_rest() {
+ set_transform(rest);
+}
+
+String Bone2D::get_configuration_warning() const {
+ if (!skeleton) {
+ if (parent_bone) {
+ return TTR("This Bone2D chain should end at a Skeleton2D node.");
+ } else {
+ return TTR("A Bone2D only works with a Skeleton2D or another Bone2D as parent node.");
+ }
+ }
+
+ return Node2D::get_configuration_warning();
+}
+
+Bone2D::Bone2D() {
+ skeleton = NULL;
+ parent_bone = NULL;
+ set_notify_local_transform(true);
+}
+
+//////////////////////////////////////
+
+void Skeleton2D::_make_bone_setup_dirty() {
+
+ if (bone_setup_dirty)
+ return;
+ bone_setup_dirty = true;
+ if (is_inside_tree()) {
+ call_deferred("_update_bone_setup");
+ }
+}
+
+void Skeleton2D::_update_bone_setup() {
+
+ if (!bone_setup_dirty)
+ return;
+
+ bone_setup_dirty = false;
+ VS::get_singleton()->skeleton_allocate(skeleton, bones.size(), true);
+
+ bones.sort(); //sorty so they are always in the same order/index
+
+ for (int i = 0; i < bones.size(); i++) {
+ bones[i].rest_inverse = bones[i].bone->get_skeleton_rest(); //bind pose
+ }
+
+ transform_dirty = true;
+ _update_transform();
+}
+
+void Skeleton2D::_make_transform_dirty() {
+
+ if (transform_dirty)
+ return;
+ transform_dirty = true;
+ if (is_inside_tree()) {
+ call_deferred("_update_transform");
+ }
+}
+
+void Skeleton2D::_update_transform() {
+
+ if (bone_setup_dirty) {
+ _update_bone_setup();
+ return; //above will update transform anyway
+ }
+ if (!transform_dirty)
+ return;
+
+ transform_dirty = false;
+
+ Transform2D global_xform = get_global_transform();
+ Transform2D global_xform_inverse = global_xform.affine_inverse();
+
+ for (int i = 0; i < bones.size(); i++) {
+
+ Transform2D final_xform = bones[i].rest_inverse * bones[i].bone->get_relative_transform_to_parent(this);
+ VS::get_singleton()->skeleton_bone_set_transform_2d(skeleton, i, global_xform * (final_xform * global_xform_inverse));
+ }
+}
+
+int Skeleton2D::get_bone_count() const {
+
+ ERR_FAIL_COND_V(!is_inside_tree(), 0);
+
+ if (bone_setup_dirty) {
+ const_cast<Skeleton2D *>(this)->_update_bone_setup();
+ }
+
+ return bones.size();
+}
+
+Bone2D *Skeleton2D::get_bone(int p_idx) {
+
+ ERR_FAIL_COND_V(!is_inside_tree(), NULL);
+ ERR_FAIL_INDEX_V(p_idx, bones.size(), NULL);
+
+ return bones[p_idx].bone;
+}
+
+void Skeleton2D::_notification(int p_what) {
+
+ if (p_what == NOTIFICATION_READY) {
+
+ if (bone_setup_dirty)
+ _update_bone_setup();
+ if (transform_dirty)
+ _update_transform();
+ }
+
+ if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
+ _make_transform_dirty();
+ }
+}
+
+RID Skeleton2D::get_skeleton() const {
+ return skeleton;
+}
+void Skeleton2D::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_update_bone_setup"), &Skeleton2D::_update_bone_setup);
+ ClassDB::bind_method(D_METHOD("_update_transform"), &Skeleton2D::_update_transform);
+
+ ClassDB::bind_method(D_METHOD("get_bone_count"), &Skeleton2D::get_bone_count);
+ ClassDB::bind_method(D_METHOD("get_bone"), &Skeleton2D::get_bone);
+
+ ClassDB::bind_method(D_METHOD("get_skeleton"), &Skeleton2D::get_skeleton);
+}
+
+Skeleton2D::Skeleton2D() {
+ bone_setup_dirty = true;
+ transform_dirty = true;
+ skeleton = VS::get_singleton()->skeleton_create();
+}
+
+Skeleton2D::~Skeleton2D() {
+
+ VS::get_singleton()->free(skeleton);
+}
diff --git a/scene/2d/skeleton_2d.h b/scene/2d/skeleton_2d.h
new file mode 100644
index 0000000000..791af57bdf
--- /dev/null
+++ b/scene/2d/skeleton_2d.h
@@ -0,0 +1,68 @@
+#ifndef SKELETON_2D_H
+#define SKELETON_2D_H
+
+#include "scene/2d/node_2d.h"
+
+class Skeleton2D;
+
+class Bone2D : public Node2D {
+ GDCLASS(Bone2D, Node2D)
+
+ Bone2D *parent_bone;
+ Skeleton2D *skeleton;
+ Transform2D rest;
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ void set_rest(const Transform2D &p_rest);
+ Transform2D get_rest() const;
+ void apply_rest();
+ Transform2D get_skeleton_rest() const;
+
+ String get_configuration_warning() const;
+
+ Bone2D();
+};
+
+class Skeleton2D : public Node2D {
+ GDCLASS(Skeleton2D, Node2D);
+
+ friend class Bone2D;
+
+ struct Bone {
+ bool operator<(const Bone &p_bone) const {
+ p_bone.bone->is_greater_than(bone);
+ }
+ Bone2D *bone;
+ Transform2D rest_inverse;
+ };
+
+ Vector<Bone> bones;
+
+ bool bone_setup_dirty;
+ void _make_bone_setup_dirty();
+ void _update_bone_setup();
+
+ bool transform_dirty;
+ void _make_transform_dirty();
+ void _update_transform();
+
+ RID skeleton;
+
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+ int get_bone_count() const;
+ Bone2D *get_bone(int p_idx);
+
+ RID get_skeleton() const;
+ Skeleton2D();
+ ~Skeleton2D();
+};
+
+#endif // SKELETON_2D_H
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 378a05cdfe..8bf112b0de 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -749,7 +749,6 @@ public:
struct CommandMesh : public Command {
RID mesh;
- RID skeleton;
RID texture;
RID normal_map;
CommandMesh() { type = TYPE_MESH; }
@@ -758,7 +757,6 @@ public:
struct CommandMultiMesh : public Command {
RID multimesh;
- RID skeleton;
RID texture;
RID normal_map;
CommandMultiMesh() { type = TYPE_MULTIMESH; }
@@ -924,7 +922,7 @@ public:
case Item::Command::TYPE_MESH: {
const Item::CommandMesh *mesh = static_cast<const Item::CommandMesh *>(c);
- AABB aabb = RasterizerStorage::base_singleton->mesh_get_aabb(mesh->mesh, mesh->skeleton);
+ AABB aabb = RasterizerStorage::base_singleton->mesh_get_aabb(mesh->mesh, RID());
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
@@ -1016,7 +1014,7 @@ public:
virtual void canvas_begin() = 0;
virtual void canvas_end() = 0;
- virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light) = 0;
+ virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) = 0;
virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) = 0;
struct LightOccluderInstance : public RID_Data {
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index 330b2bd0d2..3e6e524117 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -46,7 +46,7 @@ void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Tra
for (int i = 0; i < z_range; i++) {
if (!z_list[i])
continue;
- VSG::canvas_render->canvas_render_items(z_list[i], VS::CANVAS_ITEM_Z_MIN + i, p_modulate, p_lights);
+ VSG::canvas_render->canvas_render_items(z_list[i], VS::CANVAS_ITEM_Z_MIN + i, p_modulate, p_lights, p_transform);
}
}
@@ -214,7 +214,7 @@ void VisualServerCanvas::render_canvas(Canvas *p_canvas, const Transform2D &p_tr
_light_mask_canvas_items(VS::CANVAS_ITEM_Z_MIN + i, z_list[i], p_masked_lights);
}
- VSG::canvas_render->canvas_render_items(z_list[i], VS::CANVAS_ITEM_Z_MIN + i, p_canvas->modulate, p_lights);
+ VSG::canvas_render->canvas_render_items(z_list[i], VS::CANVAS_ITEM_Z_MIN + i, p_canvas->modulate, p_lights, p_transform);
}
} else {
@@ -742,7 +742,7 @@ void VisualServerCanvas::canvas_item_add_set_transform(RID p_item, const Transfo
canvas_item->commands.push_back(tr);
}
-void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture, RID p_normal_map, RID p_skeleton) {
+void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture, RID p_normal_map) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -752,7 +752,6 @@ void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID
m->mesh = p_mesh;
m->texture = p_texture;
m->normal_map = p_normal_map;
- m->skeleton = p_skeleton;
canvas_item->commands.push_back(m);
}
@@ -776,7 +775,7 @@ void VisualServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles,
canvas_item->commands.push_back(part);
}
-void VisualServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture, RID p_normal_map, RID p_skeleton) {
+void VisualServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture, RID p_normal_map) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -784,7 +783,6 @@ void VisualServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p
Item::CommandMultiMesh *mm = memnew(Item::CommandMultiMesh);
ERR_FAIL_COND(!mm);
mm->multimesh = p_mesh;
- mm->skeleton = p_skeleton;
mm->texture = p_texture;
mm->normal_map = p_normal_map;
@@ -826,6 +824,15 @@ void VisualServerCanvas::canvas_item_set_z_as_relative_to_parent(RID p_item, boo
canvas_item->z_relative = p_enable;
}
+
+void VisualServerCanvas::canvas_item_attach_skeleton(RID p_item, RID p_skeleton) {
+
+ Item *canvas_item = canvas_item_owner.getornull(p_item);
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->skeleton = p_skeleton;
+}
+
void VisualServerCanvas::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect) {
Item *canvas_item = canvas_item_owner.getornull(p_item);
diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h
index 250ba5cb08..6a5a7623b6 100644
--- a/servers/visual/visual_server_canvas.h
+++ b/servers/visual/visual_server_canvas.h
@@ -51,6 +51,8 @@ public:
Vector<Item *> child_items;
+ RID skeleton;
+
Item() {
children_order_dirty = true;
E = NULL;
@@ -182,8 +184,8 @@ public:
void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID());
void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false);
void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID());
- void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture = RID(), RID p_normal_map = RID(), RID p_skeleton = RID());
- void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID(), RID p_skeleton = RID());
+ void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture = RID(), RID p_normal_map = RID());
+ void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID());
void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal, int p_h_frames, int p_v_frames);
void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform);
void canvas_item_add_clip_ignore(RID p_item, bool p_ignore);
@@ -191,6 +193,7 @@ public:
void canvas_item_set_z_index(RID p_item, int p_z);
void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable);
void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect);
+ void canvas_item_attach_skeleton(RID p_item, RID p_skeleton);
void canvas_item_clear(RID p_item);
void canvas_item_set_draw_index(RID p_item, int p_index);
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index b34fbbdec9..a94e110b5d 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -581,8 +581,8 @@ public:
BIND7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID)
BIND7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool)
BIND8(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, int, RID)
- BIND5(canvas_item_add_mesh, RID, const RID &, RID, RID, RID)
- BIND5(canvas_item_add_multimesh, RID, RID, RID, RID, RID)
+ BIND4(canvas_item_add_mesh, RID, const RID &, RID, RID)
+ BIND4(canvas_item_add_multimesh, RID, RID, RID, RID)
BIND6(canvas_item_add_particles, RID, RID, RID, RID, int, int)
BIND2(canvas_item_add_set_transform, RID, const Transform2D &)
BIND2(canvas_item_add_clip_ignore, RID, bool)
@@ -590,6 +590,7 @@ public:
BIND2(canvas_item_set_z_index, RID, int)
BIND2(canvas_item_set_z_as_relative_to_parent, RID, bool)
BIND3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &)
+ BIND2(canvas_item_attach_skeleton, RID, RID)
BIND1(canvas_item_clear, RID)
BIND2(canvas_item_set_draw_index, RID, int)
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index 5a126fb175..b91f80d137 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -499,8 +499,8 @@ public:
FUNC7(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID)
FUNC7(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, bool)
FUNC8(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, int, RID)
- FUNC5(canvas_item_add_mesh, RID, const RID &, RID, RID, RID)
- FUNC5(canvas_item_add_multimesh, RID, RID, RID, RID, RID)
+ FUNC4(canvas_item_add_mesh, RID, const RID &, RID, RID)
+ FUNC4(canvas_item_add_multimesh, RID, RID, RID, RID)
FUNC6(canvas_item_add_particles, RID, RID, RID, RID, int, int)
FUNC2(canvas_item_add_set_transform, RID, const Transform2D &)
FUNC2(canvas_item_add_clip_ignore, RID, bool)
@@ -508,6 +508,7 @@ public:
FUNC2(canvas_item_set_z_index, RID, int)
FUNC2(canvas_item_set_z_as_relative_to_parent, RID, bool)
FUNC3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &)
+ FUNC2(canvas_item_attach_skeleton, RID, RID)
FUNC1(canvas_item_clear, RID)
FUNC2(canvas_item_set_draw_index, RID, int)
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 521d0aece9..537588fd6f 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -846,8 +846,8 @@ public:
virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false) = 0;
virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID()) = 0;
- virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture = RID(), RID p_normal_map = RID(), RID p_skeleton = RID()) = 0;
- virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID(), RID p_skeleton = RID()) = 0;
+ virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, RID p_texture = RID(), RID p_normal_map = RID()) = 0;
+ virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID()) = 0;
virtual void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map, int p_h_frames, int p_v_frames) = 0;
virtual void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) = 0;
virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore) = 0;
@@ -856,6 +856,8 @@ public:
virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) = 0;
virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect) = 0;
+ virtual void canvas_item_attach_skeleton(RID p_item, RID p_skeleton) = 0;
+
virtual void canvas_item_clear(RID p_item) = 0;
virtual void canvas_item_set_draw_index(RID p_item, int p_index) = 0;