diff options
Diffstat (limited to 'scene/resources')
-rw-r--r-- | scene/resources/curve.cpp | 164 | ||||
-rw-r--r-- | scene/resources/curve.h | 55 | ||||
-rw-r--r-- | scene/resources/shape.cpp | 2 | ||||
-rw-r--r-- | scene/resources/texture.cpp | 44 | ||||
-rw-r--r-- | scene/resources/texture.h | 9 |
5 files changed, 198 insertions, 76 deletions
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 3957923c6a..bc6d0230a0 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -380,15 +380,16 @@ Curve2D::Curve2D() #endif +const char *Curve::SIGNAL_RANGE_CHANGED = "range_changed"; + Curve::Curve() { _bake_resolution = 100; _baked_cache_dirty = false; -#ifdef TOOLS_ENABLED - _disable_set_data = false; -#endif + _min_value = 0; + _max_value = 1; } -int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent) { +int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent, TangentMode left_mode, TangentMode right_mode) { // Add a point and preserve order // Curve bounds is in 0..1 @@ -400,7 +401,7 @@ int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent) { int ret = -1; if (_points.size() == 0) { - _points.push_back(Point(p_pos, left_tangent, right_tangent)); + _points.push_back(Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); ret = 0; } else if (_points.size() == 1) { @@ -409,10 +410,10 @@ int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent) { real_t diff = p_pos.x - _points[0].pos.x; if (diff > 0) { - _points.push_back(Point(p_pos, left_tangent, right_tangent)); + _points.push_back(Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); ret = 1; } else { - _points.insert(0, Point(p_pos, left_tangent, right_tangent)); + _points.insert(0, Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); ret = 0; } @@ -431,16 +432,18 @@ int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent) { if (i == 0 && p_pos.x < _points[0].pos.x) { // Insert before anything else - _points.insert(0, Point(p_pos, left_tangent, right_tangent)); + _points.insert(0, Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); ret = 0; } else { // Insert between i and i+1 ++i; - _points.insert(i, Point(p_pos, left_tangent, right_tangent)); + _points.insert(i, Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); ret = i; } } + update_auto_tangents(ret); + mark_dirty(); return ret; @@ -496,12 +499,38 @@ void Curve::clean_dupes() { void Curve::set_point_left_tangent(int i, real_t tangent) { ERR_FAIL_INDEX(i, _points.size()); _points[i].left_tangent = tangent; + _points[i].left_mode = TANGENT_FREE; mark_dirty(); } void Curve::set_point_right_tangent(int i, real_t tangent) { ERR_FAIL_INDEX(i, _points.size()); _points[i].right_tangent = tangent; + _points[i].right_mode = TANGENT_FREE; + mark_dirty(); +} + +void Curve::set_point_left_mode(int i, TangentMode p_mode) { + ERR_FAIL_INDEX(i, _points.size()); + _points[i].left_mode = p_mode; + if (i > 0) { + if (p_mode == TANGENT_LINEAR) { + Vector2 v = (_points[i - 1].pos - _points[i].pos).normalized(); + _points[i].left_tangent = v.y / v.x; + } + } + mark_dirty(); +} + +void Curve::set_point_right_mode(int i, TangentMode p_mode) { + ERR_FAIL_INDEX(i, _points.size()); + _points[i].right_mode = p_mode; + if (i + 1 < _points.size()) { + if (p_mode == TANGENT_LINEAR) { + Vector2 v = (_points[i + 1].pos - _points[i].pos).normalized(); + _points[i].right_tangent = v.y / v.x; + } + } mark_dirty(); } @@ -515,6 +544,16 @@ real_t Curve::get_point_right_tangent(int i) const { return _points[i].right_tangent; } +Curve::TangentMode Curve::get_point_left_mode(int i) const { + ERR_FAIL_INDEX_V(i, _points.size(), TANGENT_FREE); + return _points[i].left_mode; +} + +Curve::TangentMode Curve::get_point_right_mode(int i) const { + ERR_FAIL_INDEX_V(i, _points.size(), TANGENT_FREE); + return _points[i].right_mode; +} + void Curve::remove_point(int p_index) { ERR_FAIL_INDEX(p_index, _points.size()); _points.remove(p_index); @@ -529,6 +568,7 @@ void Curve::clear_points() { void Curve::set_point_value(int p_index, real_t pos) { ERR_FAIL_INDEX(p_index, _points.size()); _points[p_index].pos.y = pos; + update_auto_tangents(p_index); mark_dirty(); } @@ -539,6 +579,11 @@ int Curve::set_point_offset(int p_index, float offset) { int i = add_point(Vector2(offset, p.pos.y)); _points[i].left_tangent = p.left_tangent; _points[i].right_tangent = p.right_tangent; + _points[i].left_mode = p.left_mode; + _points[i].right_mode = p.right_mode; + if (p_index != i) + update_auto_tangents(p_index); + update_auto_tangents(i); return i; } @@ -547,6 +592,58 @@ Vector2 Curve::get_point_pos(int p_index) const { return _points[p_index].pos; } +Curve::Point Curve::get_point(int p_index) const { + ERR_FAIL_INDEX_V(p_index, _points.size(), Point()); + return _points[p_index]; +} + +void Curve::update_auto_tangents(int i) { + + Point &p = _points[i]; + + if (i > 0) { + if (p.left_mode == TANGENT_LINEAR) { + Vector2 v = (_points[i - 1].pos - p.pos).normalized(); + p.left_tangent = v.y / v.x; + } + if (_points[i - 1].right_mode == TANGENT_LINEAR) { + Vector2 v = (_points[i - 1].pos - p.pos).normalized(); + _points[i - 1].right_tangent = v.y / v.x; + } + } + + if (i + 1 < _points.size()) { + if (p.right_mode == TANGENT_LINEAR && i + 1 < _points.size()) { + Vector2 v = (_points[i + 1].pos - p.pos).normalized(); + p.right_tangent = v.y / v.x; + } + if (_points[i + 1].left_mode == TANGENT_LINEAR) { + Vector2 v = (_points[i + 1].pos - p.pos).normalized(); + _points[i + 1].left_tangent = v.y / v.x; + } + } +} + +#define MIN_Y_RANGE 0.01 + +void Curve::set_min_value(float p_min) { + if (p_min > _max_value - MIN_Y_RANGE) + _min_value = _max_value - MIN_Y_RANGE; + else + _min_value = p_min; + // Note: min and max are indicative values, + // it's still possible that existing points are out of range at this point. + emit_signal(SIGNAL_RANGE_CHANGED); +} + +void Curve::set_max_value(float p_max) { + if (p_max < _min_value + MIN_Y_RANGE) + _max_value = _min_value + MIN_Y_RANGE; + else + _max_value = p_max; + emit_signal(SIGNAL_RANGE_CHANGED); +} + real_t Curve::interpolate(real_t offset) const { if (_points.size() == 0) return 0; @@ -606,48 +703,60 @@ void Curve::mark_dirty() { Array Curve::get_data() const { Array output; - output.resize(_points.size() * 3); + const unsigned int ELEMS = 5; + output.resize(_points.size() * ELEMS); for (int j = 0; j < _points.size(); ++j) { const Point p = _points[j]; - int i = j * 3; + int i = j * ELEMS; output[i] = p.pos; output[i + 1] = p.left_tangent; output[i + 2] = p.right_tangent; + output[i + 3] = p.left_mode; + output[i + 4] = p.right_mode; } return output; } void Curve::set_data(Array input) { - ERR_FAIL_COND(input.size() % 3 != 0); - -#ifdef TOOLS_ENABLED - if (_disable_set_data) - return; -#endif + const unsigned int ELEMS = 5; + ERR_FAIL_COND(input.size() % ELEMS != 0); _points.clear(); // Validate input - for (int i = 0; i < input.size(); i += 3) { + for (int i = 0; i < input.size(); i += ELEMS) { ERR_FAIL_COND(input[i].get_type() != Variant::VECTOR2); ERR_FAIL_COND(input[i + 1].get_type() != Variant::REAL); ERR_FAIL_COND(input[i + 2].get_type() != Variant::REAL); + + ERR_FAIL_COND(input[i + 3].get_type() != Variant::INT); + int left_mode = input[i + 3]; + ERR_FAIL_COND(left_mode < 0 || left_mode >= TANGENT_MODE_COUNT); + + ERR_FAIL_COND(input[i + 4].get_type() != Variant::INT); + int right_mode = input[i + 4]; + ERR_FAIL_COND(right_mode < 0 || right_mode >= TANGENT_MODE_COUNT); } - _points.resize(input.size() / 3); + _points.resize(input.size() / ELEMS); for (int j = 0; j < _points.size(); ++j) { Point &p = _points[j]; - int i = j * 3; + int i = j * ELEMS; p.pos = input[i]; p.left_tangent = input[i + 1]; p.right_tangent = input[i + 2]; + // TODO For some reason the compiler won't convert from Variant to enum + int left_mode = input[i + 3]; + int right_mode = input[i + 4]; + p.left_mode = (TangentMode)left_mode; + p.right_mode = (TangentMode)right_mode; } mark_dirty(); @@ -716,7 +825,8 @@ real_t Curve::interpolate_baked(real_t offset) { void Curve::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_point", "pos", "left_tangent", "right_tangent"), &Curve::add_point, DEFVAL(0), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("add_point", "pos", "left_tangent", "right_tangent", "left_mode", "right_mode"), + &Curve::add_point, DEFVAL(0), DEFVAL(0), DEFVAL(TANGENT_FREE), DEFVAL(TANGENT_FREE)); ClassDB::bind_method(D_METHOD("remove_point", "index"), &Curve::remove_point); ClassDB::bind_method(D_METHOD("clear_points"), &Curve::clear_points); ClassDB::bind_method(D_METHOD("get_point_pos", "index"), &Curve::get_point_pos); @@ -726,8 +836,16 @@ void Curve::_bind_methods() { ClassDB::bind_method(D_METHOD("interpolate_baked", "offset"), &Curve::interpolate_baked); ClassDB::bind_method(D_METHOD("get_point_left_tangent", "index"), &Curve::get_point_left_tangent); ClassDB::bind_method(D_METHOD("get_point_right_tangent", "index"), &Curve::get_point_left_tangent); + ClassDB::bind_method(D_METHOD("get_point_left_mode", "index"), &Curve::get_point_left_mode); + ClassDB::bind_method(D_METHOD("get_point_right_mode", "index"), &Curve::get_point_left_mode); ClassDB::bind_method(D_METHOD("set_point_left_tangent", "index", "tangent"), &Curve::set_point_left_tangent); ClassDB::bind_method(D_METHOD("set_point_right_tangent", "index", "tangent"), &Curve::set_point_left_tangent); + ClassDB::bind_method(D_METHOD("set_point_left_mode", "index", "mode"), &Curve::set_point_left_mode); + ClassDB::bind_method(D_METHOD("set_point_right_mode", "index", "mode"), &Curve::set_point_left_mode); + ClassDB::bind_method(D_METHOD("get_min_value"), &Curve::get_min_value); + ClassDB::bind_method(D_METHOD("set_min_value", "min"), &Curve::set_min_value); + ClassDB::bind_method(D_METHOD("get_max_value"), &Curve::get_max_value); + ClassDB::bind_method(D_METHOD("set_max_value", "max"), &Curve::set_max_value); ClassDB::bind_method(D_METHOD("clean_dupes"), &Curve::clean_dupes); ClassDB::bind_method(D_METHOD("bake"), &Curve::bake); ClassDB::bind_method(D_METHOD("get_bake_resolution"), &Curve::get_bake_resolution); @@ -735,8 +853,12 @@ void Curve::_bind_methods() { ClassDB::bind_method(D_METHOD("_get_data"), &Curve::get_data); ClassDB::bind_method(D_METHOD("_set_data", "data"), &Curve::set_data); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "min_value", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_min_value", "get_min_value"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_value", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_max_value", "get_max_value"); ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_resolution", PROPERTY_HINT_RANGE, "1,1000,1"), "set_bake_resolution", "get_bake_resolution"); ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_data", "_get_data"); + + ADD_SIGNAL(MethodInfo(SIGNAL_RANGE_CHANGED)); } int Curve2D::get_point_count() const { diff --git a/scene/resources/curve.h b/scene/resources/curve.h index 63b9a07f07..83a4357bfb 100644 --- a/scene/resources/curve.h +++ b/scene/resources/curve.h @@ -89,24 +89,39 @@ public: static const int MIN_X = 0.f; static const int MAX_X = 1.f; -#ifdef TOOLS_ENABLED - bool _disable_set_data; -#endif + static const char *SIGNAL_RANGE_CHANGED; + + enum TangentMode { + TANGENT_FREE = 0, + TANGENT_LINEAR, + TANGENT_MODE_COUNT + }; struct Point { Vector2 pos; real_t left_tangent; real_t right_tangent; + TangentMode left_mode; + TangentMode right_mode; Point() { left_tangent = 0; right_tangent = 0; + left_mode = TANGENT_FREE; + right_mode = TANGENT_FREE; } - Point(Vector2 p, real_t left = 0, real_t right = 0) { - pos = p; - left_tangent = left; - right_tangent = right; + Point(Vector2 p_pos, + real_t p_left = 0, + real_t p_right = 0, + TangentMode p_left_mode = TANGENT_FREE, + TangentMode p_right_mode = TANGENT_FREE) { + + pos = p_pos; + left_tangent = p_left; + right_tangent = p_right; + left_mode = p_left_mode; + right_mode = p_right_mode; } }; @@ -114,7 +129,12 @@ public: int get_point_count() const { return _points.size(); } - int add_point(Vector2 p_pos, real_t left_tangent = 0, real_t right_tangent = 0); + int add_point(Vector2 p_pos, + real_t left_tangent = 0, + real_t right_tangent = 0, + TangentMode left_mode = TANGENT_FREE, + TangentMode right_mode = TANGENT_FREE); + void remove_point(int p_index); void clear_points(); @@ -124,6 +144,14 @@ public: int set_point_offset(int p_index, float offset); Vector2 get_point_pos(int p_index) const; + Point get_point(int p_index) const; + + float get_min_value() const { return _min_value; } + void set_min_value(float p_min); + + float get_max_value() const { return _max_value; } + void set_max_value(float p_max); + real_t interpolate(real_t offset) const; real_t interpolate_local_nocheck(int index, real_t local_offset) const; @@ -131,8 +159,15 @@ public: void set_point_left_tangent(int i, real_t tangent); void set_point_right_tangent(int i, real_t tangent); + void set_point_left_mode(int i, TangentMode p_mode); + void set_point_right_mode(int i, TangentMode p_mode); + real_t get_point_left_tangent(int i) const; real_t get_point_right_tangent(int i) const; + TangentMode get_point_left_mode(int i) const; + TangentMode get_point_right_mode(int i) const; + + void update_auto_tangents(int i); Array get_data() const; void set_data(Array input); @@ -152,8 +187,12 @@ private: bool _baked_cache_dirty; Vector<real_t> _baked_cache; int _bake_resolution; + float _min_value; + float _max_value; }; +VARIANT_ENUM_CAST(Curve::TangentMode) + class Curve2D : public Resource { GDCLASS(Curve2D, Resource); diff --git a/scene/resources/shape.cpp b/scene/resources/shape.cpp index 77f2096d9b..6be88374e5 100644 --- a/scene/resources/shape.cpp +++ b/scene/resources/shape.cpp @@ -30,7 +30,7 @@ #include "shape.h" #include "os/os.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" #include "scene/resources/mesh.h" #include "servers/physics_server.h" diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 0bd8c41228..6c7ae2445c 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -1370,12 +1370,6 @@ CubeMap::~CubeMap() { void CurveTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_max", "max"), &CurveTexture::set_max); - ClassDB::bind_method(D_METHOD("get_max"), &CurveTexture::get_max); - - ClassDB::bind_method(D_METHOD("set_min", "min"), &CurveTexture::set_min); - ClassDB::bind_method(D_METHOD("get_min"), &CurveTexture::get_min); - ClassDB::bind_method(D_METHOD("set_width", "width"), &CurveTexture::set_width); ClassDB::bind_method(D_METHOD("set_curve", "curve:Curve"), &CurveTexture::set_curve); @@ -1383,52 +1377,31 @@ void CurveTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("_update"), &CurveTexture::_update); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "min", PROPERTY_HINT_RANGE, "-1024,1024"), "set_min", "get_min"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "max", PROPERTY_HINT_RANGE, "-1024,1024"), "set_max", "get_max"); ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "32,4096"), "set_width", "get_width"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve"); } -void CurveTexture::set_max(float p_max) { - - _max = p_max; - emit_changed(); -} -float CurveTexture::get_max() const { - return _max; -} - -void CurveTexture::set_min(float p_min) { - - _min = p_min; - emit_changed(); -} -float CurveTexture::get_min() const { - - return _min; -} void CurveTexture::set_width(int p_width) { ERR_FAIL_COND(p_width < 32 || p_width > 4096); _width = p_width; _update(); } + int CurveTexture::get_width() const { return _width; } -void CurveTexture::ensure_default_setup() { - +void CurveTexture::ensure_default_setup(float p_min, float p_max) { if (_curve.is_null()) { Ref<Curve> curve = Ref<Curve>(memnew(Curve)); curve->add_point(Vector2(0, 1)); curve->add_point(Vector2(1, 1)); + curve->set_min_value(p_min); + curve->set_max_value(p_max); set_curve(curve); - } - - if (get_min() == 0 && get_max() == 1) { - set_max(32); + // Min and max is 0..1 by default } } @@ -1457,11 +1430,9 @@ void CurveTexture::_update() { if (_curve.is_valid()) { Curve &curve = **_curve; - float height = _max - _min; for (int i = 0; i < _width; ++i) { float t = i / static_cast<float>(_width); - float v = curve.interpolate_baked(t); - wd[i] = CLAMP(_min + v * height, _min, _max); + wd[i] = curve.interpolate_baked(t); } } else { @@ -1490,9 +1461,6 @@ RID CurveTexture::get_rid() const { } CurveTexture::CurveTexture() { - - _max = 1; - _min = 0; _width = 2048; _texture = VS::get_singleton()->texture_create(); } diff --git a/scene/resources/texture.h b/scene/resources/texture.h index ff5a58c221..9bbbd1d091 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -403,7 +403,6 @@ class CurveTexture : public Texture { private: RID _texture; Ref<Curve> _curve; - float _min, _max; int _width; void _update(); @@ -412,16 +411,10 @@ protected: static void _bind_methods(); public: - void set_max(float p_max); - float get_max() const; - - void set_min(float p_min); - float get_min() const; - void set_width(int p_width); int get_width() const; - void ensure_default_setup(); + void ensure_default_setup(float p_min=0, float p_max=1); void set_curve(Ref<Curve> p_curve); Ref<Curve> get_curve() const; |