From 7cd867c3fe48187dced1060dedb22cc82f5aa094 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 21 Feb 2018 17:23:27 -0300 Subject: [PATCH] 2D Skeletons WORK IN PROGRESS --- drivers/dummy/rasterizer_dummy.h | 2 +- drivers/gles3/rasterizer_canvas_gles3.cpp | 2 +- drivers/gles3/rasterizer_canvas_gles3.h | 2 +- editor/editor_node.cpp | 2 + editor/plugins/skeleton_2d_editor_plugin.cpp | 115 ++++++++++ editor/plugins/skeleton_2d_editor_plugin.h | 55 +++++ scene/2d/canvas_item.cpp | 6 +- scene/2d/canvas_item.h | 2 +- scene/2d/mesh_instance_2d.cpp | 2 +- scene/2d/skeleton_2d.cpp | 210 +++++++++++++++++++ scene/2d/skeleton_2d.h | 68 ++++++ servers/visual/rasterizer.h | 6 +- servers/visual/visual_server_canvas.cpp | 19 +- servers/visual/visual_server_canvas.h | 7 +- servers/visual/visual_server_raster.h | 5 +- servers/visual/visual_server_wrap_mt.h | 5 +- servers/visual_server.h | 6 +- 17 files changed, 488 insertions(+), 26 deletions(-) create mode 100644 editor/plugins/skeleton_2d_editor_plugin.cpp create mode 100644 editor/plugins/skeleton_2d_editor_plugin.h create mode 100644 scene/2d/skeleton_2d.cpp create mode 100644 scene/2d/skeleton_2d.h 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(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 &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 &p_mesh, const Ref &p_texture, const Ref &p_normal_map, RID p_skeleton) { +void CanvasItem::draw_mesh(const Ref &p_mesh, const Ref &p_texture, const Ref &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 &p_multimesh, const Ref &p_texture, const Ref &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()), DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("draw_mesh", "mesh", "texture", "normal_map"), &CanvasItem::draw_mesh, DEFVAL(Ref())); ClassDB::bind_method(D_METHOD("draw_multimesh", "mesh", "texture", "normal_map"), &CanvasItem::draw_mesh, DEFVAL(Ref())); 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 &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), Ref p_texture = Ref(), const Ref &p_normal_map = Ref(), bool p_antialiased = false); void draw_colored_polygon(const Vector &p_points, const Color &p_color, const Vector &p_uvs = Vector(), Ref p_texture = Ref(), const Ref &p_normal_map = Ref(), bool p_antialiased = false); - void draw_mesh(const Ref &p_mesh, const Ref &p_texture, const Ref &p_normal_map, RID p_skeleton); + void draw_mesh(const Ref &p_mesh, const Ref &p_texture, const Ref &p_normal_map); void draw_multimesh(const Ref &p_multimesh, const Ref &p_texture, const Ref &p_normal_map); void draw_string(const Ref &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(parent); + skeleton = NULL; + while (parent) { + skeleton = Object::cast_to(parent); + if (skeleton) + break; + if (!Object::cast_to(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(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 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(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 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 &p_points, const Vector &p_colors, const Vector &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 &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), RID p_texture = RID(), RID p_normal_map = RID(), bool p_antialiased = false); void canvas_item_add_triangle_array(RID p_item, const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), 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 &, const Vector &, const Vector &, RID, float, RID) BIND7(canvas_item_add_polygon, RID, const Vector &, const Vector &, const Vector &, RID, RID, bool) BIND8(canvas_item_add_triangle_array, RID, const Vector &, const Vector &, const Vector &, const Vector &, 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 &, const Vector &, const Vector &, RID, float, RID) FUNC7(canvas_item_add_polygon, RID, const Vector &, const Vector &, const Vector &, RID, RID, bool) FUNC8(canvas_item_add_triangle_array, RID, const Vector &, const Vector &, const Vector &, const Vector &, 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 &p_points, const Vector &p_colors, const Vector &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 &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), 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 &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), 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;