summaryrefslogtreecommitdiff
path: root/scene/2d/polygon_2d.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/2d/polygon_2d.cpp')
-rw-r--r--scene/2d/polygon_2d.cpp170
1 files changed, 167 insertions, 3 deletions
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index bf5bf29b2e..4d6ebc81c3 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -30,7 +30,7 @@
#include "polygon_2d.h"
#include "core/math/geometry.h"
-
+#include "skeleton_2d.h"
Dictionary Polygon2D::_edit_get_state() const {
Dictionary state = Node2D::_edit_get_state();
state["offset"] = offset;
@@ -91,8 +91,20 @@ void Polygon2D::_notification(int p_what) {
if (polygon.size() < 3)
return;
+ Skeleton2D *skeleton_node = NULL;
+ if (has_node(skeleton)) {
+ skeleton_node = Object::cast_to<Skeleton2D>(get_node(skeleton));
+ }
+
+ if (skeleton_node)
+ VS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), skeleton_node->get_skeleton());
+ else
+ VS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), RID());
+
Vector<Vector2> points;
Vector<Vector2> uvs;
+ Vector<int> bones;
+ Vector<float> weights;
points.resize(polygon.size());
@@ -180,6 +192,70 @@ void Polygon2D::_notification(int p_what) {
}
}
+ if (!invert && bone_weights.size()) {
+ //a skeleton is set! fill indices and weights
+ int vc = points.size();
+ bones.resize(vc * 4);
+ weights.resize(vc * 4);
+
+ int *bonesw = bones.ptrw();
+ float *weightsw = weights.ptrw();
+
+ for (int i = 0; i < vc * 4; i++) {
+ bonesw[i] = 0;
+ weightsw[i] = 0;
+ }
+
+ for (int i = 0; i < bone_weights.size(); i++) {
+ if (bone_weights[i].weights.size() != points.size()) {
+ continue; //different number of vertices, sorry not using.
+ }
+ if (!skeleton_node->has_node(bone_weights[i].path)) {
+ continue; //node does not exist
+ }
+ Bone2D *bone = Object::cast_to<Bone2D>(skeleton_node->get_node(bone_weights[i].path));
+ if (!bone) {
+ continue;
+ }
+
+ int bone_index = bone->get_index_in_skeleton();
+ PoolVector<float>::Read r = bone_weights[i].weights.read();
+ for (int j = 0; j < vc; j++) {
+ if (r[j] == 0.0)
+ continue; //weight is unpainted, skip
+ //find an index with a weight
+ for (int k = 0; k < 4; k++) {
+ if (weightsw[j * 4 + k] < r[j]) {
+ //this is less than this weight, insert weight!
+ for (int l = 3; l > k; l--) {
+ weightsw[j * 4 + l] = weightsw[j * 4 + l - 1];
+ bonesw[j * 4 + l] = bonesw[j * 4 + l - 1];
+ }
+ weightsw[j * 4 + k] = r[j];
+ bonesw[j * 4 + k] = bone_index;
+ break;
+ }
+ }
+ }
+ }
+
+ //normalize the weights
+ for (int i = 0; i < vc; i++) {
+ float tw = 0;
+ for (int j = 0; j < 4; j++) {
+ tw += weightsw[i * 4 + j];
+ }
+ if (tw == 0)
+ continue; //unpainted, do nothing
+
+ //normalize
+ for (int j = 0; j < 4; j++) {
+ weightsw[i * 4 + j] /= tw;
+ // print_line("point " + itos(i) + " idx " + itos(j) + " index: " + itos(bonesw[i * 4 + j]) + " weight: " + rtos(weightsw[i * 4 + j]));
+ }
+ }
+ }
+
Vector<Color> colors;
int color_len = vertex_colors.size();
colors.resize(len);
@@ -197,7 +273,8 @@ void Polygon2D::_notification(int p_what) {
// VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, texture.is_valid() ? texture->get_rid() : RID());
if (invert || splits.size() == 0) {
- VS::get_singleton()->canvas_item_add_polygon(get_canvas_item(), points, colors, uvs, texture.is_valid() ? texture->get_rid() : RID(), RID(), antialiased);
+ Vector<int> indices = Geometry::triangulate_polygon(points);
+ VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID());
} else {
//use splits
Vector<int> loop;
@@ -268,7 +345,7 @@ void Polygon2D::_notification(int p_what) {
//print_line("loops: " + itos(loops.size()) + " indices: " + itos(indices.size()));
- VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, texture.is_valid() ? texture->get_rid() : RID());
+ VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID());
}
} break;
@@ -430,6 +507,74 @@ Vector2 Polygon2D::get_offset() const {
return offset;
}
+void Polygon2D::add_bone(const NodePath &p_path, const PoolVector<float> &p_weights) {
+
+ Bone bone;
+ bone.path = p_path;
+ bone.weights = p_weights;
+ bone_weights.push_back(bone);
+}
+int Polygon2D::get_bone_count() const {
+ return bone_weights.size();
+}
+NodePath Polygon2D::get_bone_path(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, bone_weights.size(), NodePath());
+ return bone_weights[p_index].path;
+}
+PoolVector<float> Polygon2D::get_bone_weights(int p_index) const {
+
+ ERR_FAIL_INDEX_V(p_index, bone_weights.size(), PoolVector<float>());
+ return bone_weights[p_index].weights;
+}
+void Polygon2D::erase_bone(int p_idx) {
+
+ ERR_FAIL_INDEX(p_idx, bone_weights.size());
+ bone_weights.remove(p_idx);
+}
+
+void Polygon2D::clear_bones() {
+ bone_weights.clear();
+}
+
+void Polygon2D::set_bone_weights(int p_index, const PoolVector<float> &p_weights) {
+ ERR_FAIL_INDEX(p_index, bone_weights.size());
+ bone_weights[p_index].weights = p_weights;
+ update();
+}
+void Polygon2D::set_bone_path(int p_index, const NodePath &p_path) {
+ ERR_FAIL_INDEX(p_index, bone_weights.size());
+ bone_weights[p_index].path = p_path;
+ update();
+}
+
+Array Polygon2D::_get_bones() const {
+ Array bones;
+ for (int i = 0; i < get_bone_count(); i++) {
+ bones.push_back(get_bone_path(i));
+ bones.push_back(get_bone_weights(i));
+ }
+ return bones;
+}
+void Polygon2D::_set_bones(const Array &p_bones) {
+
+ ERR_FAIL_COND(p_bones.size() & 1);
+ clear_bones();
+ for (int i = 0; i < p_bones.size(); i += 2) {
+ add_bone(p_bones[i], p_bones[i + 1]);
+ }
+}
+
+void Polygon2D::set_skeleton(const NodePath &p_skeleton) {
+ if (skeleton == p_skeleton)
+ return;
+ skeleton = p_skeleton;
+ update();
+}
+
+NodePath Polygon2D::get_skeleton() const {
+ return skeleton;
+}
+
void Polygon2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_polygon", "polygon"), &Polygon2D::set_polygon);
@@ -474,6 +619,21 @@ void Polygon2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_offset", "offset"), &Polygon2D::set_offset);
ClassDB::bind_method(D_METHOD("get_offset"), &Polygon2D::get_offset);
+ ClassDB::bind_method(D_METHOD("add_bone", "path", "weights"), &Polygon2D::add_bone);
+ ClassDB::bind_method(D_METHOD("get_bone_count"), &Polygon2D::get_bone_count);
+ ClassDB::bind_method(D_METHOD("get_bone_path", "index"), &Polygon2D::get_bone_path);
+ ClassDB::bind_method(D_METHOD("get_bone_weights", "index"), &Polygon2D::get_bone_weights);
+ ClassDB::bind_method(D_METHOD("erase_bone", "index"), &Polygon2D::erase_bone);
+ ClassDB::bind_method(D_METHOD("clear_bones"), &Polygon2D::clear_bones);
+ ClassDB::bind_method(D_METHOD("set_bone_path", "index", "path"), &Polygon2D::set_bone_path);
+ ClassDB::bind_method(D_METHOD("set_bone_weights", "index", "weights"), &Polygon2D::set_bone_weights);
+
+ ClassDB::bind_method(D_METHOD("set_skeleton", "skeleton"), &Polygon2D::set_skeleton);
+ ClassDB::bind_method(D_METHOD("get_skeleton"), &Polygon2D::get_skeleton);
+
+ ClassDB::bind_method(D_METHOD("_set_bones", "bones"), &Polygon2D::_set_bones);
+ ClassDB::bind_method(D_METHOD("_get_bones"), &Polygon2D::_get_bones);
+
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon");
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "uv"), "set_uv", "get_uv");
ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "splits"), "set_splits", "get_splits");
@@ -488,10 +648,14 @@ void Polygon2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "texture_scale"), "set_texture_scale", "get_texture_scale");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "texture_rotation_degrees", PROPERTY_HINT_RANGE, "-1440,1440,0.1"), "set_texture_rotation_degrees", "get_texture_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "texture_rotation", PROPERTY_HINT_NONE, "", 0), "set_texture_rotation", "get_texture_rotation");
+ ADD_GROUP("Skeleton", "");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton"), "set_skeleton", "get_skeleton");
ADD_GROUP("Invert", "invert_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "invert_enable"), "set_invert", "get_invert");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "invert_border", PROPERTY_HINT_RANGE, "0.1,16384,0.1"), "set_invert_border", "get_invert_border");
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bones", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_bones", "_get_bones");
}
Polygon2D::Polygon2D() {