diff options
author | Juan Linietsky <reduzio@gmail.com> | 2017-06-23 20:07:01 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-23 20:07:01 -0300 |
commit | 693eb0fa06a5be6e9664f7a413199f0100b7d289 (patch) | |
tree | db94c76d34d51e9ec97213a08c9654825707fad4 /scene | |
parent | 00e5ba314393ce2cc4df883bc1742306007ed117 (diff) | |
parent | 659897cfb8bda0377d798a6f73505d537e521cf9 (diff) |
Merge pull request #8591 from Zylann/curve_1d
Added Curve resource
Diffstat (limited to 'scene')
-rw-r--r-- | scene/3d/particles.cpp | 22 | ||||
-rw-r--r-- | scene/register_scene_types.cpp | 1 | ||||
-rw-r--r-- | scene/resources/curve.cpp | 359 | ||||
-rw-r--r-- | scene/resources/curve.h | 72 | ||||
-rw-r--r-- | scene/resources/texture.cpp | 242 | ||||
-rw-r--r-- | scene/resources/texture.h | 27 |
6 files changed, 510 insertions, 213 deletions
diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp index 8508962521..722b698b75 100644 --- a/scene/3d/particles.cpp +++ b/scene/3d/particles.cpp @@ -1082,16 +1082,9 @@ void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture> case PARAM_SCALE: { VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_texture, p_texture); - Ref<CurveTexture> curve = p_texture; - if (curve.is_valid()) { - if (curve->get_min() == 0 && curve->get_max() == 1) { - - curve->set_max(32); - PoolVector<Vector2> points; - points.push_back(Vector2(0, 1)); - points.push_back(Vector2(1, 1)); - curve->set_points(points); - } + Ref<CurveTexture> curve_tex = p_texture; + if (curve_tex.is_valid()) { + curve_tex->ensure_default_setup(); } } break; @@ -1257,14 +1250,7 @@ void ParticlesMaterial::set_trail_size_modifier(const Ref<CurveTexture> &p_trail Ref<CurveTexture> curve = trail_size_modifier; if (curve.is_valid()) { - if (curve->get_min() == 0 && curve->get_max() == 1) { - - curve->set_max(32); - PoolVector<Vector2> points; - points.push_back(Vector2(0, 1)); - points.push_back(Vector2(1, 1)); - curve->set_points(points); - } + curve->ensure_default_setup(); } RID texture; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 69d1a3aeb8..151bc80321 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -580,6 +580,7 @@ void register_scene_types() { ClassDB::register_class<Animation>(); ClassDB::register_virtual_class<Font>(); ClassDB::register_class<BitmapFont>(); + ClassDB::register_class<Curve>(); ClassDB::register_class<DynamicFontData>(); ClassDB::register_class<DynamicFont>(); diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 10c12c9411..006e7de562 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -380,6 +380,365 @@ Curve2D::Curve2D() #endif +Curve::Curve() { + _bake_resolution = 100; + _baked_cache_dirty = false; +#ifdef TOOLS_ENABLED + _disable_set_data = false; +#endif +} + +int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent) { + // Add a point and preserve order + + // Curve bounds is in 0..1 + if (p_pos.x > MAX_X) + p_pos.x = MAX_X; + else if (p_pos.x < MIN_X) + p_pos.x = MIN_X; + + int ret = -1; + + if (_points.size() == 0) { + _points.push_back(Point(p_pos, left_tangent, right_tangent)); + ret = 0; + + } else if (_points.size() == 1) { + // TODO Is the `else` able to handle this block already? + + real_t diff = p_pos.x - _points[0].pos.x; + + if (diff > 0) { + _points.push_back(Point(p_pos, left_tangent, right_tangent)); + ret = 1; + } else { + _points.insert(0, Point(p_pos, left_tangent, right_tangent)); + ret = 0; + } + + } else { + + int i = get_index(p_pos.x); + + int nearest_index = i; + if (i + 1 < _points.size()) { + real_t diff0 = p_pos.x - _points[i].pos.x; + real_t diff1 = _points[i + 1].pos.x - p_pos.x; + + if (diff1 < diff0) + nearest_index = i + 1; + } + + if (i == 0 && p_pos.x < _points[0].pos.x) { + // Insert before anything else + _points.insert(0, Point(p_pos, left_tangent, right_tangent)); + ret = 0; + } else { + // Insert between i and i+1 + ++i; + _points.insert(i, Point(p_pos, left_tangent, right_tangent)); + ret = i; + } + } + + mark_dirty(); + + return ret; +} + +int Curve::get_index(real_t offset) const { + + // Lower-bound float binary search + + int imin = 0; + int imax = _points.size() - 1; + + while (imax - imin > 1) { + int m = (imin + imax) / 2; + + real_t a = _points[m].pos.x; + real_t b = _points[m + 1].pos.x; + + if (a < offset && b < offset) { + imin = m; + + } else if (a > offset) { + imax = m; + + } else { + return m; + } + } + + // Will happen if the offset is out of bounds + if (offset > _points[imax].pos.x) + return imax; + return imin; +} + +void Curve::clean_dupes() { + + bool dirty = false; + + for (int i = 1; i < _points.size(); ++i) { + real_t diff = _points[i - 1].pos.x - _points[i].pos.x; + if (diff <= CMP_EPSILON) { + _points.remove(i); + --i; + dirty = true; + } + } + + if (dirty) + mark_dirty(); +} + +void Curve::set_point_left_tangent(int i, real_t tangent) { + ERR_FAIL_INDEX(i, _points.size()); + _points[i].left_tangent = tangent; + mark_dirty(); +} + +void Curve::set_point_right_tangent(int i, real_t tangent) { + ERR_FAIL_INDEX(i, _points.size()); + _points[i].right_tangent = tangent; + mark_dirty(); +} + +real_t Curve::get_point_left_tangent(int i) const { + ERR_FAIL_INDEX_V(i, _points.size(), 0); + return _points[i].left_tangent; +} + +real_t Curve::get_point_right_tangent(int i) const { + ERR_FAIL_INDEX_V(i, _points.size(), 0); + return _points[i].right_tangent; +} + +void Curve::remove_point(int p_index) { + ERR_FAIL_INDEX(p_index, _points.size()); + _points.remove(p_index); + mark_dirty(); +} + +void Curve::clear_points() { + _points.clear(); + mark_dirty(); +} + +void Curve::set_point_value(int p_index, real_t pos) { + ERR_FAIL_INDEX(p_index, _points.size()); + _points[p_index].pos.y = pos; + mark_dirty(); +} + +int Curve::set_point_offset(int p_index, float offset) { + ERR_FAIL_INDEX_V(p_index, _points.size(), -1); + Point p = _points[p_index]; + remove_point(p_index); + int i = add_point(Vector2(offset, p.pos.y)); + _points[i].left_tangent = p.left_tangent; + _points[i].right_tangent = p.right_tangent; + return i; +} + +Vector2 Curve::get_point_pos(int p_index) const { + ERR_FAIL_INDEX_V(p_index, _points.size(), Vector2(0, 0)); + return _points[p_index].pos; +} + +real_t Curve::interpolate(real_t offset) const { + if (_points.size() == 0) + return 0; + if (_points.size() == 1) + return _points[0].pos.y; + + int i = get_index(offset); + + if (i == _points.size() - 1) + return _points[i].pos.y; + + real_t local = offset - _points[i].pos.x; + + if (i == 0 && local <= 0) + return _points[0].pos.y; + + return interpolate_local_nocheck(i, local); +} + +real_t Curve::interpolate_local_nocheck(int index, real_t local_offset) const { + + const Point a = _points[index]; + const Point b = _points[index + 1]; + + // Cubic bezier + + // ac-----bc + // / \ + // / \ Here with a.right_tangent > 0 + // / \ and b.left_tangent < 0 + // / \ + // a b + // + // |-d1--|-d2--|-d3--| + // + // d1 == d2 == d3 == d / 3 + + // Control points are chosen at equal distances + real_t d = b.pos.x - a.pos.x; + if (Math::abs(d) <= CMP_EPSILON) + return b.pos.y; + local_offset /= d; + d /= 3.0; + real_t yac = a.pos.y + d * a.right_tangent; + real_t ybc = b.pos.y - d * b.left_tangent; + + real_t y = _bezier_interp(local_offset, a.pos.y, yac, ybc, b.pos.y); + + return y; +} + +void Curve::mark_dirty() { + _baked_cache_dirty = true; + emit_signal(CoreStringNames::get_singleton()->changed); +} + +Array Curve::get_data() const { + + Array output; + output.resize(_points.size() * 3); + + for (int j = 0; j < _points.size(); ++j) { + + const Point p = _points[j]; + int i = j * 3; + + output[i] = p.pos; + output[i + 1] = p.left_tangent; + output[i + 2] = p.right_tangent; + } + + return output; +} + +void Curve::set_data(Array input) { + ERR_FAIL_COND(input.size() % 3 != 0); + +#ifdef TOOLS_ENABLED + if (_disable_set_data) + return; +#endif + + _points.clear(); + + // Validate input + for (int i = 0; i < input.size(); i += 3) { + 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); + } + + _points.resize(input.size() / 3); + + for (int j = 0; j < _points.size(); ++j) { + + Point &p = _points[j]; + int i = j * 3; + + p.pos = input[i]; + p.left_tangent = input[i + 1]; + p.right_tangent = input[i + 2]; + } + + mark_dirty(); +} + +void Curve::bake() { + _baked_cache.clear(); + + _baked_cache.resize(_bake_resolution); + + for (int i = 1; i < _bake_resolution - 1; ++i) { + real_t x = i / static_cast<real_t>(_bake_resolution); + real_t y = interpolate(x); + _baked_cache[i] = y; + } + + if (_points.size() != 0) { + _baked_cache[0] = _points[0].pos.y; + _baked_cache[_baked_cache.size() - 1] = _points[_points.size() - 1].pos.y; + } + + _baked_cache_dirty = false; +} + +void Curve::set_bake_resolution(int p_resolution) { + ERR_FAIL_COND(p_resolution < 1); + ERR_FAIL_COND(p_resolution > 1000); + _bake_resolution = p_resolution; + _baked_cache_dirty = true; +} + +real_t Curve::interpolate_baked(real_t offset) { + if (_baked_cache_dirty) { + // Last-second bake if not done already + bake(); + } + + // Special cases if the cache is too small + if (_baked_cache.size() == 0) { + if (_points.size() == 0) + return 0; + return _points[0].pos.y; + } else if (_baked_cache.size() == 1) { + return _baked_cache[0]; + } + + // Get interpolation index + real_t fi = offset * _baked_cache.size(); + int i = Math::floor(fi); + if (i < 0) { + i = 0; + fi = 0; + } else if (i >= _baked_cache.size()) { + i = _baked_cache.size() - 1; + fi = 0; + } + + // Interpolate + if (i + 1 < _baked_cache.size()) { + real_t t = fi - i; + return Math::lerp(_baked_cache[i], _baked_cache[i + 1], t); + } else { + return _baked_cache[_baked_cache.size() - 1]; + } +} + +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("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); + ClassDB::bind_method(D_METHOD("set_point_value", "index, y"), &Curve::set_point_value); + ClassDB::bind_method(D_METHOD("set_point_offset", "index, offset"), &Curve::set_point_value); + ClassDB::bind_method(D_METHOD("interpolate", "offset"), &Curve::interpolate); + 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("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("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); + ClassDB::bind_method(D_METHOD("set_bake_resolution", "resolution"), &Curve::set_bake_resolution); + 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::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"); +} + int Curve2D::get_point_count() const { return points.size(); diff --git a/scene/resources/curve.h b/scene/resources/curve.h index 17c0ac9f5e..63b9a07f07 100644 --- a/scene/resources/curve.h +++ b/scene/resources/curve.h @@ -82,6 +82,78 @@ public: #endif +// y(x) curve +class Curve : public Resource { + GDCLASS(Curve, Resource) +public: + static const int MIN_X = 0.f; + static const int MAX_X = 1.f; + +#ifdef TOOLS_ENABLED + bool _disable_set_data; +#endif + + struct Point { + Vector2 pos; + real_t left_tangent; + real_t right_tangent; + + Point() { + left_tangent = 0; + right_tangent = 0; + } + + Point(Vector2 p, real_t left = 0, real_t right = 0) { + pos = p; + left_tangent = left; + right_tangent = right; + } + }; + + Curve(); + + int get_point_count() const { return _points.size(); } + + int add_point(Vector2 p_pos, real_t left_tangent = 0, real_t right_tangent = 0); + void remove_point(int p_index); + void clear_points(); + + int get_index(real_t offset) const; + + void set_point_value(int p_index, real_t pos); + int set_point_offset(int p_index, float offset); + Vector2 get_point_pos(int p_index) const; + + real_t interpolate(real_t offset) const; + real_t interpolate_local_nocheck(int index, real_t local_offset) const; + + void clean_dupes(); + + void set_point_left_tangent(int i, real_t tangent); + void set_point_right_tangent(int i, real_t tangent); + real_t get_point_left_tangent(int i) const; + real_t get_point_right_tangent(int i) const; + + Array get_data() const; + void set_data(Array input); + + void bake(); + int get_bake_resolution() const { return _bake_resolution; } + void set_bake_resolution(int p_interval); + real_t interpolate_baked(real_t offset); + +protected: + static void _bind_methods(); + +private: + void mark_dirty(); + + Vector<Point> _points; + bool _baked_cache_dirty; + Vector<real_t> _baked_cache; + int _bake_resolution; +}; + class Curve2D : public Resource { GDCLASS(Curve2D, Resource); diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 2120b37497..7b393233f1 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -30,7 +30,9 @@ #include "texture.h" #include "core/method_bind_ext.inc" #include "core/os/os.h" +#include "core_string_names.h" #include "io/image_loader.h" + Size2 Texture::get_size() const { return Size2(get_width(), get_height()); @@ -1376,254 +1378,126 @@ void CurveTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_width", "width"), &CurveTexture::set_width); - ClassDB::bind_method(D_METHOD("set_points", "points"), &CurveTexture::set_points); - ClassDB::bind_method(D_METHOD("get_points"), &CurveTexture::get_points); + ClassDB::bind_method(D_METHOD("set_curve", "curve:Curve"), &CurveTexture::set_curve); + ClassDB::bind_method(D_METHOD("get_curve:Curve"), &CurveTexture::get_curve); + + 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::POOL_VECTOR2_ARRAY, "points"), "set_points", "get_points"); + 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; + _max = p_max; emit_changed(); } float CurveTexture::get_max() const { - return max; + return _max; } void CurveTexture::set_min(float p_min) { - min = p_min; + _min = p_min; emit_changed(); } float CurveTexture::get_min() const { - return min; + return _min; } void CurveTexture::set_width(int p_width) { ERR_FAIL_COND(p_width < 32 || p_width > 4096); - width = p_width; - if (points.size()) - set_points(points); + _width = p_width; + _update(); } int CurveTexture::get_width() const { - return width; + return _width; } -static void _plot_curve(const Vector2 &p_a, const Vector2 &p_b, const Vector2 &p_c, const Vector2 &p_d, float *p_heights, bool *p_useds, int p_width, float p_min, float p_max) { - - float geometry[4][4]; - float tmp1[4][4]; - float tmp2[4][4]; - float deltas[4][4]; - double x, dx, dx2, dx3; - double y, dy, dy2, dy3; - double d, d2, d3; - int lastx; - int newx; - float lasty; - float newy; - int ntimes; - int i, j; - - int xmax = p_width; - - /* construct the geometry matrix from the segment */ - for (i = 0; i < 4; i++) { - geometry[i][2] = 0; - geometry[i][3] = 0; - } +void CurveTexture::ensure_default_setup() { - geometry[0][0] = (p_a[0] * xmax); - geometry[1][0] = (p_b[0] * xmax); - geometry[2][0] = (p_c[0] * xmax); - geometry[3][0] = (p_d[0] * xmax); - - geometry[0][1] = (p_a[1]); - geometry[1][1] = (p_b[1]); - geometry[2][1] = (p_c[1]); - geometry[3][1] = (p_d[1]); - - /* subdivide the curve ntimes (1000) times */ - ntimes = 4 * xmax; - /* ntimes can be adjusted to give a finer or coarser curve */ - d = 1.0 / ntimes; - d2 = d * d; - d3 = d * d * d; - - /* construct a temporary matrix for determining the forward differencing deltas */ - tmp2[0][0] = 0; - tmp2[0][1] = 0; - tmp2[0][2] = 0; - tmp2[0][3] = 1; - tmp2[1][0] = d3; - tmp2[1][1] = d2; - tmp2[1][2] = d; - tmp2[1][3] = 0; - tmp2[2][0] = 6 * d3; - tmp2[2][1] = 2 * d2; - tmp2[2][2] = 0; - tmp2[2][3] = 0; - tmp2[3][0] = 6 * d3; - tmp2[3][1] = 0; - tmp2[3][2] = 0; - tmp2[3][3] = 0; - - /* compose the basis and geometry matrices */ - - static const float CR_basis[4][4] = { - { -0.5, 1.5, -1.5, 0.5 }, - { 1.0, -2.5, 2.0, -0.5 }, - { -0.5, 0.0, 0.5, 0.0 }, - { 0.0, 1.0, 0.0, 0.0 }, - }; - - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - tmp1[i][j] = (CR_basis[i][0] * geometry[0][j] + - CR_basis[i][1] * geometry[1][j] + - CR_basis[i][2] * geometry[2][j] + - CR_basis[i][3] * geometry[3][j]); - } + if (_curve.is_null()) { + Ref<Curve> curve = Ref<Curve>(memnew(Curve)); + curve->add_point(Vector2(0, 1)); + curve->add_point(Vector2(1, 1)); + set_curve(curve); } - /* compose the above results to get the deltas matrix */ - - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - deltas[i][j] = (tmp2[i][0] * tmp1[0][j] + - tmp2[i][1] * tmp1[1][j] + - tmp2[i][2] * tmp1[2][j] + - tmp2[i][3] * tmp1[3][j]); - } + + if (get_min() == 0 && get_max() == 1) { + set_max(32); } +} - /* extract the x deltas */ - x = deltas[0][0]; - dx = deltas[1][0]; - dx2 = deltas[2][0]; - dx3 = deltas[3][0]; - - /* extract the y deltas */ - y = deltas[0][1]; - dy = deltas[1][1]; - dy2 = deltas[2][1]; - dy3 = deltas[3][1]; - - lastx = CLAMP(x, 0, xmax); - lasty = y; - - p_heights[lastx] = lasty; - p_useds[lastx] = true; - - /* loop over the curve */ - for (i = 0; i < ntimes; i++) { - /* increment the x values */ - x += dx; - dx += dx2; - dx2 += dx3; - - /* increment the y values */ - y += dy; - dy += dy2; - dy2 += dy3; - - newx = CLAMP((Math::round(x)), 0, xmax); - newy = CLAMP(y, p_min, p_max); - - /* if this point is different than the last one...then draw it */ - if ((lastx != newx) || (lasty != newy)) { - p_useds[newx] = true; - p_heights[newx] = newy; +void CurveTexture::set_curve(Ref<Curve> p_curve) { + if (_curve != p_curve) { + if (_curve.is_valid()) { + _curve->disconnect(CoreStringNames::get_singleton()->changed, this, "_update"); } - - lastx = newx; - lasty = newy; + _curve = p_curve; + if (_curve.is_valid()) { + _curve->connect(CoreStringNames::get_singleton()->changed, this, "_update"); + } + _update(); } } -void CurveTexture::set_points(const PoolVector<Vector2> &p_points) { - - points = p_points; +void CurveTexture::_update() { PoolVector<uint8_t> data; - PoolVector<bool> used; - data.resize(width * sizeof(float)); - used.resize(width); + data.resize(_width * sizeof(float)); + + // The array is locked in that scope { PoolVector<uint8_t>::Write wd8 = data.write(); float *wd = (float *)wd8.ptr(); - PoolVector<bool>::Write wu = used.write(); - int pc = p_points.size(); - PoolVector<Vector2>::Read pr = p_points.read(); - for (int i = 0; i < width; i++) { - wd[i] = 0.0; - wu[i] = false; - } - - Vector2 prev = Vector2(0, 0); - Vector2 prev2 = Vector2(0, 0); - - for (int i = -1; i < pc; i++) { - - Vector2 next; - Vector2 next2; - if (i + 1 >= pc) { - next = Vector2(1, 0); - } else { - next = Vector2(pr[i + 1].x, pr[i + 1].y); + 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); } - if (i + 2 >= pc) { - next2 = Vector2(1, 0); - } else { - next2 = Vector2(pr[i + 2].x, pr[i + 2].y); + } else { + for (int i = 0; i < _width; ++i) { + wd[i] = 0; } - - /*if (i==-1 && prev.offset==next.offset) { - prev=next; - continue; - }*/ - - _plot_curve(prev2, prev, next, next2, wd, wu.ptr(), width, min, max); - - prev2 = prev; - prev = next; } } - Ref<Image> image = memnew(Image(width, 1, false, Image::FORMAT_RF, data)); + Ref<Image> image = memnew(Image(_width, 1, false, Image::FORMAT_RF, data)); - VS::get_singleton()->texture_allocate(texture, width, 1, Image::FORMAT_RF, VS::TEXTURE_FLAG_FILTER); - VS::get_singleton()->texture_set_data(texture, image); + VS::get_singleton()->texture_allocate(_texture, _width, 1, Image::FORMAT_RF, VS::TEXTURE_FLAG_FILTER); + VS::get_singleton()->texture_set_data(_texture, image); emit_changed(); } -PoolVector<Vector2> CurveTexture::get_points() const { +Ref<Curve> CurveTexture::get_curve() const { - return points; + return _curve; } RID CurveTexture::get_rid() const { - return texture; + return _texture; } CurveTexture::CurveTexture() { - max = 1; - min = 0; - width = 2048; - texture = VS::get_singleton()->texture_create(); + _max = 1; + _min = 0; + _width = 2048; + _texture = VS::get_singleton()->texture_create(); } CurveTexture::~CurveTexture() { - VS::get_singleton()->free(texture); + VS::get_singleton()->free(_texture); } ////////////////// diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 2b82dbd21f..2c36cdef87 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -30,6 +30,7 @@ #ifndef TEXTURE_H #define TEXTURE_H +#include "curve.h" #include "io/resource_loader.h" #include "math_2d.h" #include "resource.h" @@ -389,20 +390,22 @@ public: ~CubeMap(); }; -VARIANT_ENUM_CAST(CubeMap::Flags); -VARIANT_ENUM_CAST(CubeMap::Side); -VARIANT_ENUM_CAST(CubeMap::Storage); +VARIANT_ENUM_CAST(CubeMap::Flags) +VARIANT_ENUM_CAST(CubeMap::Side) +VARIANT_ENUM_CAST(CubeMap::Storage) class CurveTexture : public Texture { - GDCLASS(CurveTexture, Texture); - RES_BASE_EXTENSION("curvetex"); + GDCLASS(CurveTexture, Texture) + RES_BASE_EXTENSION("curvetex") private: - RID texture; - PoolVector<Vector2> points; - float min, max; - int width; + RID _texture; + Ref<Curve> _curve; + float _min, _max; + int _width; + + void _update(); protected: static void _bind_methods(); @@ -417,8 +420,10 @@ public: void set_width(int p_width); int get_width() const; - void set_points(const PoolVector<Vector2> &p_points); - PoolVector<Vector2> get_points() const; + void ensure_default_setup(); + + void set_curve(Ref<Curve> p_curve); + Ref<Curve> get_curve() const; virtual RID get_rid() const; |