diff options
Diffstat (limited to 'scene/resources')
47 files changed, 1019 insertions, 942 deletions
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 69b30b72b0..da59c4dbd1 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -313,29 +313,37 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { Dictionary d = p_value; ERR_FAIL_COND_V(!d.has("times"), false); ERR_FAIL_COND_V(!d.has("points"), false); - Vector<real_t> times = d["times"]; Vector<real_t> values = d["points"]; +#ifdef TOOLS_ENABLED + ERR_FAIL_COND_V(!d.has("handle_modes"), false); + Vector<int> handle_modes = d["handle_modes"]; +#endif // TOOLS_ENABLED - ERR_FAIL_COND_V(times.size() * 6 != values.size(), false); + ERR_FAIL_COND_V(times.size() * 5 != values.size(), false); if (times.size()) { int valcount = times.size(); const real_t *rt = times.ptr(); const real_t *rv = values.ptr(); +#ifdef TOOLS_ENABLED + const int *rh = handle_modes.ptr(); +#endif // TOOLS_ENABLED bt->values.resize(valcount); for (int i = 0; i < valcount; i++) { bt->values.write[i].time = rt[i]; bt->values.write[i].transition = 0; //unused in bezier - bt->values.write[i].value.value = rv[i * 6 + 0]; - bt->values.write[i].value.in_handle.x = rv[i * 6 + 1]; - bt->values.write[i].value.in_handle.y = rv[i * 6 + 2]; - bt->values.write[i].value.out_handle.x = rv[i * 6 + 3]; - bt->values.write[i].value.out_handle.y = rv[i * 6 + 4]; - bt->values.write[i].value.handle_mode = static_cast<HandleMode>((int)rv[i * 6 + 5]); + bt->values.write[i].value.value = rv[i * 5 + 0]; + bt->values.write[i].value.in_handle.x = rv[i * 5 + 1]; + bt->values.write[i].value.in_handle.y = rv[i * 5 + 2]; + bt->values.write[i].value.out_handle.x = rv[i * 5 + 3]; + bt->values.write[i].value.out_handle.y = rv[i * 5 + 4]; +#ifdef TOOLS_ENABLED + bt->values.write[i].value.handle_mode = static_cast<HandleMode>(rh[i]); +#endif // TOOLS_ENABLED } } @@ -699,28 +707,39 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { int kk = bt->values.size(); key_times.resize(kk); - key_points.resize(kk * 6); + key_points.resize(kk * 5); real_t *wti = key_times.ptrw(); real_t *wpo = key_points.ptrw(); +#ifdef TOOLS_ENABLED + Vector<int> handle_modes; + handle_modes.resize(kk); + int *whm = handle_modes.ptrw(); +#endif // TOOLS_ENABLED + int idx = 0; const TKey<BezierKey> *vls = bt->values.ptr(); for (int i = 0; i < kk; i++) { wti[idx] = vls[i].time; - wpo[idx * 6 + 0] = vls[i].value.value; - wpo[idx * 6 + 1] = vls[i].value.in_handle.x; - wpo[idx * 6 + 2] = vls[i].value.in_handle.y; - wpo[idx * 6 + 3] = vls[i].value.out_handle.x; - wpo[idx * 6 + 4] = vls[i].value.out_handle.y; - wpo[idx * 6 + 5] = (double)vls[i].value.handle_mode; + wpo[idx * 5 + 0] = vls[i].value.value; + wpo[idx * 5 + 1] = vls[i].value.in_handle.x; + wpo[idx * 5 + 2] = vls[i].value.in_handle.y; + wpo[idx * 5 + 3] = vls[i].value.out_handle.x; + wpo[idx * 5 + 4] = vls[i].value.out_handle.y; +#ifdef TOOLS_ENABLED + whm[idx] = static_cast<int>(vls[i].value.handle_mode); +#endif // TOOLS_ENABLED idx++; } d["times"] = key_times; d["points"] = key_points; +#ifdef TOOLS_ENABLED + d["handle_modes"] = handle_modes; +#endif // TOOLS_ENABLED r_ret = d; @@ -967,7 +986,6 @@ int Animation::find_track(const NodePath &p_path, const TrackType p_type) const void Animation::track_set_interpolation_type(int p_track, InterpolationType p_interp) { ERR_FAIL_INDEX(p_track, tracks.size()); - ERR_FAIL_INDEX(p_interp, 3); tracks[p_track]->interpolation = p_interp; emit_changed(); } @@ -1627,7 +1645,7 @@ int Animation::track_insert_key(int p_track, double p_time, const Variant &p_key BezierTrack *bt = static_cast<BezierTrack *>(t); Array arr = p_key; - ERR_FAIL_COND_V(arr.size() != 6, -1); + ERR_FAIL_COND_V(arr.size() != 5, -1); TKey<BezierKey> k; k.time = p_time; @@ -1636,9 +1654,16 @@ int Animation::track_insert_key(int p_track, double p_time, const Variant &p_key k.value.in_handle.y = arr[2]; k.value.out_handle.x = arr[3]; k.value.out_handle.y = arr[4]; - k.value.handle_mode = static_cast<HandleMode>((int)arr[5]); ret = _insert(p_time, bt->values, k); + Vector<int> key_neighborhood; + key_neighborhood.push_back(ret); + if (ret > 0) { + key_neighborhood.push_back(ret - 1); + } + if (ret < track_get_key_count(p_track) - 1) { + key_neighborhood.push_back(ret + 1); + } } break; case TYPE_AUDIO: { AudioTrack *at = static_cast<AudioTrack *>(t); @@ -1777,13 +1802,12 @@ Variant Animation::track_get_key_value(int p_track, int p_key_idx) const { ERR_FAIL_INDEX_V(p_key_idx, bt->values.size(), Variant()); Array arr; - arr.resize(6); + arr.resize(5); arr[0] = bt->values[p_key_idx].value.value; arr[1] = bt->values[p_key_idx].value.in_handle.x; arr[2] = bt->values[p_key_idx].value.in_handle.y; arr[3] = bt->values[p_key_idx].value.out_handle.x; arr[4] = bt->values[p_key_idx].value.out_handle.y; - arr[5] = (double)bt->values[p_key_idx].value.handle_mode; return arr; } break; @@ -2152,14 +2176,13 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p ERR_FAIL_INDEX(p_key_idx, bt->values.size()); Array arr = p_value; - ERR_FAIL_COND(arr.size() != 6); + ERR_FAIL_COND(arr.size() != 5); bt->values.write[p_key_idx].value.value = arr[0]; bt->values.write[p_key_idx].value.in_handle.x = arr[1]; bt->values.write[p_key_idx].value.in_handle.y = arr[2]; bt->values.write[p_key_idx].value.out_handle.x = arr[3]; bt->values.write[p_key_idx].value.out_handle.y = arr[4]; - bt->values.write[p_key_idx].value.handle_mode = static_cast<HandleMode>((int)arr[5]); } break; case TYPE_AUDIO: { @@ -2283,6 +2306,8 @@ int Animation::_find(const Vector<K> &p_keys, double p_time, bool p_backward) co return middle; } +// Linear interpolation for anytype. + Vector3 Animation::_interpolate(const Vector3 &p_a, const Vector3 &p_b, real_t p_c) const { return p_a.lerp(p_b, p_c); } @@ -2301,6 +2326,8 @@ real_t Animation::_interpolate(const real_t &p_a, const real_t &p_b, real_t p_c) return p_a * (1.0 - p_c) + p_b * p_c; } +// Cubic interpolation for anytype. + Vector3 Animation::_cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, real_t p_c) const { return p_a.cubic_interpolate(p_b, p_pre_a, p_post_b, p_c); } @@ -2389,6 +2416,96 @@ real_t Animation::_cubic_interpolate(const real_t &p_pre_a, const real_t &p_a, c return _interpolate(p_a, p_b, p_c); } +// Cubic interpolation in time for anytype. + +Vector3 Animation::_cubic_interpolate_in_time(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const { + return p_a.cubic_interpolate_in_time(p_b, p_pre_a, p_post_b, p_c, p_b_t, p_pre_a_t, p_post_b_t); +} + +Quaternion Animation::_cubic_interpolate_in_time(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const { + return p_a.spherical_cubic_interpolate_in_time(p_b, p_pre_a, p_post_b, p_c, p_b_t, p_pre_a_t, p_post_b_t); +} + +Variant Animation::_cubic_interpolate_in_time(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const { + Variant::Type type_a = p_a.get_type(); + Variant::Type type_b = p_b.get_type(); + Variant::Type type_pa = p_pre_a.get_type(); + Variant::Type type_pb = p_post_b.get_type(); + + //make int and real play along + + uint32_t vformat = 1 << type_a; + vformat |= 1 << type_b; + vformat |= 1 << type_pa; + vformat |= 1 << type_pb; + + if (vformat == ((1 << Variant::INT) | (1 << Variant::FLOAT)) || vformat == (1 << Variant::FLOAT)) { + //mix of real and int + real_t a = p_a; + real_t b = p_b; + real_t pa = p_pre_a; + real_t pb = p_post_b; + + return Math::cubic_interpolate_in_time(a, b, pa, pb, p_c, p_b_t, p_pre_a_t, p_post_b_t); + } else if ((vformat & (vformat - 1))) { + return p_a; //can't interpolate, mix of types + } + + switch (type_a) { + case Variant::VECTOR2: { + Vector2 a = p_a; + Vector2 b = p_b; + Vector2 pa = p_pre_a; + Vector2 pb = p_post_b; + + return a.cubic_interpolate_in_time(b, pa, pb, p_c, p_b_t, p_pre_a_t, p_post_b_t); + } + case Variant::RECT2: { + Rect2 a = p_a; + Rect2 b = p_b; + Rect2 pa = p_pre_a; + Rect2 pb = p_post_b; + + return Rect2( + a.position.cubic_interpolate_in_time(b.position, pa.position, pb.position, p_c, p_b_t, p_pre_a_t, p_post_b_t), + a.size.cubic_interpolate_in_time(b.size, pa.size, pb.size, p_c, p_b_t, p_pre_a_t, p_post_b_t)); + } + case Variant::VECTOR3: { + Vector3 a = p_a; + Vector3 b = p_b; + Vector3 pa = p_pre_a; + Vector3 pb = p_post_b; + + return a.cubic_interpolate_in_time(b, pa, pb, p_c, p_b_t, p_pre_a_t, p_post_b_t); + } + case Variant::QUATERNION: { + Quaternion a = p_a; + Quaternion b = p_b; + Quaternion pa = p_pre_a; + Quaternion pb = p_post_b; + + return a.spherical_cubic_interpolate_in_time(b, pa, pb, p_c, p_b_t, p_pre_a_t, p_post_b_t); + } + case Variant::AABB: { + AABB a = p_a; + AABB b = p_b; + AABB pa = p_pre_a; + AABB pb = p_post_b; + + return AABB( + a.position.cubic_interpolate_in_time(b.position, pa.position, pb.position, p_c, p_b_t, p_pre_a_t, p_post_b_t), + a.size.cubic_interpolate_in_time(b.size, pa.size, pb.size, p_c, p_b_t, p_pre_a_t, p_post_b_t)); + } + default: { + return _interpolate(p_a, p_b, p_c); + } + } +} + +real_t Animation::_cubic_interpolate_in_time(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const { + return _interpolate(p_a, p_b, p_c); +} + template <class T> T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok, bool p_backward) const { int len = _find(p_keys, length) + 1; // try to find last key (there may be more past the end) @@ -2568,26 +2685,65 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol case INTERPOLATION_LINEAR: { return _interpolate(p_keys[idx].value, p_keys[next].value, c); } break; - case INTERPOLATION_CUBIC: { - int pre = idx - 1; - if (pre < 0) { - if (loop_mode == LOOP_LINEAR && p_loop_wrap) { - pre = len - 1; - } else { - pre = 0; + case INTERPOLATION_CUBIC: + case INTERPOLATION_CUBIC_IN_TIME: { + int pre = 0; + int post = 0; + if (!p_backward) { + pre = idx - 1; + if (pre < 0) { + if (loop_mode == LOOP_LINEAR && p_loop_wrap) { + pre = len - 1; + } else { + pre = 0; + } } - } - int post = next + 1; - if (post >= len) { - if (loop_mode == LOOP_LINEAR && p_loop_wrap) { - post = 0; - } else { - post = next; + post = next + 1; + if (post >= len) { + if (loop_mode == LOOP_LINEAR && p_loop_wrap) { + post = 0; + } else { + post = next; + } + } + } else { + pre = idx + 1; + if (pre >= len) { + if (loop_mode == LOOP_LINEAR && p_loop_wrap) { + pre = 0; + } else { + pre = idx; + } + } + post = next - 1; + if (post < 0) { + if (loop_mode == LOOP_LINEAR && p_loop_wrap) { + post = len - 1; + } else { + post = 0; + } } } - return _cubic_interpolate(p_keys[pre].value, p_keys[idx].value, p_keys[next].value, p_keys[post].value, c); + if (loop_mode == LOOP_LINEAR && p_loop_wrap) { + if (p_interp == INTERPOLATION_CUBIC) { + return _cubic_interpolate(p_keys[pre].value, p_keys[idx].value, p_keys[next].value, p_keys[post].value, c); + } + return _cubic_interpolate_in_time( + p_keys[pre].value, p_keys[idx].value, p_keys[next].value, p_keys[post].value, c, + pre > idx ? -length + p_keys[pre].time - p_keys[idx].time : p_keys[pre].time - p_keys[idx].time, + next < idx ? length + p_keys[next].time - p_keys[idx].time : p_keys[next].time - p_keys[idx].time, + next < idx || post <= idx ? length + p_keys[post].time - p_keys[idx].time : p_keys[post].time - p_keys[idx].time); + } + if (p_interp == INTERPOLATION_CUBIC) { + return _cubic_interpolate(p_keys[pre].value, p_keys[idx].value, p_keys[next].value, p_keys[post].value, c); + } + return _cubic_interpolate_in_time( + p_keys[pre].value, p_keys[idx].value, p_keys[next].value, p_keys[post].value, c, + p_keys[pre].time - p_keys[idx].time, + p_keys[next].time - p_keys[idx].time, + p_keys[post].time - p_keys[idx].time); } break; default: return p_keys[idx].value; @@ -3215,7 +3371,7 @@ StringName Animation::method_track_get_name(int p_track, int p_key_idx) const { return pm->methods[p_key_idx].method; } -int Animation::bezier_track_insert_key(int p_track, double p_time, real_t p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle, const HandleMode p_handle_mode) { +int Animation::bezier_track_insert_key(int p_track, double p_time, real_t p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle) { ERR_FAIL_INDEX_V(p_track, tracks.size(), -1); Track *t = tracks[p_track]; ERR_FAIL_COND_V(t->type != TYPE_BEZIER, -1); @@ -3233,7 +3389,6 @@ int Animation::bezier_track_insert_key(int p_track, double p_time, real_t p_valu if (k.value.out_handle.x < 0) { k.value.out_handle.x = 0; } - k.value.handle_mode = p_handle_mode; int key = _insert(p_time, bt->values, k); @@ -3242,30 +3397,6 @@ int Animation::bezier_track_insert_key(int p_track, double p_time, real_t p_valu return key; } -void Animation::bezier_track_set_key_handle_mode(int p_track, int p_index, HandleMode p_mode, double p_balanced_value_time_ratio) { - ERR_FAIL_INDEX(p_track, tracks.size()); - Track *t = tracks[p_track]; - ERR_FAIL_COND(t->type != TYPE_BEZIER); - - BezierTrack *bt = static_cast<BezierTrack *>(t); - - ERR_FAIL_INDEX(p_index, bt->values.size()); - - bt->values.write[p_index].value.handle_mode = p_mode; - - if (p_mode == HANDLE_MODE_BALANCED) { - Transform2D xform; - xform.set_scale(Vector2(1.0, 1.0 / p_balanced_value_time_ratio)); - - Vector2 vec_in = xform.xform(bt->values[p_index].value.in_handle); - Vector2 vec_out = xform.xform(bt->values[p_index].value.out_handle); - - bt->values.write[p_index].value.in_handle = xform.affine_inverse().xform(-vec_out.normalized() * vec_in.length()); - } - - emit_changed(); -} - void Animation::bezier_track_set_key_value(int p_track, int p_index, real_t p_value) { ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; @@ -3276,10 +3407,11 @@ void Animation::bezier_track_set_key_value(int p_track, int p_index, real_t p_va ERR_FAIL_INDEX(p_index, bt->values.size()); bt->values.write[p_index].value.value = p_value; + emit_changed(); } -void Animation::bezier_track_set_key_in_handle(int p_track, int p_index, const Vector2 &p_handle, double p_balanced_value_time_ratio) { +void Animation::bezier_track_set_key_in_handle(int p_track, int p_index, const Vector2 &p_handle, real_t p_balanced_value_time_ratio) { ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; ERR_FAIL_COND(t->type != TYPE_BEZIER); @@ -3294,7 +3426,11 @@ void Animation::bezier_track_set_key_in_handle(int p_track, int p_index, const V } bt->values.write[p_index].value.in_handle = in_handle; - if (bt->values[p_index].value.handle_mode == HANDLE_MODE_BALANCED) { +#ifdef TOOLS_ENABLED + if (bt->values[p_index].value.handle_mode == HANDLE_MODE_LINEAR) { + bt->values.write[p_index].value.in_handle = Vector2(); + bt->values.write[p_index].value.out_handle = Vector2(); + } else if (bt->values[p_index].value.handle_mode == HANDLE_MODE_BALANCED) { Transform2D xform; xform.set_scale(Vector2(1.0, 1.0 / p_balanced_value_time_ratio)); @@ -3302,12 +3438,15 @@ void Animation::bezier_track_set_key_in_handle(int p_track, int p_index, const V Vector2 vec_in = xform.xform(in_handle); bt->values.write[p_index].value.out_handle = xform.affine_inverse().xform(-vec_in.normalized() * vec_out.length()); + } else if (bt->values[p_index].value.handle_mode == HANDLE_MODE_MIRRORED) { + bt->values.write[p_index].value.out_handle = -in_handle; } +#endif // TOOLS_ENABLED emit_changed(); } -void Animation::bezier_track_set_key_out_handle(int p_track, int p_index, const Vector2 &p_handle, double p_balanced_value_time_ratio) { +void Animation::bezier_track_set_key_out_handle(int p_track, int p_index, const Vector2 &p_handle, real_t p_balanced_value_time_ratio) { ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; ERR_FAIL_COND(t->type != TYPE_BEZIER); @@ -3322,7 +3461,11 @@ void Animation::bezier_track_set_key_out_handle(int p_track, int p_index, const } bt->values.write[p_index].value.out_handle = out_handle; - if (bt->values[p_index].value.handle_mode == HANDLE_MODE_BALANCED) { +#ifdef TOOLS_ENABLED + if (bt->values[p_index].value.handle_mode == HANDLE_MODE_LINEAR) { + bt->values.write[p_index].value.in_handle = Vector2(); + bt->values.write[p_index].value.out_handle = Vector2(); + } else if (bt->values[p_index].value.handle_mode == HANDLE_MODE_BALANCED) { Transform2D xform; xform.set_scale(Vector2(1.0, 1.0 / p_balanced_value_time_ratio)); @@ -3330,7 +3473,10 @@ void Animation::bezier_track_set_key_out_handle(int p_track, int p_index, const Vector2 vec_out = xform.xform(out_handle); bt->values.write[p_index].value.in_handle = xform.affine_inverse().xform(-vec_out.normalized() * vec_in.length()); + } else if (bt->values[p_index].value.handle_mode == HANDLE_MODE_MIRRORED) { + bt->values.write[p_index].value.in_handle = -out_handle; } +#endif // TOOLS_ENABLED emit_changed(); } @@ -3347,18 +3493,6 @@ real_t Animation::bezier_track_get_key_value(int p_track, int p_index) const { return bt->values[p_index].value.value; } -int Animation::bezier_track_get_key_handle_mode(int p_track, int p_index) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), 0); - Track *t = tracks[p_track]; - ERR_FAIL_COND_V(t->type != TYPE_BEZIER, 0); - - BezierTrack *bt = static_cast<BezierTrack *>(t); - - ERR_FAIL_INDEX_V(p_index, bt->values.size(), 0); - - return bt->values[p_index].value.handle_mode; -} - Vector2 Animation::bezier_track_get_key_in_handle(int p_track, int p_index) const { ERR_FAIL_INDEX_V(p_track, tracks.size(), Vector2()); Track *t = tracks[p_track]; @@ -3383,6 +3517,109 @@ Vector2 Animation::bezier_track_get_key_out_handle(int p_track, int p_index) con return bt->values[p_index].value.out_handle; } +#ifdef TOOLS_ENABLED +void Animation::bezier_track_set_key_handle_mode(int p_track, int p_index, HandleMode p_mode, HandleSetMode p_set_mode) { + ERR_FAIL_INDEX(p_track, tracks.size()); + Track *t = tracks[p_track]; + ERR_FAIL_COND(t->type != TYPE_BEZIER); + + BezierTrack *bt = static_cast<BezierTrack *>(t); + + ERR_FAIL_INDEX(p_index, bt->values.size()); + + bt->values.write[p_index].value.handle_mode = p_mode; + + switch (p_mode) { + case HANDLE_MODE_LINEAR: { + bt->values.write[p_index].value.in_handle = Vector2(0, 0); + bt->values.write[p_index].value.out_handle = Vector2(0, 0); + } break; + case HANDLE_MODE_BALANCED: + case HANDLE_MODE_MIRRORED: { + int prev_key = MAX(0, p_index - 1); + int next_key = MIN(bt->values.size() - 1, p_index + 1); + if (prev_key == next_key) { + break; // Exists only one key. + } + real_t in_handle_x = 0; + real_t in_handle_y = 0; + real_t out_handle_x = 0; + real_t out_handle_y = 0; + if (p_mode == HANDLE_MODE_BALANCED) { + // Note: + // If p_set_mode == HANDLE_SET_MODE_NONE, I don't know if it should change the Tangent implicitly. + // At the least, we need to avoid corrupting the handles when loading animation from the resource. + // However, changes made by the Inspector do not go through the BezierEditor, + // so if you change from Free to Balanced or Mirrored in Inspector, there is no guarantee that + // it is Balanced or Mirrored until there is a handle operation. + if (p_set_mode == HANDLE_SET_MODE_RESET) { + real_t handle_length = 1.0 / 3.0; + in_handle_x = (bt->values[prev_key].time - bt->values[p_index].time) * handle_length; + in_handle_y = 0; + out_handle_x = (bt->values[next_key].time - bt->values[p_index].time) * handle_length; + out_handle_y = 0; + bt->values.write[p_index].value.in_handle = Vector2(in_handle_x, in_handle_y); + bt->values.write[p_index].value.out_handle = Vector2(out_handle_x, out_handle_y); + } else if (p_set_mode == HANDLE_SET_MODE_AUTO) { + real_t handle_length = 1.0 / 6.0; + real_t tangent = (bt->values[next_key].value.value - bt->values[prev_key].value.value) / (bt->values[next_key].time - bt->values[prev_key].time); + in_handle_x = (bt->values[prev_key].time - bt->values[p_index].time) * handle_length; + in_handle_y = in_handle_x * tangent; + out_handle_x = (bt->values[next_key].time - bt->values[p_index].time) * handle_length; + out_handle_y = out_handle_x * tangent; + bt->values.write[p_index].value.in_handle = Vector2(in_handle_x, in_handle_y); + bt->values.write[p_index].value.out_handle = Vector2(out_handle_x, out_handle_y); + } + } else { + real_t handle_length = 1.0 / 4.0; + real_t prev_interval = Math::abs(bt->values[p_index].time - bt->values[prev_key].time); + real_t next_interval = Math::abs(bt->values[p_index].time - bt->values[next_key].time); + real_t min_time = 0; + if (Math::is_zero_approx(prev_interval)) { + min_time = next_interval; + } else if (Math::is_zero_approx(next_interval)) { + min_time = prev_interval; + } else { + min_time = MIN(prev_interval, next_interval); + } + if (p_set_mode == HANDLE_SET_MODE_RESET) { + in_handle_x = -min_time * handle_length; + in_handle_y = 0; + out_handle_x = min_time * handle_length; + out_handle_y = 0; + bt->values.write[p_index].value.in_handle = Vector2(in_handle_x, in_handle_y); + bt->values.write[p_index].value.out_handle = Vector2(out_handle_x, out_handle_y); + } else if (p_set_mode == HANDLE_SET_MODE_AUTO) { + real_t tangent = (bt->values[next_key].value.value - bt->values[prev_key].value.value) / min_time; + in_handle_x = -min_time * handle_length; + in_handle_y = in_handle_x * tangent; + out_handle_x = min_time * handle_length; + out_handle_y = out_handle_x * tangent; + bt->values.write[p_index].value.in_handle = Vector2(in_handle_x, in_handle_y); + bt->values.write[p_index].value.out_handle = Vector2(out_handle_x, out_handle_y); + } + } + } break; + default: { + } break; + } + + emit_changed(); +} + +Animation::HandleMode Animation::bezier_track_get_key_handle_mode(int p_track, int p_index) const { + ERR_FAIL_INDEX_V(p_track, tracks.size(), HANDLE_MODE_FREE); + Track *t = tracks[p_track]; + ERR_FAIL_COND_V(t->type != TYPE_BEZIER, HANDLE_MODE_FREE); + + BezierTrack *bt = static_cast<BezierTrack *>(t); + + ERR_FAIL_INDEX_V(p_index, bt->values.size(), HANDLE_MODE_FREE); + + return bt->values[p_index].value.handle_mode; +} +#endif // TOOLS_ENABLED + real_t Animation::bezier_track_interpolate(int p_track, double p_time) const { //this uses a different interpolation scheme ERR_FAIL_INDEX_V(p_track, tracks.size(), 0); @@ -3779,7 +4016,7 @@ void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("method_track_get_name", "track_idx", "key_idx"), &Animation::method_track_get_name); ClassDB::bind_method(D_METHOD("method_track_get_params", "track_idx", "key_idx"), &Animation::method_track_get_params); - ClassDB::bind_method(D_METHOD("bezier_track_insert_key", "track_idx", "time", "value", "in_handle", "out_handle", "handle_mode"), &Animation::bezier_track_insert_key, DEFVAL(Vector2()), DEFVAL(Vector2()), DEFVAL(Animation::HandleMode::HANDLE_MODE_BALANCED)); + ClassDB::bind_method(D_METHOD("bezier_track_insert_key", "track_idx", "time", "value", "in_handle", "out_handle"), &Animation::bezier_track_insert_key, DEFVAL(Vector2()), DEFVAL(Vector2())); ClassDB::bind_method(D_METHOD("bezier_track_set_key_value", "track_idx", "key_idx", "value"), &Animation::bezier_track_set_key_value); ClassDB::bind_method(D_METHOD("bezier_track_set_key_in_handle", "track_idx", "key_idx", "in_handle", "balanced_value_time_ratio"), &Animation::bezier_track_set_key_in_handle, DEFVAL(1.0)); @@ -3799,9 +4036,6 @@ void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("audio_track_get_key_start_offset", "track_idx", "key_idx"), &Animation::audio_track_get_key_start_offset); ClassDB::bind_method(D_METHOD("audio_track_get_key_end_offset", "track_idx", "key_idx"), &Animation::audio_track_get_key_end_offset); - ClassDB::bind_method(D_METHOD("bezier_track_set_key_handle_mode", "track_idx", "key_idx", "key_handle_mode", "balanced_value_time_ratio"), &Animation::bezier_track_set_key_handle_mode, DEFVAL(1.0)); - ClassDB::bind_method(D_METHOD("bezier_track_get_key_handle_mode", "track_idx", "key_idx"), &Animation::bezier_track_get_key_handle_mode); - ClassDB::bind_method(D_METHOD("animation_track_insert_key", "track_idx", "time", "animation"), &Animation::animation_track_insert_key); ClassDB::bind_method(D_METHOD("animation_track_set_key_animation", "track_idx", "key_idx", "animation"), &Animation::animation_track_set_key_animation); ClassDB::bind_method(D_METHOD("animation_track_get_key_animation", "track_idx", "key_idx"), &Animation::animation_track_get_key_animation); @@ -3839,6 +4073,7 @@ void Animation::_bind_methods() { BIND_ENUM_CONSTANT(INTERPOLATION_NEAREST); BIND_ENUM_CONSTANT(INTERPOLATION_LINEAR); BIND_ENUM_CONSTANT(INTERPOLATION_CUBIC); + BIND_ENUM_CONSTANT(INTERPOLATION_CUBIC_IN_TIME); BIND_ENUM_CONSTANT(UPDATE_CONTINUOUS); BIND_ENUM_CONSTANT(UPDATE_DISCRETE); @@ -3848,9 +4083,6 @@ void Animation::_bind_methods() { BIND_ENUM_CONSTANT(LOOP_NONE); BIND_ENUM_CONSTANT(LOOP_LINEAR); BIND_ENUM_CONSTANT(LOOP_PINGPONG); - - BIND_ENUM_CONSTANT(HANDLE_MODE_FREE); - BIND_ENUM_CONSTANT(HANDLE_MODE_BALANCED); } void Animation::clear() { @@ -3868,316 +4100,208 @@ void Animation::clear() { emit_signal(SceneStringNames::get_singleton()->tracks_changed); } -bool Animation::_position_track_optimize_key(const TKey<Vector3> &t0, const TKey<Vector3> &t1, const TKey<Vector3> &t2, real_t p_allowed_linear_err, real_t p_allowed_angular_error, const Vector3 &p_norm) { - const Vector3 &v0 = t0.value; - const Vector3 &v1 = t1.value; - const Vector3 &v2 = t2.value; - - if (v0.is_equal_approx(v2)) { - //0 and 2 are close, let's see if 1 is close - if (!v0.is_equal_approx(v1)) { - //not close, not optimizable - return false; - } - - } else { - Vector3 pd = (v2 - v0); - real_t d0 = pd.dot(v0); - real_t d1 = pd.dot(v1); - real_t d2 = pd.dot(v2); - if (d1 < d0 || d1 > d2) { - return false; - } - - Vector3 s[2] = { v0, v2 }; - real_t d = Geometry3D::get_closest_point_to_segment(v1, s).distance_to(v1); - - if (d > pd.length() * p_allowed_linear_err) { - return false; //beyond allowed error for collinearity - } - - if (p_norm != Vector3() && Math::acos(pd.normalized().dot(p_norm)) > p_allowed_angular_error) { - return false; - } +bool Animation::_vector3_track_optimize_key(const TKey<Vector3> t0, const TKey<Vector3> t1, const TKey<Vector3> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error) { + // Remove overlapping keys. + if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) { + return true; } - - return true; -} - -bool Animation::_rotation_track_optimize_key(const TKey<Quaternion> &t0, const TKey<Quaternion> &t1, const TKey<Quaternion> &t2, real_t p_allowed_angular_error, float p_max_optimizable_angle) { - const Quaternion &q0 = t0.value; - const Quaternion &q1 = t1.value; - const Quaternion &q2 = t2.value; - - //localize both to rotation from q0 - - if (q0.is_equal_approx(q2)) { - if (!q0.is_equal_approx(q1)) { - return false; - } - - } else { - Quaternion r02 = (q0.inverse() * q2).normalized(); - Quaternion r01 = (q0.inverse() * q1).normalized(); - - Vector3 v02, v01; - real_t a02, a01; - - r02.get_axis_angle(v02, a02); - r01.get_axis_angle(v01, a01); - - if (Math::abs(a02) > p_max_optimizable_angle) { - return false; - } - - if (v01.dot(v02) < 0) { - //make sure both rotations go the same way to compare - v02 = -v02; - a02 = -a02; - } - - real_t err_01 = Math::acos(v01.normalized().dot(v02.normalized())) / Math_PI; - if (err_01 > p_allowed_angular_error) { - //not rotating in the same axis - return false; - } - - if (a01 * a02 < 0) { - //not rotating in the same direction - return false; - } - - real_t tr = a01 / a02; - if (tr < 0 || tr > 1) { - return false; //rotating too much or too less + if ((t0.value - t1.value).length() < p_allowed_precision_error && (t1.value - t2.value).length() < p_allowed_precision_error) { + return true; + } + // Calc velocities. + Vector3 vc0 = (t1.value - t0.value) / (t1.time - t0.time); + Vector3 vc1 = (t2.value - t1.value) / (t2.time - t1.time); + real_t v0 = vc0.length(); + real_t v1 = vc1.length(); + // Avoid zero div but check equality. + if (abs(v0 - v1) < p_allowed_precision_error) { + return true; + } else if (abs(v0) < p_allowed_precision_error || abs(v1) < p_allowed_precision_error) { + return false; + } + // Check axis. + if (vc0.normalized().dot(vc1.normalized()) >= 1.0 - p_allowed_angular_error * 2.0) { + real_t ratio = v0 < v1 ? v0 / v1 : v1 / v0; + if (ratio >= 1.0 - p_allowed_velocity_err) { + return true; } } - - return true; + return false; } -bool Animation::_scale_track_optimize_key(const TKey<Vector3> &t0, const TKey<Vector3> &t1, const TKey<Vector3> &t2, real_t p_allowed_linear_error) { - const Vector3 &v0 = t0.value; - const Vector3 &v1 = t1.value; - const Vector3 &v2 = t2.value; - - if (v0.is_equal_approx(v2)) { - //0 and 2 are close, let's see if 1 is close - if (!v0.is_equal_approx(v1)) { - //not close, not optimizable +bool Animation::_quaternion_track_optimize_key(const TKey<Quaternion> t0, const TKey<Quaternion> t1, const TKey<Quaternion> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error) { + // Remove overlapping keys. + if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) { + return true; + } + if ((t0.value - t1.value).length() < p_allowed_precision_error && (t1.value - t2.value).length() < p_allowed_precision_error) { + return true; + } + // Check axis. + Quaternion q0 = t0.value * t1.value * t0.value.inverse(); + Quaternion q1 = t1.value * t2.value * t1.value.inverse(); + if (q0.get_axis().dot(q1.get_axis()) >= 1.0 - p_allowed_angular_error * 2.0) { + // Calc velocities. + real_t v0 = Math::acos(t0.value.dot(t1.value)) / (t1.time - t0.time); + real_t v1 = Math::acos(t1.value.dot(t2.value)) / (t2.time - t1.time); + // Avoid zero div but check equality. + if (abs(v0 - v1) < p_allowed_precision_error) { + return true; + } else if (abs(v0) < p_allowed_precision_error || abs(v1) < p_allowed_precision_error) { return false; } - - } else { - Vector3 pd = (v2 - v0); - real_t d0 = pd.dot(v0); - real_t d1 = pd.dot(v1); - real_t d2 = pd.dot(v2); - if (d1 < d0 || d1 > d2) { - return false; //beyond segment range - } - - Vector3 s[2] = { v0, v2 }; - real_t d = Geometry3D::get_closest_point_to_segment(v1, s).distance_to(v1); - - if (d > pd.length() * p_allowed_linear_error) { - return false; //beyond allowed error for colinearity + real_t ratio = v0 < v1 ? v0 / v1 : v1 / v0; + if (ratio >= 1.0 - p_allowed_velocity_err) { + return true; } } - - return true; + return false; } -bool Animation::_blend_shape_track_optimize_key(const TKey<float> &t0, const TKey<float> &t1, const TKey<float> &t2, real_t p_allowed_unit_error) { - float v0 = t0.value; - float v1 = t1.value; - float v2 = t2.value; - - if (Math::is_equal_approx(v1, v2, (float)p_allowed_unit_error)) { - //0 and 2 are close, let's see if 1 is close - if (!Math::is_equal_approx(v0, v1, (float)p_allowed_unit_error)) { - //not close, not optimizable - return false; - } - } else { - /* - TODO eventually discuss a way to optimize these better. - float pd = (v2 - v0); - real_t d0 = pd.dot(v0); - real_t d1 = pd.dot(v1); - real_t d2 = pd.dot(v2); - if (d1 < d0 || d1 > d2) { - return false; //beyond segment range - } - - float s[2] = { v0, v2 }; - real_t d = Geometry3D::get_closest_point_to_segment(v1, s).distance_to(v1); - - if (d > pd.length() * p_allowed_linear_error) { - return false; //beyond allowed error for colinearity +bool Animation::_float_track_optimize_key(const TKey<float> t0, const TKey<float> t1, const TKey<float> t2, real_t p_allowed_velocity_err, real_t p_allowed_precision_error) { + // Remove overlapping keys. + if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) { + return true; + } + if (abs(t0.value - t1.value) < p_allowed_precision_error && abs(t1.value - t2.value) < p_allowed_precision_error) { + return true; + } + // Calc velocities. + real_t v0 = (t1.value - t0.value) / (t1.time - t0.time); + real_t v1 = (t2.value - t1.value) / (t2.time - t1.time); + // Avoid zero div but check equality. + if (abs(v0 - v1) < p_allowed_precision_error) { + return true; + } else if (abs(v0) < p_allowed_precision_error || abs(v1) < p_allowed_precision_error) { + return false; + } + if (!signbit(v0 * v1)) { + real_t ratio = v0 < v1 ? v0 / v1 : v1 / v0; + if (ratio >= 1.0 - p_allowed_velocity_err) { + return true; } -*/ } - - return true; + return false; } -void Animation::_position_track_optimize(int p_idx, real_t p_allowed_linear_err, real_t p_allowed_angular_err) { +void Animation::_position_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error) { ERR_FAIL_INDEX(p_idx, tracks.size()); ERR_FAIL_COND(tracks[p_idx]->type != TYPE_POSITION_3D); PositionTrack *tt = static_cast<PositionTrack *>(tracks[p_idx]); - bool prev_erased = false; - TKey<Vector3> first_erased; - - Vector3 norm; - for (int i = 1; i < tt->positions.size() - 1; i++) { - TKey<Vector3> &t0 = tt->positions.write[i - 1]; - TKey<Vector3> &t1 = tt->positions.write[i]; - TKey<Vector3> &t2 = tt->positions.write[i + 1]; - - bool erase = _position_track_optimize_key(t0, t1, t2, p_allowed_linear_err, p_allowed_angular_err, norm); - if (erase && !prev_erased) { - norm = (t2.value - t1.value).normalized(); - } - - if (prev_erased && !_position_track_optimize_key(t0, first_erased, t2, p_allowed_linear_err, p_allowed_angular_err, norm)) { - //avoid error to go beyond first erased key - erase = false; - } + int i = 0; + while (i < tt->positions.size() - 2) { + TKey<Vector3> t0 = tt->positions[i]; + TKey<Vector3> t1 = tt->positions[i + 1]; + TKey<Vector3> t2 = tt->positions[i + 2]; + bool erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error); if (erase) { - if (!prev_erased) { - first_erased = t1; - prev_erased = true; - } - - tt->positions.remove_at(i); - i--; - + tt->positions.remove_at(i + 1); } else { - prev_erased = false; - norm = Vector3(); + i++; + } + } + + if (tt->positions.size() == 2) { + if ((tt->positions[0].value - tt->positions[1].value).length() < p_allowed_precision_error) { + tt->positions.remove_at(1); } } } -void Animation::_rotation_track_optimize(int p_idx, real_t p_allowed_angular_err, real_t p_max_optimizable_angle) { +void Animation::_rotation_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error) { ERR_FAIL_INDEX(p_idx, tracks.size()); ERR_FAIL_COND(tracks[p_idx]->type != TYPE_ROTATION_3D); RotationTrack *tt = static_cast<RotationTrack *>(tracks[p_idx]); - bool prev_erased = false; - TKey<Quaternion> first_erased; - - for (int i = 1; i < tt->rotations.size() - 1; i++) { - TKey<Quaternion> &t0 = tt->rotations.write[i - 1]; - TKey<Quaternion> &t1 = tt->rotations.write[i]; - TKey<Quaternion> &t2 = tt->rotations.write[i + 1]; - bool erase = _rotation_track_optimize_key(t0, t1, t2, p_allowed_angular_err, p_max_optimizable_angle); - - if (prev_erased && !_rotation_track_optimize_key(t0, first_erased, t2, p_allowed_angular_err, p_max_optimizable_angle)) { - //avoid error to go beyond first erased key - erase = false; - } + int i = 0; + while (i < tt->rotations.size() - 2) { + TKey<Quaternion> t0 = tt->rotations[i]; + TKey<Quaternion> t1 = tt->rotations[i + 1]; + TKey<Quaternion> t2 = tt->rotations[i + 2]; + bool erase = _quaternion_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error); if (erase) { - if (!prev_erased) { - first_erased = t1; - prev_erased = true; - } - - tt->rotations.remove_at(i); - i--; - + tt->rotations.remove_at(i + 1); } else { - prev_erased = false; + i++; + } + } + + if (tt->rotations.size() == 2) { + if ((tt->rotations[0].value - tt->rotations[1].value).length() < p_allowed_precision_error) { + tt->rotations.remove_at(1); } } } -void Animation::_scale_track_optimize(int p_idx, real_t p_allowed_linear_err) { +void Animation::_scale_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error) { ERR_FAIL_INDEX(p_idx, tracks.size()); ERR_FAIL_COND(tracks[p_idx]->type != TYPE_SCALE_3D); ScaleTrack *tt = static_cast<ScaleTrack *>(tracks[p_idx]); - bool prev_erased = false; - TKey<Vector3> first_erased; - - for (int i = 1; i < tt->scales.size() - 1; i++) { - TKey<Vector3> &t0 = tt->scales.write[i - 1]; - TKey<Vector3> &t1 = tt->scales.write[i]; - TKey<Vector3> &t2 = tt->scales.write[i + 1]; - bool erase = _scale_track_optimize_key(t0, t1, t2, p_allowed_linear_err); - - if (prev_erased && !_scale_track_optimize_key(t0, first_erased, t2, p_allowed_linear_err)) { - //avoid error to go beyond first erased key - erase = false; - } + int i = 0; + while (i < tt->scales.size() - 2) { + TKey<Vector3> t0 = tt->scales[i]; + TKey<Vector3> t1 = tt->scales[i + 1]; + TKey<Vector3> t2 = tt->scales[i + 2]; + bool erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error); if (erase) { - if (!prev_erased) { - first_erased = t1; - prev_erased = true; - } - - tt->scales.remove_at(i); - i--; - + tt->scales.remove_at(i + 1); } else { - prev_erased = false; + i++; + } + } + + if (tt->scales.size() == 2) { + if ((tt->scales[0].value - tt->scales[1].value).length() < p_allowed_precision_error) { + tt->scales.remove_at(1); } } } -void Animation::_blend_shape_track_optimize(int p_idx, real_t p_allowed_linear_err) { +void Animation::_blend_shape_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_precision_error) { ERR_FAIL_INDEX(p_idx, tracks.size()); ERR_FAIL_COND(tracks[p_idx]->type != TYPE_BLEND_SHAPE); BlendShapeTrack *tt = static_cast<BlendShapeTrack *>(tracks[p_idx]); - bool prev_erased = false; - TKey<float> first_erased; - first_erased.value = 0.0; - - for (int i = 1; i < tt->blend_shapes.size() - 1; i++) { - TKey<float> &t0 = tt->blend_shapes.write[i - 1]; - TKey<float> &t1 = tt->blend_shapes.write[i]; - TKey<float> &t2 = tt->blend_shapes.write[i + 1]; - bool erase = _blend_shape_track_optimize_key(t0, t1, t2, p_allowed_linear_err); - - if (prev_erased && !_blend_shape_track_optimize_key(t0, first_erased, t2, p_allowed_linear_err)) { - //avoid error to go beyond first erased key - erase = false; - } + int i = 0; + while (i < tt->blend_shapes.size() - 2) { + TKey<float> t0 = tt->blend_shapes[i]; + TKey<float> t1 = tt->blend_shapes[i + 1]; + TKey<float> t2 = tt->blend_shapes[i + 2]; + bool erase = _float_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_precision_error); if (erase) { - if (!prev_erased) { - first_erased = t1; - prev_erased = true; - } - - tt->blend_shapes.remove_at(i); - i--; - + tt->blend_shapes.remove_at(i + 1); } else { - prev_erased = false; + i++; + } + } + + if (tt->blend_shapes.size() == 2) { + if (abs(tt->blend_shapes[0].value - tt->blend_shapes[1].value) < p_allowed_precision_error) { + tt->blend_shapes.remove_at(1); } } } -void Animation::optimize(real_t p_allowed_linear_err, real_t p_allowed_angular_err, real_t p_max_optimizable_angle) { +void Animation::optimize(real_t p_allowed_velocity_err, real_t p_allowed_angular_err, int p_precision) { + real_t precision = Math::pow(0.1, p_precision); for (int i = 0; i < tracks.size(); i++) { if (track_is_compressed(i)) { continue; //not possible to optimize compressed track } if (tracks[i]->type == TYPE_POSITION_3D) { - _position_track_optimize(i, p_allowed_linear_err, p_allowed_angular_err); + _position_track_optimize(i, p_allowed_velocity_err, p_allowed_angular_err, precision); } else if (tracks[i]->type == TYPE_ROTATION_3D) { - _rotation_track_optimize(i, p_allowed_angular_err, p_max_optimizable_angle); + _rotation_track_optimize(i, p_allowed_velocity_err, p_allowed_angular_err, precision); } else if (tracks[i]->type == TYPE_SCALE_3D) { - _scale_track_optimize(i, p_allowed_linear_err); + _scale_track_optimize(i, p_allowed_velocity_err, p_allowed_angular_err, precision); } else if (tracks[i]->type == TYPE_BLEND_SHAPE) { - _blend_shape_track_optimize(i, p_allowed_linear_err); + _blend_shape_track_optimize(i, p_allowed_velocity_err, precision); } } } diff --git a/scene/resources/animation.h b/scene/resources/animation.h index bf9f786a0d..5e88980397 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -56,7 +56,8 @@ public: enum InterpolationType { INTERPOLATION_NEAREST, INTERPOLATION_LINEAR, - INTERPOLATION_CUBIC + INTERPOLATION_CUBIC, + INTERPOLATION_CUBIC_IN_TIME, }; enum UpdateMode { @@ -72,10 +73,19 @@ public: LOOP_PINGPONG, }; +#ifdef TOOLS_ENABLED enum HandleMode { HANDLE_MODE_FREE, + HANDLE_MODE_LINEAR, HANDLE_MODE_BALANCED, + HANDLE_MODE_MIRRORED, }; + enum HandleSetMode { + HANDLE_SET_MODE_NONE, + HANDLE_SET_MODE_RESET, + HANDLE_SET_MODE_AUTO, + }; +#endif // TOOLS_ENABLED private: struct Track { @@ -165,8 +175,10 @@ private: struct BezierKey { Vector2 in_handle; //relative (x always <0) Vector2 out_handle; //relative (x always >0) - HandleMode handle_mode = HANDLE_MODE_BALANCED; real_t value = 0.0; +#ifdef TOOLS_ENABLED + HandleMode handle_mode = HANDLE_MODE_FREE; +#endif // TOOLS_ENABLED }; struct BezierTrack : public Track { @@ -231,6 +243,11 @@ private: _FORCE_INLINE_ Variant _cubic_interpolate(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c) const; _FORCE_INLINE_ real_t _cubic_interpolate(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c) const; + _FORCE_INLINE_ Vector3 _cubic_interpolate_in_time(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; + _FORCE_INLINE_ Quaternion _cubic_interpolate_in_time(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; + _FORCE_INLINE_ Variant _cubic_interpolate_in_time(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; + _FORCE_INLINE_ real_t _cubic_interpolate_in_time(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; + template <class T> _FORCE_INLINE_ T _interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok, bool p_backward = false) const; @@ -351,15 +368,14 @@ private: return idxr; } - bool _position_track_optimize_key(const TKey<Vector3> &t0, const TKey<Vector3> &t1, const TKey<Vector3> &t2, real_t p_alowed_linear_err, real_t p_allowed_angular_error, const Vector3 &p_norm); - bool _rotation_track_optimize_key(const TKey<Quaternion> &t0, const TKey<Quaternion> &t1, const TKey<Quaternion> &t2, real_t p_allowed_angular_error, float p_max_optimizable_angle); - bool _scale_track_optimize_key(const TKey<Vector3> &t0, const TKey<Vector3> &t1, const TKey<Vector3> &t2, real_t p_allowed_linear_error); - bool _blend_shape_track_optimize_key(const TKey<float> &t0, const TKey<float> &t1, const TKey<float> &t2, real_t p_allowed_unit_error); + bool _vector3_track_optimize_key(const TKey<Vector3> t0, const TKey<Vector3> t1, const TKey<Vector3> t2, real_t p_alowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error); + bool _quaternion_track_optimize_key(const TKey<Quaternion> t0, const TKey<Quaternion> t1, const TKey<Quaternion> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error); + bool _float_track_optimize_key(const TKey<float> t0, const TKey<float> t1, const TKey<float> t2, real_t p_allowed_velocity_err, real_t p_allowed_precision_error); - void _position_track_optimize(int p_idx, real_t p_allowed_linear_err, real_t p_allowed_angular_err); - void _rotation_track_optimize(int p_idx, real_t p_allowed_angular_err, real_t p_max_optimizable_angle); - void _scale_track_optimize(int p_idx, real_t p_allowed_linear_err); - void _blend_shape_track_optimize(int p_idx, real_t p_allowed_unit_error); + void _position_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error); + void _rotation_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error); + void _scale_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error); + void _blend_shape_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_precision_error); protected: bool _set(const StringName &p_name, const Variant &p_value); @@ -424,15 +440,17 @@ public: void track_set_interpolation_type(int p_track, InterpolationType p_interp); InterpolationType track_get_interpolation_type(int p_track) const; - int bezier_track_insert_key(int p_track, double p_time, real_t p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle, const HandleMode p_handle_mode = HandleMode::HANDLE_MODE_BALANCED); - void bezier_track_set_key_handle_mode(int p_track, int p_index, HandleMode p_mode, double p_balanced_value_time_ratio = 1.0); + int bezier_track_insert_key(int p_track, double p_time, real_t p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle); void bezier_track_set_key_value(int p_track, int p_index, real_t p_value); - void bezier_track_set_key_in_handle(int p_track, int p_index, const Vector2 &p_handle, double p_balanced_value_time_ratio = 1.0); - void bezier_track_set_key_out_handle(int p_track, int p_index, const Vector2 &p_handle, double p_balanced_value_time_ratio = 1.0); + void bezier_track_set_key_in_handle(int p_track, int p_index, const Vector2 &p_handle, real_t p_balanced_value_time_ratio = 1.0); + void bezier_track_set_key_out_handle(int p_track, int p_index, const Vector2 &p_handle, real_t p_balanced_value_time_ratio = 1.0); real_t bezier_track_get_key_value(int p_track, int p_index) const; - int bezier_track_get_key_handle_mode(int p_track, int p_index) const; Vector2 bezier_track_get_key_in_handle(int p_track, int p_index) const; Vector2 bezier_track_get_key_out_handle(int p_track, int p_index) const; +#ifdef TOOLS_ENABLED + void bezier_track_set_key_handle_mode(int p_track, int p_index, HandleMode p_mode, HandleSetMode p_set_mode = HANDLE_SET_MODE_NONE); + HandleMode bezier_track_get_key_handle_mode(int p_track, int p_index) const; +#endif // TOOLS_ENABLED real_t bezier_track_interpolate(int p_track, double p_time) const; @@ -475,7 +493,7 @@ public: void clear(); - void optimize(real_t p_allowed_linear_err = 0.05, real_t p_allowed_angular_err = 0.01, real_t p_max_optimizable_angle = Math_PI * 0.125); + void optimize(real_t p_allowed_velocity_err = 0.01, real_t p_allowed_angular_err = 0.01, int p_precision = 3); void compress(uint32_t p_page_size = 8192, uint32_t p_fps = 120, float p_split_tolerance = 4.0); // 4.0 seems to be the split tolerance sweet spot from many tests Animation(); @@ -485,7 +503,10 @@ public: VARIANT_ENUM_CAST(Animation::TrackType); VARIANT_ENUM_CAST(Animation::InterpolationType); VARIANT_ENUM_CAST(Animation::UpdateMode); -VARIANT_ENUM_CAST(Animation::HandleMode); VARIANT_ENUM_CAST(Animation::LoopMode); +#ifdef TOOLS_ENABLED +VARIANT_ENUM_CAST(Animation::HandleMode); +VARIANT_ENUM_CAST(Animation::HandleSetMode); +#endif // TOOLS_ENABLED #endif // ANIMATION_H diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp index bef431e980..9b1adde00a 100644 --- a/scene/resources/bit_map.cpp +++ b/scene/resources/bit_map.cpp @@ -31,6 +31,7 @@ #include "bit_map.h" #include "core/io/image_loader.h" +#include "core/variant/typed_array.h" void BitMap::create(const Size2 &p_size) { ERR_FAIL_COND(p_size.width < 1); @@ -576,12 +577,12 @@ void BitMap::shrink_mask(int p_pixels, const Rect2 &p_rect) { grow_mask(-p_pixels, p_rect); } -Array BitMap::_opaque_to_polygons_bind(const Rect2 &p_rect, float p_epsilon) const { +TypedArray<PackedVector2Array> BitMap::_opaque_to_polygons_bind(const Rect2 &p_rect, float p_epsilon) const { Vector<Vector<Vector2>> result = clip_opaque_to_polygons(p_rect, p_epsilon); // Convert result to bindable types - Array result_array; + TypedArray<PackedVector2Array> result_array; result_array.resize(result.size()); for (int i = 0; i < result.size(); i++) { const Vector<Vector2> &polygon = result[i]; diff --git a/scene/resources/bit_map.h b/scene/resources/bit_map.h index 0d0d779c32..d8507dfa8b 100644 --- a/scene/resources/bit_map.h +++ b/scene/resources/bit_map.h @@ -35,6 +35,9 @@ #include "core/io/resource.h" #include "core/io/resource_loader.h" +template <typename T> +class TypedArray; + class BitMap : public Resource { GDCLASS(BitMap, Resource); OBJ_SAVE_TYPE(BitMap); @@ -45,7 +48,7 @@ class BitMap : public Resource { Vector<Vector2> _march_square(const Rect2i &rect, const Point2i &start) const; - Array _opaque_to_polygons_bind(const Rect2 &p_rect, float p_epsilon) const; + TypedArray<PackedVector2Array> _opaque_to_polygons_bind(const Rect2 &p_rect, float p_epsilon) const; protected: void _set_data(const Dictionary &p_d); diff --git a/scene/resources/bone_map.cpp b/scene/resources/bone_map.cpp index aff917b2d4..dfaf82f36a 100644 --- a/scene/resources/bone_map.cpp +++ b/scene/resources/bone_map.cpp @@ -82,9 +82,13 @@ StringName BoneMap::get_skeleton_bone_name(StringName p_profile_bone_name) const return bone_map.get(p_profile_bone_name); } -void BoneMap::set_skeleton_bone_name(StringName p_profile_bone_name, const StringName p_skeleton_bone_name) { +void BoneMap::_set_skeleton_bone_name(StringName p_profile_bone_name, const StringName p_skeleton_bone_name) { ERR_FAIL_COND(!bone_map.has(p_profile_bone_name)); bone_map.insert(p_profile_bone_name, p_skeleton_bone_name); +} + +void BoneMap::set_skeleton_bone_name(StringName p_profile_bone_name, const StringName p_skeleton_bone_name) { + _set_skeleton_bone_name(p_profile_bone_name, p_skeleton_bone_name); emit_signal("bone_map_updated"); } @@ -168,7 +172,9 @@ void BoneMap::_bind_methods() { } void BoneMap::_validate_property(PropertyInfo &property) const { - // + if (property.name == "bonemap" || property.name == "profile") { + property.usage = PROPERTY_USAGE_NO_EDITOR; + } } BoneMap::BoneMap() { diff --git a/scene/resources/bone_map.h b/scene/resources/bone_map.h index 17452dfc73..a07a776e27 100644 --- a/scene/resources/bone_map.h +++ b/scene/resources/bone_map.h @@ -45,14 +45,11 @@ class BoneMap : public Resource { protected: bool _get(const StringName &p_path, Variant &r_ret) const; bool _set(const StringName &p_path, const Variant &p_value); - virtual void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; void _get_property_list(List<PropertyInfo> *p_list) const; static void _bind_methods(); public: - int get_profile_type() const; - void set_profile_type(const int p_profile_type); - Ref<SkeletonProfile> get_profile() const; void set_profile(const Ref<SkeletonProfile> &p_profile); @@ -60,6 +57,7 @@ public: StringName get_skeleton_bone_name(StringName p_profile_bone_name) const; void set_skeleton_bone_name(StringName p_profile_bone_name, const StringName p_skeleton_bone_name); + void _set_skeleton_bone_name(StringName p_profile_bone_name, const StringName p_skeleton_bone_name); // Avoid to emit signal for editor. StringName find_profile_bone_name(StringName p_skeleton_bone_name) const; diff --git a/scene/resources/camera_effects.cpp b/scene/resources/camera_effects.cpp index 97617adbae..0b11366591 100644 --- a/scene/resources/camera_effects.cpp +++ b/scene/resources/camera_effects.cpp @@ -145,11 +145,11 @@ void CameraEffects::_update_override_exposure() { // Private methods, constructor and destructor -void CameraEffects::_validate_property(PropertyInfo &property) const { - if ((!dof_blur_far_enabled && (property.name == "dof_blur_far_distance" || property.name == "dof_blur_far_transition")) || - (!dof_blur_near_enabled && (property.name == "dof_blur_near_distance" || property.name == "dof_blur_near_transition")) || - (!override_exposure_enabled && property.name == "override_exposure")) { - property.usage = PROPERTY_USAGE_NO_EDITOR; +void CameraEffects::_validate_property(PropertyInfo &p_property) const { + if ((!dof_blur_far_enabled && (p_property.name == "dof_blur_far_distance" || p_property.name == "dof_blur_far_transition")) || + (!dof_blur_near_enabled && (p_property.name == "dof_blur_near_distance" || p_property.name == "dof_blur_near_transition")) || + (!override_exposure_enabled && p_property.name == "override_exposure")) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } diff --git a/scene/resources/camera_effects.h b/scene/resources/camera_effects.h index 85ae64cdf5..7353931d16 100644 --- a/scene/resources/camera_effects.h +++ b/scene/resources/camera_effects.h @@ -59,7 +59,7 @@ private: protected: static void _bind_methods(); - void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; public: virtual RID get_rid() const override; diff --git a/scene/resources/canvas_item_material.cpp b/scene/resources/canvas_item_material.cpp index aa6cc4aded..b16059c218 100644 --- a/scene/resources/canvas_item_material.cpp +++ b/scene/resources/canvas_item_material.cpp @@ -227,9 +227,9 @@ bool CanvasItemMaterial::get_particles_anim_loop() const { return particles_anim_loop; } -void CanvasItemMaterial::_validate_property(PropertyInfo &property) const { - if (property.name.begins_with("particles_anim_") && !particles_animation) { - property.usage = PROPERTY_USAGE_NONE; +void CanvasItemMaterial::_validate_property(PropertyInfo &p_property) const { + if (p_property.name.begins_with("particles_anim_") && !particles_animation) { + p_property.usage = PROPERTY_USAGE_NONE; } } diff --git a/scene/resources/canvas_item_material.h b/scene/resources/canvas_item_material.h index 160c67d6b1..7eaf5051d4 100644 --- a/scene/resources/canvas_item_material.h +++ b/scene/resources/canvas_item_material.h @@ -117,7 +117,7 @@ private: protected: static void _bind_methods(); - void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; public: void set_blend_mode(BlendMode p_blend_mode); diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index f29cfec92f..6d99073fa4 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -84,7 +84,7 @@ static Ref<ImageTexture> generate_icon(int p_index) { // with integer scales. const bool upsample = !Math::is_equal_approx(Math::round(scale), scale); ImageLoaderSVG img_loader; - img_loader.create_image_from_string(img, default_theme_icons_sources[p_index], scale, upsample, false); + img_loader.create_image_from_string(img, default_theme_icons_sources[p_index], scale, upsample, HashMap<Color, Color>()); #endif return ImageTexture::create_from_image(img); @@ -177,6 +177,27 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("h_separation", "Button", 2 * scale); + // MenuBar + theme->set_stylebox("normal", "MenuBar", button_normal); + theme->set_stylebox("hover", "MenuBar", button_hover); + theme->set_stylebox("pressed", "MenuBar", button_pressed); + theme->set_stylebox("disabled", "MenuBar", button_disabled); + theme->set_stylebox("focus", "MenuBar", focus); + + theme->set_font("font", "MenuBar", Ref<Font>()); + theme->set_font_size("font_size", "MenuBar", -1); + theme->set_constant("outline_size", "MenuBar", 0 * scale); + + theme->set_color("font_color", "MenuBar", control_font_color); + theme->set_color("font_pressed_color", "MenuBar", control_font_pressed_color); + theme->set_color("font_hover_color", "MenuBar", control_font_hover_color); + theme->set_color("font_focus_color", "MenuBar", control_font_focus_color); + theme->set_color("font_hover_pressed_color", "MenuBar", control_font_pressed_color); + theme->set_color("font_disabled_color", "MenuBar", control_font_disabled_color); + theme->set_color("font_outline_color", "MenuBar", Color(1, 1, 1)); + + theme->set_constant("h_separation", "MenuBar", 4 * scale); + // LinkButton theme->set_stylebox("focus", "LinkButton", focus); @@ -669,6 +690,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_color("font_outline_color", "PopupMenu", Color(1, 1, 1)); theme->set_color("font_separator_outline_color", "PopupMenu", Color(1, 1, 1)); + theme->set_constant("indent", "PopupMenu", 10 * scale); theme->set_constant("h_separation", "PopupMenu", 4 * scale); theme->set_constant("v_separation", "PopupMenu", 4 * scale); theme->set_constant("outline_size", "PopupMenu", 0); diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index d361b34da8..f7a7818b3b 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -1037,46 +1037,46 @@ void Environment::_update_adjustment() { // Private methods, constructor and destructor -void Environment::_validate_property(PropertyInfo &property) const { - if (property.name == "sky" || property.name == "sky_custom_fov" || property.name == "sky_rotation" || property.name == "ambient_light/sky_contribution") { +void Environment::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "sky" || p_property.name == "sky_custom_fov" || p_property.name == "sky_rotation" || p_property.name == "ambient_light_sky_contribution") { if (bg_mode != BG_SKY && ambient_source != AMBIENT_SOURCE_SKY && reflection_source != REFLECTION_SOURCE_SKY) { - property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } - if (property.name == "fog_aerial_perspective") { + if (p_property.name == "fog_aerial_perspective") { if (bg_mode != BG_SKY) { - property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } - if (property.name == "tonemap_white" && tone_mapper == TONE_MAPPER_LINEAR) { - property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + if (p_property.name == "tonemap_white" && tone_mapper == TONE_MAPPER_LINEAR) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } - if (property.name == "glow_intensity" && glow_blend_mode == GLOW_BLEND_MODE_MIX) { - property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + if (p_property.name == "glow_intensity" && glow_blend_mode == GLOW_BLEND_MODE_MIX) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } - if (property.name == "glow_mix" && glow_blend_mode != GLOW_BLEND_MODE_MIX) { - property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + if (p_property.name == "glow_mix" && glow_blend_mode != GLOW_BLEND_MODE_MIX) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } - if (property.name == "background_color") { + if (p_property.name == "background_color") { if (bg_mode != BG_COLOR && ambient_source != AMBIENT_SOURCE_COLOR) { - property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } - if (property.name == "background_canvas_max_layer") { + if (p_property.name == "background_canvas_max_layer") { if (bg_mode != BG_CANVAS) { - property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } - if (property.name == "background_camera_feed_id") { + if (p_property.name == "background_camera_feed_id") { if (bg_mode != BG_CAMERA_FEED) { - property.usage = PROPERTY_USAGE_NO_EDITOR; + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } @@ -1107,8 +1107,8 @@ void Environment::_validate_property(PropertyInfo &property) const { String prefix = String(*prefixes); String enabled = prefix + "enabled"; - if (property.name.begins_with(prefix) && property.name != enabled && !bool(get(enabled))) { - property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + if (p_property.name.begins_with(prefix) && p_property.name != enabled && !bool(get(enabled))) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; return; } @@ -1120,8 +1120,8 @@ void Environment::_validate_property(PropertyInfo &property) const { while (*prefixes) { String prefix = String(*prefixes); - if (property.name.begins_with(prefix)) { - property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; + if (p_property.name.begins_with(prefix)) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; return; } diff --git a/scene/resources/environment.h b/scene/resources/environment.h index 385d815230..d39cb1acd8 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -211,7 +211,7 @@ private: protected: static void _bind_methods(); - virtual void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; #ifndef DISABLE_DEPRECATED // Kept for compatibility from 3.x to 4.0. bool _set(const StringName &p_name, const Variant &p_value); diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 880876baed..f8651fecd6 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -1267,7 +1267,7 @@ void FontFile::_get_property_list(List<PropertyInfo> *p_list) const { } for (int i = 0; i < cache.size(); i++) { String prefix = "cache/" + itos(i) + "/"; - Array sizes = get_size_cache_list(i); + TypedArray<Vector2i> sizes = get_size_cache_list(i); p_list->push_back(PropertyInfo(Variant::DICTIONARY, prefix + "variation_coordinates", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); p_list->push_back(PropertyInfo(Variant::INT, "face_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); p_list->push_back(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); @@ -1289,7 +1289,7 @@ void FontFile::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, prefix_sz + "textures/" + itos(k) + "/offsets", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); p_list->push_back(PropertyInfo(Variant::OBJECT, prefix_sz + "textures/" + itos(k) + "/image", PROPERTY_HINT_RESOURCE_TYPE, "Image", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT)); } - Array glyphs = get_glyph_list(i, sz); + PackedInt32Array glyphs = get_glyph_list(i, sz); for (int k = 0; k < glyphs.size(); k++) { const int32_t &gl = glyphs[k]; if (sz.y == 0) { @@ -1301,7 +1301,7 @@ void FontFile::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::INT, prefix_sz + "glyphs/" + itos(gl) + "/texture_idx", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); } if (sz.y == 0) { - Array kerning_map = get_kerning_list(i, sz.x); + TypedArray<Vector2i> kerning_map = get_kerning_list(i, sz.x); for (int k = 0; k < kerning_map.size(); k++) { const Vector2i &gl_pair = kerning_map[k]; p_list->push_back(PropertyInfo(Variant::VECTOR2, prefix_sz + "kerning_overrides/" + itos(gl_pair.x) + "/" + itos(gl_pair.y), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); @@ -2089,7 +2089,7 @@ void FontFile::remove_cache(int p_cache_index) { emit_changed(); } -Array FontFile::get_size_cache_list(int p_cache_index) const { +TypedArray<Vector2i> FontFile::get_size_cache_list(int p_cache_index) const { ERR_FAIL_COND_V(p_cache_index < 0, Array()); _ensure_rid(p_cache_index); return TS->font_get_size_cache_list(cache[p_cache_index]); @@ -2260,8 +2260,8 @@ PackedInt32Array FontFile::get_texture_offsets(int p_cache_index, const Vector2i return TS->font_get_texture_offsets(cache[p_cache_index], p_size, p_texture_index); } -Array FontFile::get_glyph_list(int p_cache_index, const Vector2i &p_size) const { - ERR_FAIL_COND_V(p_cache_index < 0, Array()); +PackedInt32Array FontFile::get_glyph_list(int p_cache_index, const Vector2i &p_size) const { + ERR_FAIL_COND_V(p_cache_index < 0, PackedInt32Array()); _ensure_rid(p_cache_index); return TS->font_get_glyph_list(cache[p_cache_index], p_size); } @@ -2338,7 +2338,7 @@ int FontFile::get_glyph_texture_idx(int p_cache_index, const Vector2i &p_size, i return TS->font_get_glyph_texture_idx(cache[p_cache_index], p_size, p_glyph); } -Array FontFile::get_kerning_list(int p_cache_index, int p_size) const { +TypedArray<Vector2i> FontFile::get_kerning_list(int p_cache_index, int p_size) const { ERR_FAIL_COND_V(p_cache_index < 0, Array()); _ensure_rid(p_cache_index); return TS->font_get_kerning_list(cache[p_cache_index], p_size); @@ -2714,6 +2714,9 @@ void SystemFont::_bind_methods() { ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &SystemFont::set_subpixel_positioning); ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &SystemFont::get_subpixel_positioning); + ClassDB::bind_method(D_METHOD("set_multichannel_signed_distance_field", "msdf"), &SystemFont::set_multichannel_signed_distance_field); + ClassDB::bind_method(D_METHOD("is_multichannel_signed_distance_field"), &SystemFont::is_multichannel_signed_distance_field); + ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &SystemFont::set_oversampling); ClassDB::bind_method(D_METHOD("get_oversampling"), &SystemFont::get_oversampling); @@ -2729,6 +2732,7 @@ void SystemFont::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_autohinter"), "set_force_autohinter", "is_force_autohinter"); ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), "set_hinting", "get_hinting"); ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), "set_subpixel_positioning", "get_subpixel_positioning"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field"), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), "set_oversampling", "get_oversampling"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font")), "set_fallbacks", "get_fallbacks"); } @@ -2805,6 +2809,7 @@ void SystemFont::_update_base_font() { file->set_force_autohinter(force_autohinter); file->set_hinting(hinting); file->set_subpixel_positioning(subpixel_positioning); + file->set_multichannel_signed_distance_field(msdf); file->set_oversampling(oversampling); base_font = file; @@ -2842,6 +2847,7 @@ void SystemFont::reset_state() { hinting = TextServer::HINTING_LIGHT; subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_DISABLED; oversampling = 0.f; + msdf = false; Font::reset_state(); } @@ -2971,6 +2977,20 @@ TextServer::SubpixelPositioning SystemFont::get_subpixel_positioning() const { return subpixel_positioning; } +void SystemFont::set_multichannel_signed_distance_field(bool p_msdf) { + if (msdf != p_msdf) { + msdf = p_msdf; + if (base_font.is_valid()) { + base_font->set_multichannel_signed_distance_field(msdf); + } + emit_changed(); + } +} + +bool SystemFont::is_multichannel_signed_distance_field() const { + return msdf; +} + void SystemFont::set_oversampling(real_t p_oversampling) { if (oversampling != p_oversampling) { oversampling = p_oversampling; diff --git a/scene/resources/font.h b/scene/resources/font.h index 260b4e521f..decbcfbb69 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -230,7 +230,7 @@ public: virtual void clear_cache(); virtual void remove_cache(int p_cache_index); - virtual Array get_size_cache_list(int p_cache_index) const; + virtual TypedArray<Vector2i> get_size_cache_list(int p_cache_index) const; virtual void clear_size_cache(int p_cache_index); virtual void remove_size_cache(int p_cache_index, const Vector2i &p_size); @@ -271,7 +271,7 @@ public: virtual void set_texture_offsets(int p_cache_index, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset); virtual PackedInt32Array get_texture_offsets(int p_cache_index, const Vector2i &p_size, int p_texture_index) const; - virtual Array get_glyph_list(int p_cache_index, const Vector2i &p_size) const; + virtual PackedInt32Array get_glyph_list(int p_cache_index, const Vector2i &p_size) const; virtual void clear_glyphs(int p_cache_index, const Vector2i &p_size); virtual void remove_glyph(int p_cache_index, const Vector2i &p_size, int32_t p_glyph); @@ -290,7 +290,7 @@ public: virtual void set_glyph_texture_idx(int p_cache_index, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx); virtual int get_glyph_texture_idx(int p_cache_index, const Vector2i &p_size, int32_t p_glyph) const; - virtual Array get_kerning_list(int p_cache_index, int p_size) const; + virtual TypedArray<Vector2i> get_kerning_list(int p_cache_index, int p_size) const; virtual void clear_kerning_map(int p_cache_index, int p_size); virtual void remove_kerning(int p_cache_index, int p_size, const Vector2i &p_glyph_pair); @@ -404,6 +404,7 @@ class SystemFont : public Font { TextServer::Hinting hinting = TextServer::HINTING_LIGHT; TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO; real_t oversampling = 0.f; + bool msdf = false; protected: static void _bind_methods(); @@ -434,6 +435,9 @@ public: virtual void set_oversampling(real_t p_oversampling); virtual real_t get_oversampling() const; + virtual void set_multichannel_signed_distance_field(bool p_msdf); + virtual bool is_multichannel_signed_distance_field() const; + virtual void set_font_names(const PackedStringArray &p_names); virtual PackedStringArray get_font_names() const; diff --git a/scene/resources/immediate_mesh.cpp b/scene/resources/immediate_mesh.cpp index 044477e744..90cc3ea5f4 100644 --- a/scene/resources/immediate_mesh.cpp +++ b/scene/resources/immediate_mesh.cpp @@ -340,8 +340,8 @@ Array ImmediateMesh::surface_get_arrays(int p_surface) const { ERR_FAIL_INDEX_V(p_surface, int(surfaces.size()), Array()); return RS::get_singleton()->mesh_surface_get_arrays(mesh, p_surface); } -Array ImmediateMesh::surface_get_blend_shape_arrays(int p_surface) const { - return Array(); +TypedArray<Array> ImmediateMesh::surface_get_blend_shape_arrays(int p_surface) const { + return TypedArray<Array>(); } Dictionary ImmediateMesh::surface_get_lods(int p_surface) const { return Dictionary(); diff --git a/scene/resources/immediate_mesh.h b/scene/resources/immediate_mesh.h index de10fdbfbe..0dad62f555 100644 --- a/scene/resources/immediate_mesh.h +++ b/scene/resources/immediate_mesh.h @@ -97,7 +97,7 @@ public: virtual int surface_get_array_len(int p_idx) const override; virtual int surface_get_array_index_len(int p_idx) const override; virtual Array surface_get_arrays(int p_surface) const override; - virtual Array surface_get_blend_shape_arrays(int p_surface) const override; + virtual TypedArray<Array> surface_get_blend_shape_arrays(int p_surface) const override; virtual Dictionary surface_get_lods(int p_surface) const override; virtual uint32_t surface_get_format(int p_idx) const override; virtual PrimitiveType surface_get_primitive_type(int p_idx) const override; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 88bc01fb25..bd0e470112 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -71,12 +71,12 @@ RID Material::get_rid() const { return material; } -void Material::_validate_property(PropertyInfo &property) const { - if (!_can_do_next_pass() && property.name == "next_pass") { - property.usage = PROPERTY_USAGE_NONE; +void Material::_validate_property(PropertyInfo &p_property) const { + if (!_can_do_next_pass() && p_property.name == "next_pass") { + p_property.usage = PROPERTY_USAGE_NONE; } - if (!_can_use_render_priority() && property.name == "render_priority") { - property.usage = PROPERTY_USAGE_NONE; + if (!_can_use_render_priority() && p_property.name == "render_priority") { + p_property.usage = PROPERTY_USAGE_NONE; } } @@ -297,7 +297,7 @@ void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const { } } -bool ShaderMaterial::property_can_revert(const String &p_name) { +bool ShaderMaterial::_property_can_revert(const StringName &p_name) const { if (shader.is_valid()) { StringName pr = shader->remap_uniform(p_name); if (pr) { @@ -310,15 +310,15 @@ bool ShaderMaterial::property_can_revert(const String &p_name) { return false; } -Variant ShaderMaterial::property_get_revert(const String &p_name) { - Variant r_ret; +bool ShaderMaterial::_property_get_revert(const StringName &p_name, Variant &r_property) const { if (shader.is_valid()) { StringName pr = shader->remap_uniform(p_name); if (pr) { - r_ret = RenderingServer::get_singleton()->shader_get_param_default(shader->get_rid(), pr); + r_property = RenderingServer::get_singleton()->shader_get_param_default(shader->get_rid(), pr); + return true; } } - return r_ret; + return false; } void ShaderMaterial::set_shader(const Ref<Shader> &p_shader) { @@ -386,8 +386,6 @@ void ShaderMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("get_shader"), &ShaderMaterial::get_shader); ClassDB::bind_method(D_METHOD("set_shader_uniform", "param", "value"), &ShaderMaterial::set_shader_uniform); ClassDB::bind_method(D_METHOD("get_shader_uniform", "param"), &ShaderMaterial::get_shader_uniform); - ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &ShaderMaterial::property_can_revert); - ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &ShaderMaterial::property_get_revert); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shader", PROPERTY_HINT_RESOURCE_TYPE, "Shader"), "set_shader", "get_shader"); } @@ -1869,61 +1867,61 @@ void BaseMaterial3D::_validate_high_end(const String &text, PropertyInfo &proper } } -void BaseMaterial3D::_validate_property(PropertyInfo &property) const { - _validate_feature("normal", FEATURE_NORMAL_MAPPING, property); - _validate_feature("emission", FEATURE_EMISSION, property); - _validate_feature("rim", FEATURE_RIM, property); - _validate_feature("clearcoat", FEATURE_CLEARCOAT, property); - _validate_feature("anisotropy", FEATURE_ANISOTROPY, property); - _validate_feature("ao", FEATURE_AMBIENT_OCCLUSION, property); - _validate_feature("heightmap", FEATURE_HEIGHT_MAPPING, property); - _validate_feature("subsurf_scatter", FEATURE_SUBSURFACE_SCATTERING, property); - _validate_feature("backlight", FEATURE_BACKLIGHT, property); - _validate_feature("refraction", FEATURE_REFRACTION, property); - _validate_feature("detail", FEATURE_DETAIL, property); +void BaseMaterial3D::_validate_property(PropertyInfo &p_property) const { + _validate_feature("normal", FEATURE_NORMAL_MAPPING, p_property); + _validate_feature("emission", FEATURE_EMISSION, p_property); + _validate_feature("rim", FEATURE_RIM, p_property); + _validate_feature("clearcoat", FEATURE_CLEARCOAT, p_property); + _validate_feature("anisotropy", FEATURE_ANISOTROPY, p_property); + _validate_feature("ao", FEATURE_AMBIENT_OCCLUSION, p_property); + _validate_feature("heightmap", FEATURE_HEIGHT_MAPPING, p_property); + _validate_feature("subsurf_scatter", FEATURE_SUBSURFACE_SCATTERING, p_property); + _validate_feature("backlight", FEATURE_BACKLIGHT, p_property); + _validate_feature("refraction", FEATURE_REFRACTION, p_property); + _validate_feature("detail", FEATURE_DETAIL, p_property); - _validate_high_end("refraction", property); - _validate_high_end("subsurf_scatter", property); - _validate_high_end("heightmap", property); + _validate_high_end("refraction", p_property); + _validate_high_end("subsurf_scatter", p_property); + _validate_high_end("heightmap", p_property); - if (property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name == "billboard_keep_scale" && billboard_mode == BILLBOARD_DISABLED) { - property.usage = PROPERTY_USAGE_NO_EDITOR; + if (p_property.name == "billboard_keep_scale" && billboard_mode == BILLBOARD_DISABLED) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } - if (property.name == "grow_amount" && !grow_enabled) { - property.usage = PROPERTY_USAGE_NO_EDITOR; + if (p_property.name == "grow_amount" && !grow_enabled) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } - if (property.name == "point_size" && !flags[FLAG_USE_POINT_SIZE]) { - property.usage = PROPERTY_USAGE_NO_EDITOR; + if (p_property.name == "point_size" && !flags[FLAG_USE_POINT_SIZE]) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } - if (property.name == "proximity_fade_distance" && !proximity_fade_enabled) { - property.usage = PROPERTY_USAGE_NO_EDITOR; + if (p_property.name == "proximity_fade_distance" && !proximity_fade_enabled) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } - if (property.name == "msdf_pixel_range" && !flags[FLAG_ALBEDO_TEXTURE_MSDF]) { - property.usage = PROPERTY_USAGE_NO_EDITOR; + if (p_property.name == "msdf_pixel_range" && !flags[FLAG_ALBEDO_TEXTURE_MSDF]) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } - if (property.name == "msdf_outline_size" && !flags[FLAG_ALBEDO_TEXTURE_MSDF]) { - property.usage = PROPERTY_USAGE_NO_EDITOR; + if (p_property.name == "msdf_outline_size" && !flags[FLAG_ALBEDO_TEXTURE_MSDF]) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } - if ((property.name == "distance_fade_max_distance" || property.name == "distance_fade_min_distance") && distance_fade == DISTANCE_FADE_DISABLED) { - property.usage = PROPERTY_USAGE_NO_EDITOR; + if ((p_property.name == "distance_fade_max_distance" || p_property.name == "distance_fade_min_distance") && distance_fade == DISTANCE_FADE_DISABLED) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } - if ((property.name == "uv1_triplanar_sharpness" || property.name == "uv1_world_triplanar") && !flags[FLAG_UV1_USE_TRIPLANAR]) { - property.usage = PROPERTY_USAGE_NO_EDITOR; + if ((p_property.name == "uv1_triplanar_sharpness" || p_property.name == "uv1_world_triplanar") && !flags[FLAG_UV1_USE_TRIPLANAR]) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } - if ((property.name == "uv2_triplanar_sharpness" || property.name == "uv2_world_triplanar") && !flags[FLAG_UV2_USE_TRIPLANAR]) { - property.usage = PROPERTY_USAGE_NO_EDITOR; + if ((p_property.name == "uv2_triplanar_sharpness" || p_property.name == "uv2_world_triplanar") && !flags[FLAG_UV2_USE_TRIPLANAR]) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } // you can only enable anti-aliasing (in materials) on alpha scissor and alpha hash @@ -1932,96 +1930,96 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const { const bool alpha_aa_enabled = (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF) && can_select_aa; // alpha scissor slider isn't needed when alpha antialiasing is enabled - if (property.name == "alpha_scissor_threshold" && transparency != TRANSPARENCY_ALPHA_SCISSOR) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name == "alpha_scissor_threshold" && transparency != TRANSPARENCY_ALPHA_SCISSOR) { + p_property.usage = PROPERTY_USAGE_NONE; } // alpha hash scale slider is only needed if transparency is alpha hash - if (property.name == "alpha_hash_scale" && transparency != TRANSPARENCY_ALPHA_HASH) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name == "alpha_hash_scale" && transparency != TRANSPARENCY_ALPHA_HASH) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name == "alpha_antialiasing_mode" && !can_select_aa) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name == "alpha_antialiasing_mode" && !can_select_aa) { + p_property.usage = PROPERTY_USAGE_NONE; } // we can't choose an antialiasing mode if alpha isn't possible - if (property.name == "alpha_antialiasing_edge" && !alpha_aa_enabled) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name == "alpha_antialiasing_edge" && !alpha_aa_enabled) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name == "blend_mode" && alpha_aa_enabled) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name == "blend_mode" && alpha_aa_enabled) { + p_property.usage = PROPERTY_USAGE_NONE; } - if ((property.name == "heightmap_min_layers" || property.name == "heightmap_max_layers") && !deep_parallax) { - property.usage = PROPERTY_USAGE_NONE; + if ((p_property.name == "heightmap_min_layers" || p_property.name == "heightmap_max_layers") && !deep_parallax) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (flags[FLAG_SUBSURFACE_MODE_SKIN] && (property.name == "subsurf_scatter_transmittance_color" || property.name == "subsurf_scatter_transmittance_texture")) { - property.usage = PROPERTY_USAGE_NONE; + if (flags[FLAG_SUBSURFACE_MODE_SKIN] && (p_property.name == "subsurf_scatter_transmittance_color" || p_property.name == "subsurf_scatter_transmittance_texture")) { + p_property.usage = PROPERTY_USAGE_NONE; } if (orm) { - if (property.name == "shading_mode") { + if (p_property.name == "shading_mode") { // Vertex not supported in ORM mode, since no individual roughness. - property.hint_string = "Unshaded,Per-Pixel"; + p_property.hint_string = "Unshaded,Per-Pixel"; } - if (property.name.begins_with("roughness") || property.name.begins_with("metallic") || property.name.begins_with("ao_texture")) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name.begins_with("roughness") || p_property.name.begins_with("metallic") || p_property.name.begins_with("ao_texture")) { + p_property.usage = PROPERTY_USAGE_NONE; } } else { - if (property.name == "orm_texture") { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name == "orm_texture") { + p_property.usage = PROPERTY_USAGE_NONE; } } if (shading_mode != SHADING_MODE_PER_PIXEL) { if (shading_mode != SHADING_MODE_PER_VERTEX) { //these may still work per vertex - if (property.name.begins_with("ao")) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name.begins_with("ao")) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name.begins_with("emission")) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name.begins_with("emission")) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name.begins_with("metallic")) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name.begins_with("metallic")) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name.begins_with("rim")) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name.begins_with("rim")) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name.begins_with("roughness")) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name.begins_with("roughness")) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name.begins_with("subsurf_scatter")) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name.begins_with("subsurf_scatter")) { + p_property.usage = PROPERTY_USAGE_NONE; } } //these definitely only need per pixel - if (property.name.begins_with("anisotropy")) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name.begins_with("anisotropy")) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name.begins_with("clearcoat")) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name.begins_with("clearcoat")) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name.begins_with("normal")) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name.begins_with("normal")) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name.begins_with("backlight")) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name.begins_with("backlight")) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name.begins_with("transmittance")) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name.begins_with("transmittance")) { + p_property.usage = PROPERTY_USAGE_NONE; } } } @@ -2054,8 +2052,9 @@ Vector3 BaseMaterial3D::get_uv1_offset() const { } void BaseMaterial3D::set_uv1_triplanar_blend_sharpness(float p_sharpness) { - uv1_triplanar_sharpness = p_sharpness; - RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_blend_sharpness, p_sharpness); + // Negative values or values higher than 150 can result in NaNs, leading to broken rendering. + uv1_triplanar_sharpness = CLAMP(p_sharpness, 0.0, 150.0); + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_blend_sharpness, uv1_triplanar_sharpness); } float BaseMaterial3D::get_uv1_triplanar_blend_sharpness() const { @@ -2081,8 +2080,9 @@ Vector3 BaseMaterial3D::get_uv2_offset() const { } void BaseMaterial3D::set_uv2_triplanar_blend_sharpness(float p_sharpness) { - uv2_triplanar_sharpness = p_sharpness; - RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_blend_sharpness, p_sharpness); + // Negative values or values higher than 150 can result in NaNs, leading to broken rendering. + uv2_triplanar_sharpness = CLAMP(p_sharpness, 0.0, 150.0); + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_blend_sharpness, uv2_triplanar_sharpness); } float BaseMaterial3D::get_uv2_triplanar_blend_sharpness() const { diff --git a/scene/resources/material.h b/scene/resources/material.h index ca5b17dd07..c6be1b8766 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -54,7 +54,7 @@ protected: virtual bool _can_do_next_pass() const; virtual bool _can_use_render_priority() const; - void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; GDVIRTUAL0RC(RID, _get_shader_rid) GDVIRTUAL0RC(Shader::Mode, _get_shader_mode) @@ -99,8 +99,8 @@ protected: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List<PropertyInfo> *p_list) const; - bool property_can_revert(const String &p_name); - Variant property_get_revert(const String &p_name); + bool _property_can_revert(const StringName &p_name) const; + bool _property_get_revert(const StringName &p_name, Variant &r_property) const; static void _bind_methods(); @@ -553,7 +553,7 @@ private: protected: static void _bind_methods(); - void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; virtual bool _can_do_next_pass() const override { return true; } virtual bool _can_use_render_priority() const override { return true; } diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index ec9db89794..7f318af899 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -32,11 +32,10 @@ #include "core/math/convex_hull.h" #include "core/templates/pair.h" +#include "scene/resources/surface_tool.h" + #include "scene/resources/concave_polygon_shape_3d.h" #include "scene/resources/convex_polygon_shape_3d.h" -#include "surface_tool.h" - -#include <stdlib.h> Mesh::ConvexDecompositionFunc Mesh::convex_decomposition_function = nullptr; @@ -72,13 +71,13 @@ Array Mesh::surface_get_arrays(int p_surface) const { return Array(); } -Array Mesh::surface_get_blend_shape_arrays(int p_surface) const { - Array ret; +TypedArray<Array> Mesh::surface_get_blend_shape_arrays(int p_surface) const { + TypedArray<Array> ret; if (GDVIRTUAL_REQUIRED_CALL(_surface_get_blend_shape_arrays, p_surface, ret)) { return ret; } - return Array(); + return TypedArray<Array>(); } Dictionary Mesh::surface_get_lods(int p_surface) const { @@ -201,7 +200,9 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { continue; } int len = (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? surface_get_array_index_len(i) : surface_get_array_len(i); - if ((primitive == PRIMITIVE_TRIANGLES && (len == 0 || (len % 3) != 0)) || (primitive == PRIMITIVE_TRIANGLE_STRIP && len < 3)) { + if ((primitive == PRIMITIVE_TRIANGLES && (len == 0 || (len % 3) != 0)) || + (primitive == PRIMITIVE_TRIANGLE_STRIP && len < 3) || + (surface_get_format(i) & ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY)) { // Error was already shown, just skip (including zero). continue; } @@ -211,6 +212,7 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { int vc = surface_get_array_len(i); Vector<Vector3> vertices = a[ARRAY_VERTEX]; + ERR_FAIL_COND_V(vertices.is_empty(), Ref<TriangleMesh>()); const Vector3 *vr = vertices.ptr(); int32_t from_index = widx / 3; @@ -863,27 +865,6 @@ static Mesh::PrimitiveType _old_primitives[7] = { }; #endif // DISABLE_DEPRECATED -// Convert Octahedron-mapped normalized vector back to Cartesian -// Assumes normalized format (elements of v within range [-1, 1]) -Vector3 _oct_to_norm(const Vector2 v) { - Vector3 res(v.x, v.y, 1 - (Math::absf(v.x) + Math::absf(v.y))); - float t = MAX(-res.z, 0.0f); - res.x += t * -SIGN(res.x); - res.y += t * -SIGN(res.y); - return res.normalized(); -} - -// Convert Octahedron-mapped normalized tangent vector back to Cartesian -// out_sign provides the direction for the original cartesian tangent -// Assumes normalized format (elements of v within range [-1, 1]) -Vector3 _oct_to_tangent(const Vector2 v, float *out_sign) { - Vector2 v_decompressed = v; - v_decompressed.y = Math::absf(v_decompressed.y) * 2 - 1; - Vector3 res = _oct_to_norm(v_decompressed); - *out_sign = SIGN(v[1]); - return res; -} - void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_old_format, uint32_t p_new_format, uint32_t p_elements, Vector<uint8_t> &vertex_data, Vector<uint8_t> &attribute_data, Vector<uint8_t> &skin_data) { uint32_t dst_vertex_stride; uint32_t dst_attribute_stride; @@ -954,127 +935,93 @@ void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_old_forma if ((p_old_format & OLD_ARRAY_COMPRESS_NORMAL) && (p_old_format & OLD_ARRAY_FORMAT_TANGENT) && (p_old_format & OLD_ARRAY_COMPRESS_TANGENT)) { for (uint32_t i = 0; i < p_elements; i++) { const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; - uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; - const Vector2 src_vec(src[0] / 127.0f, src[1] / 127.0f); - - const Vector3 res = _oct_to_norm(src_vec) * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5); - *dst = 0; - *dst |= CLAMP(int(res.x * 1023.0f), 0, 1023); - *dst |= CLAMP(int(res.y * 1023.0f), 0, 1023) << 10; - *dst |= CLAMP(int(res.z * 1023.0f), 0, 1023) << 20; + int16_t *dst = (int16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; + + dst[0] = (int16_t)CLAMP(src[0] / 127.0f * 32767, -32768, 32767); + dst[1] = (int16_t)CLAMP(src[1] / 127.0f * 32767, -32768, 32767); } - src_offset += sizeof(int8_t) * 2; + src_offset += sizeof(int16_t) * 2; } else { for (uint32_t i = 0; i < p_elements; i++) { const int16_t *src = (const int16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; - uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; - const Vector2 src_vec(src[0] / 32767.0f, src[1] / 32767.0f); - - const Vector3 res = _oct_to_norm(src_vec) * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5); - *dst = 0; - *dst |= CLAMP(int(res.x * 1023.0f), 0, 1023); - *dst |= CLAMP(int(res.y * 1023.0f), 0, 1023) << 10; - *dst |= CLAMP(int(res.z * 1023.0f), 0, 1023) << 20; + int16_t *dst = (int16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; + + dst[0] = src[0]; + dst[1] = src[1]; } src_offset += sizeof(int16_t) * 2; } } else { // No Octahedral compression if (p_old_format & OLD_ARRAY_COMPRESS_NORMAL) { - const float multiplier = 1.f / 127.f * 1023.0f; - for (uint32_t i = 0; i < p_elements; i++) { const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; - uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; + const Vector3 original_normal(src[0], src[1], src[2]); + Vector2 res = original_normal.octahedron_encode(); - *dst = 0; - *dst |= CLAMP(int(src[0] * multiplier), 0, 1023); - *dst |= CLAMP(int(src[1] * multiplier), 0, 1023) << 10; - *dst |= CLAMP(int(src[2] * multiplier), 0, 1023) << 20; + uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; + dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); + dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); } - src_offset += sizeof(uint32_t); + src_offset += sizeof(uint16_t) * 2; } else { for (uint32_t i = 0; i < p_elements; i++) { const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; - uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; + const Vector3 original_normal(src[0], src[1], src[2]); + Vector2 res = original_normal.octahedron_encode(); - *dst = 0; - *dst |= CLAMP(int(src[0] * 1023.0), 0, 1023); - *dst |= CLAMP(int(src[1] * 1023.0), 0, 1023) << 10; - *dst |= CLAMP(int(src[2] * 1023.0), 0, 1023) << 20; + uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; + dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); + dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); } - src_offset += sizeof(float) * 3; + src_offset += sizeof(uint16_t) * 2; } } } break; case OLD_ARRAY_TANGENT: { if (p_old_format & OLD_ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) { - if (p_old_format & OLD_ARRAY_COMPRESS_TANGENT) { // int8 + if (p_old_format & OLD_ARRAY_COMPRESS_TANGENT) { // int8 SNORM -> uint16 UNORM for (uint32_t i = 0; i < p_elements; i++) { const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; - uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]]; - const Vector2 src_vec(src[0] / 127.0f, src[1] / 127.0f); - float out_sign; - const Vector3 res = _oct_to_tangent(src_vec, &out_sign) * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5); - - *dst = 0; - *dst |= CLAMP(int(res.x * 1023.0), 0, 1023); - *dst |= CLAMP(int(res.y * 1023.0), 0, 1023) << 10; - *dst |= CLAMP(int(res.z * 1023.0), 0, 1023) << 20; - if (out_sign > 0) { - *dst |= 3 << 30; - } + uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]]; + + dst[0] = (uint16_t)CLAMP((src[0] / 127.0f * .5f + .5f) * 65535, 0, 65535); + dst[1] = (uint16_t)CLAMP((src[1] / 127.0f * .5f + .5f) * 65535, 0, 65535); } - src_offset += sizeof(int8_t) * 2; - } else { // int16 + src_offset += sizeof(uint16_t) * 2; + } else { // int16 SNORM -> uint16 UNORM for (uint32_t i = 0; i < p_elements; i++) { const int16_t *src = (const int16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; - uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]]; - const Vector2 src_vec(src[0] / 32767.0f, src[1] / 32767.0f); - float out_sign; - Vector3 res = _oct_to_tangent(src_vec, &out_sign) * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5); - - *dst = 0; - *dst |= CLAMP(int(res.x * 1023.0), 0, 1023); - *dst |= CLAMP(int(res.y * 1023.0), 0, 1023) << 10; - *dst |= CLAMP(int(res.z * 1023.0), 0, 1023) << 20; - if (out_sign > 0) { - *dst |= 3 << 30; - } + uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]]; + + dst[0] = (uint16_t)CLAMP((src[0] / 32767.0f * .5f + .5f) * 65535, 0, 65535); + dst[1] = (uint16_t)CLAMP((src[1] / 32767.0f * .5f + .5f) * 65535, 0, 65535); } - src_offset += sizeof(int16_t) * 2; + src_offset += sizeof(uint16_t) * 2; } } else { // No Octahedral compression if (p_old_format & OLD_ARRAY_COMPRESS_TANGENT) { - const float multiplier = 1.f / 127.f * 1023.0f; - for (uint32_t i = 0; i < p_elements; i++) { const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; - uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]]; - - *dst = 0; - *dst |= CLAMP(int(src[0] * multiplier), 0, 1023); - *dst |= CLAMP(int(src[1] * multiplier), 0, 1023) << 10; - *dst |= CLAMP(int(src[2] * multiplier), 0, 1023) << 20; - if (src[3] > 0) { - *dst |= 3 << 30; - } + const Vector3 original_tangent(src[0], src[1], src[2]); + Vector2 res = original_tangent.octahedron_tangent_encode(src[3]); + + uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; + dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); + dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); } - src_offset += sizeof(uint32_t); + src_offset += sizeof(uint16_t) * 2; } else { for (uint32_t i = 0; i < p_elements; i++) { const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; - uint32_t *dst = (uint32_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]]; - - *dst = 0; - *dst |= CLAMP(int(src[0] * 1023.0), 0, 1023); - *dst |= CLAMP(int(src[1] * 1023.0), 0, 1023) << 10; - *dst |= CLAMP(int(src[2] * 1023.0), 0, 1023) << 20; - if (src[3] > 0) { - *dst |= 3 << 30; - } + const Vector3 original_tangent(src[0], src[1], src[2]); + Vector2 res = original_tangent.octahedron_tangent_encode(src[3]); + + uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; + dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); + dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); } - src_offset += sizeof(float) * 4; + src_offset += sizeof(uint16_t) * 2; } } } break; @@ -1693,8 +1640,8 @@ Array ArrayMesh::surface_get_arrays(int p_surface) const { return RenderingServer::get_singleton()->mesh_surface_get_arrays(mesh, p_surface); } -Array ArrayMesh::surface_get_blend_shape_arrays(int p_surface) const { - ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); +TypedArray<Array> ArrayMesh::surface_get_blend_shape_arrays(int p_surface) const { + ERR_FAIL_INDEX_V(p_surface, surfaces.size(), TypedArray<Array>()); return RenderingServer::get_singleton()->mesh_surface_get_blend_shape_arrays(mesh, p_surface); } diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 142373ce7f..fd3c2c4fa4 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -63,7 +63,7 @@ protected: GDVIRTUAL1RC(int, _surface_get_array_len, int) GDVIRTUAL1RC(int, _surface_get_array_index_len, int) GDVIRTUAL1RC(Array, _surface_get_arrays, int) - GDVIRTUAL1RC(Array, _surface_get_blend_shape_arrays, int) + GDVIRTUAL1RC(TypedArray<Array>, _surface_get_blend_shape_arrays, int) GDVIRTUAL1RC(Dictionary, _surface_get_lods, int) GDVIRTUAL1RC(uint32_t, _surface_get_format, int) GDVIRTUAL1RC(uint32_t, _surface_get_primitive_type, int) @@ -144,13 +144,14 @@ public: ARRAY_FLAG_USE_DYNAMIC_UPDATE = RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE, ARRAY_FLAG_USE_8_BONE_WEIGHTS = RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS, + ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY = RS::ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY, }; virtual int get_surface_count() const; virtual int surface_get_array_len(int p_idx) const; virtual int surface_get_array_index_len(int p_idx) const; virtual Array surface_get_arrays(int p_surface) const; - virtual Array surface_get_blend_shape_arrays(int p_surface) const; + virtual TypedArray<Array> surface_get_blend_shape_arrays(int p_surface) const; virtual Dictionary surface_get_lods(int p_surface) const; virtual uint32_t surface_get_format(int p_idx) const; virtual PrimitiveType surface_get_primitive_type(int p_idx) const; @@ -168,9 +169,6 @@ public: void generate_debug_mesh_lines(Vector<Vector3> &r_lines); void generate_debug_mesh_indices(Vector<Vector3> &r_points); - Ref<Shape3D> create_trimesh_shape() const; - Ref<Shape3D> create_convex_shape(bool p_clean = true, bool p_simplify = false) const; - Ref<Mesh> create_outline(float p_margin) const; void set_lightmap_size_hint(const Size2i &p_size); @@ -213,6 +211,8 @@ public: static ConvexDecompositionFunc convex_decomposition_function; Vector<Ref<Shape3D>> convex_decompose(const ConvexDecompositionSettings &p_settings) const; + Ref<Shape3D> create_convex_shape(bool p_clean = true, bool p_simplify = false) const; + Ref<Shape3D> create_trimesh_shape() const; virtual int get_builtin_bind_pose_count() const; virtual Transform3D get_builtin_bind_pose(int p_index) const; @@ -270,7 +270,7 @@ public: void add_surface(uint32_t p_format, PrimitiveType p_primitive, const Vector<uint8_t> &p_array, const Vector<uint8_t> &p_attribute_array, const Vector<uint8_t> &p_skin_array, int p_vertex_count, const Vector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<uint8_t> &p_blend_shape_data = Vector<uint8_t>(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>(), const Vector<RS::SurfaceData::LOD> &p_lods = Vector<RS::SurfaceData::LOD>()); Array surface_get_arrays(int p_surface) const override; - Array surface_get_blend_shape_arrays(int p_surface) const override; + TypedArray<Array> surface_get_blend_shape_arrays(int p_surface) const override; Dictionary surface_get_lods(int p_surface) const override; void add_blend_shape(const StringName &p_name); @@ -345,7 +345,7 @@ public: virtual int surface_get_array_len(int p_idx) const override { return 0; } virtual int surface_get_array_index_len(int p_idx) const override { return 0; } virtual Array surface_get_arrays(int p_surface) const override { return Array(); } - virtual Array surface_get_blend_shape_arrays(int p_surface) const override { return Array(); } + virtual TypedArray<Array> surface_get_blend_shape_arrays(int p_surface) const override { return TypedArray<Array>(); } virtual Dictionary surface_get_lods(int p_surface) const override { return Dictionary(); } virtual uint32_t surface_get_format(int p_idx) const override { return 0; } virtual PrimitiveType surface_get_primitive_type(int p_idx) const override { return PRIMITIVE_TRIANGLES; } diff --git a/scene/resources/mesh_library.h b/scene/resources/mesh_library.h index 4105bd6960..79acb41c4e 100644 --- a/scene/resources/mesh_library.h +++ b/scene/resources/mesh_library.h @@ -33,8 +33,8 @@ #include "core/io/resource.h" #include "core/templates/rb_map.h" -#include "mesh.h" #include "scene/3d/navigation_region_3d.h" +#include "scene/resources/mesh.h" #include "shape_3d.h" class MeshLibrary : public Resource { diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp index ac5493efdc..6c9c8ffdba 100644 --- a/scene/resources/navigation_mesh.cpp +++ b/scene/resources/navigation_mesh.cpp @@ -614,8 +614,10 @@ void NavigationMesh::_bind_methods() { ADD_GROUP("Geometry", "geometry_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry_parsed_geometry_type", PROPERTY_HINT_ENUM, "Mesh Instances,Static Colliders,Both"), "set_parsed_geometry_type", "get_parsed_geometry_type"); ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry_collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_PROPERTY_DEFAULT("geometry_collision_mask", 0xFFFFFFFF); ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry_source_geometry_mode", PROPERTY_HINT_ENUM, "NavMesh Children, Group With Children, Group Explicit"), "set_source_geometry_mode", "get_source_geometry_mode"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "geometry_source_group_name"), "set_source_group_name", "get_source_group_name"); + ADD_PROPERTY_DEFAULT("geometry_source_group_name", StringName("navmesh")); ADD_GROUP("Cells", "cell_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size", PROPERTY_HINT_RANGE, "0.01,500.0,0.01,or_greater,suffix:m"), "set_cell_size", "get_cell_size"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_height", PROPERTY_HINT_RANGE, "0.01,500.0,0.01,or_greater,suffix:m"), "set_cell_height", "get_cell_height"); @@ -658,17 +660,17 @@ void NavigationMesh::_bind_methods() { BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_MAX); } -void NavigationMesh::_validate_property(PropertyInfo &property) const { - if (property.name == "geometry/collision_mask") { +void NavigationMesh::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "geometry_collision_mask") { if (parsed_geometry_type == PARSED_GEOMETRY_MESH_INSTANCES) { - property.usage = PROPERTY_USAGE_NONE; + p_property.usage = PROPERTY_USAGE_NONE; return; } } - if (property.name == "geometry/source_group_name") { + if (p_property.name == "geometry_source_group_name") { if (source_geometry_mode == SOURCE_GEOMETRY_NAVMESH_CHILDREN) { - property.usage = PROPERTY_USAGE_NONE; + p_property.usage = PROPERTY_USAGE_NONE; return; } } diff --git a/scene/resources/navigation_mesh.h b/scene/resources/navigation_mesh.h index 79d8962d24..c66025dc6d 100644 --- a/scene/resources/navigation_mesh.h +++ b/scene/resources/navigation_mesh.h @@ -33,8 +33,6 @@ #include "scene/resources/mesh.h" -class Mesh; - class NavigationMesh : public Resource { GDCLASS(NavigationMesh, Resource); @@ -60,7 +58,7 @@ class NavigationMesh : public Resource { protected: static void _bind_methods(); - virtual void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; #ifndef DISABLE_DEPRECATED bool _set(const StringName &p_name, const Variant &p_value); diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index 4b2e029f47..29a06622a3 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -287,7 +287,7 @@ void ParticlesMaterial::_update_shader() { code += "uniform sampler2D anim_offset_texture : repeat_disable;\n"; } - if (collision_enabled) { + if (collision_mode == COLLISION_RIGID) { code += "uniform float collision_friction;\n"; code += "uniform float collision_bounce;\n"; } @@ -695,8 +695,10 @@ void ParticlesMaterial::_update_shader() { } code += " vec3 noise_direction = get_noise_direction(TRANSFORM[3].xyz, EMISSION_TRANSFORM[3].xyz, time_noise);\n"; // If collision happened, turbulence is no longer applied. + // We don't need this check when the collision mode is "hide on contact", + // as the particle will be hidden anyway. String extra_tab = ""; - if (collision_enabled) { + if (collision_mode != COLLISION_RIGID) { code += " if (!COLLIDED) {\n"; extra_tab = " "; } @@ -704,7 +706,7 @@ void ParticlesMaterial::_update_shader() { code += extra_tab + " float vel_mag = length(VELOCITY);\n"; code += extra_tab + " float vel_infl = clamp(mix(turbulence_influence_min, turbulence_influence_max, rand_from_seed(alt_seed)) * turbulence_influence, 0.0, 1.0);\n"; code += extra_tab + " VELOCITY = mix(VELOCITY, normalize(noise_direction) * vel_mag * (1.0 + (1.0 - vel_infl) * 0.2), vel_infl);\n"; - if (collision_enabled) { + if (collision_mode != COLLISION_RIGID) { code += " }"; } } @@ -828,7 +830,7 @@ void ParticlesMaterial::_update_shader() { code += " TRANSFORM[3].z = 0.0;\n"; } - if (collision_enabled) { + if (collision_mode == COLLISION_RIGID) { code += " if (COLLIDED) {\n"; code += " if (length(VELOCITY) > 3.0) {\n"; code += " TRANSFORM[3].xyz += COLLISION_NORMAL * COLLISION_DEPTH;\n"; @@ -851,6 +853,18 @@ void ParticlesMaterial::_update_shader() { code += " TRANSFORM[1].xyz *= base_scale * sign(tex_scale.g) * max(abs(tex_scale.g), 0.001);\n"; code += " TRANSFORM[2].xyz *= base_scale * sign(tex_scale.b) * max(abs(tex_scale.b), 0.001);\n"; + if (collision_mode == COLLISION_RIGID) { + code += " if (COLLIDED) {\n"; + code += " TRANSFORM[3].xyz+=COLLISION_NORMAL * COLLISION_DEPTH;\n"; + code += " VELOCITY -= COLLISION_NORMAL * dot(COLLISION_NORMAL, VELOCITY) * (1.0 + collision_bounce);\n"; + code += " VELOCITY = mix(VELOCITY,vec3(0.0),collision_friction * DELTA * 100.0);\n"; + code += " }\n"; + } else if (collision_mode == COLLISION_HIDE_ON_CONTACT) { + code += " if (COLLIDED) {\n"; + code += " ACTIVE = false;\n"; + code += " }\n"; + } + if (sub_emitter_mode != SUB_EMITTER_DISABLED) { code += " int emit_count = 0;\n"; switch (sub_emitter_mode) { @@ -1386,56 +1400,64 @@ RID ParticlesMaterial::get_shader_rid() const { return shader_map[current_key].shader; } -void ParticlesMaterial::_validate_property(PropertyInfo &property) const { - if (property.name == "emission_sphere_radius" && (emission_shape != EMISSION_SHAPE_SPHERE && emission_shape != EMISSION_SHAPE_SPHERE_SURFACE)) { - property.usage = PROPERTY_USAGE_NONE; +void ParticlesMaterial::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "emission_sphere_radius" && (emission_shape != EMISSION_SHAPE_SPHERE && emission_shape != EMISSION_SHAPE_SPHERE_SURFACE)) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name == "emission_box_extents" && emission_shape != EMISSION_SHAPE_BOX) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name == "emission_box_extents" && emission_shape != EMISSION_SHAPE_BOX) { + p_property.usage = PROPERTY_USAGE_NONE; } - if ((property.name == "emission_point_texture" || property.name == "emission_color_texture") && (emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS)) { - property.usage = PROPERTY_USAGE_NONE; + if ((p_property.name == "emission_point_texture" || p_property.name == "emission_color_texture") && (emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS)) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name == "emission_normal_texture" && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name == "emission_normal_texture" && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name == "emission_point_count" && (emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS)) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name == "emission_point_count" && (emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS)) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name.begins_with("emission_ring_") && emission_shape != EMISSION_SHAPE_RING) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name.begins_with("emission_ring_") && emission_shape != EMISSION_SHAPE_RING) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name == "sub_emitter_frequency" && sub_emitter_mode != SUB_EMITTER_CONSTANT) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name == "sub_emitter_frequency" && sub_emitter_mode != SUB_EMITTER_CONSTANT) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name == "sub_emitter_amount_at_end" && sub_emitter_mode != SUB_EMITTER_AT_END) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name == "sub_emitter_amount_at_end" && sub_emitter_mode != SUB_EMITTER_AT_END) { + p_property.usage = PROPERTY_USAGE_NONE; } - if (property.name.begins_with("orbit_") && !particle_flags[PARTICLE_FLAG_DISABLE_Z]) { - property.usage = PROPERTY_USAGE_NONE; + if (p_property.name.begins_with("orbit_") && !particle_flags[PARTICLE_FLAG_DISABLE_Z]) { + p_property.usage = PROPERTY_USAGE_NONE; } if (!turbulence_enabled) { - if (property.name == "turbulence_noise_strength" || - property.name == "turbulence_noise_scale" || - property.name == "turbulence_noise_speed" || - property.name == "turbulence_noise_speed_random" || - property.name == "turbulence_influence_over_life" || - property.name == "turbulence_influence_min" || - property.name == "turbulence_influence_max" || - property.name == "turbulence_initial_displacement_min" || - property.name == "turbulence_initial_displacement_max") { - property.usage = PROPERTY_USAGE_NO_EDITOR; + if (p_property.name == "turbulence_noise_strength" || + p_property.name == "turbulence_noise_scale" || + p_property.name == "turbulence_noise_speed" || + p_property.name == "turbulence_noise_speed_random" || + p_property.name == "turbulence_influence_over_life" || + p_property.name == "turbulence_influence_min" || + p_property.name == "turbulence_influence_max" || + p_property.name == "turbulence_initial_displacement_min" || + p_property.name == "turbulence_initial_displacement_max") { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } + + if (p_property.name == "collision_friction" && collision_mode != COLLISION_RIGID) { + p_property.usage = PROPERTY_USAGE_NONE; + } + + if (p_property.name == "collision_bounce" && collision_mode != COLLISION_RIGID) { + p_property.usage = PROPERTY_USAGE_NONE; + } } void ParticlesMaterial::set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode) { @@ -1483,13 +1505,14 @@ bool ParticlesMaterial::is_attractor_interaction_enabled() const { return attractor_interaction_enabled; } -void ParticlesMaterial::set_collision_enabled(bool p_enabled) { - collision_enabled = p_enabled; +void ParticlesMaterial::set_collision_mode(CollisionMode p_collision_mode) { + collision_mode = p_collision_mode; _queue_shader_change(); + notify_property_list_changed(); } -bool ParticlesMaterial::is_collision_enabled() const { - return collision_enabled; +ParticlesMaterial::CollisionMode ParticlesMaterial::get_collision_mode() const { + return collision_mode; } void ParticlesMaterial::set_collision_use_scale(bool p_scale) { @@ -1623,8 +1646,8 @@ void ParticlesMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_attractor_interaction_enabled", "enabled"), &ParticlesMaterial::set_attractor_interaction_enabled); ClassDB::bind_method(D_METHOD("is_attractor_interaction_enabled"), &ParticlesMaterial::is_attractor_interaction_enabled); - ClassDB::bind_method(D_METHOD("set_collision_enabled", "enabled"), &ParticlesMaterial::set_collision_enabled); - ClassDB::bind_method(D_METHOD("is_collision_enabled"), &ParticlesMaterial::is_collision_enabled); + ClassDB::bind_method(D_METHOD("set_collision_mode", "mode"), &ParticlesMaterial::set_collision_mode); + ClassDB::bind_method(D_METHOD("get_collision_mode"), &ParticlesMaterial::get_collision_mode); ClassDB::bind_method(D_METHOD("set_collision_use_scale", "radius"), &ParticlesMaterial::set_collision_use_scale); ClassDB::bind_method(D_METHOD("is_collision_using_scale"), &ParticlesMaterial::is_collision_using_scale); @@ -1734,7 +1757,7 @@ void ParticlesMaterial::_bind_methods() { ADD_GROUP("Attractor Interaction", "attractor_interaction_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "attractor_interaction_enabled"), "set_attractor_interaction_enabled", "is_attractor_interaction_enabled"); ADD_GROUP("Collision", "collision_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_enabled"), "set_collision_enabled", "is_collision_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mode", PROPERTY_HINT_ENUM, "Disabled,Rigid,Hide On Contact"), "set_collision_mode", "get_collision_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_friction", "get_collision_friction"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_bounce", "get_collision_bounce"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_use_scale"), "set_collision_use_scale", "is_collision_using_scale"); @@ -1776,6 +1799,11 @@ void ParticlesMaterial::_bind_methods() { BIND_ENUM_CONSTANT(SUB_EMITTER_AT_END); BIND_ENUM_CONSTANT(SUB_EMITTER_AT_COLLISION); BIND_ENUM_CONSTANT(SUB_EMITTER_MAX); + + BIND_ENUM_CONSTANT(COLLISION_DISABLED); + BIND_ENUM_CONSTANT(COLLISION_RIGID); + BIND_ENUM_CONSTANT(COLLISION_HIDE_ON_CONTACT); + BIND_ENUM_CONSTANT(COLLISION_MAX); } ParticlesMaterial::ParticlesMaterial() : @@ -1834,7 +1862,7 @@ ParticlesMaterial::ParticlesMaterial() : set_sub_emitter_keep_velocity(false); set_attractor_interaction_enabled(true); - set_collision_enabled(false); + set_collision_mode(COLLISION_DISABLED); set_collision_bounce(0.0); set_collision_friction(0.0); set_collision_use_scale(false); diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h index 7fb46d6ac5..2e94e7e01a 100644 --- a/scene/resources/particles_material.h +++ b/scene/resources/particles_material.h @@ -93,6 +93,14 @@ public: SUB_EMITTER_MAX }; + // When extending, make sure not to overflow the size of the MaterialKey below. + enum CollisionMode { + COLLISION_DISABLED, + COLLISION_RIGID, + COLLISION_HIDE_ON_CONTACT, + COLLISION_MAX + }; + private: union MaterialKey { // The bit size of the struct must be kept below or equal to 32 bits. @@ -106,7 +114,7 @@ private: uint32_t has_emission_color : 1; uint32_t sub_emitter : 2; uint32_t attractor_enabled : 1; - uint32_t collision_enabled : 1; + uint32_t collision_mode : 2; uint32_t collision_scale : 1; uint32_t turbulence_enabled : 1; }; @@ -153,7 +161,7 @@ private: mk.emission_shape = emission_shape; mk.has_emission_color = emission_shape >= EMISSION_SHAPE_POINTS && emission_color_texture.is_valid(); mk.sub_emitter = sub_emitter_mode; - mk.collision_enabled = collision_enabled; + mk.collision_mode = collision_mode; mk.attractor_enabled = attractor_interaction_enabled; mk.collision_scale = collision_scale; mk.turbulence_enabled = turbulence_enabled; @@ -300,14 +308,14 @@ private: //do not save emission points here bool attractor_interaction_enabled = false; - bool collision_enabled = false; + CollisionMode collision_mode; bool collision_scale = false; float collision_friction = 0.0f; float collision_bounce = 0.0f; protected: static void _bind_methods(); - virtual void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; public: void set_direction(Vector3 p_direction); @@ -385,8 +393,8 @@ public: void set_attractor_interaction_enabled(bool p_enable); bool is_attractor_interaction_enabled() const; - void set_collision_enabled(bool p_enabled); - bool is_collision_enabled() const; + void set_collision_mode(CollisionMode p_collision_mode); + CollisionMode get_collision_mode() const; void set_collision_use_scale(bool p_scale); bool is_collision_using_scale() const; @@ -425,5 +433,6 @@ VARIANT_ENUM_CAST(ParticlesMaterial::Parameter) VARIANT_ENUM_CAST(ParticlesMaterial::ParticleFlags) VARIANT_ENUM_CAST(ParticlesMaterial::EmissionShape) VARIANT_ENUM_CAST(ParticlesMaterial::SubEmitterMode) +VARIANT_ENUM_CAST(ParticlesMaterial::CollisionMode) #endif // PARTICLES_MATERIAL_H diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index f038a79b8f..7847acb318 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -152,8 +152,8 @@ Dictionary PrimitiveMesh::surface_get_lods(int p_surface) const { return Dictionary(); //not really supported } -Array PrimitiveMesh::surface_get_blend_shape_arrays(int p_surface) const { - return Array(); //not really supported +TypedArray<Array> PrimitiveMesh::surface_get_blend_shape_arrays(int p_surface) const { + return TypedArray<Array>(); //not really supported } uint32_t PrimitiveMesh::surface_get_format(int p_idx) const { @@ -990,6 +990,13 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const { Size2 start_pos = size * -0.5; + Vector3 normal = Vector3(0.0, 1.0, 0.0); + if (orientation == FACE_X) { + normal = Vector3(1.0, 0.0, 0.0); + } else if (orientation == FACE_Z) { + normal = Vector3(0.0, 0.0, 1.0); + } + Vector<Vector3> points; Vector<Vector3> normals; Vector<float> tangents; @@ -1015,8 +1022,14 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const { u /= (subdivide_w + 1.0); v /= (subdivide_d + 1.0); - points.push_back(Vector3(-x, 0.0, -z) + center_offset); - normals.push_back(Vector3(0.0, 1.0, 0.0)); + if (orientation == FACE_X) { + points.push_back(Vector3(0.0, z, x) + center_offset); + } else if (orientation == FACE_Y) { + points.push_back(Vector3(-x, 0.0, -z) + center_offset); + } else if (orientation == FACE_Z) { + points.push_back(Vector3(-x, z, 0.0) + center_offset); + } + normals.push_back(normal); ADD_TANGENT(1.0, 0.0, 0.0, 1.0); uvs.push_back(Vector2(1.0 - u, 1.0 - v)); /* 1.0 - uv to match orientation with Quad */ point++; @@ -1053,13 +1066,22 @@ void PlaneMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("get_subdivide_width"), &PlaneMesh::get_subdivide_width); ClassDB::bind_method(D_METHOD("set_subdivide_depth", "subdivide"), &PlaneMesh::set_subdivide_depth); ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PlaneMesh::get_subdivide_depth); + ClassDB::bind_method(D_METHOD("set_center_offset", "offset"), &PlaneMesh::set_center_offset); ClassDB::bind_method(D_METHOD("get_center_offset"), &PlaneMesh::get_center_offset); + ClassDB::bind_method(D_METHOD("set_orientation", "orientation"), &PlaneMesh::set_orientation); + ClassDB::bind_method(D_METHOD("get_orientation"), &PlaneMesh::get_orientation); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_width", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_width", "get_subdivide_width"); ADD_PROPERTY(PropertyInfo(Variant::INT, "subdivide_depth", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_depth", "get_subdivide_depth"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_center_offset", "get_center_offset"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "orientation", PROPERTY_HINT_ENUM, "Face X, Face Y, Face Z"), "set_orientation", "get_orientation"); + + BIND_ENUM_CONSTANT(FACE_X) + BIND_ENUM_CONSTANT(FACE_Y) + BIND_ENUM_CONSTANT(FACE_Z) } void PlaneMesh::set_size(const Size2 &p_size) { @@ -1098,6 +1120,15 @@ Vector3 PlaneMesh::get_center_offset() const { return center_offset; } +void PlaneMesh::set_orientation(const Orientation p_orientation) { + orientation = p_orientation; + _request_update(); +} + +PlaneMesh::Orientation PlaneMesh::get_orientation() const { + return orientation; +} + PlaneMesh::PlaneMesh() {} /** @@ -1381,98 +1412,6 @@ int PrismMesh::get_subdivide_depth() const { PrismMesh::PrismMesh() {} /** - QuadMesh -*/ - -void QuadMesh::_create_mesh_array(Array &p_arr) const { - Vector<Vector3> faces; - Vector<Vector3> normals; - Vector<float> tangents; - Vector<Vector2> uvs; - - faces.resize(6); - normals.resize(6); - tangents.resize(6 * 4); - uvs.resize(6); - - Vector2 _size = Vector2(size.x / 2.0f, size.y / 2.0f); - - Vector3 quad_faces[4] = { - Vector3(-_size.x, -_size.y, 0) + center_offset, - Vector3(-_size.x, _size.y, 0) + center_offset, - Vector3(_size.x, _size.y, 0) + center_offset, - Vector3(_size.x, -_size.y, 0) + center_offset, - }; - - static const int indices[6] = { - 0, 1, 2, - 0, 2, 3 - }; - - for (int i = 0; i < 6; i++) { - int j = indices[i]; - faces.set(i, quad_faces[j]); - normals.set(i, Vector3(0, 0, 1)); - tangents.set(i * 4 + 0, 1.0); - tangents.set(i * 4 + 1, 0.0); - tangents.set(i * 4 + 2, 0.0); - tangents.set(i * 4 + 3, 1.0); - - static const Vector2 quad_uv[4] = { - Vector2(0, 1), - Vector2(0, 0), - Vector2(1, 0), - Vector2(1, 1), - }; - - uvs.set(i, quad_uv[j]); - } - - p_arr[RS::ARRAY_VERTEX] = faces; - p_arr[RS::ARRAY_NORMAL] = normals; - p_arr[RS::ARRAY_TANGENT] = tangents; - p_arr[RS::ARRAY_TEX_UV] = uvs; -} - -void QuadMesh::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_size", "size"), &QuadMesh::set_size); - ClassDB::bind_method(D_METHOD("get_size"), &QuadMesh::get_size); - ClassDB::bind_method(D_METHOD("set_center_offset", "center_offset"), &QuadMesh::set_center_offset); - ClassDB::bind_method(D_METHOD("get_center_offset"), &QuadMesh::get_center_offset); - - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "suffix:m"), "set_size", "get_size"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_center_offset", "get_center_offset"); -} - -uint32_t QuadMesh::surface_get_format(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, 1, 0); - - return RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV; -} - -QuadMesh::QuadMesh() { - primitive_type = PRIMITIVE_TRIANGLES; -} - -void QuadMesh::set_size(const Size2 &p_size) { - size = p_size; - _request_update(); -} - -Size2 QuadMesh::get_size() const { - return size; -} - -void QuadMesh::set_center_offset(Vector3 p_center_offset) { - center_offset = p_center_offset; - _request_update(); -} - -Vector3 QuadMesh::get_center_offset() const { - return center_offset; -} - -/** SphereMesh */ diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index 64eefd2c07..3cf161db00 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -75,7 +75,7 @@ public: virtual int surface_get_array_len(int p_idx) const override; virtual int surface_get_array_index_len(int p_idx) const override; virtual Array surface_get_arrays(int p_surface) const override; - virtual Array surface_get_blend_shape_arrays(int p_surface) const override; + virtual TypedArray<Array> surface_get_blend_shape_arrays(int p_surface) const override; virtual Dictionary surface_get_lods(int p_surface) const override; virtual uint32_t surface_get_format(int p_idx) const override; virtual Mesh::PrimitiveType surface_get_primitive_type(int p_idx) const override; @@ -217,17 +217,25 @@ public: CylinderMesh(); }; -/** - Similar to quadmesh but with tessellation support +/* + A flat rectangle, can be used as quad or heightmap. */ class PlaneMesh : public PrimitiveMesh { GDCLASS(PlaneMesh, PrimitiveMesh); +public: + enum Orientation { + FACE_X, + FACE_Y, + FACE_Z, + }; + private: Size2 size = Size2(2.0, 2.0); int subdivide_w = 0; int subdivide_d = 0; Vector3 center_offset; + Orientation orientation = FACE_Y; protected: static void _bind_methods(); @@ -246,9 +254,14 @@ public: void set_center_offset(const Vector3 p_offset); Vector3 get_center_offset() const; + void set_orientation(const Orientation p_orientation); + Orientation get_orientation() const; + PlaneMesh(); }; +VARIANT_ENUM_CAST(PlaneMesh::Orientation) + /** A prism shapen, handy for ramps, triangles, etc. */ @@ -286,33 +299,6 @@ public: }; /** - Our original quadmesh... -*/ - -class QuadMesh : public PrimitiveMesh { - GDCLASS(QuadMesh, PrimitiveMesh); - -private: - Size2 size = Size2(1.0, 1.0); - Vector3 center_offset; - -protected: - static void _bind_methods(); - virtual void _create_mesh_array(Array &p_arr) const override; - -public: - virtual uint32_t surface_get_format(int p_idx) const override; - - QuadMesh(); - - void set_size(const Size2 &p_size); - Size2 get_size() const; - - void set_center_offset(const Vector3 p_offset); - Vector3 get_center_offset() const; -}; - -/** A sphere.. */ class SphereMesh : public PrimitiveMesh { diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp index 16ef45829f..fe43f345d4 100644 --- a/scene/resources/shape_2d.cpp +++ b/scene/resources/shape_2d.cpp @@ -59,39 +59,39 @@ bool Shape2D::collide(const Transform2D &p_local_xform, const Ref<Shape2D> &p_sh return PhysicsServer2D::get_singleton()->shape_collide(get_rid(), p_local_xform, Vector2(), p_shape->get_rid(), p_shape_xform, Vector2(), nullptr, 0, r); } -Array Shape2D::collide_with_motion_and_get_contacts(const Transform2D &p_local_xform, const Vector2 &p_local_motion, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform, const Vector2 &p_shape_motion) { - ERR_FAIL_COND_V(p_shape.is_null(), Array()); +PackedVector2Array Shape2D::collide_with_motion_and_get_contacts(const Transform2D &p_local_xform, const Vector2 &p_local_motion, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform, const Vector2 &p_shape_motion) { + ERR_FAIL_COND_V(p_shape.is_null(), PackedVector2Array()); const int max_contacts = 16; Vector2 result[max_contacts * 2]; int contacts = 0; if (!PhysicsServer2D::get_singleton()->shape_collide(get_rid(), p_local_xform, p_local_motion, p_shape->get_rid(), p_shape_xform, p_shape_motion, result, max_contacts, contacts)) { - return Array(); + return PackedVector2Array(); } - Array results; + PackedVector2Array results; results.resize(contacts * 2); for (int i = 0; i < contacts * 2; i++) { - results[i] = result[i]; + results.write[i] = result[i]; } return results; } -Array Shape2D::collide_and_get_contacts(const Transform2D &p_local_xform, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform) { - ERR_FAIL_COND_V(p_shape.is_null(), Array()); +PackedVector2Array Shape2D::collide_and_get_contacts(const Transform2D &p_local_xform, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform) { + ERR_FAIL_COND_V(p_shape.is_null(), PackedVector2Array()); const int max_contacts = 16; Vector2 result[max_contacts * 2]; int contacts = 0; if (!PhysicsServer2D::get_singleton()->shape_collide(get_rid(), p_local_xform, Vector2(), p_shape->get_rid(), p_shape_xform, Vector2(), result, max_contacts, contacts)) { - return Array(); + return PackedVector2Array(); } - Array results; + PackedVector2Array results; results.resize(contacts * 2); for (int i = 0; i < contacts * 2; i++) { - results[i] = result[i]; + results.write[i] = result[i]; } return results; diff --git a/scene/resources/shape_2d.h b/scene/resources/shape_2d.h index e9dc10eeae..a15aecee93 100644 --- a/scene/resources/shape_2d.h +++ b/scene/resources/shape_2d.h @@ -53,8 +53,8 @@ public: bool collide_with_motion(const Transform2D &p_local_xform, const Vector2 &p_local_motion, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform, const Vector2 &p_shape_motion); bool collide(const Transform2D &p_local_xform, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform); - Array collide_with_motion_and_get_contacts(const Transform2D &p_local_xform, const Vector2 &p_local_motion, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform, const Vector2 &p_shape_motion); - Array collide_and_get_contacts(const Transform2D &p_local_xform, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform); + PackedVector2Array collide_with_motion_and_get_contacts(const Transform2D &p_local_xform, const Vector2 &p_local_motion, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform, const Vector2 &p_shape_motion); + PackedVector2Array collide_and_get_contacts(const Transform2D &p_local_xform, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform); virtual void draw(const RID &p_to_rid, const Color &p_color) {} virtual Rect2 get_rect() const { return Rect2(); } diff --git a/scene/resources/skeleton_modification_3d_ccdik.h b/scene/resources/skeleton_modification_3d_ccdik.h index 7098794038..1fe53e94b6 100644 --- a/scene/resources/skeleton_modification_3d_ccdik.h +++ b/scene/resources/skeleton_modification_3d_ccdik.h @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef SKELETON_MODIFICATION_3D_CCDIK_H +#define SKELETON_MODIFICATION_3D_CCDIK_H + #include "core/templates/local_vector.h" #include "scene/3d/skeleton_3d.h" #include "scene/resources/skeleton_modification_3d.h" -#ifndef SKELETON_MODIFICATION_3D_CCDIK_H -#define SKELETON_MODIFICATION_3D_CCDIK_H - class SkeletonModification3DCCDIK : public SkeletonModification3D { GDCLASS(SkeletonModification3DCCDIK, SkeletonModification3D); diff --git a/scene/resources/skeleton_modification_3d_fabrik.h b/scene/resources/skeleton_modification_3d_fabrik.h index 3d66bb6d99..e2e490d636 100644 --- a/scene/resources/skeleton_modification_3d_fabrik.h +++ b/scene/resources/skeleton_modification_3d_fabrik.h @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef SKELETON_MODIFICATION_3D_FABRIK_H +#define SKELETON_MODIFICATION_3D_FABRIK_H + #include "core/templates/local_vector.h" #include "scene/3d/skeleton_3d.h" #include "scene/resources/skeleton_modification_3d.h" -#ifndef SKELETON_MODIFICATION_3D_FABRIK_H -#define SKELETON_MODIFICATION_3D_FABRIK_H - class SkeletonModification3DFABRIK : public SkeletonModification3D { GDCLASS(SkeletonModification3DFABRIK, SkeletonModification3D); diff --git a/scene/resources/skeleton_modification_3d_jiggle.h b/scene/resources/skeleton_modification_3d_jiggle.h index f41ffcd58d..bd1ee51d93 100644 --- a/scene/resources/skeleton_modification_3d_jiggle.h +++ b/scene/resources/skeleton_modification_3d_jiggle.h @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef SKELETON_MODIFICATION_3D_JIGGLE_H +#define SKELETON_MODIFICATION_3D_JIGGLE_H + #include "core/templates/local_vector.h" #include "scene/3d/skeleton_3d.h" #include "scene/resources/skeleton_modification_3d.h" -#ifndef SKELETON_MODIFICATION_3D_JIGGLE_H -#define SKELETON_MODIFICATION_3D_JIGGLE_H - class SkeletonModification3DJiggle : public SkeletonModification3D { GDCLASS(SkeletonModification3DJiggle, SkeletonModification3D); diff --git a/scene/resources/skeleton_modification_3d_lookat.h b/scene/resources/skeleton_modification_3d_lookat.h index 4e5714b5dc..cea63fc34f 100644 --- a/scene/resources/skeleton_modification_3d_lookat.h +++ b/scene/resources/skeleton_modification_3d_lookat.h @@ -28,12 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "scene/3d/skeleton_3d.h" -#include "scene/resources/skeleton_modification_3d.h" - #ifndef SKELETON_MODIFICATION_3D_LOOKAT_H #define SKELETON_MODIFICATION_3D_LOOKAT_H +#include "scene/3d/skeleton_3d.h" +#include "scene/resources/skeleton_modification_3d.h" + class SkeletonModification3DLookAt : public SkeletonModification3D { GDCLASS(SkeletonModification3DLookAt, SkeletonModification3D); diff --git a/scene/resources/skeleton_modification_3d_stackholder.h b/scene/resources/skeleton_modification_3d_stackholder.h index ae22099158..2071de5457 100644 --- a/scene/resources/skeleton_modification_3d_stackholder.h +++ b/scene/resources/skeleton_modification_3d_stackholder.h @@ -28,12 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "scene/3d/skeleton_3d.h" -#include "scene/resources/skeleton_modification_3d.h" - #ifndef SKELETON_MODIFICATION_3D_STACKHOLDER_H #define SKELETON_MODIFICATION_3D_STACKHOLDER_H +#include "scene/3d/skeleton_3d.h" +#include "scene/resources/skeleton_modification_3d.h" + class SkeletonModification3DStackHolder : public SkeletonModification3D { GDCLASS(SkeletonModification3DStackHolder, SkeletonModification3D); diff --git a/scene/resources/skeleton_modification_3d_twoboneik.h b/scene/resources/skeleton_modification_3d_twoboneik.h index 57e8237511..7bd7c8291d 100644 --- a/scene/resources/skeleton_modification_3d_twoboneik.h +++ b/scene/resources/skeleton_modification_3d_twoboneik.h @@ -28,12 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "scene/3d/skeleton_3d.h" -#include "scene/resources/skeleton_modification_3d.h" - #ifndef SKELETON_MODIFICATION_3D_TWOBONEIK_H #define SKELETON_MODIFICATION_3D_TWOBONEIK_H +#include "scene/3d/skeleton_3d.h" +#include "scene/resources/skeleton_modification_3d.h" + class SkeletonModification3DTwoBoneIK : public SkeletonModification3D { GDCLASS(SkeletonModification3DTwoBoneIK, SkeletonModification3D); diff --git a/scene/resources/skeleton_profile.cpp b/scene/resources/skeleton_profile.cpp index bfb4bb6e2b..1367ea86dd 100644 --- a/scene/resources/skeleton_profile.cpp +++ b/scene/resources/skeleton_profile.cpp @@ -121,26 +121,26 @@ bool SkeletonProfile::_get(const StringName &p_path, Variant &r_ret) const { return true; } -void SkeletonProfile::_validate_property(PropertyInfo &property) const { +void SkeletonProfile::_validate_property(PropertyInfo &p_property) const { if (is_read_only) { - if (property.name == ("group_size") || property.name == ("bone_size") || property.name == ("root_bone") || property.name == ("scale_base_bone")) { - property.usage = PROPERTY_USAGE_NO_EDITOR; + if (p_property.name == ("group_size") || p_property.name == ("bone_size") || p_property.name == ("root_bone") || p_property.name == ("scale_base_bone")) { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; return; } } - if (property.name == ("root_bone") || property.name == ("scale_base_bone")) { + if (p_property.name == ("root_bone") || p_property.name == ("scale_base_bone")) { String hint = ""; for (int i = 0; i < bones.size(); i++) { hint += i == 0 ? String(bones[i].bone_name) : "," + String(bones[i].bone_name); } - property.hint_string = hint; + p_property.hint_string = hint; } - PackedStringArray split = property.name.split("/"); + PackedStringArray split = p_property.name.split("/"); if (split.size() == 3 && split[0] == "bones") { if (split[2] == "bone_tail" && get_tail_direction(split[1].to_int()) != TAIL_DIRECTION_SPECIFIC_CHILD) { - property.usage = PROPERTY_USAGE_NONE; + p_property.usage = PROPERTY_USAGE_NONE; } } } @@ -506,7 +506,7 @@ SkeletonProfileHumanoid::SkeletonProfileHumanoid() { bones.write[5].reference_pose = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0); bones.write[5].handle_offset = Vector2(0.5, 0.23); bones.write[5].group = "Body"; - bones.write[5].require = true; + bones.write[5].require = false; bones.write[6].bone_name = "Head"; bones.write[6].bone_parent = "Neck"; diff --git a/scene/resources/skeleton_profile.h b/scene/resources/skeleton_profile.h index 84dfca458e..66344d954d 100644 --- a/scene/resources/skeleton_profile.h +++ b/scene/resources/skeleton_profile.h @@ -72,7 +72,7 @@ protected: bool _get(const StringName &p_path, Variant &r_ret) const; bool _set(const StringName &p_path, const Variant &p_value); - virtual void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; void _get_property_list(List<PropertyInfo> *p_list) const; static void _bind_methods(); diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp index a53c299d00..ff5210f1b3 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -842,9 +842,9 @@ float StyleBoxFlat::get_style_margin(Side p_side) const { return border_width[p_side]; } -void StyleBoxFlat::_validate_property(PropertyInfo &property) const { - if (!anti_aliased && property.name == "anti_aliasing_size") { - property.usage = PROPERTY_USAGE_NO_EDITOR; +void StyleBoxFlat::_validate_property(PropertyInfo &p_property) const { + if (!anti_aliased && p_property.name == "anti_aliasing_size") { + p_property.usage = PROPERTY_USAGE_NO_EDITOR; } } diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h index 9f4f69d3ba..88db4f5fbd 100644 --- a/scene/resources/style_box.h +++ b/scene/resources/style_box.h @@ -166,7 +166,7 @@ class StyleBoxFlat : public StyleBox { protected: virtual float get_style_margin(Side p_side) const override; static void _bind_methods(); - void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; public: void set_bg_color(const Color &p_color); diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 05ed9238b8..25f5006c4f 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -35,8 +35,8 @@ #include "core/io/marshalls.h" #include "core/math/geometry_2d.h" #include "core/os/os.h" -#include "mesh.h" #include "scene/resources/bit_map.h" +#include "scene/resources/mesh.h" #include "servers/camera/camera_feed.h" int Texture2D::get_width() const { int ret; @@ -1038,7 +1038,7 @@ void CompressedTexture2D::reload_from_file() { load(path); } -void CompressedTexture2D::_validate_property(PropertyInfo &property) const { +void CompressedTexture2D::_validate_property(PropertyInfo &p_property) const { } void CompressedTexture2D::_bind_methods() { @@ -1394,7 +1394,7 @@ void CompressedTexture3D::reload_from_file() { load(path); } -void CompressedTexture3D::_validate_property(PropertyInfo &property) const { +void CompressedTexture3D::_validate_property(PropertyInfo &p_property) const { } void CompressedTexture3D::_bind_methods() { @@ -2537,13 +2537,6 @@ void GradientTexture2D::_bind_methods() { ////////////////////////////////////// -void ProxyTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_base", "base"), &ProxyTexture::set_base); - ClassDB::bind_method(D_METHOD("get_base"), &ProxyTexture::get_base); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "base", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_base", "get_base"); -} - void ProxyTexture::set_base(const Ref<Texture2D> &p_texture) { ERR_FAIL_COND(p_texture == this); @@ -2796,12 +2789,12 @@ bool AnimatedTexture::is_pixel_opaque(int p_x, int p_y) const { return true; } -void AnimatedTexture::_validate_property(PropertyInfo &property) const { - String prop = property.name; +void AnimatedTexture::_validate_property(PropertyInfo &p_property) const { + String prop = p_property.name; if (prop.begins_with("frame_")) { int frame = prop.get_slicec('/', 0).get_slicec('_', 1).to_int(); if (frame >= frame_count) { - property.usage = PROPERTY_USAGE_NONE; + p_property.usage = PROPERTY_USAGE_NONE; } } } @@ -3221,7 +3214,7 @@ void CompressedTextureLayered::reload_from_file() { load(path); } -void CompressedTextureLayered::_validate_property(PropertyInfo &property) const { +void CompressedTextureLayered::_validate_property(PropertyInfo &p_property) const { } void CompressedTextureLayered::_bind_methods() { diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 36b193c5d4..133b312d27 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -251,7 +251,7 @@ private: protected: static void _bind_methods(); - void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; public: static Ref<Image> load_image_from_file(Ref<FileAccess> p_file, int p_size_limit); @@ -506,7 +506,7 @@ private: protected: static void _bind_methods(); - void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; public: Image::Format get_format() const override; @@ -651,7 +651,7 @@ private: protected: static void _bind_methods(); - void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; public: Image::Format get_format() const override; @@ -883,8 +883,6 @@ VARIANT_ENUM_CAST(GradientTexture2D::Fill); VARIANT_ENUM_CAST(GradientTexture2D::Repeat); class ProxyTexture : public Texture2D { - GDCLASS(ProxyTexture, Texture2D); - private: mutable RID proxy_ph; mutable RID proxy; @@ -942,7 +940,7 @@ private: protected: static void _bind_methods(); - void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; public: void set_frames(int p_frames); diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index b0b9f1228f..552d856034 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -3302,11 +3302,11 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { } } -void TileSet::_validate_property(PropertyInfo &property) const { - if (property.name == "tile_layout" && tile_shape == TILE_SHAPE_SQUARE) { - property.usage ^= PROPERTY_USAGE_READ_ONLY; - } else if (property.name == "tile_offset_axis" && tile_shape == TILE_SHAPE_SQUARE) { - property.usage ^= PROPERTY_USAGE_READ_ONLY; +void TileSet::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "tile_layout" && tile_shape == TILE_SHAPE_SQUARE) { + p_property.usage ^= PROPERTY_USAGE_READ_ONLY; + } else if (p_property.name == "tile_offset_axis" && tile_shape == TILE_SHAPE_SQUARE) { + p_property.usage ^= PROPERTY_USAGE_READ_ONLY; } } diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index 6ea3889fce..4c0823cdf2 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -295,7 +295,7 @@ protected: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List<PropertyInfo> *p_list) const; - virtual void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; private: // --- TileSet data --- diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index a67716d52b..90f1a1bff1 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -1036,11 +1036,11 @@ void VisualShader::disconnect_nodes(Type p_type, int p_from_node, int p_from_por } } -Array VisualShader::_get_node_connections(Type p_type) const { +TypedArray<Dictionary> VisualShader::_get_node_connections(Type p_type) const { ERR_FAIL_INDEX_V(p_type, TYPE_MAX, Array()); const Graph *g = &graph[p_type]; - Array ret; + TypedArray<Dictionary> ret; for (const Connection &E : g->connections) { Dictionary d; d["from_node"] = E.from_node; @@ -1698,13 +1698,13 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui inputs[i] = "(" + src_var + " ? 1.0 : 0.0)"; } break; case VisualShaderNode::PORT_TYPE_VECTOR_2D: { - inputs[i] = "dot(" + src_var + ", vec2(0.5, 0.5))"; + inputs[i] = src_var + ".x"; } break; case VisualShaderNode::PORT_TYPE_VECTOR_3D: { - inputs[i] = "dot(" + src_var + ", vec3(0.333333, 0.333333, 0.333333))"; + inputs[i] = src_var + ".x"; } break; case VisualShaderNode::PORT_TYPE_VECTOR_4D: { - inputs[i] = "dot(" + src_var + ", vec4(0.25, 0.25, 0.25, 0.25))"; + inputs[i] = src_var + ".x"; } break; default: break; @@ -2214,6 +2214,12 @@ void VisualShader::_update_shader() const { case VaryingType::VARYING_TYPE_FLOAT: global_code += "float "; break; + case VaryingType::VARYING_TYPE_INT: + if (E.value.mode == VaryingMode::VARYING_MODE_VERTEX_TO_FRAG_LIGHT) { + global_code += "flat "; + } + global_code += "int "; + break; case VaryingType::VARYING_TYPE_VECTOR_2D: global_code += "vec2 "; break; @@ -2223,8 +2229,11 @@ void VisualShader::_update_shader() const { case VaryingType::VARYING_TYPE_VECTOR_4D: global_code += "vec4 "; break; - case VaryingType::VARYING_TYPE_COLOR: - global_code += "vec4 "; + case VaryingType::VARYING_TYPE_BOOLEAN: + if (E.value.mode == VaryingMode::VARYING_MODE_VERTEX_TO_FRAG_LIGHT) { + global_code += "flat "; + } + global_code += "bool "; break; case VaryingType::VARYING_TYPE_TRANSFORM: global_code += "mat4 "; @@ -2277,6 +2286,9 @@ void VisualShader::_update_shader() const { case VaryingType::VARYING_TYPE_FLOAT: code2 += "0.0"; break; + case VaryingType::VARYING_TYPE_INT: + code2 += "0"; + break; case VaryingType::VARYING_TYPE_VECTOR_2D: code2 += "vec2(0.0)"; break; @@ -2286,8 +2298,8 @@ void VisualShader::_update_shader() const { case VaryingType::VARYING_TYPE_VECTOR_4D: code2 += "vec4(0.0)"; break; - case VaryingType::VARYING_TYPE_COLOR: - code2 += "vec4(0.0)"; + case VaryingType::VARYING_TYPE_BOOLEAN: + code2 += "false"; break; case VaryingType::VARYING_TYPE_TRANSFORM: code2 += "mat4(1.0)"; @@ -2585,10 +2597,11 @@ void VisualShader::_bind_methods() { BIND_ENUM_CONSTANT(VARYING_MODE_MAX); BIND_ENUM_CONSTANT(VARYING_TYPE_FLOAT); + BIND_ENUM_CONSTANT(VARYING_TYPE_INT); BIND_ENUM_CONSTANT(VARYING_TYPE_VECTOR_2D); BIND_ENUM_CONSTANT(VARYING_TYPE_VECTOR_3D); BIND_ENUM_CONSTANT(VARYING_TYPE_VECTOR_4D); - BIND_ENUM_CONSTANT(VARYING_TYPE_COLOR); + BIND_ENUM_CONSTANT(VARYING_TYPE_BOOLEAN); BIND_ENUM_CONSTANT(VARYING_TYPE_TRANSFORM); BIND_ENUM_CONSTANT(VARYING_TYPE_MAX); @@ -3153,8 +3166,8 @@ String VisualShaderNodeInput::get_input_index_name(int p_index) const { return ""; } -void VisualShaderNodeInput::_validate_property(PropertyInfo &property) const { - if (property.name == "input_name") { +void VisualShaderNodeInput::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "input_name") { String port_list; int idx = 0; @@ -3172,7 +3185,7 @@ void VisualShaderNodeInput::_validate_property(PropertyInfo &property) const { if (port_list.is_empty()) { port_list = RTR("None"); } - property.hint_string = port_list; + p_property.hint_string = port_list; } } @@ -4632,21 +4645,23 @@ void VisualShaderNodeVarying::_bind_methods() { ClassDB::bind_method(D_METHOD("get_varying_type"), &VisualShaderNodeVarying::get_varying_type); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "varying_name"), "set_varying_name", "get_varying_name"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "varying_type", PROPERTY_HINT_ENUM, "Float,Vector,Transform"), "set_varying_type", "get_varying_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "varying_type", PROPERTY_HINT_ENUM, "Float,Int,Vector2,Vector3,Vector4,Boolean,Transform"), "set_varying_type", "get_varying_type"); } String VisualShaderNodeVarying::get_type_str() const { switch (varying_type) { case VisualShader::VARYING_TYPE_FLOAT: return "float"; + case VisualShader::VARYING_TYPE_INT: + return "int"; case VisualShader::VARYING_TYPE_VECTOR_2D: return "vec2"; case VisualShader::VARYING_TYPE_VECTOR_3D: return "vec3"; case VisualShader::VARYING_TYPE_VECTOR_4D: return "vec4"; - case VisualShader::VARYING_TYPE_COLOR: - return "vec4"; + case VisualShader::VARYING_TYPE_BOOLEAN: + return "bool"; case VisualShader::VARYING_TYPE_TRANSFORM: return "mat4"; default: @@ -4657,17 +4672,16 @@ String VisualShaderNodeVarying::get_type_str() const { VisualShaderNodeVarying::PortType VisualShaderNodeVarying::get_port_type(VisualShader::VaryingType p_type, int p_port) const { switch (p_type) { + case VisualShader::VARYING_TYPE_INT: + return PORT_TYPE_SCALAR_INT; case VisualShader::VARYING_TYPE_VECTOR_2D: return PORT_TYPE_VECTOR_2D; case VisualShader::VARYING_TYPE_VECTOR_3D: return PORT_TYPE_VECTOR_3D; case VisualShader::VARYING_TYPE_VECTOR_4D: return PORT_TYPE_VECTOR_4D; - case VisualShader::VARYING_TYPE_COLOR: - if (p_port == 1) { - break; // scalar - } - return PORT_TYPE_VECTOR_3D; + case VisualShader::VARYING_TYPE_BOOLEAN: + return PORT_TYPE_BOOLEAN; case VisualShader::VARYING_TYPE_TRANSFORM: return PORT_TYPE_TRANSFORM; default: @@ -4711,9 +4725,6 @@ String VisualShaderNodeVaryingSetter::get_caption() const { } int VisualShaderNodeVaryingSetter::get_input_port_count() const { - if (varying_type == VisualShader::VARYING_TYPE_COLOR) { - return 2; - } return 1; } @@ -4722,13 +4733,6 @@ VisualShaderNodeVaryingSetter::PortType VisualShaderNodeVaryingSetter::get_input } String VisualShaderNodeVaryingSetter::get_input_port_name(int p_port) const { - if (varying_type == VisualShader::VARYING_TYPE_COLOR) { - if (p_port == 0) { - return "color"; - } else { - return "alpha"; - } - } return ""; } @@ -4744,20 +4748,12 @@ String VisualShaderNodeVaryingSetter::get_output_port_name(int p_port) const { return ""; } -String VisualShaderNodeVaryingSetter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - return vformat("varying %s %s;\n", get_type_str(), varying_name); -} - String VisualShaderNodeVaryingSetter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { String code; if (varying_name == "[None]") { return code; } - if (varying_type == VisualShader::VARYING_TYPE_COLOR) { - code += vformat(" %s = vec4(%s, %s);\n", varying_name, p_input_vars[0], p_input_vars[1]); - } else { - code += vformat(" %s = %s;\n", varying_name, p_input_vars[0]); - } + code += vformat(" %s = %s;\n", varying_name, p_input_vars[0]); return code; } @@ -4783,9 +4779,6 @@ String VisualShaderNodeVaryingGetter::get_input_port_name(int p_port) const { } int VisualShaderNodeVaryingGetter::get_output_port_count() const { - if (varying_type == VisualShader::VARYING_TYPE_COLOR) { - return 2; - } return 1; } @@ -4794,13 +4787,6 @@ VisualShaderNodeVaryingGetter::PortType VisualShaderNodeVaryingGetter::get_outpu } String VisualShaderNodeVaryingGetter::get_output_port_name(int p_port) const { - if (varying_type == VisualShader::VARYING_TYPE_COLOR) { - if (p_port == 0) { - return "color"; - } else { - return "alpha"; - } - } return ""; } @@ -4817,6 +4803,9 @@ String VisualShaderNodeVaryingGetter::generate_code(Shader::Mode p_mode, VisualS case VisualShader::VARYING_TYPE_FLOAT: from = "0.0"; break; + case VisualShader::VARYING_TYPE_INT: + from = "0"; + break; case VisualShader::VARYING_TYPE_VECTOR_2D: from = "vec2(0.0)"; break; @@ -4826,9 +4815,8 @@ String VisualShaderNodeVaryingGetter::generate_code(Shader::Mode p_mode, VisualS case VisualShader::VARYING_TYPE_VECTOR_4D: from = "vec4(0.0)"; break; - case VisualShader::VARYING_TYPE_COLOR: - from = "vec3(0.0)"; - from2 = "0.0"; + case VisualShader::VARYING_TYPE_BOOLEAN: + from = "false"; break; case VisualShader::VARYING_TYPE_TRANSFORM: from = "mat4(1.0)"; @@ -4836,16 +4824,6 @@ String VisualShaderNodeVaryingGetter::generate_code(Shader::Mode p_mode, VisualS default: break; } - } else if (varying_type == VisualShader::VARYING_TYPE_COLOR) { - from = varying_name + ".rgb"; - from2 = varying_name + ".a"; - } - - if (varying_type == VisualShader::VARYING_TYPE_COLOR) { - String code; - code += vformat(" %s = %s;\n", p_output_vars[0], from); - code += vformat(" %s = %s;\n", p_output_vars[1], from2); - return code; } return vformat(" %s = %s;\n", p_output_vars[0], from); } diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 7ca4e5fc4a..09a3917a16 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -79,10 +79,11 @@ public: enum VaryingType { VARYING_TYPE_FLOAT, + VARYING_TYPE_INT, VARYING_TYPE_VECTOR_2D, VARYING_TYPE_VECTOR_3D, VARYING_TYPE_VECTOR_4D, - VARYING_TYPE_COLOR, + VARYING_TYPE_BOOLEAN, VARYING_TYPE_TRANSFORM, VARYING_TYPE_MAX, }; @@ -132,7 +133,7 @@ private: Shader::Mode shader_mode = Shader::MODE_SPATIAL; mutable String previous_code; - Array _get_node_connections(Type p_type) const; + TypedArray<Dictionary> _get_node_connections(Type p_type) const; Vector2 graph_offset; @@ -428,7 +429,7 @@ public: protected: static void _bind_methods(); - void _validate_property(PropertyInfo &property) const override; + void _validate_property(PropertyInfo &p_property) const; public: virtual int get_input_port_count() const override; @@ -828,7 +829,6 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; VisualShaderNodeVaryingSetter(); diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index b422d298b2..2911d726b4 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -1015,7 +1015,7 @@ Vector<StringName> VisualShaderNodeCurveTexture::get_editable_properties() const } String VisualShaderNodeCurveTexture::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - return "uniform sampler2D " + make_unique_id(p_type, p_id, "curve") + ";\n"; + return "uniform sampler2D " + make_unique_id(p_type, p_id, "curve") + " : repeat_disable;\n"; } String VisualShaderNodeCurveTexture::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { @@ -6830,23 +6830,23 @@ void VisualShaderNodeMultiplyAdd::set_op_type(OpType p_op_type) { switch (p_op_type) { case OP_TYPE_SCALAR: { set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); - set_input_port_default_value(1, 0.0, get_input_port_default_value(1)); + set_input_port_default_value(1, 1.0, get_input_port_default_value(1)); set_input_port_default_value(2, 0.0, get_input_port_default_value(2)); } break; case OP_TYPE_VECTOR_2D: { set_input_port_default_value(0, Vector2(), get_input_port_default_value(0)); - set_input_port_default_value(1, Vector2(), get_input_port_default_value(1)); + set_input_port_default_value(1, Vector2(1.0, 1.0), get_input_port_default_value(1)); set_input_port_default_value(2, Vector2(), get_input_port_default_value(2)); } break; case OP_TYPE_VECTOR_3D: { set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); - set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); + set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0), get_input_port_default_value(1)); set_input_port_default_value(2, Vector3(), get_input_port_default_value(2)); } break; case OP_TYPE_VECTOR_4D: { - set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0)); - set_input_port_default_value(1, Quaternion(), get_input_port_default_value(1)); - set_input_port_default_value(2, Quaternion(), get_input_port_default_value(2)); + set_input_port_default_value(0, Vector4(), get_input_port_default_value(0)); + set_input_port_default_value(1, Vector4(1.0, 1.0, 1.0, 1.0), get_input_port_default_value(1)); + set_input_port_default_value(2, Vector4(), get_input_port_default_value(2)); } break; default: break; @@ -6880,7 +6880,7 @@ void VisualShaderNodeMultiplyAdd::_bind_methods() { VisualShaderNodeMultiplyAdd::VisualShaderNodeMultiplyAdd() { set_input_port_default_value(0, 0.0); - set_input_port_default_value(1, 0.0); + set_input_port_default_value(1, 1.0); set_input_port_default_value(2, 0.0); } |