diff options
-rw-r--r-- | AUTHORS.md | 3 | ||||
-rw-r--r-- | DONORS.md | 42 | ||||
-rw-r--r-- | core/math/math_2d.cpp | 10 | ||||
-rw-r--r-- | core/math/math_2d.h | 2 | ||||
-rw-r--r-- | core/math/vector3.h | 6 | ||||
-rw-r--r-- | core/variant_call.cpp | 6 | ||||
-rw-r--r-- | doc/classes/Engine.xml | 6 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.cpp | 27 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.h | 1 | ||||
-rw-r--r-- | drivers/gles3/shaders/canvas.glsl | 64 | ||||
-rw-r--r-- | editor/editor_settings.cpp | 4 | ||||
-rw-r--r-- | editor/icons/icon_bone_2_d.svg | 61 | ||||
-rw-r--r-- | editor/plugins/canvas_item_editor_plugin.cpp | 227 | ||||
-rw-r--r-- | editor/plugins/canvas_item_editor_plugin.h | 25 | ||||
-rw-r--r-- | editor/plugins/polygon_2d_editor_plugin.cpp | 147 | ||||
-rw-r--r-- | editor/plugins/polygon_2d_editor_plugin.h | 4 | ||||
-rw-r--r-- | scene/2d/skeleton_2d.cpp | 15 | ||||
-rw-r--r-- | scene/2d/skeleton_2d.h | 4 | ||||
-rw-r--r-- | scene/resources/primitive_meshes.cpp | 16 | ||||
-rw-r--r-- | scene/resources/primitive_meshes.h | 4 |
20 files changed, 502 insertions, 172 deletions
diff --git a/AUTHORS.md b/AUTHORS.md index a5ef24e825..67563298f2 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -97,6 +97,7 @@ name is available. Ramesh Ravone (RameshRavone) Ray Koopa (RayKoopa) Rémi Verschelde (akien-mga) + Roberto F. Arroyo (robfram) Ruslan Mustakov (endragor) Saniko (sanikoyes) SaracenOne @@ -108,6 +109,7 @@ name is available. Wilhem Barbier (nounoursheureux) Will Nations (willnationsdev) Wilson E. Alvarez (Rubonnek) + Xavier Cho (mysticfall) Yuri Roubinski (Chaosus) Zher Huei Lee (leezh) ZuBsPaCe @@ -117,7 +119,6 @@ name is available. m4nu3lf marynate mrezai - robfram romulox-x rraallvv sersoong @@ -27,7 +27,7 @@ generous deed immortalized in the next stable release of Godot Engine. Christian Uldall Pedersen Christopher Igoe Christoph Woinke - codetrotter + Claudiu Dumitru E Hewert Hein-Pieter van Braam Igors Vaitkus @@ -61,10 +61,10 @@ generous deed immortalized in the next stable release of Godot Engine. Allen Schade Andreas Schüle Austen McRae - Benjamin Botwin Bernhard Liebl Catalin Moldovan DeepSquid + Duane Johnson Florian Breisch Gary Oberbrunner Johannes Wuensch @@ -72,13 +72,13 @@ generous deed immortalized in the next stable release of Godot Engine. Joshua Lesperance Libre-Dépanne Matthew Bennett + Paul LaMotte Ranoller - Rob Messick Svenne Krap Timothy Hagberg BanjoNode2D - Brandon + Beliar Chris Serino Conrad Curry Craig Smith @@ -87,18 +87,17 @@ generous deed immortalized in the next stable release of Godot Engine. Dexter Miguel Garrett Dockins Guilherme Felipe de C. G. da Silva - Harman Bains John Justo Delgado Baudí - Karsten Bock Laurence Bannister Rami Robert Willes Robin Arys - Rufus Sasparilla + Rufus Xavier Sarsaparilla ScottMakesGames Testus Maximus Thomas Bjarnelöf + William Connell Wojciech Chojnacki Xavier Tan Zaq Poi @@ -107,15 +106,19 @@ generous deed immortalized in the next stable release of Godot Engine. Alexey Dyadchenko Amanda Haldy Chris Brown + Chris Petrich Chris Wilson Cody Parker D Daniel Eliasinski + E.G. Eric Monson flesk François Cantin G Barnes GGGames.org + Giovanni Solimeno + Hasen Judy Heath Hayes Jeppe Zapp Jeremi Biernacki @@ -126,18 +129,18 @@ generous deed immortalized in the next stable release of Godot Engine. Justin Arnold Leandro Voltolino Lisandro Lorea - Marco Andrew Cafolla Markus Wiesner Marvin + Mohammad Taleb Nick Nikitin Pablo Cholaky Patrick Schnorbus Pete Goodwin Phyronnaz + SeokHui Lee Simon De Greve Sofox Ted - Travis Womack Trent McPheron Vladimir @@ -149,8 +152,7 @@ generous deed immortalized in the next stable release of Godot Engine. Alder Stefano Alessandro Senese Álvaro Domínguez López - Andrea Badii - Andrew Thomas + Anders Jensen-Urstad Anthony Bongiovanni Arda Erol Arthur S. Muszynski @@ -161,22 +163,24 @@ generous deed immortalized in the next stable release of Godot Engine. Benjamin Beshara Ben Vercammen Blair Allen - Bryanna M + Brandon Bryan Stevenson Carwyn Edwards Casey Foote Chris Chapin Christian Baune Christian Winter + Christopher Schmitt Collin Shooltz Daniel Egger Daniel Kaplan - Daniel Langegger + DanielMaximiano Daniel Mircea David David Cravens David May Dominik Wetzel + Edward Herbert Eric Martini Fabian Becker fengjiongmax @@ -193,11 +197,13 @@ generous deed immortalized in the next stable release of Godot Engine. Hunter Jones ialex32x Ivan Vodopiviz + Jahn Johansen Jaime Ruiz-Borau Vizárraga Jed Jeff Hungerford Joel Fivat Johan Lindberg + Jonas Rudlang Jonas Yamazaki Jonathan Martin Jonathan Nieto @@ -212,6 +218,7 @@ generous deed immortalized in the next stable release of Godot Engine. Kevin Boyer Kevin Kamper Meejach Petersen Klavdij Voncina + Krzysztof Jankowski Lars pfeffer Linus Lind Lundgren Macil @@ -231,12 +238,15 @@ generous deed immortalized in the next stable release of Godot Engine. Moritz Laass nee Neil Blakey-Milner + Nick Pavlica Niclas Eriksen - Nik Lee + Nicolás Montaña + Nicolas SAN AGUSTIN Niko Leopold nivardus Noi Sek Oleg Tyshchenko + Oleksandr Yemets Pablo Seibelt Pan Ip Pat LaBine @@ -252,6 +262,7 @@ generous deed immortalized in the next stable release of Godot Engine. Roger Smith Roman Tinkov Ryan Whited + Samuel El-Borai Sasori Olkof Scott D. Yelich Sootstone @@ -260,11 +271,12 @@ generous deed immortalized in the next stable release of Godot Engine. Thomas Bell Thomas Herzog & Xananax Thomas Kurz + Tomasz Wacławek Tom Larrow Tyler Stafos UltyX + Victor Victor Gonzalez Fernandez - Victor Holt Viktor Ferenczi werner mendizabal Wout Standaert diff --git a/core/math/math_2d.cpp b/core/math/math_2d.cpp index 3767d298a1..a053ffbd93 100644 --- a/core/math/math_2d.cpp +++ b/core/math/math_2d.cpp @@ -103,6 +103,16 @@ Vector2 Vector2::floor() const { return Vector2(Math::floor(x), Math::floor(y)); } +Vector2 Vector2::ceil() const { + + return Vector2(Math::ceil(x), Math::ceil(y)); +} + +Vector2 Vector2::round() const { + + return Vector2(Math::round(x), Math::round(y)); +} + Vector2 Vector2::rotated(real_t p_by) const { Vector2 v; diff --git a/core/math/math_2d.h b/core/math/math_2d.h index e7188da85b..611d47e3ff 100644 --- a/core/math/math_2d.h +++ b/core/math/math_2d.h @@ -162,6 +162,8 @@ struct Vector2 { } Vector2 floor() const; + Vector2 ceil() const; + Vector2 round() const; Vector2 snapped(const Vector2 &p_by) const; real_t aspect() const { return width / height; } diff --git a/core/math/vector3.h b/core/math/vector3.h index 10ec4f5641..3bbfd7627c 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -103,6 +103,7 @@ struct Vector3 { _FORCE_INLINE_ Vector3 floor() const; _FORCE_INLINE_ Vector3 sign() const; _FORCE_INLINE_ Vector3 ceil() const; + _FORCE_INLINE_ Vector3 round() const; _FORCE_INLINE_ real_t distance_to(const Vector3 &p_b) const; _FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_b) const; @@ -204,6 +205,11 @@ Vector3 Vector3::ceil() const { return Vector3(Math::ceil(x), Math::ceil(y), Math::ceil(z)); } +Vector3 Vector3::round() const { + + return Vector3(Math::round(x), Math::round(y), Math::round(z)); +} + Vector3 Vector3::linear_interpolate(const Vector3 &p_b, real_t p_t) const { return Vector3( diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 1b938e3f41..bd1cde5a82 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -344,6 +344,8 @@ struct _VariantCall { VCALL_LOCALMEM1R(Vector2, rotated); VCALL_LOCALMEM0R(Vector2, tangent); VCALL_LOCALMEM0R(Vector2, floor); + VCALL_LOCALMEM0R(Vector2, ceil); + VCALL_LOCALMEM0R(Vector2, round); VCALL_LOCALMEM1R(Vector2, snapped); VCALL_LOCALMEM0R(Vector2, aspect); VCALL_LOCALMEM1R(Vector2, dot); @@ -386,6 +388,7 @@ struct _VariantCall { VCALL_LOCALMEM0R(Vector3, abs); VCALL_LOCALMEM0R(Vector3, floor); VCALL_LOCALMEM0R(Vector3, ceil); + VCALL_LOCALMEM0R(Vector3, round); VCALL_LOCALMEM1R(Vector3, distance_to); VCALL_LOCALMEM1R(Vector3, distance_squared_to); VCALL_LOCALMEM1R(Vector3, angle_to); @@ -1519,6 +1522,8 @@ void register_variant_methods() { ADDFUNC1R(VECTOR2, VECTOR2, Vector2, rotated, REAL, "phi", varray()); ADDFUNC0R(VECTOR2, VECTOR2, Vector2, tangent, varray()); ADDFUNC0R(VECTOR2, VECTOR2, Vector2, floor, varray()); + ADDFUNC0R(VECTOR2, VECTOR2, Vector2, ceil, varray()); + ADDFUNC0R(VECTOR2, VECTOR2, Vector2, round, varray()); ADDFUNC1R(VECTOR2, VECTOR2, Vector2, snapped, VECTOR2, "by", varray()); ADDFUNC0R(VECTOR2, REAL, Vector2, aspect, varray()); ADDFUNC1R(VECTOR2, REAL, Vector2, dot, VECTOR2, "with", varray()); @@ -1560,6 +1565,7 @@ void register_variant_methods() { ADDFUNC0R(VECTOR3, VECTOR3, Vector3, abs, varray()); ADDFUNC0R(VECTOR3, VECTOR3, Vector3, floor, varray()); ADDFUNC0R(VECTOR3, VECTOR3, Vector3, ceil, varray()); + ADDFUNC0R(VECTOR3, VECTOR3, Vector3, round, varray()); ADDFUNC1R(VECTOR3, REAL, Vector3, distance_to, VECTOR3, "b", varray()); ADDFUNC1R(VECTOR3, REAL, Vector3, distance_squared_to, VECTOR3, "b", varray()); ADDFUNC1R(VECTOR3, REAL, Vector3, angle_to, VECTOR3, "to", varray()); diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml index ea3c404346..6384b4d0fd 100644 --- a/doc/classes/Engine.xml +++ b/doc/classes/Engine.xml @@ -46,9 +46,9 @@ <description> Returns the current engine version information in a Dictionary. - "major" - Holds the major version number as a String - "minor" - Holds the minor version number as a String - "patch" - Holds the patch version number as a String + "major" - Holds the major version number as an int + "minor" - Holds the minor version number as an int + "patch" - Holds the patch version number as an int "status" - Holds the status (e.g. "beta", "rc1", "rc2", ... "stable") as a String "build" - Holds the build name (e.g. "custom-build") as a String "string" - major + minor + patch + status + build in a single String diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 12da7351bd..b221a41893 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -287,7 +287,8 @@ void RasterizerCanvasGLES3::_set_texture_rect_mode(bool p_enable, bool p_ninepat state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform); state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, state.extra_matrix); if (state.using_skeleton) { - state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TO_OBJECT_LOCAL_MATRIX, state.skeleton_transform); + state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM, state.skeleton_transform); + state.canvas_shader.set_uniform(CanvasShaderGLES3::SKELETON_TRANSFORM_INVERSE, state.skeleton_transform_inverse); } if (storage->frame.current_rt) { state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height)); @@ -306,11 +307,17 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun uint32_t buffer_ofs = 0; //vertex +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_vertices); glEnableVertexAttribArray(VS::ARRAY_VERTEX); glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, false, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs); buffer_ofs += sizeof(Vector2) * p_vertex_count; //color +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif if (p_singlecolor) { glDisableVertexAttribArray(VS::ARRAY_COLOR); @@ -327,6 +334,10 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun buffer_ofs += sizeof(Color) * p_vertex_count; } +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif + if (p_uvs) { glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); @@ -338,11 +349,16 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun glDisableVertexAttribArray(VS::ARRAY_TEX_UV); } +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif + if (p_bones && p_weights) { glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(int) * 4 * p_vertex_count, p_bones); glEnableVertexAttribArray(VS::ARRAY_BONES); - glVertexAttribPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, false, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs); + //glVertexAttribPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, false, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs); + glVertexAttribIPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, sizeof(int) * 4, ((uint8_t *)0) + buffer_ofs); buffer_ofs += sizeof(int) * 4 * p_vertex_count; glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(float) * 4 * p_vertex_count, p_weights); @@ -355,6 +371,10 @@ void RasterizerCanvasGLES3::_draw_polygon(const int *p_indices, int p_index_coun glVertexAttrib4f(VS::ARRAY_WEIGHTS, 0, 0, 0, 0); } +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(buffer_ofs > data.polygon_buffer_size); +#endif + //bind the indices buffer. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices); @@ -1145,7 +1165,8 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons if (!skeleton->use_2d) { skeleton = NULL; } else { - state.skeleton_transform = ci->final_transform.affine_inverse() * (p_transform * skeleton->base_transform_2d); + state.skeleton_transform = p_transform * skeleton->base_transform_2d; + state.skeleton_transform_inverse = state.skeleton_transform.affine_inverse(); } } diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index 73a0f85bc9..bfaf1fdb4b 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -86,6 +86,7 @@ public: Transform2D final_transform; bool using_skeleton; Transform2D skeleton_transform; + Transform2D skeleton_transform_inverse; } state; diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 910867c9b1..326aab4c7c 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -58,7 +58,8 @@ out highp vec2 pixel_size_interp; #ifdef USE_SKELETON uniform mediump sampler2D skeleton_texture; // texunit:-1 -uniform mat4 skeleton_to_object_local_matrix; +uniform highp mat4 skeleton_transform; +uniform highp mat4 skeleton_transform_inverse; #endif #ifdef USE_LIGHTING @@ -156,6 +157,36 @@ void main() { #endif + +#define extra_matrix extra_matrix2 + +{ + +VERTEX_SHADER_CODE + +} + + +#ifdef USE_NINEPATCH + + pixel_size_interp=abs(dst_rect.zw) * vertex; +#endif + +#if !defined(SKIP_TRANSFORM_USED) + outvec = extra_matrix * outvec; + outvec = modelview_matrix * outvec; +#endif + +#undef extra_matrix + + color_interp = color; + +#ifdef USE_PIXEL_SNAP + + outvec.xy=floor(outvec+0.5).xy; +#endif + + #ifdef USE_SKELETON if (bone_weights!=vec4(0.0)){ //must be a valid bone @@ -192,42 +223,13 @@ void main() { texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0) ) * bone_weights.w; - mat4 bone_matrix = /*skeleton_to_object_local_matrix */ transpose(mat4(m[0],m[1],vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0))); + mat4 bone_matrix = skeleton_transform * transpose(mat4(m[0],m[1],vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0))) * skeleton_transform_inverse; outvec = bone_matrix * outvec; } #endif -#define extra_matrix extra_matrix2 - -{ - -VERTEX_SHADER_CODE - -} - - -#ifdef USE_NINEPATCH - - pixel_size_interp=abs(dst_rect.zw) * vertex; -#endif - -#if !defined(SKIP_TRANSFORM_USED) - outvec = extra_matrix * outvec; - outvec = modelview_matrix * outvec; -#endif - -#undef extra_matrix - - color_interp = color; - -#ifdef USE_PIXEL_SNAP - - outvec.xy=floor(outvec+0.5).xy; -#endif - - gl_Position = projection_matrix * outvec; #ifdef USE_LIGHTING diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 15d3b28da8..9f55ae32b0 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -454,9 +454,11 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("editors/2d/guides_color", Color(0.6, 0.0, 0.8)); _initial_set("editors/2d/bone_width", 5); _initial_set("editors/2d/bone_color1", Color(1.0, 1.0, 1.0, 0.9)); - _initial_set("editors/2d/bone_color2", Color(0.75, 0.75, 0.75, 0.9)); + _initial_set("editors/2d/bone_color2", Color(0.6, 0.6, 0.6, 0.9)); _initial_set("editors/2d/bone_selected_color", Color(0.9, 0.45, 0.45, 0.9)); _initial_set("editors/2d/bone_ik_color", Color(0.9, 0.9, 0.45, 0.9)); + _initial_set("editors/2d/bone_outline_color", Color(0.35, 0.35, 0.35)); + _initial_set("editors/2d/bone_outline_size", 2); _initial_set("editors/2d/keep_margins_when_changing_anchors", false); _initial_set("editors/2d/warped_mouse_panning", true); _initial_set("editors/2d/simple_spacebar_panning", false); diff --git a/editor/icons/icon_bone_2_d.svg b/editor/icons/icon_bone_2_d.svg new file mode 100644 index 0000000000..efcbc17e13 --- /dev/null +++ b/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> diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index ff38e12250..8cad40c9ce 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/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" @@ -2586,43 +2587,58 @@ void CanvasItemEditor::_draw_bones() { Color bone_color1 = EditorSettings::get_singleton()->get("editors/2d/bone_color1"); Color bone_color2 = EditorSettings::get_singleton()->get("editors/2d/bone_color2"); Color bone_ik_color = EditorSettings::get_singleton()->get("editors/2d/bone_ik_color"); + Color bone_outline_color = EditorSettings::get_singleton()->get("editors/2d/bone_outline_color"); 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->is_inside_tree()) + continue; //may have been removed + 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; Vector2 rel = to - from; Vector2 relt = rel.tangent().normalized() * bone_width; + Vector2 reln = rel.normalized(); + Vector2 reltn = relt.normalized(); Vector<Vector2> bone_shape; bone_shape.push_back(from); bone_shape.push_back(from + rel * 0.2 + relt); bone_shape.push_back(to); bone_shape.push_back(from + rel * 0.2 - relt); + + Vector<Vector2> bone_shape_outline; + bone_shape_outline.push_back(from + (-reln - reltn) * bone_outline_size); + bone_shape_outline.push_back(from + (-reln + reltn) * bone_outline_size); + bone_shape_outline.push_back(from + rel * 0.2 + relt + reltn * bone_outline_size); + bone_shape_outline.push_back(to + (reln + reltn) * bone_outline_size); + bone_shape_outline.push_back(to + (reln - reltn) * bone_outline_size); + 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); @@ -2635,14 +2651,26 @@ void CanvasItemEditor::_draw_bones() { colors.push_back(bone_color2); } - VisualServer::get_singleton()->canvas_item_add_primitive(ci, bone_shape, colors, Vector<Vector2>(), RID()); - - if (editor_selection->is_selected(pi)) { - for (int i = 0; i < bone_shape.size(); i++) { + Vector<Color> outline_colors; - VisualServer::get_singleton()->canvas_item_add_line(ci, bone_shape[i], bone_shape[(i + 1) % bone_shape.size()], bone_selected_color, 2); - } + 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); + outline_colors.push_back(bone_selected_color); + outline_colors.push_back(bone_selected_color); + outline_colors.push_back(bone_selected_color); + } else { + outline_colors.push_back(bone_outline_color); + outline_colors.push_back(bone_outline_color); + outline_colors.push_back(bone_outline_color); + outline_colors.push_back(bone_outline_color); + outline_colors.push_back(bone_outline_color); + outline_colors.push_back(bone_outline_color); } + + VisualServer::get_singleton()->canvas_item_add_polygon(ci, bone_shape_outline, outline_colors); + VisualServer::get_singleton()->canvas_item_add_primitive(ci, bone_shape, colors, Vector<Vector2>(), RID()); } } } @@ -2766,26 +2794,75 @@ 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; + } + + Node *p = c->get_parent(); + if (!p) { + return false; + } + + if (!c->is_visible()) { + return false; + } + + if (Object::cast_to<Bone2D>(c)) { - ObjectID id = c->get_instance_id(); - if (!bone_list.has(id)) { - BoneList bone; - bone_list[id] = bone; + if (Object::cast_to<Bone2D>(p)) { + //add as bone->parent relationship + 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[id].last_pass = bone_last_frame; + bone_list[bk].last_pass = bone_last_frame; + } + + 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; + } + + 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() { @@ -2912,9 +2989,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(); @@ -2926,9 +3003,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 = b2->get_global_transform(); + 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().length = bone->get_default_length(); viewport->update(); } } @@ -2944,12 +3030,19 @@ void CanvasItemEditor::_notification(int p_what) { AnimationPlayerEditor::singleton->get_key_editor()->connect("visibility_changed", this, "_keying_changed"); _keying_changed(); + get_tree()->connect("node_added", this, "_tree_changed", varray()); + get_tree()->connect("node_removed", this, "_tree_changed", varray()); } else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { select_sb->set_texture(get_icon("EditorRect2D", "EditorIcons")); } + if (p_what == NOTIFICATION_EXIT_TREE) { + get_tree()->disconnect("node_added", this, "_tree_changed"); + get_tree()->disconnect("node_removed", this, "_tree_changed"); + } + if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { select_button->set_icon(get_icon("ToolSelect", "EditorIcons")); list_select_button->set_icon(get_icon("ListSelect", "EditorIcons")); @@ -3034,6 +3127,47 @@ void CanvasItemEditor::edit(CanvasItem *p_canvas_item) { editor_selection->add_node(p_canvas_item); } +void CanvasItemEditor::_queue_update_bone_list() { + + if (bone_list_dirty) + return; + + call_deferred("_update_bone_list"); + bone_list_dirty = true; +} + +void CanvasItemEditor::_update_bone_list() { + + bone_last_frame++; + + if (editor->get_edited_scene()) { + _build_bones_list(editor->get_edited_scene()); + } + + 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); + continue; + } + + Node *node = Object::cast_to<Node>(ObjectDB::get_instance(E->key().from)); + if (!node || !node->is_inside_tree() || (node != get_tree()->get_edited_scene_root() && !get_tree()->get_edited_scene_root()->is_a_parent_of(node))) { + bone_to_erase.push_back(E); + continue; + } + } + while (bone_to_erase.size()) { + bone_list.erase(bone_to_erase.front()->get()); + bone_to_erase.pop_front(); + } + bone_list_dirty = false; +} + +void CanvasItemEditor::_tree_changed(Node *) { + _queue_update_bone_list(); +} + void CanvasItemEditor::_update_scrollbars() { updating_scroll = true; @@ -3058,22 +3192,7 @@ void CanvasItemEditor::_update_scrollbars() { Size2 screen_rect = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height")); Rect2 local_rect = Rect2(Point2(), viewport->get_size() - Size2(vmin.width, hmin.height)); - bone_last_frame++; - - if (editor->get_edited_scene()) { - _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()) { - if (E->get().last_pass != bone_last_frame) { - bone_to_erase.push_back(E); - } - } - while (bone_to_erase.size()) { - bone_list.erase(bone_to_erase.front()->get()); - bone_to_erase.pop_front(); - } + _queue_update_bone_list(); // Calculate scrollable area Rect2 canvas_item_rect = Rect2(Point2(), screen_rect); @@ -3837,6 +3956,9 @@ void CanvasItemEditor::_bind_methods() { ClassDB::bind_method("_draw_viewport", &CanvasItemEditor::_draw_viewport); ClassDB::bind_method("_gui_input_viewport", &CanvasItemEditor::_gui_input_viewport); ClassDB::bind_method("_snap_changed", &CanvasItemEditor::_snap_changed); + ClassDB::bind_method("_update_bone_list", &CanvasItemEditor::_update_bone_list); + ClassDB::bind_method("_tree_changed", &CanvasItemEditor::_tree_changed); + ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &CanvasItemEditor::_selection_result_pressed); ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &CanvasItemEditor::_selection_menu_hide); ClassDB::bind_method(D_METHOD("set_state"), &CanvasItemEditor::set_state); @@ -4040,6 +4162,7 @@ void CanvasItemEditor::focus_selection() { CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { + bone_list_dirty = false; tool = TOOL_SELECT; undo_redo = p_editor->get_undo_redo(); editor = p_editor; @@ -4224,13 +4347,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)); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 373a4b799e..eb3595cae6 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/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); @@ -433,6 +447,11 @@ class CanvasItemEditor : public VBoxContainer { HSplitContainer *palette_split; VSplitContainer *bottom_split; + bool bone_list_dirty; + void _queue_update_bone_list(); + void _update_bone_list(); + void _tree_changed(Node *); + friend class CanvasItemEditorPlugin; protected: diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 14d2550000..f04e0a801c 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -380,23 +380,23 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_drag_from = Vector2(mb->get_position().x, mb->get_position().y); uv_drag = true; - uv_prev = node->get_uv(); + points_prev = node->get_uv(); if (uv_edit_mode[0]->is_pressed()) { //edit uv - uv_prev = node->get_uv(); + points_prev = node->get_uv(); } else { //edit polygon - uv_prev = node->get_polygon(); + points_prev = node->get_polygon(); } uv_move_current = uv_mode; if (uv_move_current == UV_MODE_CREATE) { if (!uv_create) { - uv_prev.resize(0); + points_prev.resize(0); Vector2 tuv = mtx.affine_inverse().xform(Vector2(mb->get_position().x, mb->get_position().y)); - uv_prev.push_back(tuv); + points_prev.push_back(tuv); uv_create_to = tuv; - uv_drag_index = 0; + point_drag_index = 0; uv_drag_from = tuv; uv_drag = true; uv_create = true; @@ -404,18 +404,18 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_create_poly_prev = node->get_polygon(); uv_create_bones_prev = node->call("_get_bones"); splits_prev = node->get_splits(); - node->set_polygon(uv_prev); - node->set_uv(uv_prev); + node->set_polygon(points_prev); + node->set_uv(points_prev); } else { Vector2 tuv = mtx.affine_inverse().xform(Vector2(mb->get_position().x, mb->get_position().y)); - if (uv_prev.size() > 3 && tuv.distance_to(uv_prev[0]) < 8) { + if (points_prev.size() > 3 && tuv.distance_to(points_prev[0]) < 8) { undo_redo->create_action(TTR("Create Polygon & UV")); undo_redo->add_do_method(node, "set_uv", node->get_uv()); - undo_redo->add_undo_method(node, "set_uv", uv_prev); + undo_redo->add_undo_method(node, "set_uv", points_prev); undo_redo->add_do_method(node, "set_polygon", node->get_polygon()); - undo_redo->add_undo_method(node, "set_polygon", uv_prev); + undo_redo->add_undo_method(node, "set_polygon", points_prev); undo_redo->add_do_method(node, "clear_bones"); undo_redo->add_undo_method(node, "_set_bones", node->call("_get_bones")); undo_redo->add_do_method(uv_edit_draw, "update"); @@ -425,12 +425,12 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_create = false; _uv_mode(UV_MODE_EDIT_POINT); } else { - uv_prev.push_back(tuv); - uv_drag_index = uv_prev.size() - 1; + points_prev.push_back(tuv); + point_drag_index = points_prev.size() - 1; uv_drag_from = tuv; } - node->set_polygon(uv_prev); - node->set_uv(uv_prev); + node->set_polygon(points_prev); + node->set_uv(points_prev); } } @@ -446,34 +446,34 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { if (uv_move_current == UV_MODE_EDIT_POINT) { - uv_drag_index = -1; - for (int i = 0; i < uv_prev.size(); i++) { + point_drag_index = -1; + for (int i = 0; i < points_prev.size(); i++) { - Vector2 tuv = mtx.xform(uv_prev[i]); + Vector2 tuv = mtx.xform(points_prev[i]); if (tuv.distance_to(Vector2(mb->get_position().x, mb->get_position().y)) < 8) { uv_drag_from = tuv; - uv_drag_index = i; + point_drag_index = i; } } - if (uv_drag_index == -1) { + if (point_drag_index == -1) { uv_drag = false; } } if (uv_move_current == UV_MODE_ADD_SPLIT) { - int drag_index = -1; - drag_index = -1; - for (int i = 0; i < uv_prev.size(); i++) { + int split_to_index = -1; + split_to_index = -1; + for (int i = 0; i < points_prev.size(); i++) { - Vector2 tuv = mtx.xform(uv_prev[i]); + Vector2 tuv = mtx.xform(points_prev[i]); if (tuv.distance_to(Vector2(mb->get_position().x, mb->get_position().y)) < 8) { - drag_index = i; + split_to_index = i; } } - if (drag_index == -1) { + if (split_to_index == -1) { split_create = false; return; } @@ -481,41 +481,65 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { if (split_create) { split_create = false; - if (drag_index < uv_drag_index) { - SWAP(drag_index, uv_drag_index); + if (split_to_index < point_drag_index) { + SWAP(split_to_index, point_drag_index); } bool valid = true; - if (drag_index == uv_drag_index) { + String split_error; + if (split_to_index == point_drag_index) { + split_error = TTR("Split point with itself."); valid = false; } - if (drag_index + 1 == uv_drag_index) { + if (split_to_index + 1 == point_drag_index) { //not a split,goes along the edge + split_error = TTR("Split can't form an existing edge."); valid = false; } - if (drag_index == uv_prev.size() - 1 && uv_drag_index == 0) { + if (split_to_index == points_prev.size() - 1 && point_drag_index == 0) { //not a split,goes along the edge + split_error = TTR("Split can't form an existing edge."); valid = false; } + for (int i = 0; i < splits_prev.size(); i += 2) { - if (splits_prev[i] == uv_drag_index && splits_prev[i + 1] == drag_index) { + + if (splits_prev[i] == point_drag_index && splits_prev[i + 1] == split_to_index) { //already exists + split_error = TTR("Split already exists."); valid = false; + break; } - if (splits_prev[i] > uv_drag_index && splits_prev[i + 1] > drag_index) { - //crossing - valid = false; + + int a_state; //-1, outside split, 0 split point, +1, inside split + if (point_drag_index == splits_prev[i] || point_drag_index == splits_prev[i + 1]) { + a_state = 0; + } else if (point_drag_index < splits_prev[i] || point_drag_index > splits_prev[i + 1]) { + a_state = -1; + } else { + a_state = 1; } - if (splits_prev[i] < uv_drag_index && splits_prev[i + 1] < drag_index) { - //crossing opposite direction + int b_state; //-1, outside split, 0 split point, +1, inside split + if (split_to_index == splits_prev[i] || split_to_index == splits_prev[i + 1]) { + b_state = 0; + } else if (split_to_index < splits_prev[i] || split_to_index > splits_prev[i + 1]) { + b_state = -1; + } else { + b_state = 1; + } + + if (b_state * a_state < 0) { + //crossing + split_error = "Split crosses another split."; valid = false; + break; } } if (valid) { - splits_prev.push_back(uv_drag_index); - splits_prev.push_back(drag_index); + splits_prev.push_back(point_drag_index); + splits_prev.push_back(split_to_index); undo_redo->create_action(TTR("Add Split")); @@ -525,13 +549,14 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { undo_redo->add_undo_method(uv_edit_draw, "update"); undo_redo->commit_action(); } else { - error->set_text(TTR("Invalid Split")); + error->set_text(TTR("Invalid Split: ") + split_error); error->popup_centered_minsize(); } } else { - uv_drag_index = drag_index; + point_drag_index = split_to_index; split_create = true; + splits_prev = node->get_splits(); uv_create_to = mtx.affine_inverse().xform(Vector2(mb->get_position().x, mb->get_position().y)); } } @@ -539,11 +564,11 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { if (uv_move_current == UV_MODE_REMOVE_SPLIT) { for (int i = 0; i < splits_prev.size(); i += 2) { - if (splits_prev[i] < 0 || splits_prev[i] >= uv_prev.size()) + if (splits_prev[i] < 0 || splits_prev[i] >= points_prev.size()) continue; - if (splits_prev[i + 1] < 0 || splits_prev[i] >= uv_prev.size()) + if (splits_prev[i + 1] < 0 || splits_prev[i] >= points_prev.size()) continue; - Vector2 e[2] = { mtx.xform(uv_prev[splits_prev[i]]), mtx.xform(uv_prev[splits_prev[i + 1]]) }; + Vector2 e[2] = { mtx.xform(points_prev[splits_prev[i]]), mtx.xform(points_prev[splits_prev[i + 1]]) }; Vector2 mp = Vector2(mb->get_position().x, mb->get_position().y); Vector2 cp = Geometry::get_closest_point_to_segment_2d(mp, e); if (cp.distance_to(mp) < 8) { @@ -574,7 +599,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } } - if (bone_selected != -1 && node->get_bone_weights(bone_selected).size() == uv_prev.size()) { + if (bone_selected != -1 && node->get_bone_weights(bone_selected).size() == points_prev.size()) { prev_weights = node->get_bone_weights(bone_selected); bone_painting = true; @@ -588,10 +613,10 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { if (uv_edit_mode[0]->is_pressed()) { //edit uv undo_redo->add_do_method(node, "set_uv", node->get_uv()); - undo_redo->add_undo_method(node, "set_uv", uv_prev); + undo_redo->add_undo_method(node, "set_uv", points_prev); } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon undo_redo->add_do_method(node, "set_polygon", node->get_polygon()); - undo_redo->add_undo_method(node, "set_polygon", uv_prev); + undo_redo->add_undo_method(node, "set_polygon", points_prev); } undo_redo->add_do_method(uv_edit_draw, "update"); undo_redo->add_undo_method(uv_edit_draw, "update"); @@ -624,9 +649,9 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_drag = false; if (uv_edit_mode[0]->is_pressed()) { //edit uv - node->set_uv(uv_prev); + node->set_uv(points_prev); } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon - node->set_polygon(uv_prev); + node->set_polygon(points_prev); } uv_edit_draw->update(); } else if (split_create) { @@ -669,8 +694,8 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } break; case UV_MODE_EDIT_POINT: { - PoolVector<Vector2> uv_new = uv_prev; - uv_new.set(uv_drag_index, uv_new[uv_drag_index] + drag); + PoolVector<Vector2> uv_new = points_prev; + uv_new.set(point_drag_index, uv_new[point_drag_index] + drag); if (uv_edit_mode[0]->is_pressed()) { //edit uv node->set_uv(uv_new); @@ -680,7 +705,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } break; case UV_MODE_MOVE: { - PoolVector<Vector2> uv_new = uv_prev; + PoolVector<Vector2> uv_new = points_prev; for (int i = 0; i < uv_new.size(); i++) uv_new.set(i, uv_new[i] + drag); @@ -694,16 +719,16 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { case UV_MODE_ROTATE: { Vector2 center; - PoolVector<Vector2> uv_new = uv_prev; + PoolVector<Vector2> uv_new = points_prev; for (int i = 0; i < uv_new.size(); i++) - center += uv_prev[i]; + center += points_prev[i]; center /= uv_new.size(); float angle = (uv_drag_from - mtx.xform(center)).normalized().angle_to((uv_drag_to - mtx.xform(center)).normalized()); for (int i = 0; i < uv_new.size(); i++) { - Vector2 rel = uv_prev[i] - center; + Vector2 rel = points_prev[i] - center; rel = rel.rotated(angle); uv_new.set(i, center + rel); } @@ -718,10 +743,10 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { case UV_MODE_SCALE: { Vector2 center; - PoolVector<Vector2> uv_new = uv_prev; + PoolVector<Vector2> uv_new = points_prev; for (int i = 0; i < uv_new.size(); i++) - center += uv_prev[i]; + center += points_prev[i]; center /= uv_new.size(); float from_dist = uv_drag_from.distance_to(mtx.xform(center)); @@ -732,7 +757,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { float scale = to_dist / from_dist; for (int i = 0; i < uv_new.size(); i++) { - Vector2 rel = uv_prev[i] - center; + Vector2 rel = points_prev[i] - center; rel = rel * scale; uv_new.set(i, center + rel); } @@ -760,7 +785,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { PoolVector<float>::Write w = painted_weights.write(); PoolVector<float>::Read r = prev_weights.read(); - PoolVector<Vector2>::Read rv = uv_prev.read(); + PoolVector<Vector2>::Read rv = points_prev.read(); for (int i = 0; i < pc; i++) { if (mtx.xform(rv[i]).distance_to(bone_paint_pos) < radius) { @@ -899,7 +924,7 @@ void Polygon2DEditor::_uv_draw() { } if (split_create) { - Vector2 from = uvs[uv_drag_index]; + Vector2 from = uvs[point_drag_index]; Vector2 to = uv_create_to; uv_edit_draw->draw_line(mtx.xform(from), mtx.xform(to), Color(0.9, 0.5, 0.5), 2); } @@ -1232,7 +1257,7 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_edit_draw->connect("draw", this, "_uv_draw"); uv_edit_draw->connect("gui_input", this, "_uv_input"); uv_draw_zoom = 1.0; - uv_drag_index = -1; + point_drag_index = -1; uv_drag = false; uv_create = false; updating_uv_scroll = false; diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h index cf529b39f7..f9b42a21c2 100644 --- a/editor/plugins/polygon_2d_editor_plugin.h +++ b/editor/plugins/polygon_2d_editor_plugin.h @@ -99,14 +99,14 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { Vector2 uv_draw_ofs; float uv_draw_zoom; - PoolVector<Vector2> uv_prev; + PoolVector<Vector2> points_prev; PoolVector<Vector2> uv_create_uv_prev; PoolVector<Vector2> uv_create_poly_prev; Array uv_create_bones_prev; PoolVector<int> splits_prev; Vector2 uv_create_to; - int uv_drag_index; + int point_drag_index; bool uv_drag; bool uv_create; bool split_create; diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index 9197127235..2363c791fa 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/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++) { diff --git a/scene/2d/skeleton_2d.h b/scene/2d/skeleton_2d.h index 9ae74b56d3..cd270dac85 100644 --- a/scene/2d/skeleton_2d.h +++ b/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(); diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index 056ac2772b..ad63422aad 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -166,7 +166,11 @@ void PrimitiveMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("get_mesh_arrays"), &PrimitiveMesh::get_mesh_arrays); + ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &PrimitiveMesh::set_custom_aabb); + ClassDB::bind_method(D_METHOD("get_custom_aabb"), &PrimitiveMesh::get_custom_aabb); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "SpatialMaterial,ShaderMaterial"), "set_material", "get_material"); + ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, ""), "set_custom_aabb", "get_custom_aabb"); } void PrimitiveMesh::set_material(const Ref<Material> &p_material) { @@ -187,6 +191,18 @@ Array PrimitiveMesh::get_mesh_arrays() const { return surface_get_arrays(0); } +void PrimitiveMesh::set_custom_aabb(const AABB &p_custom) { + + custom_aabb = p_custom; + VS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); + emit_changed(); +} + +AABB PrimitiveMesh::get_custom_aabb() const { + + return custom_aabb; +} + PrimitiveMesh::PrimitiveMesh() { // defaults mesh = VisualServer::get_singleton()->mesh_create(); diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index 94a7a055a3..23d1671d5c 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -48,6 +48,7 @@ class PrimitiveMesh : public Mesh { private: RID mesh; mutable AABB aabb; + AABB custom_aabb; Ref<Material> material; @@ -81,6 +82,9 @@ public: Array get_mesh_arrays() const; + void set_custom_aabb(const AABB &p_custom); + AABB get_custom_aabb() const; + PrimitiveMesh(); ~PrimitiveMesh(); }; |