diff options
Diffstat (limited to 'scene/resources')
122 files changed, 14583 insertions, 10466 deletions
diff --git a/scene/resources/SCsub b/scene/resources/SCsub index 5e5b6f8fd5..3a86b22835 100644 --- a/scene/resources/SCsub +++ b/scene/resources/SCsub @@ -1,6 +1,6 @@ #!/usr/bin/env python -Import('env') +Import("env") env.add_source_files(env.scene_sources, "*.cpp") diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 91d1e32053..b8edd70712 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -31,43 +31,33 @@ #include "animation.h" #include "scene/scene_string_names.h" -#include "core/math/geometry.h" +#include "core/math/geometry_3d.h" #define ANIM_MIN_LENGTH 0.001 bool Animation::_set(const StringName &p_name, const Variant &p_value) { - String name = p_name; if (name.begins_with("tracks/")) { - int track = name.get_slicec('/', 1).to_int(); String what = name.get_slicec('/', 2); if (tracks.size() == track && what == "type") { - String type = p_value; if (type == "transform") { - add_track(TYPE_TRANSFORM); } else if (type == "value") { - add_track(TYPE_VALUE); } else if (type == "method") { - add_track(TYPE_METHOD); } else if (type == "bezier") { - add_track(TYPE_BEZIER); } else if (type == "audio") { - add_track(TYPE_AUDIO); } else if (type == "animation") { - add_track(TYPE_ANIMATION); } else { - return false; } @@ -76,31 +66,28 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { ERR_FAIL_INDEX_V(track, tracks.size(), false); - if (what == "path") + if (what == "path") { track_set_path(track, p_value); - else if (what == "interp") + } else if (what == "interp") { track_set_interpolation_type(track, InterpolationType(p_value.operator int())); - else if (what == "loop_wrap") + } else if (what == "loop_wrap") { track_set_interpolation_loop_wrap(track, p_value); - else if (what == "imported") + } else if (what == "imported") { track_set_imported(track, p_value); - else if (what == "enabled") + } else if (what == "enabled") { track_set_enabled(track, p_value); - else if (what == "keys" || what == "key_values") { - + } else if (what == "keys" || what == "key_values") { if (track_get_type(track) == TYPE_TRANSFORM) { - TransformTrack *tt = static_cast<TransformTrack *>(tracks[track]); - PoolVector<float> values = p_value; + Vector<float> values = p_value; int vcount = values.size(); ERR_FAIL_COND_V(vcount % 12, false); // should be multiple of 11 - PoolVector<float>::Read r = values.read(); + const float *r = values.ptr(); tt->transforms.resize(vcount / 12); for (int i = 0; i < (vcount / 12); i++) { - TKey<TransformKey> &tk = tt->transforms.write[i]; const float *ofs = &r[i * 12]; tk.time = ofs[0]; @@ -121,7 +108,6 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { } } else if (track_get_type(track) == TYPE_VALUE) { - ValueTrack *vt = static_cast<ValueTrack *>(tracks[track]); Dictionary d = p_value; ERR_FAIL_COND_V(!d.has("times"), false); @@ -133,41 +119,38 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { if (d.has("update")) { int um = d["update"]; - if (um < 0) + if (um < 0) { um = 0; - else if (um > 3) + } else if (um > 3) { um = 3; + } vt->update_mode = UpdateMode(um); } - PoolVector<float> times = d["times"]; + Vector<float> times = d["times"]; Array values = d["values"]; ERR_FAIL_COND_V(times.size() != values.size(), false); if (times.size()) { - int valcount = times.size(); - PoolVector<float>::Read rt = times.read(); + const float *rt = times.ptr(); vt->values.resize(valcount); for (int i = 0; i < valcount; i++) { - vt->values.write[i].time = rt[i]; vt->values.write[i].value = values[i]; } if (d.has("transitions")) { - - PoolVector<float> transitions = d["transitions"]; + Vector<float> transitions = d["transitions"]; ERR_FAIL_COND_V(transitions.size() != valcount, false); - PoolVector<float>::Read rtr = transitions.read(); + const float *rtr = transitions.ptr(); for (int i = 0; i < valcount; i++) { - vt->values.write[i].transition = rtr[i]; } } @@ -176,66 +159,59 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { return true; } else if (track_get_type(track) == TYPE_METHOD) { - - while (track_get_key_count(track)) + while (track_get_key_count(track)) { track_remove_key(track, 0); //well shouldn't be set anyway + } Dictionary d = p_value; ERR_FAIL_COND_V(!d.has("times"), false); ERR_FAIL_COND_V(!d.has("values"), false); - PoolVector<float> times = d["times"]; + Vector<float> times = d["times"]; Array values = d["values"]; ERR_FAIL_COND_V(times.size() != values.size(), false); if (times.size()) { - int valcount = times.size(); - PoolVector<float>::Read rt = times.read(); + const float *rt = times.ptr(); for (int i = 0; i < valcount; i++) { - track_insert_key(track, rt[i], values[i]); } if (d.has("transitions")) { - - PoolVector<float> transitions = d["transitions"]; + Vector<float> transitions = d["transitions"]; ERR_FAIL_COND_V(transitions.size() != valcount, false); - PoolVector<float>::Read rtr = transitions.read(); + const float *rtr = transitions.ptr(); for (int i = 0; i < valcount; i++) { - track_set_key_transition(track, i, rtr[i]); } } } } else if (track_get_type(track) == TYPE_BEZIER) { - BezierTrack *bt = static_cast<BezierTrack *>(tracks[track]); Dictionary d = p_value; ERR_FAIL_COND_V(!d.has("times"), false); ERR_FAIL_COND_V(!d.has("points"), false); - PoolVector<float> times = d["times"]; - PoolRealArray values = d["points"]; + Vector<float> times = d["times"]; + PackedFloat32Array values = d["points"]; ERR_FAIL_COND_V(times.size() * 5 != values.size(), false); if (times.size()) { - int valcount = times.size(); - PoolVector<float>::Read rt = times.read(); - PoolVector<float>::Read rv = values.read(); + const float *rt = times.ptr(); + const float *rv = values.ptr(); 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 * 5 + 0]; @@ -248,34 +224,34 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { return true; } else if (track_get_type(track) == TYPE_AUDIO) { - AudioTrack *ad = static_cast<AudioTrack *>(tracks[track]); Dictionary d = p_value; ERR_FAIL_COND_V(!d.has("times"), false); ERR_FAIL_COND_V(!d.has("clips"), false); - PoolVector<float> times = d["times"]; + Vector<float> times = d["times"]; Array clips = d["clips"]; ERR_FAIL_COND_V(clips.size() != times.size(), false); if (times.size()) { - int valcount = times.size(); - PoolVector<float>::Read rt = times.read(); + const float *rt = times.ptr(); ad->values.clear(); for (int i = 0; i < valcount; i++) { - Dictionary d2 = clips[i]; - if (!d2.has("start_offset")) + if (!d2.has("start_offset")) { continue; - if (!d2.has("end_offset")) + } + if (!d2.has("end_offset")) { continue; - if (!d2.has("stream")) + } + if (!d2.has("stream")) { continue; + } TKey<AudioKey> ak; ak.time = rt[i]; @@ -289,28 +265,25 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { return true; } else if (track_get_type(track) == TYPE_ANIMATION) { - AnimationTrack *an = static_cast<AnimationTrack *>(tracks[track]); Dictionary d = p_value; ERR_FAIL_COND_V(!d.has("times"), false); ERR_FAIL_COND_V(!d.has("clips"), false); - PoolVector<float> times = d["times"]; - PoolVector<String> clips = d["clips"]; + Vector<float> times = d["times"]; + Vector<String> clips = d["clips"]; ERR_FAIL_COND_V(clips.size() != times.size(), false); if (times.size()) { - int valcount = times.size(); - PoolVector<float>::Read rt = times.read(); - PoolVector<String>::Read rc = clips.read(); + const float *rt = times.ptr(); + const String *rc = clips.ptr(); an->values.resize(valcount); for (int i = 0; i < valcount; i++) { - TKey<StringName> ak; ak.time = rt[i]; ak.value = rc[i]; @@ -322,66 +295,73 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { } else { return false; } - } else + } else { return false; - } else + } + } else { return false; + } return true; } bool Animation::_get(const StringName &p_name, Variant &r_ret) const { - String name = p_name; - if (name == "length") + if (name == "length") { r_ret = length; - else if (name == "loop") + } else if (name == "loop") { r_ret = loop; - else if (name == "step") + } else if (name == "step") { r_ret = step; - else if (name.begins_with("tracks/")) { - + } else if (name.begins_with("tracks/")) { int track = name.get_slicec('/', 1).to_int(); String what = name.get_slicec('/', 2); ERR_FAIL_INDEX_V(track, tracks.size(), false); if (what == "type") { - switch (track_get_type(track)) { - - case TYPE_TRANSFORM: r_ret = "transform"; break; - case TYPE_VALUE: r_ret = "value"; break; - case TYPE_METHOD: r_ret = "method"; break; - case TYPE_BEZIER: r_ret = "bezier"; break; - case TYPE_AUDIO: r_ret = "audio"; break; - case TYPE_ANIMATION: r_ret = "animation"; break; + case TYPE_TRANSFORM: + r_ret = "transform"; + break; + case TYPE_VALUE: + r_ret = "value"; + break; + case TYPE_METHOD: + r_ret = "method"; + break; + case TYPE_BEZIER: + r_ret = "bezier"; + break; + case TYPE_AUDIO: + r_ret = "audio"; + break; + case TYPE_ANIMATION: + r_ret = "animation"; + break; } return true; - } else if (what == "path") + } else if (what == "path") { r_ret = track_get_path(track); - else if (what == "interp") + } else if (what == "interp") { r_ret = track_get_interpolation_type(track); - else if (what == "loop_wrap") + } else if (what == "loop_wrap") { r_ret = track_get_interpolation_loop_wrap(track); - else if (what == "imported") + } else if (what == "imported") { r_ret = track_is_imported(track); - else if (what == "enabled") + } else if (what == "enabled") { r_ret = track_is_enabled(track); - else if (what == "keys") { - + } else if (what == "keys") { if (track_get_type(track) == TYPE_TRANSFORM) { - - PoolVector<real_t> keys; + Vector<float> keys; int kk = track_get_key_count(track); keys.resize(kk * 12); - PoolVector<real_t>::Write w = keys.write(); + real_t *w = keys.ptrw(); int idx = 0; for (int i = 0; i < track_get_key_count(track); i++) { - Vector3 loc; Quat rot; Vector3 scale; @@ -403,18 +383,16 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { w[idx++] = scale.z; } - w.release(); r_ret = keys; return true; } else if (track_get_type(track) == TYPE_VALUE) { - const ValueTrack *vt = static_cast<const ValueTrack *>(tracks[track]); Dictionary d; - PoolVector<float> key_times; - PoolVector<float> key_transitions; + Vector<float> key_times; + Vector<float> key_transitions; Array key_values; int kk = vt->values.size(); @@ -423,24 +401,20 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { key_transitions.resize(kk); key_values.resize(kk); - PoolVector<float>::Write wti = key_times.write(); - PoolVector<float>::Write wtr = key_transitions.write(); + float *wti = key_times.ptrw(); + float *wtr = key_transitions.ptrw(); int idx = 0; const TKey<Variant> *vls = vt->values.ptr(); for (int i = 0; i < kk; i++) { - wti[idx] = vls[i].time; wtr[idx] = vls[i].transition; key_values[idx] = vls[i].value; idx++; } - wti.release(); - wtr.release(); - d["times"] = key_times; d["transitions"] = key_transitions; d["values"] = key_values; @@ -453,11 +427,10 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { return true; } else if (track_get_type(track) == TYPE_METHOD) { - Dictionary d; - PoolVector<float> key_times; - PoolVector<float> key_transitions; + Vector<float> key_times; + Vector<float> key_transitions; Array key_values; int kk = track_get_key_count(track); @@ -466,21 +439,17 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { key_transitions.resize(kk); key_values.resize(kk); - PoolVector<float>::Write wti = key_times.write(); - PoolVector<float>::Write wtr = key_transitions.write(); + float *wti = key_times.ptrw(); + float *wtr = key_transitions.ptrw(); int idx = 0; for (int i = 0; i < track_get_key_count(track); i++) { - wti[idx] = track_get_key_time(track, i); wtr[idx] = track_get_key_transition(track, i); key_values[idx] = track_get_key_value(track, i); idx++; } - wti.release(); - wtr.release(); - d["times"] = key_times; d["transitions"] = key_transitions; d["values"] = key_values; @@ -492,28 +461,26 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { return true; } else if (track_get_type(track) == TYPE_BEZIER) { - const BezierTrack *bt = static_cast<const BezierTrack *>(tracks[track]); Dictionary d; - PoolVector<float> key_times; - PoolVector<float> key_points; + Vector<float> key_times; + Vector<float> key_points; int kk = bt->values.size(); key_times.resize(kk); key_points.resize(kk * 5); - PoolVector<float>::Write wti = key_times.write(); - PoolVector<float>::Write wpo = key_points.write(); + float *wti = key_times.ptrw(); + float *wpo = key_points.ptrw(); int idx = 0; const TKey<BezierKey> *vls = bt->values.ptr(); for (int i = 0; i < kk; i++) { - wti[idx] = vls[i].time; wpo[idx * 5 + 0] = vls[i].value.value; wpo[idx * 5 + 1] = vls[i].value.in_handle.x; @@ -523,9 +490,6 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { idx++; } - wti.release(); - wpo.release(); - d["times"] = key_times; d["points"] = key_points; @@ -533,26 +497,24 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { return true; } else if (track_get_type(track) == TYPE_AUDIO) { - const AudioTrack *ad = static_cast<const AudioTrack *>(tracks[track]); Dictionary d; - PoolVector<float> key_times; + Vector<float> key_times; Array clips; int kk = ad->values.size(); key_times.resize(kk); - PoolVector<float>::Write wti = key_times.write(); + float *wti = key_times.ptrw(); int idx = 0; const TKey<AudioKey> *vls = ad->values.ptr(); for (int i = 0; i < kk; i++) { - wti[idx] = vls[i].time; Dictionary clip; clip["start_offset"] = vls[i].value.start_offset; @@ -562,8 +524,6 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { idx++; } - wti.release(); - d["times"] = key_times; d["clips"] = clips; @@ -571,33 +531,28 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { return true; } else if (track_get_type(track) == TYPE_ANIMATION) { - const AnimationTrack *an = static_cast<const AnimationTrack *>(tracks[track]); Dictionary d; - PoolVector<float> key_times; - PoolVector<String> clips; + Vector<float> key_times; + Vector<String> clips; int kk = an->values.size(); key_times.resize(kk); clips.resize(kk); - PoolVector<float>::Write wti = key_times.write(); - PoolVector<String>::Write wcl = clips.write(); + float *wti = key_times.ptrw(); + String *wcl = clips.ptrw(); const TKey<StringName> *vls = an->values.ptr(); for (int i = 0; i < kk; i++) { - wti[i] = vls[i].time; wcl[i] = vls[i].value; } - wti.release(); - wcl.release(); - d["times"] = key_times; d["clips"] = clips; @@ -605,17 +560,18 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const { return true; } - } else + } else { return false; - } else + } + } else { return false; + } return true; } void Animation::_get_property_list(List<PropertyInfo> *p_list) const { for (int i = 0; i < tracks.size(); i++) { - p_list->push_back(PropertyInfo(Variant::STRING, "tracks/" + itos(i) + "/type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::NODE_PATH, "tracks/" + itos(i) + "/path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::INT, "tracks/" + itos(i) + "/interp", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); @@ -627,44 +583,36 @@ void Animation::_get_property_list(List<PropertyInfo> *p_list) const { } int Animation::add_track(TrackType p_type, int p_at_pos) { - - if (p_at_pos < 0 || p_at_pos >= tracks.size()) + if (p_at_pos < 0 || p_at_pos >= tracks.size()) { p_at_pos = tracks.size(); + } switch (p_type) { - case TYPE_TRANSFORM: { - TransformTrack *tt = memnew(TransformTrack); tracks.insert(p_at_pos, tt); } break; case TYPE_VALUE: { - tracks.insert(p_at_pos, memnew(ValueTrack)); } break; case TYPE_METHOD: { - tracks.insert(p_at_pos, memnew(MethodTrack)); } break; case TYPE_BEZIER: { - tracks.insert(p_at_pos, memnew(BezierTrack)); } break; case TYPE_AUDIO: { - tracks.insert(p_at_pos, memnew(AudioTrack)); } break; case TYPE_ANIMATION: { - tracks.insert(p_at_pos, memnew(AnimationTrack)); } break; default: { - ERR_PRINT("Unknown track type"); } } @@ -674,44 +622,36 @@ int Animation::add_track(TrackType p_type, int p_at_pos) { } void Animation::remove_track(int p_track) { - ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; switch (t->type) { - case TYPE_TRANSFORM: { - TransformTrack *tt = static_cast<TransformTrack *>(t); _clear(tt->transforms); } break; case TYPE_VALUE: { - ValueTrack *vt = static_cast<ValueTrack *>(t); _clear(vt->values); } break; case TYPE_METHOD: { - MethodTrack *mt = static_cast<MethodTrack *>(t); _clear(mt->methods); } break; case TYPE_BEZIER: { - BezierTrack *bz = static_cast<BezierTrack *>(t); _clear(bz->values); } break; case TYPE_AUDIO: { - AudioTrack *ad = static_cast<AudioTrack *>(t); _clear(ad->values); } break; case TYPE_ANIMATION: { - AnimationTrack *an = static_cast<AnimationTrack *>(t); _clear(an->values); @@ -725,18 +665,15 @@ void Animation::remove_track(int p_track) { } int Animation::get_track_count() const { - return tracks.size(); } Animation::TrackType Animation::track_get_type(int p_track) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), TYPE_TRANSFORM); return tracks[p_track]->type; } void Animation::track_set_path(int p_track, const NodePath &p_path) { - ERR_FAIL_INDEX(p_track, tracks.size()); tracks[p_track]->path = p_path; emit_changed(); @@ -744,23 +681,20 @@ void Animation::track_set_path(int p_track, const NodePath &p_path) { } NodePath Animation::track_get_path(int p_track) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), NodePath()); return tracks[p_track]->path; } int Animation::find_track(const NodePath &p_path) const { - for (int i = 0; i < tracks.size(); i++) { - - if (tracks[i]->path == p_path) + if (tracks[i]->path == p_path) { return i; + } }; return -1; }; 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; @@ -768,7 +702,6 @@ void Animation::track_set_interpolation_type(int p_track, InterpolationType p_in } Animation::InterpolationType Animation::track_get_interpolation_type(int p_track) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), INTERPOLATION_NEAREST); return tracks[p_track]->interpolation; } @@ -780,7 +713,6 @@ void Animation::track_set_interpolation_loop_wrap(int p_track, bool p_enable) { } bool Animation::track_get_interpolation_loop_wrap(int p_track) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), INTERPOLATION_NEAREST); return tracks[p_track]->loop_wrap; } @@ -811,23 +743,22 @@ int Animation::_insert_pos(float p_time, T& p_keys) { } } + */ template <class T, class V> int Animation::_insert(float p_time, T &p_keys, const V &p_value) { - int idx = p_keys.size(); while (true) { - // Condition for replacement. if (idx > 0 && Math::is_equal_approx(p_keys[idx - 1].time, p_time)) { - + float transition = p_keys[idx - 1].transition; p_keys.write[idx - 1] = p_value; + p_keys.write[idx - 1].transition = transition; return idx - 1; // Condition for insert. } else if (idx == 0 || p_keys[idx - 1].time < p_time) { - p_keys.insert(idx, p_value); return idx; } @@ -840,12 +771,10 @@ int Animation::_insert(float p_time, T &p_keys, const V &p_value) { template <class T> void Animation::_clear(T &p_keys) { - p_keys.clear(); } Error Animation::transform_track_get_key(int p_track, int p_key, Vector3 *r_loc, Quat *r_rot, Vector3 *r_scale) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), ERR_INVALID_PARAMETER); Track *t = tracks[p_track]; @@ -853,18 +782,20 @@ Error Animation::transform_track_get_key(int p_track, int p_key, Vector3 *r_loc, ERR_FAIL_COND_V(t->type != TYPE_TRANSFORM, ERR_INVALID_PARAMETER); ERR_FAIL_INDEX_V(p_key, tt->transforms.size(), ERR_INVALID_PARAMETER); - if (r_loc) + if (r_loc) { *r_loc = tt->transforms[p_key].value.loc; - if (r_rot) + } + if (r_rot) { *r_rot = tt->transforms[p_key].value.rot; - if (r_scale) + } + if (r_scale) { *r_scale = tt->transforms[p_key].value.scale; + } return OK; } int Animation::transform_track_insert_key(int p_track, float p_time, const Vector3 &p_loc, const Quat &p_rot, const Vector3 &p_scale) { - ERR_FAIL_INDEX_V(p_track, tracks.size(), -1); Track *t = tracks[p_track]; ERR_FAIL_COND_V(t->type != TYPE_TRANSFORM, -1); @@ -883,55 +814,47 @@ int Animation::transform_track_insert_key(int p_track, float p_time, const Vecto } void Animation::track_remove_key_at_position(int p_track, float p_pos) { - int idx = track_find_key(p_track, p_pos, true); ERR_FAIL_COND(idx < 0); track_remove_key(p_track, idx); } void Animation::track_remove_key(int p_track, int p_idx) { - ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; switch (t->type) { case TYPE_TRANSFORM: { - TransformTrack *tt = static_cast<TransformTrack *>(t); ERR_FAIL_INDEX(p_idx, tt->transforms.size()); tt->transforms.remove(p_idx); } break; case TYPE_VALUE: { - ValueTrack *vt = static_cast<ValueTrack *>(t); ERR_FAIL_INDEX(p_idx, vt->values.size()); vt->values.remove(p_idx); } break; case TYPE_METHOD: { - MethodTrack *mt = static_cast<MethodTrack *>(t); ERR_FAIL_INDEX(p_idx, mt->methods.size()); mt->methods.remove(p_idx); } break; case TYPE_BEZIER: { - BezierTrack *bz = static_cast<BezierTrack *>(t); ERR_FAIL_INDEX(p_idx, bz->values.size()); bz->values.remove(p_idx); } break; case TYPE_AUDIO: { - AudioTrack *ad = static_cast<AudioTrack *>(t); ERR_FAIL_INDEX(p_idx, ad->values.size()); ad->values.remove(p_idx); } break; case TYPE_ANIMATION: { - AnimationTrack *an = static_cast<AnimationTrack *>(t); ERR_FAIL_INDEX(p_idx, an->values.size()); an->values.remove(p_idx); @@ -943,74 +866,79 @@ void Animation::track_remove_key(int p_track, int p_idx) { } int Animation::track_find_key(int p_track, float p_time, bool p_exact) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), -1); Track *t = tracks[p_track]; switch (t->type) { case TYPE_TRANSFORM: { - TransformTrack *tt = static_cast<TransformTrack *>(t); int k = _find(tt->transforms, p_time); - if (k < 0 || k >= tt->transforms.size()) + if (k < 0 || k >= tt->transforms.size()) { return -1; - if (tt->transforms[k].time != p_time && p_exact) + } + if (tt->transforms[k].time != p_time && p_exact) { return -1; + } return k; } break; case TYPE_VALUE: { - ValueTrack *vt = static_cast<ValueTrack *>(t); int k = _find(vt->values, p_time); - if (k < 0 || k >= vt->values.size()) + if (k < 0 || k >= vt->values.size()) { return -1; - if (vt->values[k].time != p_time && p_exact) + } + if (vt->values[k].time != p_time && p_exact) { return -1; + } return k; } break; case TYPE_METHOD: { - MethodTrack *mt = static_cast<MethodTrack *>(t); int k = _find(mt->methods, p_time); - if (k < 0 || k >= mt->methods.size()) + if (k < 0 || k >= mt->methods.size()) { return -1; - if (mt->methods[k].time != p_time && p_exact) + } + if (mt->methods[k].time != p_time && p_exact) { return -1; + } return k; } break; case TYPE_BEZIER: { - BezierTrack *bt = static_cast<BezierTrack *>(t); int k = _find(bt->values, p_time); - if (k < 0 || k >= bt->values.size()) + if (k < 0 || k >= bt->values.size()) { return -1; - if (bt->values[k].time != p_time && p_exact) + } + if (bt->values[k].time != p_time && p_exact) { return -1; + } return k; } break; case TYPE_AUDIO: { - AudioTrack *at = static_cast<AudioTrack *>(t); int k = _find(at->values, p_time); - if (k < 0 || k >= at->values.size()) + if (k < 0 || k >= at->values.size()) { return -1; - if (at->values[k].time != p_time && p_exact) + } + if (at->values[k].time != p_time && p_exact) { return -1; + } return k; } break; case TYPE_ANIMATION: { - AnimationTrack *at = static_cast<AnimationTrack *>(t); int k = _find(at->values, p_time); - if (k < 0 || k >= at->values.size()) + if (k < 0 || k >= at->values.size()) { return -1; - if (at->values[k].time != p_time && p_exact) + } + if (at->values[k].time != p_time && p_exact) { return -1; + } return k; } break; @@ -1020,33 +948,32 @@ int Animation::track_find_key(int p_track, float p_time, bool p_exact) const { } void Animation::track_insert_key(int p_track, float p_time, const Variant &p_key, float p_transition) { - ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; switch (t->type) { - case TYPE_TRANSFORM: { - Dictionary d = p_key; Vector3 loc; - if (d.has("location")) + if (d.has("location")) { loc = d["location"]; + } Quat rot; - if (d.has("rotation")) + if (d.has("rotation")) { rot = d["rotation"]; + } Vector3 scale; - if (d.has("scale")) + if (d.has("scale")) { scale = d["scale"]; + } int idx = transform_track_insert_key(p_track, p_time, loc, rot, scale); track_set_key_transition(p_track, idx, p_transition); } break; case TYPE_VALUE: { - ValueTrack *vt = static_cast<ValueTrack *>(t); TKey<Variant> k; @@ -1057,13 +984,12 @@ void Animation::track_insert_key(int p_track, float p_time, const Variant &p_key } break; case TYPE_METHOD: { - MethodTrack *mt = static_cast<MethodTrack *>(t); ERR_FAIL_COND(p_key.get_type() != Variant::DICTIONARY); Dictionary d = p_key; - ERR_FAIL_COND(!d.has("method") || d["method"].get_type() != Variant::STRING); + ERR_FAIL_COND(!d.has("method") || (d["method"].get_type() != Variant::STRING_NAME && d["method"].get_type() != Variant::STRING)); ERR_FAIL_COND(!d.has("args") || !d["args"].is_array()); MethodKey k; @@ -1077,7 +1003,6 @@ void Animation::track_insert_key(int p_track, float p_time, const Variant &p_key } break; case TYPE_BEZIER: { - BezierTrack *bt = static_cast<BezierTrack *>(t); Array arr = p_key; @@ -1094,7 +1019,6 @@ void Animation::track_insert_key(int p_track, float p_time, const Variant &p_key } break; case TYPE_AUDIO: { - AudioTrack *at = static_cast<AudioTrack *>(t); Dictionary k = p_key; @@ -1111,7 +1035,6 @@ void Animation::track_insert_key(int p_track, float p_time, const Variant &p_key } break; case TYPE_ANIMATION: { - AnimationTrack *at = static_cast<AnimationTrack *>(t); TKey<StringName> ak; @@ -1127,40 +1050,32 @@ void Animation::track_insert_key(int p_track, float p_time, const Variant &p_key } int Animation::track_get_key_count(int p_track) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), -1); Track *t = tracks[p_track]; switch (t->type) { - case TYPE_TRANSFORM: { - TransformTrack *tt = static_cast<TransformTrack *>(t); return tt->transforms.size(); } break; case TYPE_VALUE: { - ValueTrack *vt = static_cast<ValueTrack *>(t); return vt->values.size(); } break; case TYPE_METHOD: { - MethodTrack *mt = static_cast<MethodTrack *>(t); return mt->methods.size(); } break; case TYPE_BEZIER: { - BezierTrack *bt = static_cast<BezierTrack *>(t); return bt->values.size(); } break; case TYPE_AUDIO: { - AudioTrack *at = static_cast<AudioTrack *>(t); return at->values.size(); } break; case TYPE_ANIMATION: { - AnimationTrack *at = static_cast<AnimationTrack *>(t); return at->values.size(); } break; @@ -1170,14 +1085,11 @@ int Animation::track_get_key_count(int p_track) const { } Variant Animation::track_get_key_value(int p_track, int p_key_idx) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), Variant()); Track *t = tracks[p_track]; switch (t->type) { - case TYPE_TRANSFORM: { - TransformTrack *tt = static_cast<TransformTrack *>(t); ERR_FAIL_INDEX_V(p_key_idx, tt->transforms.size(), Variant()); @@ -1189,14 +1101,12 @@ Variant Animation::track_get_key_value(int p_track, int p_key_idx) const { return d; } break; case TYPE_VALUE: { - ValueTrack *vt = static_cast<ValueTrack *>(t); ERR_FAIL_INDEX_V(p_key_idx, vt->values.size(), Variant()); return vt->values[p_key_idx].value; } break; case TYPE_METHOD: { - MethodTrack *mt = static_cast<MethodTrack *>(t); ERR_FAIL_INDEX_V(p_key_idx, mt->methods.size(), Variant()); Dictionary d; @@ -1206,7 +1116,6 @@ Variant Animation::track_get_key_value(int p_track, int p_key_idx) const { } break; case TYPE_BEZIER: { - BezierTrack *bt = static_cast<BezierTrack *>(t); ERR_FAIL_INDEX_V(p_key_idx, bt->values.size(), Variant()); @@ -1221,7 +1130,6 @@ Variant Animation::track_get_key_value(int p_track, int p_key_idx) const { } break; case TYPE_AUDIO: { - AudioTrack *at = static_cast<AudioTrack *>(t); ERR_FAIL_INDEX_V(p_key_idx, at->values.size(), Variant()); @@ -1233,7 +1141,6 @@ Variant Animation::track_get_key_value(int p_track, int p_key_idx) const { } break; case TYPE_ANIMATION: { - AnimationTrack *at = static_cast<AnimationTrack *>(t); ERR_FAIL_INDEX_V(p_key_idx, at->values.size(), Variant()); @@ -1246,48 +1153,40 @@ Variant Animation::track_get_key_value(int p_track, int p_key_idx) const { } float Animation::track_get_key_time(int p_track, int p_key_idx) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), -1); Track *t = tracks[p_track]; switch (t->type) { - case TYPE_TRANSFORM: { - TransformTrack *tt = static_cast<TransformTrack *>(t); ERR_FAIL_INDEX_V(p_key_idx, tt->transforms.size(), -1); return tt->transforms[p_key_idx].time; } break; case TYPE_VALUE: { - ValueTrack *vt = static_cast<ValueTrack *>(t); ERR_FAIL_INDEX_V(p_key_idx, vt->values.size(), -1); return vt->values[p_key_idx].time; } break; case TYPE_METHOD: { - MethodTrack *mt = static_cast<MethodTrack *>(t); ERR_FAIL_INDEX_V(p_key_idx, mt->methods.size(), -1); return mt->methods[p_key_idx].time; } break; case TYPE_BEZIER: { - BezierTrack *bt = static_cast<BezierTrack *>(t); ERR_FAIL_INDEX_V(p_key_idx, bt->values.size(), -1); return bt->values[p_key_idx].time; } break; case TYPE_AUDIO: { - AudioTrack *at = static_cast<AudioTrack *>(t); ERR_FAIL_INDEX_V(p_key_idx, at->values.size(), -1); return at->values[p_key_idx].time; } break; case TYPE_ANIMATION: { - AnimationTrack *at = static_cast<AnimationTrack *>(t); ERR_FAIL_INDEX_V(p_key_idx, at->values.size(), -1); return at->values[p_key_idx].time; @@ -1299,14 +1198,11 @@ float Animation::track_get_key_time(int p_track, int p_key_idx) const { } void Animation::track_set_key_time(int p_track, int p_key_idx, float p_time) { - ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; switch (t->type) { - case TYPE_TRANSFORM: { - TransformTrack *tt = static_cast<TransformTrack *>(t); ERR_FAIL_INDEX(p_key_idx, tt->transforms.size()); TKey<TransformKey> key = tt->transforms[p_key_idx]; @@ -1316,7 +1212,6 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, float p_time) { return; } case TYPE_VALUE: { - ValueTrack *vt = static_cast<ValueTrack *>(t); ERR_FAIL_INDEX(p_key_idx, vt->values.size()); TKey<Variant> key = vt->values[p_key_idx]; @@ -1326,7 +1221,6 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, float p_time) { return; } case TYPE_METHOD: { - MethodTrack *mt = static_cast<MethodTrack *>(t); ERR_FAIL_INDEX(p_key_idx, mt->methods.size()); MethodKey key = mt->methods[p_key_idx]; @@ -1336,7 +1230,6 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, float p_time) { return; } case TYPE_BEZIER: { - BezierTrack *bt = static_cast<BezierTrack *>(t); ERR_FAIL_INDEX(p_key_idx, bt->values.size()); TKey<BezierKey> key = bt->values[p_key_idx]; @@ -1346,7 +1239,6 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, float p_time) { return; } case TYPE_AUDIO: { - AudioTrack *at = static_cast<AudioTrack *>(t); ERR_FAIL_INDEX(p_key_idx, at->values.size()); TKey<AudioKey> key = at->values[p_key_idx]; @@ -1356,7 +1248,6 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, float p_time) { return; } case TYPE_ANIMATION: { - AnimationTrack *at = static_cast<AnimationTrack *>(t); ERR_FAIL_INDEX(p_key_idx, at->values.size()); TKey<StringName> key = at->values[p_key_idx]; @@ -1371,42 +1262,34 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, float p_time) { } float Animation::track_get_key_transition(int p_track, int p_key_idx) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), -1); Track *t = tracks[p_track]; switch (t->type) { - case TYPE_TRANSFORM: { - TransformTrack *tt = static_cast<TransformTrack *>(t); ERR_FAIL_INDEX_V(p_key_idx, tt->transforms.size(), -1); return tt->transforms[p_key_idx].transition; } break; case TYPE_VALUE: { - ValueTrack *vt = static_cast<ValueTrack *>(t); ERR_FAIL_INDEX_V(p_key_idx, vt->values.size(), -1); return vt->values[p_key_idx].transition; } break; case TYPE_METHOD: { - MethodTrack *mt = static_cast<MethodTrack *>(t); ERR_FAIL_INDEX_V(p_key_idx, mt->methods.size(), -1); return mt->methods[p_key_idx].transition; } break; case TYPE_BEZIER: { - return 1; //bezier does not really use transitions } break; case TYPE_AUDIO: { - return 1; //audio does not really use transitions } break; case TYPE_ANIMATION: { - return 1; //animation does not really use transitions } break; } @@ -1415,29 +1298,28 @@ float Animation::track_get_key_transition(int p_track, int p_key_idx) const { } void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p_value) { - ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; switch (t->type) { - case TYPE_TRANSFORM: { - TransformTrack *tt = static_cast<TransformTrack *>(t); ERR_FAIL_INDEX(p_key_idx, tt->transforms.size()); Dictionary d = p_value; - if (d.has("location")) + if (d.has("location")) { tt->transforms.write[p_key_idx].value.loc = d["location"]; - if (d.has("rotation")) + } + if (d.has("rotation")) { tt->transforms.write[p_key_idx].value.rot = d["rotation"]; - if (d.has("scale")) + } + if (d.has("scale")) { tt->transforms.write[p_key_idx].value.scale = d["scale"]; + } } break; case TYPE_VALUE: { - ValueTrack *vt = static_cast<ValueTrack *>(t); ERR_FAIL_INDEX(p_key_idx, vt->values.size()); @@ -1445,20 +1327,20 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p } break; case TYPE_METHOD: { - MethodTrack *mt = static_cast<MethodTrack *>(t); ERR_FAIL_INDEX(p_key_idx, mt->methods.size()); Dictionary d = p_value; - if (d.has("method")) + if (d.has("method")) { mt->methods.write[p_key_idx].method = d["method"]; - if (d.has("args")) + } + if (d.has("args")) { mt->methods.write[p_key_idx].params = d["args"]; + } } break; case TYPE_BEZIER: { - BezierTrack *bt = static_cast<BezierTrack *>(t); ERR_FAIL_INDEX(p_key_idx, bt->values.size()); @@ -1473,7 +1355,6 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p } break; case TYPE_AUDIO: { - AudioTrack *at = static_cast<AudioTrack *>(t); ERR_FAIL_INDEX(p_key_idx, at->values.size()); @@ -1488,7 +1369,6 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p } break; case TYPE_ANIMATION: { - AnimationTrack *at = static_cast<AnimationTrack *>(t); ERR_FAIL_INDEX(p_key_idx, at->values.size()); @@ -1501,27 +1381,22 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p } void Animation::track_set_key_transition(int p_track, int p_key_idx, float p_transition) { - ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; switch (t->type) { - case TYPE_TRANSFORM: { - TransformTrack *tt = static_cast<TransformTrack *>(t); ERR_FAIL_INDEX(p_key_idx, tt->transforms.size()); tt->transforms.write[p_key_idx].transition = p_transition; } break; case TYPE_VALUE: { - ValueTrack *vt = static_cast<ValueTrack *>(t); ERR_FAIL_INDEX(p_key_idx, vt->values.size()); vt->values.write[p_key_idx].transition = p_transition; } break; case TYPE_METHOD: { - MethodTrack *mt = static_cast<MethodTrack *>(t); ERR_FAIL_INDEX(p_key_idx, mt->methods.size()); mt->methods.write[p_key_idx].transition = p_transition; @@ -1539,42 +1414,43 @@ void Animation::track_set_key_transition(int p_track, int p_key_idx, float p_tra template <class K> int Animation::_find(const Vector<K> &p_keys, float p_time) const { - int len = p_keys.size(); - if (len == 0) + if (len == 0) { return -2; + } int low = 0; int high = len - 1; int middle = 0; #ifdef DEBUG_ENABLED - if (low > high) + if (low > high) { ERR_PRINT("low > high, this may be a bug"); + } #endif const K *keys = &p_keys[0]; while (low <= high) { - middle = (low + high) / 2; if (Math::is_equal_approx(p_time, keys[middle].time)) { //match return middle; - } else if (p_time < keys[middle].time) + } else if (p_time < keys[middle].time) { high = middle - 1; //search low end of array - else + } else { low = middle + 1; //search high end of array + } } - if (keys[middle].time > p_time) + if (keys[middle].time > p_time) { middle--; + } return middle; } Animation::TransformKey Animation::_interpolate(const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, float p_c) const { - TransformKey ret; ret.loc = _interpolate(p_a.loc, p_b.loc, p_c); ret.rot = _interpolate(p_a.rot, p_b.rot, p_c); @@ -1584,27 +1460,24 @@ Animation::TransformKey Animation::_interpolate(const Animation::TransformKey &p } Vector3 Animation::_interpolate(const Vector3 &p_a, const Vector3 &p_b, float p_c) const { - - return p_a.linear_interpolate(p_b, p_c); + return p_a.lerp(p_b, p_c); } -Quat Animation::_interpolate(const Quat &p_a, const Quat &p_b, float p_c) const { +Quat Animation::_interpolate(const Quat &p_a, const Quat &p_b, float p_c) const { return p_a.slerp(p_b, p_c); } -Variant Animation::_interpolate(const Variant &p_a, const Variant &p_b, float p_c) const { +Variant Animation::_interpolate(const Variant &p_a, const Variant &p_b, float p_c) const { Variant dst; Variant::interpolate(p_a, p_b, p_c, dst); return dst; } float Animation::_interpolate(const float &p_a, const float &p_b, float p_c) const { - return p_a * (1.0 - p_c) + p_b * p_c; } Animation::TransformKey Animation::_cubic_interpolate(const Animation::TransformKey &p_pre_a, const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, const Animation::TransformKey &p_post_b, float p_c) const { - Animation::TransformKey tk; tk.loc = p_a.loc.cubic_interpolate(p_b.loc, p_pre_a.loc, p_post_b.loc, p_c); @@ -1613,16 +1486,16 @@ Animation::TransformKey Animation::_cubic_interpolate(const Animation::Transform return tk; } -Vector3 Animation::_cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, float p_c) const { +Vector3 Animation::_cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, float p_c) const { return p_a.cubic_interpolate(p_b, p_pre_a, p_post_b, p_c); } -Quat Animation::_cubic_interpolate(const Quat &p_pre_a, const Quat &p_a, const Quat &p_b, const Quat &p_post_b, float p_c) const { +Quat Animation::_cubic_interpolate(const Quat &p_pre_a, const Quat &p_a, const Quat &p_b, const Quat &p_post_b, float p_c) const { return p_a.cubic_slerp(p_b, p_pre_a, p_post_b, p_c); } -Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, float p_c) const { +Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, float p_c) 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(); @@ -1635,7 +1508,7 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a vformat |= 1 << type_pa; vformat |= 1 << type_pb; - if (vformat == ((1 << Variant::INT) | (1 << Variant::REAL)) || vformat == (1 << Variant::REAL)) { + if (vformat == ((1 << Variant::INT) | (1 << Variant::FLOAT)) || vformat == (1 << Variant::FLOAT)) { //mix of real and int real_t p0 = p_pre_a; @@ -1653,14 +1526,11 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3); } 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; @@ -1669,7 +1539,6 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a return a.cubic_interpolate(b, pa, pb, p_c); } case Variant::RECT2: { - Rect2 a = p_a; Rect2 b = p_b; Rect2 pa = p_pre_a; @@ -1680,7 +1549,6 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a a.size.cubic_interpolate(b.size, pa.size, pb.size, p_c)); } case Variant::VECTOR3: { - Vector3 a = p_a; Vector3 b = p_b; Vector3 pa = p_pre_a; @@ -1689,7 +1557,6 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a return a.cubic_interpolate(b, pa, pb, p_c); } case Variant::QUAT: { - Quat a = p_a; Quat b = p_b; Quat pa = p_pre_a; @@ -1698,7 +1565,6 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a return a.cubic_slerp(b, pa, pb, p_c); } case Variant::AABB: { - AABB a = p_a; AABB b = p_b; AABB pa = p_pre_a; @@ -1709,31 +1575,31 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a a.size.cubic_interpolate(b.size, pa.size, pb.size, p_c)); } default: { - return _interpolate(p_a, p_b, p_c); } } } -float Animation::_cubic_interpolate(const float &p_pre_a, const float &p_a, const float &p_b, const float &p_post_b, float p_c) const { +float Animation::_cubic_interpolate(const float &p_pre_a, const float &p_a, const float &p_b, const float &p_post_b, float p_c) const { return _interpolate(p_a, p_b, p_c); } template <class T> -T Animation::_interpolate(const Vector<TKey<T> > &p_keys, float p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok) const { - +T Animation::_interpolate(const Vector<TKey<T>> &p_keys, float p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok) const { int len = _find(p_keys, length) + 1; // try to find last key (there may be more past the end) if (len <= 0) { // (-1 or -2 returned originally) (plus one above) // meaning no keys, or only key time is larger than length - if (p_ok) + if (p_ok) { *p_ok = false; + } return T(); } else if (len == 1) { // one key found (0+1), return it - if (p_ok) + if (p_ok) { *p_ok = true; + } return p_keys[0].value; } @@ -1749,28 +1615,27 @@ T Animation::_interpolate(const Vector<TKey<T> > &p_keys, float p_time, Interpol if (loop && p_loop_wrap) { // loop if (idx >= 0) { - if ((idx + 1) < len) { - next = idx + 1; float delta = p_keys[next].time - p_keys[idx].time; float from = p_time - p_keys[idx].time; - if (Math::is_zero_approx(delta)) + if (Math::is_zero_approx(delta)) { c = 0; - else + } else { c = from / delta; + } } else { - next = 0; float delta = (length - p_keys[idx].time) + p_keys[next].time; float from = p_time - p_keys[idx].time; - if (Math::is_zero_approx(delta)) + if (Math::is_zero_approx(delta)) { c = 0; - else + } else { c = from / delta; + } } } else { @@ -1778,51 +1643,53 @@ T Animation::_interpolate(const Vector<TKey<T> > &p_keys, float p_time, Interpol idx = len - 1; next = 0; float endtime = (length - p_keys[idx].time); - if (endtime < 0) // may be keys past the end + if (endtime < 0) { // may be keys past the end endtime = 0; + } float delta = endtime + p_keys[next].time; float from = endtime + p_time; - if (Math::is_zero_approx(delta)) + if (Math::is_zero_approx(delta)) { c = 0; - else + } else { c = from / delta; + } } } else { // no loop if (idx >= 0) { - if ((idx + 1) < len) { - next = idx + 1; float delta = p_keys[next].time - p_keys[idx].time; float from = p_time - p_keys[idx].time; - if (Math::is_zero_approx(delta)) + if (Math::is_zero_approx(delta)) { c = 0; - else + } else { c = from / delta; + } } else { - next = idx; } } else { - // only allow extending first key to anim start if looping - if (loop) + if (loop) { idx = next = 0; - else + } else { result = false; + } } } - if (p_ok) + if (p_ok) { *p_ok = result; - if (!result) + } + if (!result) { return T(); + } float tr = p_keys[idx].transition; @@ -1832,39 +1699,37 @@ T Animation::_interpolate(const Vector<TKey<T> > &p_keys, float p_time, Interpol } if (tr != 1.0) { - c = Math::ease(c, tr); } switch (p_interp) { - case INTERPOLATION_NEAREST: { - return p_keys[idx].value; } break; 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 (pre < 0) { pre = 0; + } int post = next + 1; - if (post >= len) + if (post >= len) { post = next; + } return _cubic_interpolate(p_keys[pre].value, p_keys[idx].value, p_keys[next].value, p_keys[post].value, c); } break; - default: return p_keys[idx].value; + default: + return p_keys[idx].value; } // do a barrel roll } Error Animation::transform_track_interpolate(int p_track, float p_time, Vector3 *r_loc, Quat *r_rot, Vector3 *r_scale) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), ERR_INVALID_PARAMETER); Track *t = tracks[p_track]; ERR_FAIL_COND_V(t->type != TYPE_TRANSFORM, ERR_INVALID_PARAMETER); @@ -1875,23 +1740,26 @@ Error Animation::transform_track_interpolate(int p_track, float p_time, Vector3 TransformKey tk = _interpolate(tt->transforms, p_time, tt->interpolation, tt->loop_wrap, &ok); - if (!ok) + if (!ok) { return ERR_UNAVAILABLE; + } - if (r_loc) + if (r_loc) { *r_loc = tk.loc; + } - if (r_rot) + if (r_rot) { *r_rot = tk.rot; + } - if (r_scale) + if (r_scale) { *r_scale = tk.scale; + } return OK; } Variant Animation::value_track_interpolate(int p_track, float p_time) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), 0); Track *t = tracks[p_track]; ERR_FAIL_COND_V(t->type != TYPE_VALUE, Variant()); @@ -1902,7 +1770,6 @@ Variant Animation::value_track_interpolate(int p_track, float p_time) const { Variant res = _interpolate(vt->values, p_time, (vt->update_mode == UPDATE_CONTINUOUS || vt->update_mode == UPDATE_CAPTURE) ? vt->interpolation : INTERPOLATION_NEAREST, vt->loop_wrap, &ok); if (ok) { - return res; } @@ -1910,9 +1777,9 @@ Variant Animation::value_track_interpolate(int p_track, float p_time) const { } void Animation::_value_track_get_key_indices_in_range(const ValueTrack *vt, float from_time, float to_time, List<int> *p_indices) const { - - if (from_time != length && to_time == length) + if (from_time != length && to_time == length) { to_time = length * 1.001; //include a little more if at the end + } int to = _find(vt->values, to_time); if (to >= 0 && from_time == to_time && vt->values[to].time == from_time) { @@ -1923,29 +1790,30 @@ void Animation::_value_track_get_key_indices_in_range(const ValueTrack *vt, floa // can't really send the events == time, will be sent in the next frame. // if event>=len then it will probably never be requested by the anim player. - if (to >= 0 && vt->values[to].time >= to_time) + if (to >= 0 && vt->values[to].time >= to_time) { to--; + } - if (to < 0) + if (to < 0) { return; // not bother + } int from = _find(vt->values, from_time); // position in the right first event.+ - if (from < 0 || vt->values[from].time < from_time) + if (from < 0 || vt->values[from].time < from_time) { from++; + } int max = vt->values.size(); for (int i = from; i <= to; i++) { - ERR_CONTINUE(i < 0 || i >= max); // shouldn't happen p_indices->push_back(i); } } void Animation::value_track_get_key_indices(int p_track, float p_time, float p_delta, List<int> *p_indices) const { - ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; ERR_FAIL_COND(t->type != TYPE_VALUE); @@ -1955,11 +1823,11 @@ void Animation::value_track_get_key_indices(int p_track, float p_time, float p_d float from_time = p_time - p_delta; float to_time = p_time; - if (from_time > to_time) + if (from_time > to_time) { SWAP(from_time, to_time); + } if (loop) { - from_time = Math::fposmod(from_time, length); to_time = Math::fposmod(to_time, length); @@ -1970,23 +1838,25 @@ void Animation::value_track_get_key_indices(int p_track, float p_time, float p_d return; } } else { - - if (from_time < 0) + if (from_time < 0) { from_time = 0; - if (from_time > length) + } + if (from_time > length) { from_time = length; + } - if (to_time < 0) + if (to_time < 0) { to_time = 0; - if (to_time > length) + } + if (to_time > length) { to_time = length; + } } _value_track_get_key_indices_in_range(vt, from_time, to_time, p_indices); } void Animation::value_track_set_update_mode(int p_track, UpdateMode p_mode) { - ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; ERR_FAIL_COND(t->type != TYPE_VALUE); @@ -1997,7 +1867,6 @@ void Animation::value_track_set_update_mode(int p_track, UpdateMode p_mode) { } Animation::UpdateMode Animation::value_track_get_update_mode(int p_track) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), UPDATE_CONTINUOUS); Track *t = tracks[p_track]; ERR_FAIL_COND_V(t->type != TYPE_VALUE, UPDATE_CONTINUOUS); @@ -2008,97 +1877,93 @@ Animation::UpdateMode Animation::value_track_get_update_mode(int p_track) const template <class T> void Animation::_track_get_key_indices_in_range(const Vector<T> &p_array, float from_time, float to_time, List<int> *p_indices) const { - - if (from_time != length && to_time == length) + if (from_time != length && to_time == length) { to_time = length * 1.01; //include a little more if at the end + } int to = _find(p_array, to_time); // can't really send the events == time, will be sent in the next frame. // if event>=len then it will probably never be requested by the anim player. - if (to >= 0 && p_array[to].time >= to_time) + if (to >= 0 && p_array[to].time >= to_time) { to--; + } - if (to < 0) + if (to < 0) { return; // not bother + } int from = _find(p_array, from_time); // position in the right first event.+ - if (from < 0 || p_array[from].time < from_time) + if (from < 0 || p_array[from].time < from_time) { from++; + } int max = p_array.size(); for (int i = from; i <= to; i++) { - ERR_CONTINUE(i < 0 || i >= max); // shouldn't happen p_indices->push_back(i); } } void Animation::track_get_key_indices_in_range(int p_track, float p_time, float p_delta, List<int> *p_indices) const { - ERR_FAIL_INDEX(p_track, tracks.size()); const Track *t = tracks[p_track]; float from_time = p_time - p_delta; float to_time = p_time; - if (from_time > to_time) + if (from_time > to_time) { SWAP(from_time, to_time); + } if (loop) { - - if (from_time > length || from_time < 0) + if (from_time > length || from_time < 0) { from_time = Math::fposmod(from_time, length); + } - if (to_time > length || to_time < 0) + if (to_time > length || to_time < 0) { to_time = Math::fposmod(to_time, length); + } if (from_time > to_time) { // handle loop by splitting switch (t->type) { - case TYPE_TRANSFORM: { - const TransformTrack *tt = static_cast<const TransformTrack *>(t); _track_get_key_indices_in_range(tt->transforms, from_time, length, p_indices); _track_get_key_indices_in_range(tt->transforms, 0, to_time, p_indices); } break; case TYPE_VALUE: { - const ValueTrack *vt = static_cast<const ValueTrack *>(t); _track_get_key_indices_in_range(vt->values, from_time, length, p_indices); _track_get_key_indices_in_range(vt->values, 0, to_time, p_indices); } break; case TYPE_METHOD: { - const MethodTrack *mt = static_cast<const MethodTrack *>(t); _track_get_key_indices_in_range(mt->methods, from_time, length, p_indices); _track_get_key_indices_in_range(mt->methods, 0, to_time, p_indices); } break; case TYPE_BEZIER: { - const BezierTrack *bz = static_cast<const BezierTrack *>(t); _track_get_key_indices_in_range(bz->values, from_time, length, p_indices); _track_get_key_indices_in_range(bz->values, 0, to_time, p_indices); } break; case TYPE_AUDIO: { - const AudioTrack *ad = static_cast<const AudioTrack *>(t); _track_get_key_indices_in_range(ad->values, from_time, length, p_indices); _track_get_key_indices_in_range(ad->values, 0, to_time, p_indices); } break; case TYPE_ANIMATION: { - const AnimationTrack *an = static_cast<const AnimationTrack *>(t); _track_get_key_indices_in_range(an->values, from_time, length, p_indices); _track_get_key_indices_in_range(an->values, 0, to_time, p_indices); @@ -2108,52 +1973,48 @@ void Animation::track_get_key_indices_in_range(int p_track, float p_time, float return; } } else { - - if (from_time < 0) + if (from_time < 0) { from_time = 0; - if (from_time > length) + } + if (from_time > length) { from_time = length; + } - if (to_time < 0) + if (to_time < 0) { to_time = 0; - if (to_time > length) + } + if (to_time > length) { to_time = length; + } } switch (t->type) { - case TYPE_TRANSFORM: { - const TransformTrack *tt = static_cast<const TransformTrack *>(t); _track_get_key_indices_in_range(tt->transforms, from_time, to_time, p_indices); } break; case TYPE_VALUE: { - const ValueTrack *vt = static_cast<const ValueTrack *>(t); _track_get_key_indices_in_range(vt->values, from_time, to_time, p_indices); } break; case TYPE_METHOD: { - const MethodTrack *mt = static_cast<const MethodTrack *>(t); _track_get_key_indices_in_range(mt->methods, from_time, to_time, p_indices); } break; case TYPE_BEZIER: { - const BezierTrack *bz = static_cast<const BezierTrack *>(t); _track_get_key_indices_in_range(bz->values, from_time, to_time, p_indices); } break; case TYPE_AUDIO: { - const AudioTrack *ad = static_cast<const AudioTrack *>(t); _track_get_key_indices_in_range(ad->values, from_time, to_time, p_indices); } break; case TYPE_ANIMATION: { - const AnimationTrack *an = static_cast<const AnimationTrack *>(t); _track_get_key_indices_in_range(an->values, from_time, to_time, p_indices); @@ -2162,38 +2023,39 @@ void Animation::track_get_key_indices_in_range(int p_track, float p_time, float } void Animation::_method_track_get_key_indices_in_range(const MethodTrack *mt, float from_time, float to_time, List<int> *p_indices) const { - - if (from_time != length && to_time == length) + if (from_time != length && to_time == length) { to_time = length * 1.01; //include a little more if at the end + } int to = _find(mt->methods, to_time); // can't really send the events == time, will be sent in the next frame. // if event>=len then it will probably never be requested by the anim player. - if (to >= 0 && mt->methods[to].time >= to_time) + if (to >= 0 && mt->methods[to].time >= to_time) { to--; + } - if (to < 0) + if (to < 0) { return; // not bother + } int from = _find(mt->methods, from_time); // position in the right first event.+ - if (from < 0 || mt->methods[from].time < from_time) + if (from < 0 || mt->methods[from].time < from_time) { from++; + } int max = mt->methods.size(); for (int i = from; i <= to; i++) { - ERR_CONTINUE(i < 0 || i >= max); // shouldn't happen p_indices->push_back(i); } } void Animation::method_track_get_key_indices(int p_track, float p_time, float p_delta, List<int> *p_indices) const { - ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; ERR_FAIL_COND(t->type != TYPE_METHOD); @@ -2203,16 +2065,18 @@ void Animation::method_track_get_key_indices(int p_track, float p_time, float p_ float from_time = p_time - p_delta; float to_time = p_time; - if (from_time > to_time) + if (from_time > to_time) { SWAP(from_time, to_time); + } if (loop) { - - if (from_time > length || from_time < 0) + if (from_time > length || from_time < 0) { from_time = Math::fposmod(from_time, length); + } - if (to_time > length || to_time < 0) + if (to_time > length || to_time < 0) { to_time = Math::fposmod(to_time, length); + } if (from_time > to_time) { // handle loop by splitting @@ -2221,22 +2085,25 @@ void Animation::method_track_get_key_indices(int p_track, float p_time, float p_ return; } } else { - - if (from_time < 0) + if (from_time < 0) { from_time = 0; - if (from_time > length) + } + if (from_time > length) { from_time = length; + } - if (to_time < 0) + if (to_time < 0) { to_time = 0; - if (to_time > length) + } + if (to_time > length) { to_time = length; + } } _method_track_get_key_indices_in_range(mt, from_time, to_time, p_indices); } -Vector<Variant> Animation::method_track_get_params(int p_track, int p_key_idx) const { +Vector<Variant> Animation::method_track_get_params(int p_track, int p_key_idx) const { ERR_FAIL_INDEX_V(p_track, tracks.size(), Vector<Variant>()); Track *t = tracks[p_track]; ERR_FAIL_COND_V(t->type != TYPE_METHOD, Vector<Variant>()); @@ -2249,8 +2116,8 @@ Vector<Variant> Animation::method_track_get_params(int p_track, int p_key_idx) c return mk.params; } -StringName Animation::method_track_get_name(int p_track, int p_key_idx) const { +StringName Animation::method_track_get_name(int p_track, int p_key_idx) const { ERR_FAIL_INDEX_V(p_track, tracks.size(), StringName()); Track *t = tracks[p_track]; ERR_FAIL_COND_V(t->type != TYPE_METHOD, StringName()); @@ -2263,7 +2130,6 @@ StringName Animation::method_track_get_name(int p_track, int p_key_idx) const { } int Animation::bezier_track_insert_key(int p_track, float p_time, float 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); @@ -2290,7 +2156,6 @@ int Animation::bezier_track_insert_key(int p_track, float p_time, float p_value, } void Animation::bezier_track_set_key_value(int p_track, int p_index, float p_value) { - ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; ERR_FAIL_COND(t->type != TYPE_BEZIER); @@ -2304,7 +2169,6 @@ void Animation::bezier_track_set_key_value(int p_track, int p_index, float p_val } void Animation::bezier_track_set_key_in_handle(int p_track, int p_index, const Vector2 &p_handle) { - ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; ERR_FAIL_COND(t->type != TYPE_BEZIER); @@ -2319,8 +2183,8 @@ void Animation::bezier_track_set_key_in_handle(int p_track, int p_index, const V } emit_changed(); } -void Animation::bezier_track_set_key_out_handle(int p_track, int p_index, const Vector2 &p_handle) { +void Animation::bezier_track_set_key_out_handle(int p_track, int p_index, const Vector2 &p_handle) { ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; ERR_FAIL_COND(t->type != TYPE_BEZIER); @@ -2335,8 +2199,8 @@ void Animation::bezier_track_set_key_out_handle(int p_track, int p_index, const } emit_changed(); } -float Animation::bezier_track_get_key_value(int p_track, int p_index) const { +float Animation::bezier_track_get_key_value(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); @@ -2347,8 +2211,8 @@ float Animation::bezier_track_get_key_value(int p_track, int p_index) const { return bt->values[p_index].value.value; } -Vector2 Animation::bezier_track_get_key_in_handle(int p_track, int p_index) const { +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]; ERR_FAIL_COND_V(t->type != TYPE_BEZIER, Vector2()); @@ -2359,8 +2223,8 @@ Vector2 Animation::bezier_track_get_key_in_handle(int p_track, int p_index) cons return bt->values[p_index].value.in_handle; } -Vector2 Animation::bezier_track_get_key_out_handle(int p_track, int p_index) const { +Vector2 Animation::bezier_track_get_key_out_handle(int p_track, int p_index) const { ERR_FAIL_INDEX_V(p_track, tracks.size(), Vector2()); Track *t = tracks[p_track]; ERR_FAIL_COND_V(t->type != TYPE_BEZIER, Vector2()); @@ -2430,7 +2294,6 @@ float Animation::bezier_track_interpolate(int p_track, float p_time) const { //narrow high and low as much as possible for (int i = 0; i < iterations; i++) { - middle = (low + high) / 2; Vector2 interp = _bezier_interp(middle, start, start_out, end_in, end); @@ -2447,11 +2310,10 @@ float Animation::bezier_track_interpolate(int p_track, float p_time) const { Vector2 high_pos = _bezier_interp(high, start, start_out, end_in, end); float c = (t - low_pos.x) / (high_pos.x - low_pos.x); - return low_pos.linear_interpolate(high_pos, c).y; + return low_pos.lerp(high_pos, c).y; } int Animation::audio_track_insert_key(int p_track, float p_time, const RES &p_stream, float p_start_offset, float p_end_offset) { - ERR_FAIL_INDEX_V(p_track, tracks.size(), -1); Track *t = tracks[p_track]; ERR_FAIL_COND_V(t->type != TYPE_AUDIO, -1); @@ -2462,11 +2324,13 @@ int Animation::audio_track_insert_key(int p_track, float p_time, const RES &p_st k.time = p_time; k.value.stream = p_stream; k.value.start_offset = p_start_offset; - if (k.value.start_offset < 0) + if (k.value.start_offset < 0) { k.value.start_offset = 0; + } k.value.end_offset = p_end_offset; - if (k.value.end_offset < 0) + if (k.value.end_offset < 0) { k.value.end_offset = 0; + } int key = _insert(p_time, at->values, k); @@ -2476,7 +2340,6 @@ int Animation::audio_track_insert_key(int p_track, float p_time, const RES &p_st } void Animation::audio_track_set_key_stream(int p_track, int p_key, const RES &p_stream) { - ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; ERR_FAIL_COND(t->type != TYPE_AUDIO); @@ -2491,7 +2354,6 @@ void Animation::audio_track_set_key_stream(int p_track, int p_key, const RES &p_ } void Animation::audio_track_set_key_start_offset(int p_track, int p_key, float p_offset) { - ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; ERR_FAIL_COND(t->type != TYPE_AUDIO); @@ -2500,8 +2362,9 @@ void Animation::audio_track_set_key_start_offset(int p_track, int p_key, float p ERR_FAIL_INDEX(p_key, at->values.size()); - if (p_offset < 0) + if (p_offset < 0) { p_offset = 0; + } at->values.write[p_key].value.start_offset = p_offset; @@ -2509,7 +2372,6 @@ void Animation::audio_track_set_key_start_offset(int p_track, int p_key, float p } void Animation::audio_track_set_key_end_offset(int p_track, int p_key, float p_offset) { - ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; ERR_FAIL_COND(t->type != TYPE_AUDIO); @@ -2518,8 +2380,9 @@ void Animation::audio_track_set_key_end_offset(int p_track, int p_key, float p_o ERR_FAIL_INDEX(p_key, at->values.size()); - if (p_offset < 0) + if (p_offset < 0) { p_offset = 0; + } at->values.write[p_key].value.end_offset = p_offset; @@ -2527,7 +2390,6 @@ void Animation::audio_track_set_key_end_offset(int p_track, int p_key, float p_o } RES Animation::audio_track_get_key_stream(int p_track, int p_key) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), RES()); const Track *t = tracks[p_track]; ERR_FAIL_COND_V(t->type != TYPE_AUDIO, RES()); @@ -2538,8 +2400,8 @@ RES Animation::audio_track_get_key_stream(int p_track, int p_key) const { return at->values[p_key].value.stream; } -float Animation::audio_track_get_key_start_offset(int p_track, int p_key) const { +float Animation::audio_track_get_key_start_offset(int p_track, int p_key) const { ERR_FAIL_INDEX_V(p_track, tracks.size(), 0); const Track *t = tracks[p_track]; ERR_FAIL_COND_V(t->type != TYPE_AUDIO, 0); @@ -2550,8 +2412,8 @@ float Animation::audio_track_get_key_start_offset(int p_track, int p_key) const return at->values[p_key].value.start_offset; } -float Animation::audio_track_get_key_end_offset(int p_track, int p_key) const { +float Animation::audio_track_get_key_end_offset(int p_track, int p_key) const { ERR_FAIL_INDEX_V(p_track, tracks.size(), 0); const Track *t = tracks[p_track]; ERR_FAIL_COND_V(t->type != TYPE_AUDIO, 0); @@ -2566,7 +2428,6 @@ float Animation::audio_track_get_key_end_offset(int p_track, int p_key) const { // int Animation::animation_track_insert_key(int p_track, float p_time, const StringName &p_animation) { - ERR_FAIL_INDEX_V(p_track, tracks.size(), -1); Track *t = tracks[p_track]; ERR_FAIL_COND_V(t->type != TYPE_ANIMATION, -1); @@ -2585,7 +2446,6 @@ int Animation::animation_track_insert_key(int p_track, float p_time, const Strin } void Animation::animation_track_set_key_animation(int p_track, int p_key, const StringName &p_animation) { - ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; ERR_FAIL_COND(t->type != TYPE_ANIMATION); @@ -2600,7 +2460,6 @@ void Animation::animation_track_set_key_animation(int p_track, int p_key, const } StringName Animation::animation_track_get_key_animation(int p_track, int p_key) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), StringName()); const Track *t = tracks[p_track]; ERR_FAIL_COND_V(t->type != TYPE_ANIMATION, StringName()); @@ -2613,57 +2472,49 @@ StringName Animation::animation_track_get_key_animation(int p_track, int p_key) } void Animation::set_length(float p_length) { - if (p_length < ANIM_MIN_LENGTH) { p_length = ANIM_MIN_LENGTH; } length = p_length; emit_changed(); } -float Animation::get_length() const { +float Animation::get_length() const { return length; } void Animation::set_loop(bool p_enabled) { - loop = p_enabled; emit_changed(); } -bool Animation::has_loop() const { +bool Animation::has_loop() const { return loop; } void Animation::track_set_imported(int p_track, bool p_imported) { - ERR_FAIL_INDEX(p_track, tracks.size()); tracks[p_track]->imported = p_imported; } bool Animation::track_is_imported(int p_track) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), false); return tracks[p_track]->imported; } void Animation::track_set_enabled(int p_track, bool p_enabled) { - ERR_FAIL_INDEX(p_track, tracks.size()); tracks[p_track]->enabled = p_enabled; emit_changed(); } bool Animation::track_is_enabled(int p_track) const { - ERR_FAIL_INDEX_V(p_track, tracks.size(), false); return tracks[p_track]->enabled; } void Animation::track_move_up(int p_track) { - if (p_track >= 0 && p_track < (tracks.size() - 1)) { - SWAP(tracks.write[p_track], tracks.write[p_track + 1]); } @@ -2672,9 +2523,7 @@ void Animation::track_move_up(int p_track) { } void Animation::track_move_down(int p_track) { - if (p_track > 0 && p_track < tracks.size()) { - SWAP(tracks.write[p_track], tracks.write[p_track - 1]); } @@ -2683,11 +2532,11 @@ void Animation::track_move_down(int p_track) { } void Animation::track_move_to(int p_track, int p_to_index) { - ERR_FAIL_INDEX(p_track, tracks.size()); ERR_FAIL_INDEX(p_to_index, tracks.size() + 1); - if (p_track == p_to_index || p_track == p_to_index - 1) + if (p_track == p_to_index || p_track == p_to_index - 1) { return; + } Track *track = tracks.get(p_track); tracks.remove(p_track); @@ -2699,11 +2548,11 @@ void Animation::track_move_to(int p_track, int p_to_index) { } void Animation::track_swap(int p_track, int p_with_track) { - ERR_FAIL_INDEX(p_track, tracks.size()); ERR_FAIL_INDEX(p_with_track, tracks.size()); - if (p_track == p_with_track) + if (p_track == p_with_track) { return; + } SWAP(tracks.write[p_track], tracks.write[p_with_track]); emit_changed(); @@ -2711,13 +2560,11 @@ void Animation::track_swap(int p_track, int p_with_track) { } void Animation::set_step(float p_step) { - step = p_step; emit_changed(); } float Animation::get_step() const { - return step; } @@ -2732,14 +2579,16 @@ void Animation::copy_track(int p_track, Ref<Animation> p_to_animation) { p_to_animation->track_set_enabled(dst_track, track_is_enabled(p_track)); p_to_animation->track_set_interpolation_type(dst_track, track_get_interpolation_type(p_track)); p_to_animation->track_set_interpolation_loop_wrap(dst_track, track_get_interpolation_loop_wrap(p_track)); - p_to_animation->value_track_set_update_mode(dst_track, value_track_get_update_mode(p_track)); + if (track_get_type(p_track) == TYPE_VALUE) { + p_to_animation->value_track_set_update_mode(dst_track, value_track_get_update_mode(p_track)); + } + for (int i = 0; i < track_get_key_count(p_track); i++) { p_to_animation->track_insert_key(dst_track, track_get_key_time(p_track, i), track_get_key_value(p_track, i), track_get_key_transition(p_track, i)); } } void Animation::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_track", "type", "at_position"), &Animation::add_track, DEFVAL(-1)); ClassDB::bind_method(D_METHOD("remove_track", "track_idx"), &Animation::remove_track); ClassDB::bind_method(D_METHOD("get_track_count"), &Animation::get_track_count); @@ -2825,9 +2674,9 @@ void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("clear"), &Animation::clear); ClassDB::bind_method(D_METHOD("copy_track", "track_idx", "to_animation"), &Animation::copy_track); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "length", PROPERTY_HINT_RANGE, "0.001,99999,0.001"), "set_length", "get_length"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0.001,99999,0.001"), "set_length", "get_length"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "step", PROPERTY_HINT_RANGE, "0,4096,0.001"), "set_step", "get_step"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step", PROPERTY_HINT_RANGE, "0,4096,0.001"), "set_step", "get_step"); ADD_SIGNAL(MethodInfo("tracks_changed")); @@ -2849,9 +2698,9 @@ void Animation::_bind_methods() { } void Animation::clear() { - - for (int i = 0; i < tracks.size(); i++) + for (int i = 0; i < tracks.size(); i++) { memdelete(tracks[i]); + } tracks.clear(); loop = false; length = 1; @@ -2860,7 +2709,6 @@ void Animation::clear() { } bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, const TKey<TransformKey> &t1, const TKey<TransformKey> &t2, float p_alowed_linear_err, float p_alowed_angular_err, float p_max_optimizable_angle, const Vector3 &p_norm) { - real_t c = (t1.time - t0.time) / (t2.time - t0.time); real_t t[3] = { -1, -1, -1 }; @@ -2878,7 +2726,6 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons } } else { - Vector3 pd = (v2 - v0); float d0 = pd.dot(v0); float d1 = pd.dot(v1); @@ -2888,14 +2735,15 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons } Vector3 s[2] = { v0, v2 }; - real_t d = Geometry::get_closest_point_to_segment(v1, s).distance_to(v1); + real_t d = Geometry3D::get_closest_point_to_segment(v1, s).distance_to(v1); if (d > pd.length() * p_alowed_linear_err) { return false; //beyond allowed error for colinearity } - if (p_norm != Vector3() && Math::acos(pd.normalized().dot(p_norm)) > p_alowed_angular_err) + if (p_norm != Vector3() && Math::acos(pd.normalized().dot(p_norm)) > p_alowed_angular_err) { return false; + } t[0] = (d1 - d0) / (d2 - d0); } @@ -2910,12 +2758,11 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons //localize both to rotation from q0 if (q0.is_equal_approx(q2)) { - - if (!q0.is_equal_approx(q1)) + if (!q0.is_equal_approx(q1)) { return false; + } } else { - Quat r02 = (q0.inverse() * q2).normalized(); Quat r01 = (q0.inverse() * q1).normalized(); @@ -2925,8 +2772,9 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons r02.get_axis_angle(v02, a02); r01.get_axis_angle(v01, a01); - if (Math::abs(a02) > p_max_optimizable_angle) + 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 @@ -2946,8 +2794,9 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons } real_t tr = a01 / a02; - if (tr < 0 || tr > 1) + if (tr < 0 || tr > 1) { return false; //rotating too much or too less + } t[1] = tr; } @@ -2967,7 +2816,6 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons } } else { - Vector3 pd = (v2 - v0); float d0 = pd.dot(v0); float d1 = pd.dot(v1); @@ -2977,7 +2825,7 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons } Vector3 s[2] = { v0, v2 }; - real_t d = Geometry::get_closest_point_to_segment(v1, s).distance_to(v1); + real_t d = Geometry3D::get_closest_point_to_segment(v1, s).distance_to(v1); if (d > pd.length() * p_alowed_linear_err) { return false; //beyond allowed error for colinearity @@ -2989,10 +2837,8 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons bool erase = false; if (t[0] == -1 && t[1] == -1 && t[2] == -1) { - erase = true; } else { - erase = true; real_t lt = -1; for (int j = 0; j < 3; j++) { @@ -3001,8 +2847,9 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons lt = t[j]; //official t //validate rest for (int k = j + 1; k < 3; k++) { - if (t[k] == -1) + if (t[k] == -1) { continue; + } if (Math::abs(lt - t[k]) > p_alowed_linear_err) { erase = false; @@ -3016,7 +2863,6 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons ERR_FAIL_COND_V(lt == -1, false); if (erase) { - if (Math::abs(lt - c) > p_alowed_linear_err) { //todo, evaluate changing the transition if this fails? //this could be done as a second pass and would be @@ -3030,7 +2876,6 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons } void Animation::_transform_track_optimize(int p_idx, float p_allowed_linear_err, float p_allowed_angular_err, float p_max_optimizable_angle) { - ERR_FAIL_INDEX(p_idx, tracks.size()); ERR_FAIL_COND(tracks[p_idx]->type != TYPE_TRANSFORM); TransformTrack *tt = static_cast<TransformTrack *>(tracks[p_idx]); @@ -3040,7 +2885,6 @@ void Animation::_transform_track_optimize(int p_idx, float p_allowed_linear_err, Vector3 norm; for (int i = 1; i < tt->transforms.size() - 1; i++) { - TKey<TransformKey> &t0 = tt->transforms.write[i - 1]; TKey<TransformKey> &t1 = tt->transforms.write[i]; TKey<TransformKey> &t2 = tt->transforms.write[i + 1]; @@ -3056,7 +2900,6 @@ void Animation::_transform_track_optimize(int p_idx, float p_allowed_linear_err, } if (erase) { - if (!prev_erased) { first_erased = t1; prev_erased = true; @@ -3073,23 +2916,21 @@ void Animation::_transform_track_optimize(int p_idx, float p_allowed_linear_err, } void Animation::optimize(float p_allowed_linear_err, float p_allowed_angular_err, float p_max_optimizable_angle) { - for (int i = 0; i < tracks.size(); i++) { - - if (tracks[i]->type == TYPE_TRANSFORM) + if (tracks[i]->type == TYPE_TRANSFORM) { _transform_track_optimize(i, p_allowed_linear_err, p_allowed_angular_err, p_max_optimizable_angle); + } } } Animation::Animation() { - step = 0.1; loop = false; length = 1; } Animation::~Animation() { - - for (int i = 0; i < tracks.size(); i++) + for (int i = 0; i < tracks.size(); i++) { memdelete(tracks[i]); + } } diff --git a/scene/resources/animation.h b/scene/resources/animation.h index 6ac0ea04d9..722a400fd6 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -34,7 +34,6 @@ #include "core/resource.h" class Animation : public Resource { - GDCLASS(Animation, Resource); RES_BASE_EXTENSION("anim"); @@ -64,7 +63,6 @@ public: private: struct Track { - TrackType type; InterpolationType interpolation; bool loop_wrap; @@ -81,21 +79,21 @@ private: }; struct Key { - float transition; float time; // time in secs - Key() { transition = 1; } + Key() { + transition = 1; + time = 0; + } }; // transform key holds either Vector3 or Quaternion template <class T> struct TKey : public Key { - T value; }; struct TransformKey { - Vector3 loc; Quat rot; Vector3 scale; @@ -104,8 +102,7 @@ private: /* TRANSFORM TRACK */ struct TransformTrack : public Track { - - Vector<TKey<TransformKey> > transforms; + Vector<TKey<TransformKey>> transforms; TransformTrack() { type = TYPE_TRANSFORM; } }; @@ -113,10 +110,9 @@ private: /* PROPERTY VALUE TRACK */ struct ValueTrack : public Track { - UpdateMode update_mode; bool update_on_seek; - Vector<TKey<Variant> > values; + Vector<TKey<Variant>> values; ValueTrack() { type = TYPE_VALUE; @@ -127,13 +123,11 @@ private: /* METHOD TRACK */ struct MethodKey : public Key { - StringName method; Vector<Variant> params; }; struct MethodTrack : public Track { - Vector<MethodKey> methods; MethodTrack() { type = TYPE_METHOD; } }; @@ -147,8 +141,7 @@ private: }; struct BezierTrack : public Track { - - Vector<TKey<BezierKey> > values; + Vector<TKey<BezierKey>> values; BezierTrack() { type = TYPE_BEZIER; @@ -168,8 +161,7 @@ private: }; struct AudioTrack : public Track { - - Vector<TKey<AudioKey> > values; + Vector<TKey<AudioKey>> values; AudioTrack() { type = TYPE_AUDIO; @@ -179,8 +171,7 @@ private: /* AUDIO TRACK */ struct AnimationTrack : public Track { - - Vector<TKey<StringName> > values; + Vector<TKey<StringName>> values; AnimationTrack() { type = TYPE_ANIMATION; @@ -216,7 +207,7 @@ private: _FORCE_INLINE_ float _cubic_interpolate(const float &p_pre_a, const float &p_a, const float &p_b, const float &p_post_b, float p_c) const; template <class T> - _FORCE_INLINE_ T _interpolate(const Vector<TKey<T> > &p_keys, float p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok) const; + _FORCE_INLINE_ T _interpolate(const Vector<TKey<T>> &p_keys, float p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok) const; template <class T> _FORCE_INLINE_ void _track_get_key_indices_in_range(const Vector<T> &p_array, float from_time, float to_time, List<int> *p_indices) const; @@ -242,26 +233,22 @@ private: return ret; } - PoolVector<int> _value_track_get_key_indices(int p_track, float p_time, float p_delta) const { - + Vector<int> _value_track_get_key_indices(int p_track, float p_time, float p_delta) const { List<int> idxs; value_track_get_key_indices(p_track, p_time, p_delta, &idxs); - PoolVector<int> idxr; + Vector<int> idxr; for (List<int>::Element *E = idxs.front(); E; E = E->next()) { - idxr.push_back(E->get()); } return idxr; } - PoolVector<int> _method_track_get_key_indices(int p_track, float p_time, float p_delta) const { - + Vector<int> _method_track_get_key_indices(int p_track, float p_time, float p_delta) const { List<int> idxs; method_track_get_key_indices(p_track, p_time, p_delta, &idxs); - PoolVector<int> idxr; + Vector<int> idxr; for (List<int>::Element *E = idxs.front(); E; E = E->next()) { - idxr.push_back(E->get()); } return idxr; diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp index e8cb40154e..f02e7987a9 100644 --- a/scene/resources/audio_stream_sample.cpp +++ b/scene/resources/audio_stream_sample.cpp @@ -34,7 +34,6 @@ #include "core/os/file_access.h" void AudioStreamPlaybackSample::start(float p_from_pos) { - if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) { //no seeking in IMA_ADPCM for (int i = 0; i < 2; i++) { @@ -57,28 +56,25 @@ void AudioStreamPlaybackSample::start(float p_from_pos) { } void AudioStreamPlaybackSample::stop() { - active = false; } bool AudioStreamPlaybackSample::is_playing() const { - return active; } int AudioStreamPlaybackSample::get_loop_count() const { - return 0; } float AudioStreamPlaybackSample::get_playback_position() const { - return float(offset >> MIX_FRAC_BITS) / base->mix_rate; } -void AudioStreamPlaybackSample::seek(float p_time) { - if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) +void AudioStreamPlaybackSample::seek(float p_time) { + if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM) { return; //no seeking in ima-adpcm + } float max = base->get_length(); if (p_time < 0) { @@ -92,22 +88,20 @@ void AudioStreamPlaybackSample::seek(float p_time) { template <class Depth, bool is_stereo, bool is_ima_adpcm> void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &offset, int32_t &increment, uint32_t amount, IMA_ADPCM_State *ima_adpcm) { - // this function will be compiled branchless by any decent compiler int32_t final, final_r, next, next_r; while (amount) { amount--; int64_t pos = offset >> MIX_FRAC_BITS; - if (is_stereo && !is_ima_adpcm) + if (is_stereo && !is_ima_adpcm) { pos <<= 1; + } if (is_ima_adpcm) { - int64_t sample_pos = pos + ima_adpcm[0].window_ofs; while (sample_pos > ima_adpcm[0].last_nibble) { - static const int16_t _ima_adpcm_step_table[89] = { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, @@ -126,7 +120,6 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds }; for (int i = 0; i < (is_stereo ? 2 : 1); i++) { - int16_t nibble, diff, step; ima_adpcm[i].last_nibble++; @@ -138,30 +131,36 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds step = _ima_adpcm_step_table[ima_adpcm[i].step_index]; ima_adpcm[i].step_index += _ima_adpcm_index_table[nibble]; - if (ima_adpcm[i].step_index < 0) + if (ima_adpcm[i].step_index < 0) { ima_adpcm[i].step_index = 0; - if (ima_adpcm[i].step_index > 88) + } + if (ima_adpcm[i].step_index > 88) { ima_adpcm[i].step_index = 88; + } diff = step >> 3; - if (nibble & 1) + if (nibble & 1) { diff += step >> 2; - if (nibble & 2) + } + if (nibble & 2) { diff += step >> 1; - if (nibble & 4) + } + if (nibble & 4) { diff += step; - if (nibble & 8) + } + if (nibble & 8) { diff = -diff; + } ima_adpcm[i].predictor += diff; - if (ima_adpcm[i].predictor < -0x8000) + if (ima_adpcm[i].predictor < -0x8000) { ima_adpcm[i].predictor = -0x8000; - else if (ima_adpcm[i].predictor > 0x7FFF) + } else if (ima_adpcm[i].predictor > 0x7FFF) { ima_adpcm[i].predictor = 0x7FFF; + } /* store loop if there */ if (ima_adpcm[i].last_nibble == ima_adpcm[i].loop_pos) { - ima_adpcm[i].loop_step_index = ima_adpcm[i].step_index; ima_adpcm[i].loop_predictor = ima_adpcm[i].predictor; } @@ -177,17 +176,18 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds } else { final = p_src[pos]; - if (is_stereo) + if (is_stereo) { final_r = p_src[pos + 1]; + } if (sizeof(Depth) == 1) { /* conditions will not exist anymore when compiled! */ final <<= 8; - if (is_stereo) + if (is_stereo) { final_r <<= 8; + } } if (is_stereo) { - next = p_src[pos + 2]; next_r = p_src[pos + 3]; } else { @@ -196,15 +196,17 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds if (sizeof(Depth) == 1) { next <<= 8; - if (is_stereo) + if (is_stereo) { next_r <<= 8; + } } int32_t frac = int64_t(offset & MIX_FRAC_MASK); final = final + ((next - final) * frac >> MIX_FRAC_BITS); - if (is_stereo) + if (is_stereo) { final_r = final_r + ((next_r - final_r) * frac >> MIX_FRAC_BITS); + } } if (!is_stereo) { @@ -220,7 +222,6 @@ void AudioStreamPlaybackSample::do_resample(const Depth *p_src, AudioFrame *p_ds } void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) { - if (!base->data || !active) { for (int i = 0; i < p_frames; i++) { p_buffer[i] = AudioFrame(0, 0); @@ -230,9 +231,15 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in int len = base->data_bytes; switch (base->format) { - case AudioStreamSample::FORMAT_8_BITS: len /= 1; break; - case AudioStreamSample::FORMAT_16_BITS: len /= 2; break; - case AudioStreamSample::FORMAT_IMA_ADPCM: len *= 2; break; + case AudioStreamSample::FORMAT_8_BITS: + len /= 1; + break; + case AudioStreamSample::FORMAT_16_BITS: + len /= 2; + break; + case AudioStreamSample::FORMAT_IMA_ADPCM: + len *= 2; + break; } if (base->stereo) { @@ -258,7 +265,7 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in float srate = base->mix_rate; srate *= p_rate_scale; float fincrement = srate / base_rate; - int32_t increment = int32_t(fincrement * MIX_FRAC_LEN); + int32_t increment = int32_t(MAX(fincrement * MIX_FRAC_LEN, 1)); increment *= sign; //looping @@ -273,7 +280,6 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in AudioFrame *dst_buff = p_buffer; if (format == AudioStreamSample::FORMAT_IMA_ADPCM) { - if (loop_format != AudioStreamSample::LOOP_DISABLED) { ima_adpcm[0].loop_pos = loop_begin_fp >> MIX_FRAC_BITS; ima_adpcm[1].loop_pos = loop_begin_fp >> MIX_FRAC_BITS; @@ -282,7 +288,6 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in } while (todo > 0) { - int64_t limit = 0; int32_t target = 0, aux = 0; @@ -305,7 +310,6 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in } else { /* check for sample not reaching beginning */ if (offset < 0) { - active = false; break; } @@ -337,7 +341,6 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in } else { /* no loop, check for end of sample */ if (offset >= length_fp) { - active = false; break; } @@ -363,24 +366,26 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in switch (base->format) { case AudioStreamSample::FORMAT_8_BITS: { - - if (is_stereo) + if (is_stereo) { do_resample<int8_t, true, false>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm); - else + } else { do_resample<int8_t, false, false>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm); + } } break; case AudioStreamSample::FORMAT_16_BITS: { - if (is_stereo) + if (is_stereo) { do_resample<int16_t, true, false>((int16_t *)data, dst_buff, offset, increment, target, ima_adpcm); - else + } else { do_resample<int16_t, false, false>((int16_t *)data, dst_buff, offset, increment, target, ima_adpcm); + } } break; case AudioStreamSample::FORMAT_IMA_ADPCM: { - if (is_stereo) + if (is_stereo) { do_resample<int8_t, true, true>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm); - else + } else { do_resample<int8_t, false, true>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm); + } } break; } @@ -398,7 +403,6 @@ void AudioStreamPlaybackSample::mix(AudioFrame *p_buffer, float p_rate_scale, in } AudioStreamPlaybackSample::AudioStreamPlaybackSample() { - active = false; offset = 0; sign = 1; @@ -407,67 +411,66 @@ AudioStreamPlaybackSample::AudioStreamPlaybackSample() { ///////////////////// void AudioStreamSample::set_format(Format p_format) { - format = p_format; } AudioStreamSample::Format AudioStreamSample::get_format() const { - return format; } void AudioStreamSample::set_loop_mode(LoopMode p_loop_mode) { - loop_mode = p_loop_mode; } -AudioStreamSample::LoopMode AudioStreamSample::get_loop_mode() const { +AudioStreamSample::LoopMode AudioStreamSample::get_loop_mode() const { return loop_mode; } void AudioStreamSample::set_loop_begin(int p_frame) { - loop_begin = p_frame; } -int AudioStreamSample::get_loop_begin() const { +int AudioStreamSample::get_loop_begin() const { return loop_begin; } void AudioStreamSample::set_loop_end(int p_frame) { - loop_end = p_frame; } -int AudioStreamSample::get_loop_end() const { +int AudioStreamSample::get_loop_end() const { return loop_end; } void AudioStreamSample::set_mix_rate(int p_hz) { - ERR_FAIL_COND(p_hz == 0); mix_rate = p_hz; } -int AudioStreamSample::get_mix_rate() const { +int AudioStreamSample::get_mix_rate() const { return mix_rate; } -void AudioStreamSample::set_stereo(bool p_enable) { +void AudioStreamSample::set_stereo(bool p_enable) { stereo = p_enable; } -bool AudioStreamSample::is_stereo() const { +bool AudioStreamSample::is_stereo() const { return stereo; } float AudioStreamSample::get_length() const { - int len = data_bytes; switch (format) { - case AudioStreamSample::FORMAT_8_BITS: len /= 1; break; - case AudioStreamSample::FORMAT_16_BITS: len /= 2; break; - case AudioStreamSample::FORMAT_IMA_ADPCM: len *= 2; break; + case AudioStreamSample::FORMAT_8_BITS: + len /= 1; + break; + case AudioStreamSample::FORMAT_16_BITS: + len /= 2; + break; + case AudioStreamSample::FORMAT_IMA_ADPCM: + len *= 2; + break; } if (stereo) { @@ -477,40 +480,37 @@ float AudioStreamSample::get_length() const { return float(len) / mix_rate; } -void AudioStreamSample::set_data(const PoolVector<uint8_t> &p_data) { - +void AudioStreamSample::set_data(const Vector<uint8_t> &p_data) { AudioServer::get_singleton()->lock(); if (data) { - AudioServer::get_singleton()->audio_data_free(data); - data = NULL; + memfree(data); + data = nullptr; data_bytes = 0; } int datalen = p_data.size(); if (datalen) { - - PoolVector<uint8_t>::Read r = p_data.read(); + const uint8_t *r = p_data.ptr(); int alloc_len = datalen + DATA_PAD * 2; - data = AudioServer::get_singleton()->audio_data_alloc(alloc_len); //alloc with some padding for interpolation + data = memalloc(alloc_len); //alloc with some padding for interpolation zeromem(data, alloc_len); uint8_t *dataptr = (uint8_t *)data; - copymem(dataptr + DATA_PAD, r.ptr(), datalen); + copymem(dataptr + DATA_PAD, r, datalen); data_bytes = datalen; } AudioServer::get_singleton()->unlock(); } -PoolVector<uint8_t> AudioStreamSample::get_data() const { - PoolVector<uint8_t> pv; +Vector<uint8_t> AudioStreamSample::get_data() const { + Vector<uint8_t> pv; if (data) { pv.resize(data_bytes); { - - PoolVector<uint8_t>::Write w = pv.write(); + uint8_t *w = pv.ptrw(); uint8_t *dataptr = (uint8_t *)data; - copymem(w.ptr(), dataptr + DATA_PAD, data_bytes); + copymem(w, dataptr + DATA_PAD, data_bytes); } } @@ -519,7 +519,7 @@ PoolVector<uint8_t> AudioStreamSample::get_data() const { Error AudioStreamSample::save_to_wav(const String &p_path) { if (format == AudioStreamSample::FORMAT_IMA_ADPCM) { - WARN_PRINTS("Saving IMA_ADPC samples are not supported yet"); + WARN_PRINT("Saving IMA_ADPC samples are not supported yet"); return ERR_UNAVAILABLE; } @@ -536,9 +536,15 @@ Error AudioStreamSample::save_to_wav(const String &p_path) { int byte_pr_sample = 0; switch (format) { - case AudioStreamSample::FORMAT_8_BITS: byte_pr_sample = 1; break; - case AudioStreamSample::FORMAT_16_BITS: byte_pr_sample = 2; break; - case AudioStreamSample::FORMAT_IMA_ADPCM: byte_pr_sample = 4; break; + case AudioStreamSample::FORMAT_8_BITS: + byte_pr_sample = 1; + break; + case AudioStreamSample::FORMAT_16_BITS: + byte_pr_sample = 2; + break; + case AudioStreamSample::FORMAT_IMA_ADPCM: + byte_pr_sample = 4; + break; } String file_path = p_path; @@ -566,8 +572,8 @@ Error AudioStreamSample::save_to_wav(const String &p_path) { file->store_32(sub_chunk_2_size); //Subchunk2Size // Add data - PoolVector<uint8_t> data = get_data(); - PoolVector<uint8_t>::Read read_data = data.read(); + Vector<uint8_t> data = get_data(); + const uint8_t *read_data = data.ptr(); switch (format) { case AudioStreamSample::FORMAT_8_BITS: for (unsigned int i = 0; i < data_bytes; i++) { @@ -592,7 +598,6 @@ Error AudioStreamSample::save_to_wav(const String &p_path) { } Ref<AudioStreamPlayback> AudioStreamSample::instance_playback() { - Ref<AudioStreamPlaybackSample> sample; sample.instance(); sample->base = Ref<AudioStreamSample>(this); @@ -600,12 +605,10 @@ Ref<AudioStreamPlayback> AudioStreamSample::instance_playback() { } String AudioStreamSample::get_stream_name() const { - return ""; } void AudioStreamSample::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamSample::set_data); ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamSample::get_data); @@ -629,7 +632,7 @@ void AudioStreamSample::_bind_methods() { ClassDB::bind_method(D_METHOD("save_to_wav", "path"), &AudioStreamSample::save_to_wav); - ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_data", "get_data"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_data", "get_data"); ADD_PROPERTY(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_ENUM, "8-Bit,16-Bit,IMA-ADPCM"), "set_format", "get_format"); ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "Disabled,Forward,Ping-Pong,Backward"), "set_loop_mode", "get_loop_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_begin"), "set_loop_begin", "get_loop_begin"); @@ -654,14 +657,14 @@ AudioStreamSample::AudioStreamSample() { loop_begin = 0; loop_end = 0; mix_rate = 44100; - data = NULL; + data = nullptr; data_bytes = 0; } AudioStreamSample::~AudioStreamSample() { if (data) { - AudioServer::get_singleton()->audio_data_free(data); - data = NULL; + memfree(data); + data = nullptr; data_bytes = 0; } } diff --git a/scene/resources/audio_stream_sample.h b/scene/resources/audio_stream_sample.h index adcac14ea8..d91cdef57d 100644 --- a/scene/resources/audio_stream_sample.h +++ b/scene/resources/audio_stream_sample.h @@ -36,7 +36,6 @@ class AudioStreamSample; class AudioStreamPlaybackSample : public AudioStreamPlayback { - GDCLASS(AudioStreamPlaybackSample, AudioStreamPlayback); enum { MIX_FRAC_BITS = 13, @@ -45,7 +44,6 @@ class AudioStreamPlaybackSample : public AudioStreamPlayback { }; struct IMA_ADPCM_State { - int16_t step_index; int32_t predictor; /* values at loop point */ @@ -66,16 +64,16 @@ class AudioStreamPlaybackSample : public AudioStreamPlayback { void do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &offset, int32_t &increment, uint32_t amount, IMA_ADPCM_State *ima_adpcm); public: - virtual void start(float p_from_pos = 0.0); - virtual void stop(); - virtual bool is_playing() const; + virtual void start(float p_from_pos = 0.0) override; + virtual void stop() override; + virtual bool is_playing() const override; - virtual int get_loop_count() const; //times it looped + virtual int get_loop_count() const override; //times it looped - virtual float get_playback_position() const; - virtual void seek(float p_time); + virtual float get_playback_position() const override; + virtual void seek(float p_time) override; - virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames); + virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override; AudioStreamPlaybackSample(); }; @@ -136,15 +134,15 @@ public: void set_stereo(bool p_enable); bool is_stereo() const; - virtual float get_length() const; //if supported, otherwise return 0 + virtual float get_length() const override; //if supported, otherwise return 0 - void set_data(const PoolVector<uint8_t> &p_data); - PoolVector<uint8_t> get_data() const; + void set_data(const Vector<uint8_t> &p_data); + Vector<uint8_t> get_data() const; Error save_to_wav(const String &p_path); - virtual Ref<AudioStreamPlayback> instance_playback(); - virtual String get_stream_name() const; + virtual Ref<AudioStreamPlayback> instance_playback() override; + virtual String get_stream_name() const override; AudioStreamSample(); ~AudioStreamSample(); diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp index 06323a8d31..10f0de8ff8 100644 --- a/scene/resources/bit_map.cpp +++ b/scene/resources/bit_map.cpp @@ -33,7 +33,6 @@ #include "core/io/image_loader.h" void BitMap::create(const Size2 &p_size) { - ERR_FAIL_COND(p_size.width < 1); ERR_FAIL_COND(p_size.height < 1); @@ -44,7 +43,6 @@ void BitMap::create(const Size2 &p_size) { } void BitMap::create_from_image_alpha(const Ref<Image> &p_image, float p_threshold) { - ERR_FAIL_COND(p_image.is_null() || p_image->empty()); Ref<Image> img = p_image->duplicate(); img->convert(Image::FORMAT_LA8); @@ -52,11 +50,10 @@ void BitMap::create_from_image_alpha(const Ref<Image> &p_image, float p_threshol create(Size2(img->get_width(), img->get_height())); - PoolVector<uint8_t>::Read r = img->get_data().read(); + const uint8_t *r = img->get_data().ptr(); uint8_t *w = bitmask.ptrw(); for (int i = 0; i < width * height; i++) { - int bbyte = i / 8; int bbit = i % 8; if (r[i * 2 + 1] / 255.0 > p_threshold) { @@ -66,24 +63,22 @@ void BitMap::create_from_image_alpha(const Ref<Image> &p_image, float p_threshol } void BitMap::set_bit_rect(const Rect2 &p_rect, bool p_value) { - Rect2i current = Rect2i(0, 0, width, height).clip(p_rect); uint8_t *data = bitmask.ptrw(); for (int i = current.position.x; i < current.position.x + current.size.x; i++) { - for (int j = current.position.y; j < current.position.y + current.size.y; j++) { - int ofs = width * j + i; int bbyte = ofs / 8; int bbit = ofs % 8; uint8_t b = data[bbyte]; - if (p_value) + if (p_value) { b |= (1 << bbit); - else + } else { b &= ~(1 << bbit); + } data[bbyte] = b; } @@ -91,7 +86,6 @@ void BitMap::set_bit_rect(const Rect2 &p_rect, bool p_value) { } int BitMap::get_true_bit_count() const { - int ds = bitmask.size(); const uint8_t *d = bitmask.ptr(); int c = 0; @@ -99,7 +93,6 @@ int BitMap::get_true_bit_count() const { //fast, almost branchless version for (int i = 0; i < ds; i++) { - c += (d[i] & (1 << 7)) >> 7; c += (d[i] & (1 << 6)) >> 6; c += (d[i] & (1 << 5)) >> 5; @@ -114,7 +107,6 @@ int BitMap::get_true_bit_count() const { } void BitMap::set_bit(const Point2 &p_pos, bool p_value) { - int x = p_pos.x; int y = p_pos.y; @@ -127,16 +119,16 @@ void BitMap::set_bit(const Point2 &p_pos, bool p_value) { uint8_t b = bitmask[bbyte]; - if (p_value) + if (p_value) { b |= (1 << bbit); - else + } else { b &= ~(1 << bbit); + } bitmask.write[bbyte] = b; } bool BitMap::get_bit(const Point2 &p_pos) const { - int x = Math::fast_ftoi(p_pos.x); int y = Math::fast_ftoi(p_pos.y); ERR_FAIL_INDEX_V(x, width, false); @@ -150,12 +142,10 @@ bool BitMap::get_bit(const Point2 &p_pos) const { } Size2 BitMap::get_size() const { - return Size2(width, height); } void BitMap::_set_data(const Dictionary &p_d) { - ERR_FAIL_COND(!p_d.has("size")); ERR_FAIL_COND(!p_d.has("data")); @@ -164,7 +154,6 @@ void BitMap::_set_data(const Dictionary &p_d) { } Dictionary BitMap::_get_data() const { - Dictionary d; d["size"] = get_size(); d["data"] = bitmask; @@ -172,7 +161,6 @@ Dictionary BitMap::_get_data() const { } Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start) const { - int stepx = 0; int stepy = 0; int prevx = 0; @@ -209,7 +197,6 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start) } switch (sv) { - case 1: case 5: case 13: @@ -354,8 +341,9 @@ static float perpendicular_distance(const Vector2 &i, const Vector2 &start, cons } static Vector<Vector2> rdp(const Vector<Vector2> &v, float optimization) { - if (v.size() < 3) + if (v.size() < 3) { return v; + } int index = -1; float dist = 0; @@ -368,7 +356,6 @@ static Vector<Vector2> rdp(const Vector<Vector2> &v, float optimization) { } } if (dist > optimization) { - Vector<Vector2> left, right; left.resize(index); for (int i = 0; i < index; i++) { @@ -424,9 +411,8 @@ struct FillBitsStackEntry { }; static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_pos, const Rect2i &rect) { - // Using a custom stack to work iteratively to avoid stack overflow on big bitmaps - PoolVector<FillBitsStackEntry> stack; + Vector<FillBitsStackEntry> stack; // Tracking size since we won't be shrinking the stack vector int stack_size = 0; @@ -453,15 +439,17 @@ static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_ continue; } - if (i < rect.position.x || i >= rect.position.x + rect.size.x) + if (i < rect.position.x || i >= rect.position.x + rect.size.x) { continue; - if (j < rect.position.y || j >= rect.position.y + rect.size.y) + } + if (j < rect.position.y || j >= rect.position.y + rect.size.y) { continue; + } - if (p_map->get_bit(Vector2(i, j))) + if (p_map->get_bit(Vector2(i, j))) { continue; - else if (p_src->get_bit(Vector2(i, j))) { + } else if (p_src->get_bit(Vector2(i, j))) { p_map->set_bit(Vector2(i, j), true); FillBitsStackEntry se = { pos, i, j }; @@ -493,8 +481,7 @@ static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_ print_verbose("BitMap: Max stack size: " + itos(stack.size())); } -Vector<Vector<Vector2> > BitMap::clip_opaque_to_polygons(const Rect2 &p_rect, float p_epsilon) const { - +Vector<Vector<Vector2>> BitMap::clip_opaque_to_polygons(const Rect2 &p_rect, float p_epsilon) const { Rect2i r = Rect2i(0, 0, width, height).clip(p_rect); print_verbose("BitMap: Rect: " + r); @@ -503,11 +490,10 @@ Vector<Vector<Vector2> > BitMap::clip_opaque_to_polygons(const Rect2 &p_rect, fl fill.instance(); fill->create(get_size()); - Vector<Vector<Vector2> > polygons; + Vector<Vector<Vector2>> polygons; for (int i = r.position.y; i < r.position.y + r.size.height; i++) { for (int j = r.position.x; j < r.position.x + r.size.width; j++) { if (!fill->get_bit(Point2(j, i)) && get_bit(Point2(j, i))) { - fill_bits(this, fill, Point2i(j, i), r); Vector<Vector2> polygon = _march_square(r, Point2i(j, i)); @@ -529,7 +515,6 @@ Vector<Vector<Vector2> > BitMap::clip_opaque_to_polygons(const Rect2 &p_rect, fl } void BitMap::grow_mask(int p_pixels, const Rect2 &p_rect) { - if (p_pixels == 0) { return; } @@ -546,35 +531,38 @@ void BitMap::grow_mask(int p_pixels, const Rect2 &p_rect) { for (int i = r.position.y; i < r.position.y + r.size.height; i++) { for (int j = r.position.x; j < r.position.x + r.size.width; j++) { - if (bit_value == get_bit(Point2(j, i))) + if (bit_value == get_bit(Point2(j, i))) { continue; + } bool found = false; for (int y = i - p_pixels; y <= i + p_pixels; y++) { for (int x = j - p_pixels; x <= j + p_pixels; x++) { - bool outside = false; if ((x < p_rect.position.x) || (x >= p_rect.position.x + p_rect.size.x) || (y < p_rect.position.y) || (y >= p_rect.position.y + p_rect.size.y)) { // outside of rectangle counts as bit not set - if (!bit_value) + if (!bit_value) { outside = true; - else + } else { continue; + } } float d = Point2(j, i).distance_to(Point2(x, y)) - CMP_EPSILON; - if (d > p_pixels) + if (d > p_pixels) { continue; + } if (outside || (bit_value == copy->get_bit(Point2(x, y)))) { found = true; break; } } - if (found) + if (found) { break; + } } if (found) { @@ -585,27 +573,24 @@ void BitMap::grow_mask(int p_pixels, const Rect2 &p_rect) { } 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 { - - Vector<Vector<Vector2> > result = clip_opaque_to_polygons(p_rect, p_epsilon); + Vector<Vector<Vector2>> result = clip_opaque_to_polygons(p_rect, p_epsilon); // Convert result to bindable types Array result_array; result_array.resize(result.size()); for (int i = 0; i < result.size(); i++) { - const Vector<Vector2> &polygon = result[i]; - PoolVector2Array polygon_array; + PackedVector2Array polygon_array; polygon_array.resize(polygon.size()); { - PoolVector2Array::Write w = polygon_array.write(); + Vector2 *w = polygon_array.ptrw(); for (int j = 0; j < polygon.size(); j++) { w[j] = polygon[j]; } @@ -618,7 +603,6 @@ Array BitMap::_opaque_to_polygons_bind(const Rect2 &p_rect, float p_epsilon) con } void BitMap::resize(const Size2 &p_new_size) { - Ref<BitMap> new_bitmap; new_bitmap.instance(); new_bitmap->create(p_new_size); @@ -636,23 +620,20 @@ void BitMap::resize(const Size2 &p_new_size) { } Ref<Image> BitMap::convert_to_image() const { - Ref<Image> image; image.instance(); image->create(width, height, false, Image::FORMAT_L8); - image->lock(); + for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { image->set_pixel(i, j, get_bit(Point2(i, j)) ? Color(1, 1, 1) : Color(0, 0, 0)); } } - image->unlock(); - return image; } -void BitMap::blit(const Vector2 &p_pos, const Ref<BitMap> &p_bitmap) { +void BitMap::blit(const Vector2 &p_pos, const Ref<BitMap> &p_bitmap) { int x = p_pos.x; int y = p_pos.y; int w = p_bitmap->get_size().width; @@ -662,10 +643,12 @@ void BitMap::blit(const Vector2 &p_pos, const Ref<BitMap> &p_bitmap) { for (int j = 0; j < h; j++) { int px = x + i; int py = y + j; - if (px < 0 || px >= width) + if (px < 0 || px >= width) { continue; - if (py < 0 || py >= height) + } + if (py < 0 || py >= height) { continue; + } if (p_bitmap->get_bit(Vector2(i, j))) { set_bit(Vector2(x, y), true); } @@ -674,7 +657,6 @@ void BitMap::blit(const Vector2 &p_pos, const Ref<BitMap> &p_bitmap) { } void BitMap::_bind_methods() { - ClassDB::bind_method(D_METHOD("create", "size"), &BitMap::create); ClassDB::bind_method(D_METHOD("create_from_image_alpha", "image", "threshold"), &BitMap::create_from_image_alpha, DEFVAL(0.1)); @@ -696,7 +678,6 @@ void BitMap::_bind_methods() { } BitMap::BitMap() { - width = 0; height = 0; } diff --git a/scene/resources/bit_map.h b/scene/resources/bit_map.h index ed332dffa4..59f3b4dc3c 100644 --- a/scene/resources/bit_map.h +++ b/scene/resources/bit_map.h @@ -36,7 +36,6 @@ #include "core/resource.h" class BitMap : public Resource { - GDCLASS(BitMap, Resource); OBJ_SAVE_TYPE(BitMap); @@ -72,7 +71,7 @@ public: void blit(const Vector2 &p_pos, const Ref<BitMap> &p_bitmap); Ref<Image> convert_to_image() const; - Vector<Vector<Vector2> > clip_opaque_to_polygons(const Rect2 &p_rect, float p_epsilon = 2.0) const; + Vector<Vector<Vector2>> clip_opaque_to_polygons(const Rect2 &p_rect, float p_epsilon = 2.0) const; BitMap(); }; diff --git a/scene/resources/box_shape.cpp b/scene/resources/box_shape_3d.cpp index dee3943b8e..e1c8a377c0 100644 --- a/scene/resources/box_shape.cpp +++ b/scene/resources/box_shape_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* box_shape.cpp */ +/* box_shape_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "box_shape.h" -#include "servers/physics_server.h" - -Vector<Vector3> BoxShape::get_debug_mesh_lines() { +#include "box_shape_3d.h" +#include "servers/physics_server_3d.h" +Vector<Vector3> BoxShape3D::get_debug_mesh_lines() const { Vector<Vector3> lines; AABB aabb; aabb.position = -get_extents(); @@ -48,35 +47,34 @@ Vector<Vector3> BoxShape::get_debug_mesh_lines() { return lines; } -void BoxShape::_update_shape() { - - PhysicsServer::get_singleton()->shape_set_data(get_shape(), extents); - Shape::_update_shape(); +real_t BoxShape3D::get_enclosing_radius() const { + return extents.length(); } -void BoxShape::set_extents(const Vector3 &p_extents) { +void BoxShape3D::_update_shape() { + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), extents); + Shape3D::_update_shape(); +} +void BoxShape3D::set_extents(const Vector3 &p_extents) { extents = p_extents; _update_shape(); notify_change_to_owners(); _change_notify("extents"); } -Vector3 BoxShape::get_extents() const { - +Vector3 BoxShape3D::get_extents() const { return extents; } -void BoxShape::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_extents", "extents"), &BoxShape::set_extents); - ClassDB::bind_method(D_METHOD("get_extents"), &BoxShape::get_extents); +void BoxShape3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_extents", "extents"), &BoxShape3D::set_extents); + ClassDB::bind_method(D_METHOD("get_extents"), &BoxShape3D::get_extents); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents"); } -BoxShape::BoxShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_BOX)) { - +BoxShape3D::BoxShape3D() : + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_BOX)) { set_extents(Vector3(1, 1, 1)); } diff --git a/scene/resources/box_shape.h b/scene/resources/box_shape_3d.h index b577a70e1e..fe634ce568 100644 --- a/scene/resources/box_shape.h +++ b/scene/resources/box_shape_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* box_shape.h */ +/* box_shape_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -31,25 +31,25 @@ #ifndef BOX_SHAPE_H #define BOX_SHAPE_H -#include "scene/resources/shape.h" +#include "scene/resources/shape_3d.h" -class BoxShape : public Shape { - - GDCLASS(BoxShape, Shape); +class BoxShape3D : public Shape3D { + GDCLASS(BoxShape3D, Shape3D); Vector3 extents; protected: static void _bind_methods(); - virtual void _update_shape(); + virtual void _update_shape() override; public: void set_extents(const Vector3 &p_extents); Vector3 get_extents() const; - virtual Vector<Vector3> get_debug_mesh_lines(); + virtual Vector<Vector3> get_debug_mesh_lines() const override; + virtual real_t get_enclosing_radius() const override; - BoxShape(); + BoxShape3D(); }; #endif // BOX_SHAPE_H diff --git a/scene/resources/camera_effects.cpp b/scene/resources/camera_effects.cpp new file mode 100644 index 0000000000..6b6ed51ed0 --- /dev/null +++ b/scene/resources/camera_effects.cpp @@ -0,0 +1,197 @@ +/*************************************************************************/ +/* camera_effects.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "camera_effects.h" + +#include "servers/rendering_server.h" + +RID CameraEffects::get_rid() const { + return camera_effects; +} + +// DOF blur + +void CameraEffects::set_dof_blur_far_enabled(bool p_enabled) { + dof_blur_far_enabled = p_enabled; + _update_dof_blur(); + _change_notify(); +} + +bool CameraEffects::is_dof_blur_far_enabled() const { + return dof_blur_far_enabled; +} + +void CameraEffects::set_dof_blur_far_distance(float p_distance) { + dof_blur_far_distance = p_distance; + _update_dof_blur(); +} + +float CameraEffects::get_dof_blur_far_distance() const { + return dof_blur_far_distance; +} + +void CameraEffects::set_dof_blur_far_transition(float p_distance) { + dof_blur_far_transition = p_distance; + _update_dof_blur(); +} + +float CameraEffects::get_dof_blur_far_transition() const { + return dof_blur_far_transition; +} + +void CameraEffects::set_dof_blur_near_enabled(bool p_enabled) { + dof_blur_near_enabled = p_enabled; + _update_dof_blur(); + _change_notify(); +} + +bool CameraEffects::is_dof_blur_near_enabled() const { + return dof_blur_near_enabled; +} + +void CameraEffects::set_dof_blur_near_distance(float p_distance) { + dof_blur_near_distance = p_distance; + _update_dof_blur(); +} + +float CameraEffects::get_dof_blur_near_distance() const { + return dof_blur_near_distance; +} + +void CameraEffects::set_dof_blur_near_transition(float p_distance) { + dof_blur_near_transition = p_distance; + _update_dof_blur(); +} + +float CameraEffects::get_dof_blur_near_transition() const { + return dof_blur_near_transition; +} + +void CameraEffects::set_dof_blur_amount(float p_amount) { + dof_blur_amount = p_amount; + _update_dof_blur(); +} + +float CameraEffects::get_dof_blur_amount() const { + return dof_blur_amount; +} + +void CameraEffects::_update_dof_blur() { + RS::get_singleton()->camera_effects_set_dof_blur( + camera_effects, + dof_blur_far_enabled, + dof_blur_far_distance, + dof_blur_far_transition, + dof_blur_near_enabled, + dof_blur_near_distance, + dof_blur_near_transition, + dof_blur_amount); +} + +// Custom exposure + +void CameraEffects::set_override_exposure_enabled(bool p_enabled) { + override_exposure_enabled = p_enabled; + _update_override_exposure(); +} + +bool CameraEffects::is_override_exposure_enabled() const { + return override_exposure_enabled; +} + +void CameraEffects::set_override_exposure(float p_exposure) { + override_exposure = p_exposure; + _update_override_exposure(); +} + +float CameraEffects::get_override_exposure() const { + return override_exposure; +} + +void CameraEffects::_update_override_exposure() { + RS::get_singleton()->camera_effects_set_custom_exposure( + camera_effects, + override_exposure_enabled, + override_exposure); +} + +// Private methods, constructor and destructor + +void CameraEffects::_bind_methods() { + // DOF blur + + ClassDB::bind_method(D_METHOD("set_dof_blur_far_enabled", "enabled"), &CameraEffects::set_dof_blur_far_enabled); + ClassDB::bind_method(D_METHOD("is_dof_blur_far_enabled"), &CameraEffects::is_dof_blur_far_enabled); + ClassDB::bind_method(D_METHOD("set_dof_blur_far_distance", "distance"), &CameraEffects::set_dof_blur_far_distance); + ClassDB::bind_method(D_METHOD("get_dof_blur_far_distance"), &CameraEffects::get_dof_blur_far_distance); + ClassDB::bind_method(D_METHOD("set_dof_blur_far_transition", "distance"), &CameraEffects::set_dof_blur_far_transition); + ClassDB::bind_method(D_METHOD("get_dof_blur_far_transition"), &CameraEffects::get_dof_blur_far_transition); + + ClassDB::bind_method(D_METHOD("set_dof_blur_near_enabled", "enabled"), &CameraEffects::set_dof_blur_near_enabled); + ClassDB::bind_method(D_METHOD("is_dof_blur_near_enabled"), &CameraEffects::is_dof_blur_near_enabled); + ClassDB::bind_method(D_METHOD("set_dof_blur_near_distance", "distance"), &CameraEffects::set_dof_blur_near_distance); + ClassDB::bind_method(D_METHOD("get_dof_blur_near_distance"), &CameraEffects::get_dof_blur_near_distance); + ClassDB::bind_method(D_METHOD("set_dof_blur_near_transition", "distance"), &CameraEffects::set_dof_blur_near_transition); + ClassDB::bind_method(D_METHOD("get_dof_blur_near_transition"), &CameraEffects::get_dof_blur_near_transition); + + ClassDB::bind_method(D_METHOD("set_dof_blur_amount", "amount"), &CameraEffects::set_dof_blur_amount); + ClassDB::bind_method(D_METHOD("get_dof_blur_amount"), &CameraEffects::get_dof_blur_amount); + + ADD_GROUP("DOF Blur", "dof_blur_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_far_enabled"), "set_dof_blur_far_enabled", "is_dof_blur_far_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_distance", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_far_distance", "get_dof_blur_far_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_transition", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_far_transition", "get_dof_blur_far_transition"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_near_enabled"), "set_dof_blur_near_enabled", "is_dof_blur_near_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_distance", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_near_distance", "get_dof_blur_near_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_transition", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_near_transition", "get_dof_blur_near_transition"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dof_blur_amount", "get_dof_blur_amount"); + + // Override exposure + + ClassDB::bind_method(D_METHOD("set_override_exposure_enabled", "enabled"), &CameraEffects::set_override_exposure_enabled); + ClassDB::bind_method(D_METHOD("is_override_exposure_enabled"), &CameraEffects::is_override_exposure_enabled); + ClassDB::bind_method(D_METHOD("set_override_exposure", "exposure"), &CameraEffects::set_override_exposure); + ClassDB::bind_method(D_METHOD("get_override_exposure"), &CameraEffects::get_override_exposure); + + ADD_GROUP("Override Exposure", "override_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_exposure_enabled"), "set_override_exposure_enabled", "is_override_exposure_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "override_exposure", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_override_exposure", "get_override_exposure"); +} + +CameraEffects::CameraEffects() { + camera_effects = RS::get_singleton()->camera_effects_create(); + + _update_dof_blur(); + _update_override_exposure(); +} + +CameraEffects::~CameraEffects() { + RS::get_singleton()->free(camera_effects); +} diff --git a/scene/resources/space_2d.h b/scene/resources/camera_effects.h index ff88c40348..99fd4eb37c 100644 --- a/scene/resources/space_2d.h +++ b/scene/resources/camera_effects.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* space_2d.h */ +/* camera_effects.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,29 +28,67 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SPACE_2D_H -#define SPACE_2D_H +#ifndef CAMERA_EFFECTS_H +#define CAMERA_EFFECTS_H #include "core/resource.h" -#include "servers/physics_2d_server.h" +#include "core/rid.h" -class Space2D : public Resource { +class CameraEffects : public Resource { + GDCLASS(CameraEffects, Resource); - GDCLASS(Space2D, Resource); - bool active; - RID space; +private: + RID camera_effects; + + // DOF blur + bool dof_blur_far_enabled = false; + float dof_blur_far_distance = 10; + float dof_blur_far_transition = 5; + + bool dof_blur_near_enabled = false; + float dof_blur_near_distance = 2; + float dof_blur_near_transition = 1; + + float dof_blur_amount = 0.1; + void _update_dof_blur(); + + // Override exposure + bool override_exposure_enabled = false; + float override_exposure = 1.0; + void _update_override_exposure(); protected: static void _bind_methods(); public: - void set_active(bool p_active); - bool is_active() const; + virtual RID get_rid() const override; + + // DOF blur + void set_dof_blur_far_enabled(bool p_enabled); + bool is_dof_blur_far_enabled() const; + void set_dof_blur_far_distance(float p_distance); + float get_dof_blur_far_distance() const; + void set_dof_blur_far_transition(float p_distance); + float get_dof_blur_far_transition() const; + + void set_dof_blur_near_enabled(bool p_enabled); + bool is_dof_blur_near_enabled() const; + void set_dof_blur_near_distance(float p_distance); + float get_dof_blur_near_distance() const; + void set_dof_blur_near_transition(float p_distance); + float get_dof_blur_near_transition() const; + + void set_dof_blur_amount(float p_amount); + float get_dof_blur_amount() const; - virtual RID get_rid() const; + // Override exposure + void set_override_exposure_enabled(bool p_enabled); + bool is_override_exposure_enabled() const; + void set_override_exposure(float p_exposure); + float get_override_exposure() const; - Space2D(); - ~Space2D(); + CameraEffects(); + ~CameraEffects(); }; -#endif // SPACE_2D_H +#endif // CAMERA_EFFECTS_H diff --git a/scene/resources/canvas.cpp b/scene/resources/canvas.cpp deleted file mode 100644 index 1dbd02ea28..0000000000 --- a/scene/resources/canvas.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/*************************************************************************/ -/* canvas.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "canvas.h" -#include "servers/visual_server.h" - -RID Canvas::get_rid() const { - - return canvas; -} - -Canvas::Canvas() { - - canvas = VisualServer::get_singleton()->canvas_create(); -} - -Canvas::~Canvas() { - VisualServer::get_singleton()->free(canvas); -} diff --git a/scene/resources/canvas.h b/scene/resources/canvas.h deleted file mode 100644 index 621911fe0a..0000000000 --- a/scene/resources/canvas.h +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************/ -/* canvas.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef CANVAS_H -#define CANVAS_H - -#include "core/resource.h" - -class Canvas : public Resource { - - GDCLASS(Canvas, Resource); - - RID canvas; - -public: - virtual RID get_rid() const; - Canvas(); - ~Canvas(); -}; - -#endif // CANVAS_H diff --git a/scene/resources/capsule_shape_2d.cpp b/scene/resources/capsule_shape_2d.cpp index 008e8bb13d..e519970f38 100644 --- a/scene/resources/capsule_shape_2d.cpp +++ b/scene/resources/capsule_shape_2d.cpp @@ -30,66 +30,63 @@ #include "capsule_shape_2d.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "core/math/geometry_2d.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" Vector<Vector2> CapsuleShape2D::_get_points() const { - Vector<Vector2> points; for (int i = 0; i < 24; i++) { Vector2 ofs = Vector2(0, (i > 6 && i <= 18) ? -get_height() * 0.5 : get_height() * 0.5); points.push_back(Vector2(Math::sin(i * Math_PI * 2 / 24.0), Math::cos(i * Math_PI * 2 / 24.0)) * get_radius() + ofs); - if (i == 6 || i == 18) + if (i == 6 || i == 18) { points.push_back(Vector2(Math::sin(i * Math_PI * 2 / 24.0), Math::cos(i * Math_PI * 2 / 24.0)) * get_radius() - ofs); + } } return points; } bool CapsuleShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { - - return Geometry::is_point_in_polygon(p_point, _get_points()); + return Geometry2D::is_point_in_polygon(p_point, _get_points()); } void CapsuleShape2D::_update_shape() { - - Physics2DServer::get_singleton()->shape_set_data(get_rid(), Vector2(radius, height)); + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), Vector2(radius, height)); emit_changed(); } void CapsuleShape2D::set_radius(real_t p_radius) { - radius = p_radius; _update_shape(); } real_t CapsuleShape2D::get_radius() const { - return radius; } void CapsuleShape2D::set_height(real_t p_height) { - height = p_height; + if (height < 0) { + height = 0; + } + _update_shape(); } real_t CapsuleShape2D::get_height() const { - return height; } void CapsuleShape2D::draw(const RID &p_to_rid, const Color &p_color) { - Vector<Vector2> points = _get_points(); Vector<Color> col; col.push_back(p_color); - VisualServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); + RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); } Rect2 CapsuleShape2D::get_rect() const { - Vector2 he = Point2(get_radius(), get_radius() + get_height() * 0.5); Rect2 rect; rect.position = -he; @@ -97,21 +94,23 @@ Rect2 CapsuleShape2D::get_rect() const { return rect; } -void CapsuleShape2D::_bind_methods() { +real_t CapsuleShape2D::get_enclosing_radius() const { + return radius + height * 0.5; +} +void CapsuleShape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CapsuleShape2D::set_radius); ClassDB::bind_method(D_METHOD("get_radius"), &CapsuleShape2D::get_radius); ClassDB::bind_method(D_METHOD("set_height", "height"), &CapsuleShape2D::set_height); ClassDB::bind_method(D_METHOD("get_height"), &CapsuleShape2D::get_height); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "height"), "set_height", "get_height"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height"), "set_height", "get_height"); } CapsuleShape2D::CapsuleShape2D() : - Shape2D(Physics2DServer::get_singleton()->capsule_shape_create()) { - + Shape2D(PhysicsServer2D::get_singleton()->capsule_shape_create()) { radius = 10; height = 20; _update_shape(); diff --git a/scene/resources/capsule_shape_2d.h b/scene/resources/capsule_shape_2d.h index 8398fab839..1caa6c68b8 100644 --- a/scene/resources/capsule_shape_2d.h +++ b/scene/resources/capsule_shape_2d.h @@ -46,7 +46,7 @@ protected: static void _bind_methods(); public: - virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override; void set_height(real_t p_height); real_t get_height() const; @@ -54,8 +54,9 @@ public: void set_radius(real_t p_radius); real_t get_radius() const; - virtual void draw(const RID &p_to_rid, const Color &p_color); - virtual Rect2 get_rect() const; + virtual void draw(const RID &p_to_rid, const Color &p_color) override; + virtual Rect2 get_rect() const override; + virtual real_t get_enclosing_radius() const override; CapsuleShape2D(); }; diff --git a/scene/resources/capsule_shape.cpp b/scene/resources/capsule_shape_3d.cpp index 61331a336d..9d1355eec6 100644 --- a/scene/resources/capsule_shape.cpp +++ b/scene/resources/capsule_shape_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* capsule_shape.cpp */ +/* capsule_shape_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,96 +28,90 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "capsule_shape.h" -#include "servers/physics_server.h" - -Vector<Vector3> CapsuleShape::get_debug_mesh_lines() { +#include "capsule_shape_3d.h" +#include "servers/physics_server_3d.h" +Vector<Vector3> CapsuleShape3D::get_debug_mesh_lines() const { float radius = get_radius(); float height = get_height(); Vector<Vector3> points; - Vector3 d(0, 0, height * 0.5); + Vector3 d(0, height * 0.5, 0); for (int i = 0; i < 360; i++) { - float ra = Math::deg2rad((float)i); float rb = Math::deg2rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius; - points.push_back(Vector3(a.x, a.y, 0) + d); - points.push_back(Vector3(b.x, b.y, 0) + d); + points.push_back(Vector3(a.x, 0, a.y) + d); + points.push_back(Vector3(b.x, 0, b.y) + d); - points.push_back(Vector3(a.x, a.y, 0) - d); - points.push_back(Vector3(b.x, b.y, 0) - d); + points.push_back(Vector3(a.x, 0, a.y) - d); + points.push_back(Vector3(b.x, 0, b.y) - d); if (i % 90 == 0) { - - points.push_back(Vector3(a.x, a.y, 0) + d); - points.push_back(Vector3(a.x, a.y, 0) - d); + points.push_back(Vector3(a.x, 0, a.y) + d); + points.push_back(Vector3(a.x, 0, a.y) - d); } Vector3 dud = i < 180 ? d : -d; - points.push_back(Vector3(0, a.y, a.x) + dud); - points.push_back(Vector3(0, b.y, b.x) + dud); - points.push_back(Vector3(a.y, 0, a.x) + dud); - points.push_back(Vector3(b.y, 0, b.x) + dud); + points.push_back(Vector3(0, a.x, a.y) + dud); + points.push_back(Vector3(0, b.x, b.y) + dud); + points.push_back(Vector3(a.y, a.x, 0) + dud); + points.push_back(Vector3(b.y, b.x, 0) + dud); } return points; } -void CapsuleShape::_update_shape() { +real_t CapsuleShape3D::get_enclosing_radius() const { + return radius + height * 0.5; +} +void CapsuleShape3D::_update_shape() { Dictionary d; d["radius"] = radius; d["height"] = height; - PhysicsServer::get_singleton()->shape_set_data(get_shape(), d); - Shape::_update_shape(); + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), d); + Shape3D::_update_shape(); } -void CapsuleShape::set_radius(float p_radius) { - +void CapsuleShape3D::set_radius(float p_radius) { radius = p_radius; _update_shape(); notify_change_to_owners(); _change_notify("radius"); } -float CapsuleShape::get_radius() const { - +float CapsuleShape3D::get_radius() const { return radius; } -void CapsuleShape::set_height(float p_height) { - +void CapsuleShape3D::set_height(float p_height) { height = p_height; _update_shape(); notify_change_to_owners(); _change_notify("height"); } -float CapsuleShape::get_height() const { - +float CapsuleShape3D::get_height() const { return height; } -void CapsuleShape::_bind_methods() { +void CapsuleShape3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CapsuleShape3D::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &CapsuleShape3D::get_radius); + ClassDB::bind_method(D_METHOD("set_height", "height"), &CapsuleShape3D::set_height); + ClassDB::bind_method(D_METHOD("get_height"), &CapsuleShape3D::get_height); - ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CapsuleShape::set_radius); - ClassDB::bind_method(D_METHOD("get_radius"), &CapsuleShape::get_radius); - ClassDB::bind_method(D_METHOD("set_height", "height"), &CapsuleShape::set_height); - ClassDB::bind_method(D_METHOD("get_height"), &CapsuleShape::get_height); - - ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_height", "get_height"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_height", "get_height"); } -CapsuleShape::CapsuleShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CAPSULE)) { - +CapsuleShape3D::CapsuleShape3D() : + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_CAPSULE)) { radius = 1.0; height = 1.0; _update_shape(); diff --git a/scene/resources/capsule_shape.h b/scene/resources/capsule_shape_3d.h index 8e7d7bcb94..432ca5654e 100644 --- a/scene/resources/capsule_shape.h +++ b/scene/resources/capsule_shape_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* capsule_shape.h */ +/* capsule_shape_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -31,18 +31,17 @@ #ifndef CAPSULE_SHAPE_H #define CAPSULE_SHAPE_H -#include "scene/resources/shape.h" +#include "scene/resources/shape_3d.h" -class CapsuleShape : public Shape { - - GDCLASS(CapsuleShape, Shape); +class CapsuleShape3D : public Shape3D { + GDCLASS(CapsuleShape3D, Shape3D); float radius; float height; protected: static void _bind_methods(); - virtual void _update_shape(); + virtual void _update_shape() override; public: void set_radius(float p_radius); @@ -50,9 +49,10 @@ public: void set_height(float p_height); float get_height() const; - virtual Vector<Vector3> get_debug_mesh_lines(); + virtual Vector<Vector3> get_debug_mesh_lines() const override; + virtual real_t get_enclosing_radius() const override; - CapsuleShape(); + CapsuleShape3D(); }; #endif // CAPSULE_SHAPE_H diff --git a/scene/resources/circle_shape_2d.cpp b/scene/resources/circle_shape_2d.cpp index 7142309e28..dc1bf3b185 100644 --- a/scene/resources/circle_shape_2d.cpp +++ b/scene/resources/circle_shape_2d.cpp @@ -30,37 +30,32 @@ #include "circle_shape_2d.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" bool CircleShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { - return p_point.length() < get_radius() + p_tolerance; } void CircleShape2D::_update_shape() { - - Physics2DServer::get_singleton()->shape_set_data(get_rid(), radius); + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), radius); emit_changed(); } void CircleShape2D::set_radius(real_t p_radius) { - radius = p_radius; _update_shape(); } real_t CircleShape2D::get_radius() const { - return radius; } void CircleShape2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CircleShape2D::set_radius); ClassDB::bind_method(D_METHOD("get_radius"), &CircleShape2D::get_radius); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.01,16384,0.5"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,16384,0.5"), "set_radius", "get_radius"); } Rect2 CircleShape2D::get_rect() const { @@ -70,22 +65,23 @@ Rect2 CircleShape2D::get_rect() const { return rect; } -void CircleShape2D::draw(const RID &p_to_rid, const Color &p_color) { +real_t CircleShape2D::get_enclosing_radius() const { + return radius; +} +void CircleShape2D::draw(const RID &p_to_rid, const Color &p_color) { Vector<Vector2> points; for (int i = 0; i < 24; i++) { - points.push_back(Vector2(Math::cos(i * Math_PI * 2 / 24.0), Math::sin(i * Math_PI * 2 / 24.0)) * get_radius()); } Vector<Color> col; col.push_back(p_color); - VisualServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); + RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); } CircleShape2D::CircleShape2D() : - Shape2D(Physics2DServer::get_singleton()->circle_shape_create()) { - + Shape2D(PhysicsServer2D::get_singleton()->circle_shape_create()) { radius = 10; _update_shape(); } diff --git a/scene/resources/circle_shape_2d.h b/scene/resources/circle_shape_2d.h index cafd291f13..ac8757e781 100644 --- a/scene/resources/circle_shape_2d.h +++ b/scene/resources/circle_shape_2d.h @@ -43,13 +43,14 @@ protected: static void _bind_methods(); public: - virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override; void set_radius(real_t p_radius); real_t get_radius() const; - virtual void draw(const RID &p_to_rid, const Color &p_color); - virtual Rect2 get_rect() const; + virtual void draw(const RID &p_to_rid, const Color &p_color) override; + virtual Rect2 get_rect() const override; + virtual real_t get_enclosing_radius() const override; CircleShape2D(); }; diff --git a/scene/resources/concave_polygon_shape_2d.cpp b/scene/resources/concave_polygon_shape_2d.cpp index 640f395158..eecf8afa8f 100644 --- a/scene/resources/concave_polygon_shape_2d.cpp +++ b/scene/resources/concave_polygon_shape_2d.cpp @@ -30,80 +30,90 @@ #include "concave_polygon_shape_2d.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "core/math/geometry_2d.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" bool ConcavePolygonShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { - - PoolVector<Vector2> s = get_segments(); + Vector<Vector2> s = get_segments(); int len = s.size(); - if (len == 0 || (len % 2) == 1) + if (len == 0 || (len % 2) == 1) { return false; + } - PoolVector<Vector2>::Read r = s.read(); + const Vector2 *r = s.ptr(); for (int i = 0; i < len; i += 2) { - Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point, &r[i]); - if (p_point.distance_to(closest) < p_tolerance) + Vector2 closest = Geometry2D::get_closest_point_to_segment(p_point, &r[i]); + if (p_point.distance_to(closest) < p_tolerance) { return true; + } } return false; } -void ConcavePolygonShape2D::set_segments(const PoolVector<Vector2> &p_segments) { - - Physics2DServer::get_singleton()->shape_set_data(get_rid(), p_segments); +void ConcavePolygonShape2D::set_segments(const Vector<Vector2> &p_segments) { + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), p_segments); emit_changed(); } -PoolVector<Vector2> ConcavePolygonShape2D::get_segments() const { - - return Physics2DServer::get_singleton()->shape_get_data(get_rid()); +Vector<Vector2> ConcavePolygonShape2D::get_segments() const { + return PhysicsServer2D::get_singleton()->shape_get_data(get_rid()); } void ConcavePolygonShape2D::draw(const RID &p_to_rid, const Color &p_color) { - - PoolVector<Vector2> s = get_segments(); + Vector<Vector2> s = get_segments(); int len = s.size(); - if (len == 0 || (len % 2) == 1) + if (len == 0 || (len % 2) == 1) { return; + } - PoolVector<Vector2>::Read r = s.read(); + const Vector2 *r = s.ptr(); for (int i = 0; i < len; i += 2) { - VisualServer::get_singleton()->canvas_item_add_line(p_to_rid, r[i], r[i + 1], p_color, 2); + RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, r[i], r[i + 1], p_color, 2); } } Rect2 ConcavePolygonShape2D::get_rect() const { - - PoolVector<Vector2> s = get_segments(); + Vector<Vector2> s = get_segments(); int len = s.size(); - if (len == 0) + if (len == 0) { return Rect2(); + } Rect2 rect; - PoolVector<Vector2>::Read r = s.read(); + const Vector2 *r = s.ptr(); for (int i = 0; i < len; i++) { - if (i == 0) + if (i == 0) { rect.position = r[i]; - else + } else { rect.expand_to(r[i]); + } } return rect; } -void ConcavePolygonShape2D::_bind_methods() { +real_t ConcavePolygonShape2D::get_enclosing_radius() const { + Vector<Vector2> data = get_segments(); + const Vector2 *read = data.ptr(); + real_t r = 0; + for (int i(0); i < data.size(); i++) { + r = MAX(read[i].length_squared(), r); + } + return Math::sqrt(r); +} +void ConcavePolygonShape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_segments", "segments"), &ConcavePolygonShape2D::set_segments); ClassDB::bind_method(D_METHOD("get_segments"), &ConcavePolygonShape2D::get_segments); - ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "segments"), "set_segments", "get_segments"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "segments"), "set_segments", "get_segments"); } ConcavePolygonShape2D::ConcavePolygonShape2D() : - Shape2D(Physics2DServer::get_singleton()->concave_polygon_shape_create()) { - PoolVector<Vector2> empty; + Shape2D(PhysicsServer2D::get_singleton()->concave_polygon_shape_create()) { + Vector<Vector2> empty; set_segments(empty); } diff --git a/scene/resources/concave_polygon_shape_2d.h b/scene/resources/concave_polygon_shape_2d.h index b95ed100e7..df8cc9920f 100644 --- a/scene/resources/concave_polygon_shape_2d.h +++ b/scene/resources/concave_polygon_shape_2d.h @@ -40,13 +40,14 @@ protected: static void _bind_methods(); public: - virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override; - void set_segments(const PoolVector<Vector2> &p_segments); - PoolVector<Vector2> get_segments() const; + void set_segments(const Vector<Vector2> &p_segments); + Vector<Vector2> get_segments() const; - virtual void draw(const RID &p_to_rid, const Color &p_color); - virtual Rect2 get_rect() const; + virtual void draw(const RID &p_to_rid, const Color &p_color) override; + virtual Rect2 get_rect() const override; + virtual real_t get_enclosing_radius() const override; ConcavePolygonShape2D(); }; diff --git a/scene/resources/concave_polygon_shape.cpp b/scene/resources/concave_polygon_shape_3d.cpp index 48cc08eae4..7cbafcbc4d 100644 --- a/scene/resources/concave_polygon_shape.cpp +++ b/scene/resources/concave_polygon_shape_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* concave_polygon_shape.cpp */ +/* concave_polygon_shape_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,24 +28,21 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "concave_polygon_shape.h" +#include "concave_polygon_shape_3d.h" -#include "servers/physics_server.h" - -Vector<Vector3> ConcavePolygonShape::get_debug_mesh_lines() { +#include "servers/physics_server_3d.h" +Vector<Vector3> ConcavePolygonShape3D::get_debug_mesh_lines() const { Set<DrawEdge> edges; - PoolVector<Vector3> data = get_faces(); + Vector<Vector3> data = get_faces(); int datalen = data.size(); ERR_FAIL_COND_V((datalen % 3) != 0, Vector<Vector3>()); - PoolVector<Vector3>::Read r = data.read(); + const Vector3 *r = data.ptr(); for (int i = 0; i < datalen; i += 3) { - for (int j = 0; j < 3; j++) { - DrawEdge de(r[i + j], r[i + ((j + 1) % 3)]); edges.insert(de); } @@ -55,7 +52,6 @@ Vector<Vector3> ConcavePolygonShape::get_debug_mesh_lines() { points.resize(edges.size() * 2); int idx = 0; for (Set<DrawEdge>::Element *E = edges.front(); E; E = E->next()) { - points.write[idx + 0] = E->get().a; points.write[idx + 1] = E->get().b; idx += 2; @@ -64,30 +60,36 @@ Vector<Vector3> ConcavePolygonShape::get_debug_mesh_lines() { return points; } -void ConcavePolygonShape::_update_shape() { - Shape::_update_shape(); +real_t ConcavePolygonShape3D::get_enclosing_radius() const { + Vector<Vector3> data = get_faces(); + const Vector3 *read = data.ptr(); + real_t r = 0; + for (int i(0); i < data.size(); i++) { + r = MAX(read[i].length_squared(), r); + } + return Math::sqrt(r); } -void ConcavePolygonShape::set_faces(const PoolVector<Vector3> &p_faces) { +void ConcavePolygonShape3D::_update_shape() { + Shape3D::_update_shape(); +} - PhysicsServer::get_singleton()->shape_set_data(get_shape(), p_faces); +void ConcavePolygonShape3D::set_faces(const Vector<Vector3> &p_faces) { + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), p_faces); notify_change_to_owners(); } -PoolVector<Vector3> ConcavePolygonShape::get_faces() const { - - return PhysicsServer::get_singleton()->shape_get_data(get_shape()); +Vector<Vector3> ConcavePolygonShape3D::get_faces() const { + return PhysicsServer3D::get_singleton()->shape_get_data(get_shape()); } -void ConcavePolygonShape::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_faces", "faces"), &ConcavePolygonShape::set_faces); - ClassDB::bind_method(D_METHOD("get_faces"), &ConcavePolygonShape::get_faces); - ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_faces", "get_faces"); +void ConcavePolygonShape3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_faces", "faces"), &ConcavePolygonShape3D::set_faces); + ClassDB::bind_method(D_METHOD("get_faces"), &ConcavePolygonShape3D::get_faces); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_faces", "get_faces"); } -ConcavePolygonShape::ConcavePolygonShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CONCAVE_POLYGON)) { - +ConcavePolygonShape3D::ConcavePolygonShape3D() : + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_CONCAVE_POLYGON)) { //set_planes(Vector3(1,1,1)); } diff --git a/scene/resources/concave_polygon_shape.h b/scene/resources/concave_polygon_shape_3d.h index 5e371954d4..c17765b9ef 100644 --- a/scene/resources/concave_polygon_shape.h +++ b/scene/resources/concave_polygon_shape_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* concave_polygon_shape.h */ +/* concave_polygon_shape_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,24 +28,23 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CONCAVE_POLYGON_SHAPE_H -#define CONCAVE_POLYGON_SHAPE_H +#ifndef CONCAVE_POLYGON_SHAPE_3D_H +#define CONCAVE_POLYGON_SHAPE_3D_H -#include "scene/resources/shape.h" +#include "scene/resources/shape_3d.h" -class ConcavePolygonShape : public Shape { - - GDCLASS(ConcavePolygonShape, Shape); +class ConcavePolygonShape3D : public Shape3D { + GDCLASS(ConcavePolygonShape3D, Shape3D); struct DrawEdge { - Vector3 a; Vector3 b; bool operator<(const DrawEdge &p_edge) const { - if (a == p_edge.a) + if (a == p_edge.a) { return b < p_edge.b; - else + } else { return a < p_edge.a; + } } DrawEdge(const Vector3 &p_a = Vector3(), const Vector3 &p_b = Vector3()) { @@ -60,15 +59,16 @@ class ConcavePolygonShape : public Shape { protected: static void _bind_methods(); - virtual void _update_shape(); + virtual void _update_shape() override; public: - void set_faces(const PoolVector<Vector3> &p_faces); - PoolVector<Vector3> get_faces() const; + void set_faces(const Vector<Vector3> &p_faces); + Vector<Vector3> get_faces() const; - Vector<Vector3> get_debug_mesh_lines(); + virtual Vector<Vector3> get_debug_mesh_lines() const override; + virtual real_t get_enclosing_radius() const override; - ConcavePolygonShape(); + ConcavePolygonShape3D(); }; #endif // CONCAVE_POLYGON_SHAPE_H diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp index c404190398..2b7531c630 100644 --- a/scene/resources/convex_polygon_shape_2d.cpp +++ b/scene/resources/convex_polygon_shape_2d.cpp @@ -30,73 +30,74 @@ #include "convex_polygon_shape_2d.h" -#include "core/math/geometry.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "core/math/geometry_2d.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" bool ConvexPolygonShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { - - return Geometry::is_point_in_polygon(p_point, points); + return Geometry2D::is_point_in_polygon(p_point, points); } void ConvexPolygonShape2D::_update_shape() { - Vector<Vector2> final_points = points; - if (Geometry::is_polygon_clockwise(final_points)) { //needs to be counter clockwise + if (Geometry2D::is_polygon_clockwise(final_points)) { //needs to be counter clockwise final_points.invert(); } - Physics2DServer::get_singleton()->shape_set_data(get_rid(), final_points); + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), final_points); emit_changed(); } void ConvexPolygonShape2D::set_point_cloud(const Vector<Vector2> &p_points) { - - Vector<Point2> hull = Geometry::convex_hull_2d(p_points); + Vector<Point2> hull = Geometry2D::convex_hull(p_points); ERR_FAIL_COND(hull.size() < 3); set_points(hull); } void ConvexPolygonShape2D::set_points(const Vector<Vector2> &p_points) { - points = p_points; _update_shape(); } Vector<Vector2> ConvexPolygonShape2D::get_points() const { - return points; } void ConvexPolygonShape2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_point_cloud", "point_cloud"), &ConvexPolygonShape2D::set_point_cloud); ClassDB::bind_method(D_METHOD("set_points", "points"), &ConvexPolygonShape2D::set_points); ClassDB::bind_method(D_METHOD("get_points"), &ConvexPolygonShape2D::get_points); - ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "points"), "set_points", "get_points"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "points"), "set_points", "get_points"); } void ConvexPolygonShape2D::draw(const RID &p_to_rid, const Color &p_color) { - Vector<Color> col; col.push_back(p_color); - VisualServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); + RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); } Rect2 ConvexPolygonShape2D::get_rect() const { - Rect2 rect; for (int i = 0; i < points.size(); i++) { - if (i == 0) + if (i == 0) { rect.position = points[i]; - else + } else { rect.expand_to(points[i]); + } } return rect; } +real_t ConvexPolygonShape2D::get_enclosing_radius() const { + real_t r = 0; + for (int i(0); i < get_points().size(); i++) { + r = MAX(get_points()[i].length_squared(), r); + } + return Math::sqrt(r); +} + ConvexPolygonShape2D::ConvexPolygonShape2D() : - Shape2D(Physics2DServer::get_singleton()->convex_polygon_shape_create()) { + Shape2D(PhysicsServer2D::get_singleton()->convex_polygon_shape_create()) { } diff --git a/scene/resources/convex_polygon_shape_2d.h b/scene/resources/convex_polygon_shape_2d.h index ed6be738ab..294157bec5 100644 --- a/scene/resources/convex_polygon_shape_2d.h +++ b/scene/resources/convex_polygon_shape_2d.h @@ -43,14 +43,15 @@ protected: static void _bind_methods(); public: - virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override; void set_point_cloud(const Vector<Vector2> &p_points); void set_points(const Vector<Vector2> &p_points); Vector<Vector2> get_points() const; - virtual void draw(const RID &p_to_rid, const Color &p_color); - virtual Rect2 get_rect() const; + virtual void draw(const RID &p_to_rid, const Color &p_color) override; + virtual Rect2 get_rect() const override; + virtual real_t get_enclosing_radius() const override; ConvexPolygonShape2D(); }; diff --git a/scene/resources/convex_polygon_shape.cpp b/scene/resources/convex_polygon_shape_3d.cpp index 1498eb4af9..29549e1114 100644 --- a/scene/resources/convex_polygon_shape.cpp +++ b/scene/resources/convex_polygon_shape_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* convex_polygon_shape.cpp */ +/* convex_polygon_shape_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,18 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "convex_polygon_shape.h" +#include "convex_polygon_shape_3d.h" #include "core/math/quick_hull.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" -Vector<Vector3> ConvexPolygonShape::get_debug_mesh_lines() { - - PoolVector<Vector3> points = get_points(); +Vector<Vector3> ConvexPolygonShape3D::get_debug_mesh_lines() const { + Vector<Vector3> points = get_points(); if (points.size() > 3) { - Vector<Vector3> varr = Variant(points); - Geometry::MeshData md; + Geometry3D::MeshData md; Error err = QuickHull::build(varr, md); if (err == OK) { Vector<Vector3> lines; @@ -55,32 +53,38 @@ Vector<Vector3> ConvexPolygonShape::get_debug_mesh_lines() { return Vector<Vector3>(); } -void ConvexPolygonShape::_update_shape() { - - PhysicsServer::get_singleton()->shape_set_data(get_shape(), points); - Shape::_update_shape(); +real_t ConvexPolygonShape3D::get_enclosing_radius() const { + Vector<Vector3> data = get_points(); + const Vector3 *read = data.ptr(); + real_t r = 0; + for (int i(0); i < data.size(); i++) { + r = MAX(read[i].length_squared(), r); + } + return Math::sqrt(r); } -void ConvexPolygonShape::set_points(const PoolVector<Vector3> &p_points) { +void ConvexPolygonShape3D::_update_shape() { + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), points); + Shape3D::_update_shape(); +} +void ConvexPolygonShape3D::set_points(const Vector<Vector3> &p_points) { points = p_points; _update_shape(); notify_change_to_owners(); } -PoolVector<Vector3> ConvexPolygonShape::get_points() const { - +Vector<Vector3> ConvexPolygonShape3D::get_points() const { return points; } -void ConvexPolygonShape::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_points", "points"), &ConvexPolygonShape::set_points); - ClassDB::bind_method(D_METHOD("get_points"), &ConvexPolygonShape::get_points); +void ConvexPolygonShape3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_points", "points"), &ConvexPolygonShape3D::set_points); + ClassDB::bind_method(D_METHOD("get_points"), &ConvexPolygonShape3D::get_points); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "points"), "set_points", "get_points"); } -ConvexPolygonShape::ConvexPolygonShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CONVEX_POLYGON)) { +ConvexPolygonShape3D::ConvexPolygonShape3D() : + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_CONVEX_POLYGON)) { } diff --git a/scene/resources/convex_polygon_shape.h b/scene/resources/convex_polygon_shape_3d.h index 4725d09b26..f436d2f5d4 100644 --- a/scene/resources/convex_polygon_shape.h +++ b/scene/resources/convex_polygon_shape_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* convex_polygon_shape.h */ +/* convex_polygon_shape_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -31,25 +31,25 @@ #ifndef CONVEX_POLYGON_SHAPE_H #define CONVEX_POLYGON_SHAPE_H -#include "scene/resources/shape.h" +#include "scene/resources/shape_3d.h" -class ConvexPolygonShape : public Shape { - - GDCLASS(ConvexPolygonShape, Shape); - PoolVector<Vector3> points; +class ConvexPolygonShape3D : public Shape3D { + GDCLASS(ConvexPolygonShape3D, Shape3D); + Vector<Vector3> points; protected: static void _bind_methods(); - virtual void _update_shape(); + virtual void _update_shape() override; public: - void set_points(const PoolVector<Vector3> &p_points); - PoolVector<Vector3> get_points() const; + void set_points(const Vector<Vector3> &p_points); + Vector<Vector3> get_points() const; - virtual Vector<Vector3> get_debug_mesh_lines(); + virtual Vector<Vector3> get_debug_mesh_lines() const override; + virtual real_t get_enclosing_radius() const override; - ConvexPolygonShape(); + ConvexPolygonShape3D(); }; #endif // CONVEX_POLYGON_SHAPE_H diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 397f6ca906..de076670cf 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -58,10 +58,11 @@ int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent, T // Add a point and preserve order // Curve bounds is in 0..1 - if (p_pos.x > MAX_X) + if (p_pos.x > MAX_X) { p_pos.x = MAX_X; - else if (p_pos.x < MIN_X) + } else if (p_pos.x < MIN_X) { p_pos.x = MIN_X; + } int ret = -1; @@ -83,7 +84,6 @@ int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent, T } } else { - int i = get_index(p_pos.x); if (i == 0 && p_pos.x < _points[0].pos.x) { @@ -106,7 +106,6 @@ int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent, T } int Curve::get_index(real_t offset) const { - // Lower-bound float binary search int imin = 0; @@ -130,13 +129,13 @@ int Curve::get_index(real_t offset) const { } // Will happen if the offset is out of bounds - if (offset > _points[imax].pos.x) + if (offset > _points[imax].pos.x) { return imax; + } return imin; } void Curve::clean_dupes() { - bool dirty = false; for (int i = 1; i < _points.size(); ++i) { @@ -148,8 +147,9 @@ void Curve::clean_dupes() { } } - if (dirty) + if (dirty) { mark_dirty(); + } } void Curve::set_point_left_tangent(int i, real_t tangent) { @@ -237,8 +237,9 @@ int Curve::set_point_offset(int p_index, float offset) { _points.write[i].right_tangent = p.right_tangent; _points.write[i].left_mode = p.left_mode; _points.write[i].right_mode = p.right_mode; - if (p_index != i) + if (p_index != i) { update_auto_tangents(p_index); + } update_auto_tangents(i); return i; } @@ -254,7 +255,6 @@ Curve::Point Curve::get_point(int p_index) const { } void Curve::update_auto_tangents(int i) { - Point &p = _points.write[i]; if (i > 0) { @@ -305,26 +305,29 @@ void Curve::set_max_value(float p_max) { } real_t Curve::interpolate(real_t offset) const { - if (_points.size() == 0) + if (_points.size() == 0) { return 0; - if (_points.size() == 1) + } + if (_points.size() == 1) { return _points[0].pos.y; + } int i = get_index(offset); - if (i == _points.size() - 1) + if (i == _points.size() - 1) { return _points[i].pos.y; + } real_t local = offset - _points[i].pos.x; - if (i == 0 && local <= 0) + if (i == 0 && local <= 0) { return _points[0].pos.y; + } return interpolate_local_nocheck(i, local); } real_t Curve::interpolate_local_nocheck(int index, real_t local_offset) const { - const Point a = _points[index]; const Point b = _points[index + 1]; @@ -344,8 +347,9 @@ real_t Curve::interpolate_local_nocheck(int index, real_t local_offset) const { // Control points are chosen at equal distances real_t d = b.pos.x - a.pos.x; - if (Math::abs(d) <= CMP_EPSILON) + if (Math::abs(d) <= CMP_EPSILON) { return b.pos.y; + } local_offset /= d; d /= 3.0; real_t yac = a.pos.y + d * a.right_tangent; @@ -362,13 +366,11 @@ void Curve::mark_dirty() { } Array Curve::get_data() const { - Array output; const unsigned int ELEMS = 5; output.resize(_points.size() * ELEMS); for (int j = 0; j < _points.size(); ++j) { - const Point p = _points[j]; int i = j * ELEMS; @@ -392,7 +394,7 @@ void Curve::set_data(Array input) { for (int i = 0; i < input.size(); i += ELEMS) { ERR_FAIL_COND(input[i].get_type() != Variant::VECTOR2); ERR_FAIL_COND(!input[i + 1].is_num()); - ERR_FAIL_COND(input[i + 2].get_type() != Variant::REAL); + ERR_FAIL_COND(input[i + 2].get_type() != Variant::FLOAT); ERR_FAIL_COND(input[i + 3].get_type() != Variant::INT); int left_mode = input[i + 3]; @@ -406,7 +408,6 @@ void Curve::set_data(Array input) { _points.resize(input.size() / ELEMS); for (int j = 0; j < _points.size(); ++j) { - Point &p = _points.write[j]; int i = j * ELEMS; @@ -457,8 +458,9 @@ real_t Curve::interpolate_baked(real_t offset) { // Special cases if the cache is too small if (_baked_cache.size() == 0) { - if (_points.size() == 0) + if (_points.size() == 0) { return 0; + } return _points[0].pos.y; } else if (_baked_cache.size() == 1) { return _baked_cache[0]; @@ -486,7 +488,6 @@ real_t Curve::interpolate_baked(real_t offset) { void Curve::ensure_default_setup(float p_min, float p_max) { if (_points.size() == 0 && _min_value == 0 && _max_value == 1) { - add_point(Vector2(0, 1)); add_point(Vector2(1, 1)); set_min_value(p_min); @@ -495,7 +496,6 @@ void Curve::ensure_default_setup(float p_min, float p_max) { } void Curve::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_point_count"), &Curve::get_point_count); ClassDB::bind_method(D_METHOD("add_point", "position", "left_tangent", "right_tangent", "left_mode", "right_mode"), &Curve::add_point, DEFVAL(0), DEFVAL(0), DEFVAL(TANGENT_FREE), DEFVAL(TANGENT_FREE)); ClassDB::bind_method(D_METHOD("remove_point", "index"), &Curve::remove_point); @@ -524,8 +524,8 @@ void Curve::_bind_methods() { ClassDB::bind_method(D_METHOD("_get_data"), &Curve::get_data); ClassDB::bind_method(D_METHOD("_set_data", "data"), &Curve::set_data); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "min_value", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_min_value", "get_min_value"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_value", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_max_value", "get_max_value"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "min_value", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_min_value", "get_min_value"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_value", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_max_value", "get_max_value"); ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_resolution", PROPERTY_HINT_RANGE, "1,1000,1"), "set_bake_resolution", "get_bake_resolution"); ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); @@ -537,54 +537,51 @@ void Curve::_bind_methods() { } int Curve2D::get_point_count() const { - return points.size(); } -void Curve2D::add_point(const Vector2 &p_pos, const Vector2 &p_in, const Vector2 &p_out, int p_atpos) { +void Curve2D::add_point(const Vector2 &p_pos, const Vector2 &p_in, const Vector2 &p_out, int p_atpos) { Point n; n.pos = p_pos; n.in = p_in; n.out = p_out; - if (p_atpos >= 0 && p_atpos < points.size()) + if (p_atpos >= 0 && p_atpos < points.size()) { points.insert(p_atpos, n); - else + } else { points.push_back(n); + } baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } void Curve2D::set_point_position(int p_index, const Vector2 &p_pos) { - ERR_FAIL_INDEX(p_index, points.size()); points.write[p_index].pos = p_pos; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } -Vector2 Curve2D::get_point_position(int p_index) const { +Vector2 Curve2D::get_point_position(int p_index) const { ERR_FAIL_INDEX_V(p_index, points.size(), Vector2()); return points[p_index].pos; } void Curve2D::set_point_in(int p_index, const Vector2 &p_in) { - ERR_FAIL_INDEX(p_index, points.size()); points.write[p_index].in = p_in; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } -Vector2 Curve2D::get_point_in(int p_index) const { +Vector2 Curve2D::get_point_in(int p_index) const { ERR_FAIL_INDEX_V(p_index, points.size(), Vector2()); return points[p_index].in; } void Curve2D::set_point_out(int p_index, const Vector2 &p_out) { - ERR_FAIL_INDEX(p_index, points.size()); points.write[p_index].out = p_out; @@ -593,13 +590,11 @@ void Curve2D::set_point_out(int p_index, const Vector2 &p_out) { } Vector2 Curve2D::get_point_out(int p_index) const { - ERR_FAIL_INDEX_V(p_index, points.size(), Vector2()); return points[p_index].out; } void Curve2D::remove_point(int p_index) { - ERR_FAIL_INDEX(p_index, points.size()); points.remove(p_index); baked_cache_dirty = true; @@ -615,14 +610,14 @@ void Curve2D::clear_points() { } Vector2 Curve2D::interpolate(int p_index, float p_offset) const { - int pc = points.size(); ERR_FAIL_COND_V(pc == 0, Vector2()); - if (p_index >= pc - 1) + if (p_index >= pc - 1) { return points[pc - 1].pos; - else if (p_index < 0) + } else if (p_index < 0) { return points[0].pos; + } Vector2 p0 = points[p_index].pos; Vector2 p1 = p0 + points[p_index].out; @@ -633,17 +628,16 @@ Vector2 Curve2D::interpolate(int p_index, float p_offset) const { } Vector2 Curve2D::interpolatef(real_t p_findex) const { - - if (p_findex < 0) + if (p_findex < 0) { p_findex = 0; - else if (p_findex >= points.size()) + } else if (p_findex >= points.size()) { p_findex = points.size(); + } return interpolate((int)p_findex, Math::fmod(p_findex, (real_t)1.0)); } void Curve2D::_bake_segment2d(Map<float, Vector2> &r_bake, float p_begin, float p_end, const Vector2 &p_a, const Vector2 &p_out, const Vector2 &p_b, const Vector2 &p_in, int p_depth, int p_max_depth, float p_tol) const { - float mp = p_begin + (p_end - p_begin) * 0.5; Vector2 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b); Vector2 mid = _bezier_interp(mp, p_a, p_a + p_out, p_b + p_in, p_b); @@ -654,7 +648,6 @@ void Curve2D::_bake_segment2d(Map<float, Vector2> &r_bake, float p_begin, float float dp = na.dot(nb); if (dp < Math::cos(Math::deg2rad(p_tol))) { - r_bake[mp] = mid; } @@ -665,9 +658,9 @@ void Curve2D::_bake_segment2d(Map<float, Vector2> &r_bake, float p_begin, float } void Curve2D::_bake() const { - - if (!baked_cache_dirty) + if (!baked_cache_dirty) { return; + } baked_max_ofs = 0; baked_cache_dirty = false; @@ -678,7 +671,6 @@ void Curve2D::_bake() const { } if (points.size() == 1) { - baked_point_cache.resize(1); baked_point_cache.set(0, points[0].pos); return; @@ -690,15 +682,14 @@ void Curve2D::_bake() const { pointlist.push_back(pos); //start always from origin for (int i = 0; i < points.size() - 1; i++) { - float step = 0.1; // at least 10 substeps ought to be enough? float p = 0; while (p < 1.0) { - float np = p + step; - if (np > 1.0) + if (np > 1.0) { np = 1.0; + } Vector2 npp = _bezier_interp(np, points[i].pos, points[i].pos + points[i].out, points[i + 1].pos + points[i + 1].in, points[i + 1].pos); float d = pos.distance_to(npp); @@ -713,14 +704,14 @@ void Curve2D::_bake() const { float mid = low + (hi - low) * 0.5; for (int j = 0; j < iterations; j++) { - npp = _bezier_interp(mid, points[i].pos, points[i].pos + points[i].out, points[i + 1].pos + points[i + 1].in, points[i + 1].pos); d = pos.distance_to(npp); - if (bake_interval < d) + if (bake_interval < d) { hi = mid; - else + } else { low = mid; + } mid = low + (hi - low) * 0.5; } @@ -728,7 +719,6 @@ void Curve2D::_bake() const { p = mid; pointlist.push_back(pos); } else { - p = np; } } @@ -741,42 +731,45 @@ void Curve2D::_bake() const { pointlist.push_back(lastpos); baked_point_cache.resize(pointlist.size()); - PoolVector2Array::Write w = baked_point_cache.write(); + Vector2 *w = baked_point_cache.ptrw(); int idx = 0; for (List<Vector2>::Element *E = pointlist.front(); E; E = E->next()) { - w[idx] = E->get(); idx++; } } float Curve2D::get_baked_length() const { - - if (baked_cache_dirty) + if (baked_cache_dirty) { _bake(); + } return baked_max_ofs; } -Vector2 Curve2D::interpolate_baked(float p_offset, bool p_cubic) const { - if (baked_cache_dirty) +Vector2 Curve2D::interpolate_baked(float p_offset, bool p_cubic) const { + if (baked_cache_dirty) { _bake(); + } //validate// int pc = baked_point_cache.size(); ERR_FAIL_COND_V_MSG(pc == 0, Vector2(), "No points in Curve2D."); - if (pc == 1) + if (pc == 1) { return baked_point_cache.get(0); + } int bpc = baked_point_cache.size(); - PoolVector2Array::Read r = baked_point_cache.read(); + const Vector2 *r = baked_point_cache.ptr(); - if (p_offset < 0) + if (p_offset < 0) { return r[0]; - if (p_offset >= baked_max_ofs) + } + if (p_offset >= baked_max_ofs) { return r[bpc - 1]; + } int idx = Math::floor((double)p_offset / (double)bake_interval); float frac = Math::fmod(p_offset, (float)bake_interval); @@ -784,56 +777,56 @@ Vector2 Curve2D::interpolate_baked(float p_offset, bool p_cubic) const { if (idx >= bpc - 1) { return r[bpc - 1]; } else if (idx == bpc - 2) { - if (frac > 0) + if (frac > 0) { frac /= Math::fmod(baked_max_ofs, bake_interval); + } } else { frac /= bake_interval; } if (p_cubic) { - Vector2 pre = idx > 0 ? r[idx - 1] : r[idx]; Vector2 post = (idx < (bpc - 2)) ? r[idx + 2] : r[idx + 1]; return r[idx].cubic_interpolate(r[idx + 1], pre, post, frac); } else { - return r[idx].linear_interpolate(r[idx + 1], frac); + return r[idx].lerp(r[idx + 1], frac); } } -PoolVector2Array Curve2D::get_baked_points() const { - - if (baked_cache_dirty) +PackedVector2Array Curve2D::get_baked_points() const { + if (baked_cache_dirty) { _bake(); + } return baked_point_cache; } void Curve2D::set_bake_interval(float p_tolerance) { - bake_interval = p_tolerance; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } float Curve2D::get_bake_interval() const { - return bake_interval; } Vector2 Curve2D::get_closest_point(const Vector2 &p_to_point) const { // Brute force method - if (baked_cache_dirty) + if (baked_cache_dirty) { _bake(); + } //validate// int pc = baked_point_cache.size(); ERR_FAIL_COND_V_MSG(pc == 0, Vector2(), "No points in Curve2D."); - if (pc == 1) + if (pc == 1) { return baked_point_cache.get(0); + } - PoolVector2Array::Read r = baked_point_cache.read(); + const Vector2 *r = baked_point_cache.ptr(); Vector2 nearest; float nearest_dist = -1.0f; @@ -859,17 +852,19 @@ Vector2 Curve2D::get_closest_point(const Vector2 &p_to_point) const { float Curve2D::get_closest_offset(const Vector2 &p_to_point) const { // Brute force method - if (baked_cache_dirty) + if (baked_cache_dirty) { _bake(); + } //validate// int pc = baked_point_cache.size(); ERR_FAIL_COND_V_MSG(pc == 0, 0.0f, "No points in Curve2D."); - if (pc == 1) + if (pc == 1) { return 0.0f; + } - PoolVector2Array::Read r = baked_point_cache.read(); + const Vector2 *r = baked_point_cache.ptr(); float nearest = 0.0f; float nearest_dist = -1.0f; @@ -896,38 +891,33 @@ float Curve2D::get_closest_offset(const Vector2 &p_to_point) const { } Dictionary Curve2D::_get_data() const { - Dictionary dc; - PoolVector2Array d; + PackedVector2Array d; d.resize(points.size() * 3); - PoolVector2Array::Write w = d.write(); + Vector2 *w = d.ptrw(); for (int i = 0; i < points.size(); i++) { - w[i * 3 + 0] = points[i].in; w[i * 3 + 1] = points[i].out; w[i * 3 + 2] = points[i].pos; } - w = PoolVector2Array::Write(); - dc["points"] = d; return dc; } -void Curve2D::_set_data(const Dictionary &p_data) { +void Curve2D::_set_data(const Dictionary &p_data) { ERR_FAIL_COND(!p_data.has("points")); - PoolVector2Array rp = p_data["points"]; + PackedVector2Array rp = p_data["points"]; int pc = rp.size(); ERR_FAIL_COND(pc % 3 != 0); points.resize(pc / 3); - PoolVector2Array::Read r = rp.read(); + const Vector2 *r = rp.ptr(); for (int i = 0; i < points.size(); i++) { - points.write[i].in = r[i * 3 + 0]; points.write[i].out = r[i * 3 + 1]; points.write[i].pos = r[i * 3 + 2]; @@ -936,34 +926,30 @@ void Curve2D::_set_data(const Dictionary &p_data) { baked_cache_dirty = true; } -PoolVector2Array Curve2D::tessellate(int p_max_stages, float p_tolerance) const { - - PoolVector2Array tess; +PackedVector2Array Curve2D::tessellate(int p_max_stages, float p_tolerance) const { + PackedVector2Array tess; if (points.size() == 0) { return tess; } - Vector<Map<float, Vector2> > midpoints; + Vector<Map<float, Vector2>> midpoints; midpoints.resize(points.size() - 1); int pc = 1; for (int i = 0; i < points.size() - 1; i++) { - _bake_segment2d(midpoints.write[i], 0, 1, points[i].pos, points[i].out, points[i + 1].pos, points[i + 1].in, 0, p_max_stages, p_tolerance); pc++; pc += midpoints[i].size(); } tess.resize(pc); - PoolVector2Array::Write bpw = tess.write(); + Vector2 *bpw = tess.ptrw(); bpw[0] = points[0].pos; int pidx = 0; for (int i = 0; i < points.size() - 1; i++) { - for (Map<float, Vector2>::Element *E = midpoints[i].front(); E; E = E->next()) { - pidx++; bpw[pidx] = E->get(); } @@ -972,13 +958,10 @@ PoolVector2Array Curve2D::tessellate(int p_max_stages, float p_tolerance) const bpw[pidx] = points[i + 1].pos; } - bpw = PoolVector2Array::Write(); - return tess; } void Curve2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_point_count"), &Curve2D::get_point_count); ClassDB::bind_method(D_METHOD("add_point", "position", "in", "out", "at_position"), &Curve2D::add_point, DEFVAL(Vector2()), DEFVAL(Vector2()), DEFVAL(-1)); ClassDB::bind_method(D_METHOD("set_point_position", "idx", "position"), &Curve2D::set_point_position); @@ -1005,7 +988,7 @@ void Curve2D::_bind_methods() { ClassDB::bind_method(D_METHOD("_get_data"), &Curve2D::_get_data); ClassDB::bind_method(D_METHOD("_set_data"), &Curve2D::_set_data); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "bake_interval", PROPERTY_HINT_RANGE, "0.01,512,0.01"), "set_bake_interval", "get_bake_interval"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_interval", PROPERTY_HINT_RANGE, "0.01,512,0.01"), "set_bake_interval", "get_bake_interval"); ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); } @@ -1026,67 +1009,64 @@ Curve2D::Curve2D() { /***********************************************************************************/ int Curve3D::get_point_count() const { - return points.size(); } -void Curve3D::add_point(const Vector3 &p_pos, const Vector3 &p_in, const Vector3 &p_out, int p_atpos) { +void Curve3D::add_point(const Vector3 &p_pos, const Vector3 &p_in, const Vector3 &p_out, int p_atpos) { Point n; n.pos = p_pos; n.in = p_in; n.out = p_out; - if (p_atpos >= 0 && p_atpos < points.size()) + if (p_atpos >= 0 && p_atpos < points.size()) { points.insert(p_atpos, n); - else + } else { points.push_back(n); + } baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } -void Curve3D::set_point_position(int p_index, const Vector3 &p_pos) { +void Curve3D::set_point_position(int p_index, const Vector3 &p_pos) { ERR_FAIL_INDEX(p_index, points.size()); points.write[p_index].pos = p_pos; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } -Vector3 Curve3D::get_point_position(int p_index) const { +Vector3 Curve3D::get_point_position(int p_index) const { ERR_FAIL_INDEX_V(p_index, points.size(), Vector3()); return points[p_index].pos; } void Curve3D::set_point_tilt(int p_index, float p_tilt) { - ERR_FAIL_INDEX(p_index, points.size()); points.write[p_index].tilt = p_tilt; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } -float Curve3D::get_point_tilt(int p_index) const { +float Curve3D::get_point_tilt(int p_index) const { ERR_FAIL_INDEX_V(p_index, points.size(), 0); return points[p_index].tilt; } void Curve3D::set_point_in(int p_index, const Vector3 &p_in) { - ERR_FAIL_INDEX(p_index, points.size()); points.write[p_index].in = p_in; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } -Vector3 Curve3D::get_point_in(int p_index) const { +Vector3 Curve3D::get_point_in(int p_index) const { ERR_FAIL_INDEX_V(p_index, points.size(), Vector3()); return points[p_index].in; } void Curve3D::set_point_out(int p_index, const Vector3 &p_out) { - ERR_FAIL_INDEX(p_index, points.size()); points.write[p_index].out = p_out; @@ -1095,13 +1075,11 @@ void Curve3D::set_point_out(int p_index, const Vector3 &p_out) { } Vector3 Curve3D::get_point_out(int p_index) const { - ERR_FAIL_INDEX_V(p_index, points.size(), Vector3()); return points[p_index].out; } void Curve3D::remove_point(int p_index) { - ERR_FAIL_INDEX(p_index, points.size()); points.remove(p_index); baked_cache_dirty = true; @@ -1109,7 +1087,6 @@ void Curve3D::remove_point(int p_index) { } void Curve3D::clear_points() { - if (!points.empty()) { points.clear(); baked_cache_dirty = true; @@ -1118,14 +1095,14 @@ void Curve3D::clear_points() { } Vector3 Curve3D::interpolate(int p_index, float p_offset) const { - int pc = points.size(); ERR_FAIL_COND_V(pc == 0, Vector3()); - if (p_index >= pc - 1) + if (p_index >= pc - 1) { return points[pc - 1].pos; - else if (p_index < 0) + } else if (p_index < 0) { return points[0].pos; + } Vector3 p0 = points[p_index].pos; Vector3 p1 = p0 + points[p_index].out; @@ -1136,17 +1113,16 @@ Vector3 Curve3D::interpolate(int p_index, float p_offset) const { } Vector3 Curve3D::interpolatef(real_t p_findex) const { - - if (p_findex < 0) + if (p_findex < 0) { p_findex = 0; - else if (p_findex >= points.size()) + } else if (p_findex >= points.size()) { p_findex = points.size(); + } return interpolate((int)p_findex, Math::fmod(p_findex, (real_t)1.0)); } void Curve3D::_bake_segment3d(Map<float, Vector3> &r_bake, float p_begin, float p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, float p_tol) const { - float mp = p_begin + (p_end - p_begin) * 0.5; Vector3 beg = _bezier_interp(p_begin, p_a, p_a + p_out, p_b + p_in, p_b); Vector3 mid = _bezier_interp(mp, p_a, p_a + p_out, p_b + p_in, p_b); @@ -1157,7 +1133,6 @@ void Curve3D::_bake_segment3d(Map<float, Vector3> &r_bake, float p_begin, float float dp = na.dot(nb); if (dp < Math::cos(Math::deg2rad(p_tol))) { - r_bake[mp] = mid; } if (p_depth < p_max_depth) { @@ -1167,9 +1142,9 @@ void Curve3D::_bake_segment3d(Map<float, Vector3> &r_bake, float p_begin, float } void Curve3D::_bake() const { - - if (!baked_cache_dirty) + if (!baked_cache_dirty) { return; + } baked_max_ofs = 0; baked_cache_dirty = false; @@ -1182,18 +1157,17 @@ void Curve3D::_bake() const { } if (points.size() == 1) { - baked_point_cache.resize(1); baked_point_cache.set(0, points[0].pos); baked_tilt_cache.resize(1); baked_tilt_cache.set(0, points[0].tilt); if (up_vector_enabled) { - baked_up_vector_cache.resize(1); baked_up_vector_cache.set(0, Vector3(0, 1, 0)); - } else + } else { baked_up_vector_cache.resize(0); + } return; } @@ -1203,15 +1177,14 @@ void Curve3D::_bake() const { pointlist.push_back(Plane(pos, points[0].tilt)); for (int i = 0; i < points.size() - 1; i++) { - float step = 0.1; // at least 10 substeps ought to be enough? float p = 0; while (p < 1.0) { - float np = p + step; - if (np > 1.0) + if (np > 1.0) { np = 1.0; + } Vector3 npp = _bezier_interp(np, points[i].pos, points[i].pos + points[i].out, points[i + 1].pos + points[i + 1].in, points[i + 1].pos); float d = pos.distance_to(npp); @@ -1226,14 +1199,14 @@ void Curve3D::_bake() const { float mid = low + (hi - low) * 0.5; for (int j = 0; j < iterations; j++) { - npp = _bezier_interp(mid, points[i].pos, points[i].pos + points[i].out, points[i + 1].pos + points[i + 1].in, points[i + 1].pos); d = pos.distance_to(npp); - if (bake_interval < d) + if (bake_interval < d) { hi = mid; - else + } else { low = mid; + } mid = low + (hi - low) * 0.5; } @@ -1244,7 +1217,6 @@ void Curve3D::_bake() const { post.d = Math::lerp(points[i].tilt, points[i + 1].tilt, mid); pointlist.push_back(post); } else { - p = np; } } @@ -1258,14 +1230,14 @@ void Curve3D::_bake() const { pointlist.push_back(Plane(lastpos, lastilt)); baked_point_cache.resize(pointlist.size()); - PoolVector3Array::Write w = baked_point_cache.write(); + Vector3 *w = baked_point_cache.ptrw(); int idx = 0; baked_tilt_cache.resize(pointlist.size()); - PoolRealArray::Write wt = baked_tilt_cache.write(); + real_t *wt = baked_tilt_cache.ptrw(); baked_up_vector_cache.resize(up_vector_enabled ? pointlist.size() : 0); - PoolVector3Array::Write up_write = baked_up_vector_cache.write(); + Vector3 *up_write = baked_up_vector_cache.ptrw(); Vector3 sideways; Vector3 up; @@ -1276,7 +1248,6 @@ void Curve3D::_bake() const { Vector3 prev_forward = Vector3(0, 0, 1); for (List<Plane>::Element *E = pointlist.front(); E; E = E->next()) { - w[idx] = E->get().normal; wt[idx] = E->get().d; @@ -1300,8 +1271,9 @@ void Curve3D::_bake() const { up = forward.cross(sideways).normalized(); } - if (idx == 1) + if (idx == 1) { up_write[0] = up; + } up_write[idx] = up; @@ -1314,31 +1286,35 @@ void Curve3D::_bake() const { } float Curve3D::get_baked_length() const { - - if (baked_cache_dirty) + if (baked_cache_dirty) { _bake(); + } return baked_max_ofs; } -Vector3 Curve3D::interpolate_baked(float p_offset, bool p_cubic) const { - if (baked_cache_dirty) +Vector3 Curve3D::interpolate_baked(float p_offset, bool p_cubic) const { + if (baked_cache_dirty) { _bake(); + } //validate// int pc = baked_point_cache.size(); ERR_FAIL_COND_V_MSG(pc == 0, Vector3(), "No points in Curve3D."); - if (pc == 1) + if (pc == 1) { return baked_point_cache.get(0); + } int bpc = baked_point_cache.size(); - PoolVector3Array::Read r = baked_point_cache.read(); + const Vector3 *r = baked_point_cache.ptr(); - if (p_offset < 0) + if (p_offset < 0) { return r[0]; - if (p_offset >= baked_max_ofs) + } + if (p_offset >= baked_max_ofs) { return r[bpc - 1]; + } int idx = Math::floor((double)p_offset / (double)bake_interval); float frac = Math::fmod(p_offset, bake_interval); @@ -1346,41 +1322,44 @@ Vector3 Curve3D::interpolate_baked(float p_offset, bool p_cubic) const { if (idx >= bpc - 1) { return r[bpc - 1]; } else if (idx == bpc - 2) { - if (frac > 0) + if (frac > 0) { frac /= Math::fmod(baked_max_ofs, bake_interval); + } } else { frac /= bake_interval; } if (p_cubic) { - Vector3 pre = idx > 0 ? r[idx - 1] : r[idx]; Vector3 post = (idx < (bpc - 2)) ? r[idx + 2] : r[idx + 1]; return r[idx].cubic_interpolate(r[idx + 1], pre, post, frac); } else { - return r[idx].linear_interpolate(r[idx + 1], frac); + return r[idx].lerp(r[idx + 1], frac); } } float Curve3D::interpolate_baked_tilt(float p_offset) const { - - if (baked_cache_dirty) + if (baked_cache_dirty) { _bake(); + } //validate// int pc = baked_tilt_cache.size(); ERR_FAIL_COND_V_MSG(pc == 0, 0, "No tilts in Curve3D."); - if (pc == 1) + if (pc == 1) { return baked_tilt_cache.get(0); + } int bpc = baked_tilt_cache.size(); - PoolRealArray::Read r = baked_tilt_cache.read(); + const real_t *r = baked_tilt_cache.ptr(); - if (p_offset < 0) + if (p_offset < 0) { return r[0]; - if (p_offset >= baked_max_ofs) + } + if (p_offset >= baked_max_ofs) { return r[bpc - 1]; + } int idx = Math::floor((double)p_offset / (double)bake_interval); float frac = Math::fmod(p_offset, bake_interval); @@ -1388,8 +1367,9 @@ float Curve3D::interpolate_baked_tilt(float p_offset) const { if (idx >= bpc - 1) { return r[bpc - 1]; } else if (idx == bpc - 2) { - if (frac > 0) + if (frac > 0) { frac /= Math::fmod(baked_max_ofs, bake_interval); + } } else { frac /= bake_interval; } @@ -1398,29 +1378,31 @@ float Curve3D::interpolate_baked_tilt(float p_offset) const { } Vector3 Curve3D::interpolate_baked_up_vector(float p_offset, bool p_apply_tilt) const { - - if (baked_cache_dirty) + if (baked_cache_dirty) { _bake(); + } //validate// // curve may not have baked up vectors int count = baked_up_vector_cache.size(); ERR_FAIL_COND_V_MSG(count == 0, Vector3(0, 1, 0), "No up vectors in Curve3D."); - if (count == 1) + if (count == 1) { return baked_up_vector_cache.get(0); + } - PoolVector3Array::Read r = baked_up_vector_cache.read(); - PoolVector3Array::Read rp = baked_point_cache.read(); - PoolRealArray::Read rt = baked_tilt_cache.read(); + const Vector3 *r = baked_up_vector_cache.ptr(); + const Vector3 *rp = baked_point_cache.ptr(); + const real_t *rt = baked_tilt_cache.ptr(); float offset = CLAMP(p_offset, 0.0f, baked_max_ofs); int idx = Math::floor((double)offset / (double)bake_interval); float frac = Math::fmod(offset, bake_interval) / bake_interval; - if (idx == count - 1) + if (idx == count - 1) { return p_apply_tilt ? r[idx].rotated((rp[idx] - rp[idx - 1]).normalized(), rt[idx]) : r[idx]; + } Vector3 forward = (rp[idx + 1] - rp[idx]).normalized(); Vector3 up = r[idx]; @@ -1433,34 +1415,35 @@ Vector3 Curve3D::interpolate_baked_up_vector(float p_offset, bool p_apply_tilt) Vector3 axis = up.cross(up1); - if (axis.length_squared() < CMP_EPSILON2) + if (axis.length_squared() < CMP_EPSILON2) { axis = forward; - else + } else { axis.normalize(); + } return up.rotated(axis, up.angle_to(up1) * frac); } -PoolVector3Array Curve3D::get_baked_points() const { - - if (baked_cache_dirty) +PackedVector3Array Curve3D::get_baked_points() const { + if (baked_cache_dirty) { _bake(); + } return baked_point_cache; } -PoolRealArray Curve3D::get_baked_tilts() const { - - if (baked_cache_dirty) +PackedFloat32Array Curve3D::get_baked_tilts() const { + if (baked_cache_dirty) { _bake(); + } return baked_tilt_cache; } -PoolVector3Array Curve3D::get_baked_up_vectors() const { - - if (baked_cache_dirty) +PackedVector3Array Curve3D::get_baked_up_vectors() const { + if (baked_cache_dirty) { _bake(); + } return baked_up_vector_cache; } @@ -1468,17 +1451,19 @@ PoolVector3Array Curve3D::get_baked_up_vectors() const { Vector3 Curve3D::get_closest_point(const Vector3 &p_to_point) const { // Brute force method - if (baked_cache_dirty) + if (baked_cache_dirty) { _bake(); + } //validate// int pc = baked_point_cache.size(); ERR_FAIL_COND_V_MSG(pc == 0, Vector3(), "No points in Curve3D."); - if (pc == 1) + if (pc == 1) { return baked_point_cache.get(0); + } - PoolVector3Array::Read r = baked_point_cache.read(); + const Vector3 *r = baked_point_cache.ptr(); Vector3 nearest; float nearest_dist = -1.0f; @@ -1504,17 +1489,19 @@ Vector3 Curve3D::get_closest_point(const Vector3 &p_to_point) const { float Curve3D::get_closest_offset(const Vector3 &p_to_point) const { // Brute force method - if (baked_cache_dirty) + if (baked_cache_dirty) { _bake(); + } //validate// int pc = baked_point_cache.size(); ERR_FAIL_COND_V_MSG(pc == 0, 0.0f, "No points in Curve3D."); - if (pc == 1) + if (pc == 1) { return 0.0f; + } - PoolVector3Array::Read r = baked_point_cache.read(); + const Vector3 *r = baked_point_cache.ptr(); float nearest = 0.0f; float nearest_dist = -1.0f; @@ -1541,71 +1528,61 @@ float Curve3D::get_closest_offset(const Vector3 &p_to_point) const { } void Curve3D::set_bake_interval(float p_tolerance) { - bake_interval = p_tolerance; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } float Curve3D::get_bake_interval() const { - return bake_interval; } void Curve3D::set_up_vector_enabled(bool p_enable) { - up_vector_enabled = p_enable; baked_cache_dirty = true; emit_signal(CoreStringNames::get_singleton()->changed); } bool Curve3D::is_up_vector_enabled() const { - return up_vector_enabled; } Dictionary Curve3D::_get_data() const { - Dictionary dc; - PoolVector3Array d; + PackedVector3Array d; d.resize(points.size() * 3); - PoolVector3Array::Write w = d.write(); - PoolRealArray t; + Vector3 *w = d.ptrw(); + PackedFloat32Array t; t.resize(points.size()); - PoolRealArray::Write wt = t.write(); + real_t *wt = t.ptrw(); for (int i = 0; i < points.size(); i++) { - w[i * 3 + 0] = points[i].in; w[i * 3 + 1] = points[i].out; w[i * 3 + 2] = points[i].pos; wt[i] = points[i].tilt; } - w = PoolVector3Array::Write(); - wt = PoolRealArray::Write(); - dc["points"] = d; dc["tilts"] = t; return dc; } -void Curve3D::_set_data(const Dictionary &p_data) { +void Curve3D::_set_data(const Dictionary &p_data) { ERR_FAIL_COND(!p_data.has("points")); ERR_FAIL_COND(!p_data.has("tilts")); - PoolVector3Array rp = p_data["points"]; + PackedVector3Array rp = p_data["points"]; int pc = rp.size(); ERR_FAIL_COND(pc % 3 != 0); points.resize(pc / 3); - PoolVector3Array::Read r = rp.read(); - PoolRealArray rtl = p_data["tilts"]; - PoolRealArray::Read rt = rtl.read(); + const Vector3 *r = rp.ptr(); + PackedFloat32Array rtl = p_data["tilts"]; + const real_t *rt = rtl.ptr(); for (int i = 0; i < points.size(); i++) { - points.write[i].in = r[i * 3 + 0]; points.write[i].out = r[i * 3 + 1]; points.write[i].pos = r[i * 3 + 2]; @@ -1615,34 +1592,30 @@ void Curve3D::_set_data(const Dictionary &p_data) { baked_cache_dirty = true; } -PoolVector3Array Curve3D::tessellate(int p_max_stages, float p_tolerance) const { - - PoolVector3Array tess; +PackedVector3Array Curve3D::tessellate(int p_max_stages, float p_tolerance) const { + PackedVector3Array tess; if (points.size() == 0) { return tess; } - Vector<Map<float, Vector3> > midpoints; + Vector<Map<float, Vector3>> midpoints; midpoints.resize(points.size() - 1); int pc = 1; for (int i = 0; i < points.size() - 1; i++) { - _bake_segment3d(midpoints.write[i], 0, 1, points[i].pos, points[i].out, points[i + 1].pos, points[i + 1].in, 0, p_max_stages, p_tolerance); pc++; pc += midpoints[i].size(); } tess.resize(pc); - PoolVector3Array::Write bpw = tess.write(); + Vector3 *bpw = tess.ptrw(); bpw[0] = points[0].pos; int pidx = 0; for (int i = 0; i < points.size() - 1; i++) { - for (Map<float, Vector3>::Element *E = midpoints[i].front(); E; E = E->next()) { - pidx++; bpw[pidx] = E->get(); } @@ -1651,13 +1624,10 @@ PoolVector3Array Curve3D::tessellate(int p_max_stages, float p_tolerance) const bpw[pidx] = points[i + 1].pos; } - bpw = PoolVector3Array::Write(); - return tess; } void Curve3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_point_count"), &Curve3D::get_point_count); ClassDB::bind_method(D_METHOD("add_point", "position", "in", "out", "at_position"), &Curve3D::add_point, DEFVAL(Vector3()), DEFVAL(Vector3()), DEFVAL(-1)); ClassDB::bind_method(D_METHOD("set_point_position", "idx", "position"), &Curve3D::set_point_position); @@ -1691,7 +1661,7 @@ void Curve3D::_bind_methods() { ClassDB::bind_method(D_METHOD("_get_data"), &Curve3D::_get_data); ClassDB::bind_method(D_METHOD("_set_data"), &Curve3D::_set_data); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "bake_interval", PROPERTY_HINT_RANGE, "0.01,512,0.01"), "set_bake_interval", "get_bake_interval"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bake_interval", PROPERTY_HINT_RANGE, "0.01,512,0.01"), "set_bake_interval", "get_bake_interval"); ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); ADD_GROUP("Up Vector", "up_vector_"); diff --git a/scene/resources/curve.h b/scene/resources/curve.h index b02466534c..57ddaf897d 100644 --- a/scene/resources/curve.h +++ b/scene/resources/curve.h @@ -68,7 +68,6 @@ public: real_t p_right = 0, TangentMode p_left_mode = TANGENT_FREE, TangentMode p_right_mode = TANGENT_FREE) { - pos = p_pos; left_tangent = p_left; right_tangent = p_right; @@ -149,11 +148,9 @@ private: VARIANT_ENUM_CAST(Curve::TangentMode) class Curve2D : public Resource { - GDCLASS(Curve2D, Resource); struct Point { - Vector2 in; Vector2 out; Vector2 pos; @@ -162,13 +159,12 @@ class Curve2D : public Resource { Vector<Point> points; struct BakedPoint { - float ofs; Vector2 point; }; mutable bool baked_cache_dirty; - mutable PoolVector2Array baked_point_cache; + mutable PackedVector2Array baked_point_cache; mutable float baked_max_ofs; void _bake() const; @@ -202,21 +198,19 @@ public: float get_baked_length() const; Vector2 interpolate_baked(float p_offset, bool p_cubic = false) const; - PoolVector2Array get_baked_points() const; //useful for going through + PackedVector2Array get_baked_points() const; //useful for going through Vector2 get_closest_point(const Vector2 &p_to_point) const; float get_closest_offset(const Vector2 &p_to_point) const; - PoolVector2Array tessellate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display + PackedVector2Array tessellate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display Curve2D(); }; class Curve3D : public Resource { - GDCLASS(Curve3D, Resource); struct Point { - Vector3 in; Vector3 out; Vector3 pos; @@ -228,15 +222,14 @@ class Curve3D : public Resource { Vector<Point> points; struct BakedPoint { - float ofs; Vector3 point; }; mutable bool baked_cache_dirty; - mutable PoolVector3Array baked_point_cache; - mutable PoolRealArray baked_tilt_cache; - mutable PoolVector3Array baked_up_vector_cache; + mutable PackedVector3Array baked_point_cache; + mutable PackedFloat32Array baked_tilt_cache; + mutable PackedVector3Array baked_up_vector_cache; mutable float baked_max_ofs; void _bake() const; @@ -277,13 +270,13 @@ public: Vector3 interpolate_baked(float p_offset, bool p_cubic = false) const; float interpolate_baked_tilt(float p_offset) const; Vector3 interpolate_baked_up_vector(float p_offset, bool p_apply_tilt = false) const; - PoolVector3Array get_baked_points() const; //useful for going through - PoolRealArray get_baked_tilts() const; //useful for going through - PoolVector3Array get_baked_up_vectors() const; + PackedVector3Array get_baked_points() const; //useful for going through + PackedFloat32Array get_baked_tilts() const; //useful for going through + PackedVector3Array get_baked_up_vectors() const; Vector3 get_closest_point(const Vector3 &p_to_point) const; float get_closest_offset(const Vector3 &p_to_point) const; - PoolVector3Array tessellate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display + PackedVector3Array tessellate(int p_max_stages = 5, float p_tolerance = 4) const; //useful for display Curve3D(); }; diff --git a/scene/resources/cylinder_shape.cpp b/scene/resources/cylinder_shape_3d.cpp index d9f6e4f054..ad64541247 100644 --- a/scene/resources/cylinder_shape.cpp +++ b/scene/resources/cylinder_shape_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* cylinder_shape.cpp */ +/* cylinder_shape_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "cylinder_shape.h" -#include "servers/physics_server.h" - -Vector<Vector3> CylinderShape::get_debug_mesh_lines() { +#include "cylinder_shape_3d.h" +#include "servers/physics_server_3d.h" +Vector<Vector3> CylinderShape3D::get_debug_mesh_lines() const { float radius = get_radius(); float height = get_height(); @@ -40,7 +39,6 @@ Vector<Vector3> CylinderShape::get_debug_mesh_lines() { Vector3 d(0, height * 0.5, 0); for (int i = 0; i < 360; i++) { - float ra = Math::deg2rad((float)i); float rb = Math::deg2rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius; @@ -53,7 +51,6 @@ Vector<Vector3> CylinderShape::get_debug_mesh_lines() { points.push_back(Vector3(b.x, 0, b.y) - d); if (i % 90 == 0) { - points.push_back(Vector3(a.x, 0, a.y) + d); points.push_back(Vector3(a.x, 0, a.y) - d); } @@ -62,55 +59,52 @@ Vector<Vector3> CylinderShape::get_debug_mesh_lines() { return points; } -void CylinderShape::_update_shape() { +real_t CylinderShape3D::get_enclosing_radius() const { + return Vector2(radius, height * 0.5).length(); +} +void CylinderShape3D::_update_shape() { Dictionary d; d["radius"] = radius; d["height"] = height; - PhysicsServer::get_singleton()->shape_set_data(get_shape(), d); - Shape::_update_shape(); + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), d); + Shape3D::_update_shape(); } -void CylinderShape::set_radius(float p_radius) { - +void CylinderShape3D::set_radius(float p_radius) { radius = p_radius; _update_shape(); notify_change_to_owners(); _change_notify("radius"); } -float CylinderShape::get_radius() const { - +float CylinderShape3D::get_radius() const { return radius; } -void CylinderShape::set_height(float p_height) { - +void CylinderShape3D::set_height(float p_height) { height = p_height; _update_shape(); notify_change_to_owners(); _change_notify("height"); } -float CylinderShape::get_height() const { - +float CylinderShape3D::get_height() const { return height; } -void CylinderShape::_bind_methods() { +void CylinderShape3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CylinderShape3D::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &CylinderShape3D::get_radius); + ClassDB::bind_method(D_METHOD("set_height", "height"), &CylinderShape3D::set_height); + ClassDB::bind_method(D_METHOD("get_height"), &CylinderShape3D::get_height); - ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CylinderShape::set_radius); - ClassDB::bind_method(D_METHOD("get_radius"), &CylinderShape::get_radius); - ClassDB::bind_method(D_METHOD("set_height", "height"), &CylinderShape::set_height); - ClassDB::bind_method(D_METHOD("get_height"), &CylinderShape::get_height); - - ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_height", "get_height"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_height", "get_height"); } -CylinderShape::CylinderShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CYLINDER)) { - +CylinderShape3D::CylinderShape3D() : + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_CYLINDER)) { radius = 1.0; height = 2.0; _update_shape(); diff --git a/scene/resources/cylinder_shape.h b/scene/resources/cylinder_shape_3d.h index ebddd4d92f..e579e1f7cf 100644 --- a/scene/resources/cylinder_shape.h +++ b/scene/resources/cylinder_shape_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* cylinder_shape.h */ +/* cylinder_shape_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,20 +28,19 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CYLINDER_SHAPE_H -#define CYLINDER_SHAPE_H +#ifndef CYLINDER_SHAPE_3D_H +#define CYLINDER_SHAPE_3D_H -#include "scene/resources/shape.h" +#include "scene/resources/shape_3d.h" -class CylinderShape : public Shape { - - GDCLASS(CylinderShape, Shape); +class CylinderShape3D : public Shape3D { + GDCLASS(CylinderShape3D, Shape3D); float radius; float height; protected: static void _bind_methods(); - virtual void _update_shape(); + virtual void _update_shape() override; public: void set_radius(float p_radius); @@ -49,9 +48,10 @@ public: void set_height(float p_height); float get_height() const; - virtual Vector<Vector3> get_debug_mesh_lines(); + virtual Vector<Vector3> get_debug_mesh_lines() const override; + virtual real_t get_enclosing_radius() const override; - CylinderShape(); + CylinderShape3D(); }; #endif // CYLINDER_SHAPE_H diff --git a/scene/resources/default_theme/SCsub b/scene/resources/default_theme/SCsub index b01e2fd54d..fc61250247 100644 --- a/scene/resources/default_theme/SCsub +++ b/scene/resources/default_theme/SCsub @@ -1,5 +1,5 @@ #!/usr/bin/env python -Import('env') +Import("env") env.add_source_files(env.scene_sources, "*.cpp") diff --git a/scene/resources/default_theme/bookmark.png b/scene/resources/default_theme/bookmark.png Binary files differnew file mode 100644 index 0000000000..9718cf53b6 --- /dev/null +++ b/scene/resources/default_theme/bookmark.png diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index cc76df62e5..f65f78b332 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -38,38 +38,25 @@ #include "font_hidpi.inc" #include "font_lodpi.inc" -typedef Map<const void *, Ref<ImageTexture> > TexCacheMap; +typedef Map<const void *, Ref<ImageTexture>> TexCacheMap; static TexCacheMap *tex_cache; static float scale = 1; template <class T> static Ref<StyleBoxTexture> make_stylebox(T p_src, float p_left, float p_top, float p_right, float p_botton, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_botton = -1, bool p_draw_center = true) { - Ref<ImageTexture> texture; if (tex_cache->has(p_src)) { texture = (*tex_cache)[p_src]; } else { - texture = Ref<ImageTexture>(memnew(ImageTexture)); Ref<Image> img = memnew(Image(p_src)); + const Size2 orig_size = Size2(img->get_width(), img->get_height()); + img->convert(Image::FORMAT_RGBA8); + img->resize(orig_size.x * scale, orig_size.y * scale); - if (scale > 1) { - Size2 orig_size = Size2(img->get_width(), img->get_height()); - - img->convert(Image::FORMAT_RGBA8); - img->expand_x2_hq2x(); - if (scale != 2.0) { - img->resize(orig_size.x * scale, orig_size.y * scale); - } - } else if (scale < 1) { - Size2 orig_size = Size2(img->get_width(), img->get_height()); - img->convert(Image::FORMAT_RGBA8); - img->resize(orig_size.x * scale, orig_size.y * scale); - } - - texture->create_from_image(img, ImageTexture::FLAG_FILTER); + texture->create_from_image(img); (*tex_cache)[p_src] = texture; } @@ -89,7 +76,6 @@ static Ref<StyleBoxTexture> make_stylebox(T p_src, float p_left, float p_top, fl } static Ref<StyleBoxTexture> sb_expand(Ref<StyleBoxTexture> p_sbox, float p_left, float p_top, float p_right, float p_botton) { - p_sbox->set_expand_margin_size(MARGIN_LEFT, p_left * scale); p_sbox->set_expand_margin_size(MARGIN_TOP, p_top * scale); p_sbox->set_expand_margin_size(MARGIN_RIGHT, p_right * scale); @@ -98,30 +84,18 @@ static Ref<StyleBoxTexture> sb_expand(Ref<StyleBoxTexture> p_sbox, float p_left, } template <class T> -static Ref<Texture> make_icon(T p_src) { - +static Ref<Texture2D> make_icon(T p_src) { Ref<ImageTexture> texture(memnew(ImageTexture)); Ref<Image> img = memnew(Image(p_src)); - if (scale > 1) { - Size2 orig_size = Size2(img->get_width(), img->get_height()); - - img->convert(Image::FORMAT_RGBA8); - img->expand_x2_hq2x(); - if (scale != 2.0) { - img->resize(orig_size.x * scale, orig_size.y * scale); - } - } else if (scale < 1) { - Size2 orig_size = Size2(img->get_width(), img->get_height()); - img->convert(Image::FORMAT_RGBA8); - img->resize(orig_size.x * scale, orig_size.y * scale); - } - texture->create_from_image(img, ImageTexture::FLAG_FILTER); + const Size2 orig_size = Size2(img->get_width(), img->get_height()); + img->convert(Image::FORMAT_RGBA8); + img->resize(orig_size.x * scale, orig_size.y * scale); + texture->create_from_image(img); return texture; } static Ref<BitmapFont> make_font(int p_height, int p_ascent, int p_charcount, const int *p_char_rects, int p_kerning_count, const int *p_kernings, int p_w, int p_h, const unsigned char *p_img) { - Ref<BitmapFont> font(memnew(BitmapFont)); Ref<Image> image = memnew(Image(p_img)); @@ -131,7 +105,6 @@ static Ref<BitmapFont> make_font(int p_height, int p_ascent, int p_charcount, co font->add_texture(tex); for (int i = 0; i < p_charcount; i++) { - const int *c = &p_char_rects[i * 8]; int chr = c[0]; @@ -147,7 +120,6 @@ static Ref<BitmapFont> make_font(int p_height, int p_ascent, int p_charcount, co } for (int i = 0; i < p_kerning_count; i++) { - font->add_kerning_pair(p_kernings[i * 3 + 0], p_kernings[i * 3 + 1], p_kernings[i * 3 + 2]); } @@ -158,7 +130,6 @@ static Ref<BitmapFont> make_font(int p_height, int p_ascent, int p_charcount, co } static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_botton = -1) { - Ref<StyleBox> style(memnew(StyleBoxEmpty)); style->set_default_margin(MARGIN_LEFT, p_margin_left * scale); @@ -169,8 +140,7 @@ static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margi return style; } -void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &large_font, Ref<Texture> &default_icon, Ref<StyleBox> &default_style, float p_scale) { - +void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &large_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale) { scale = p_scale; tex_cache = memnew(TexCacheMap); @@ -188,6 +158,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // Panel theme->set_stylebox("panel", "Panel", make_stylebox(panel_bg_png, 0, 0, 0, 0)); + theme->set_stylebox("panel_fg", "Panel", make_stylebox(panel_bg_png, 0, 0, 0, 0)); // Focus @@ -210,7 +181,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("disabled", "Button", sb_button_disabled); theme->set_stylebox("focus", "Button", sb_button_focus); - theme->set_font("font", "Button", default_font); + theme->set_font("font", "Button", Ref<Font>()); theme->set_color("font_color", "Button", control_font_color); theme->set_color("font_color_pressed", "Button", control_font_color_pressed); @@ -223,7 +194,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("focus", "LinkButton", focus); - theme->set_font("font", "LinkButton", default_font); + theme->set_font("font", "LinkButton", Ref<Font>()); theme->set_color("font_color", "LinkButton", control_font_color); theme->set_color("font_color_pressed", "LinkButton", control_font_color_pressed); @@ -239,7 +210,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("disabled", "ColorPickerButton", sb_button_disabled); theme->set_stylebox("focus", "ColorPickerButton", sb_button_focus); - theme->set_font("font", "ColorPickerButton", default_font); + theme->set_font("font", "ColorPickerButton", Ref<Font>()); theme->set_color("font_color", "ColorPickerButton", Color(1, 1, 1, 1)); theme->set_color("font_color_pressed", "ColorPickerButton", Color(0.8, 0.8, 0.8, 1)); @@ -248,22 +219,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("hseparation", "ColorPickerButton", 2 * scale); - // ToolButton - - theme->set_stylebox("normal", "ToolButton", make_empty_stylebox(6, 4, 6, 4)); - theme->set_stylebox("pressed", "ToolButton", make_stylebox(button_pressed_png, 4, 4, 4, 4, 6, 4, 6, 4)); - theme->set_stylebox("hover", "ToolButton", make_stylebox(button_normal_png, 4, 4, 4, 4, 6, 4, 6, 4)); - theme->set_stylebox("disabled", "ToolButton", make_empty_stylebox(6, 4, 6, 4)); - theme->set_stylebox("focus", "ToolButton", focus); - theme->set_font("font", "ToolButton", default_font); - - theme->set_color("font_color", "ToolButton", control_font_color); - theme->set_color("font_color_pressed", "ToolButton", control_font_color_pressed); - theme->set_color("font_color_hover", "ToolButton", control_font_color_hover); - theme->set_color("font_color_disabled", "ToolButton", Color(0.9, 0.95, 1, 0.3)); - - theme->set_constant("hseparation", "ToolButton", 3); - // OptionButton Ref<StyleBox> sb_optbutton_normal = sb_expand(make_stylebox(option_button_normal_png, 4, 4, 21, 4, 6, 3, 9, 3), 2, 2, 2, 2); @@ -280,7 +235,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("arrow", "OptionButton", make_icon(option_arrow_png)); - theme->set_font("font", "OptionButton", default_font); + theme->set_font("font", "OptionButton", Ref<Font>()); theme->set_color("font_color", "OptionButton", control_font_color); theme->set_color("font_color_pressed", "OptionButton", control_font_color_pressed); @@ -298,7 +253,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("disabled", "MenuButton", sb_button_disabled); theme->set_stylebox("focus", "MenuButton", sb_button_focus); - theme->set_font("font", "MenuButton", default_font); + theme->set_font("font", "MenuButton", Ref<Font>()); theme->set_color("font_color", "MenuButton", control_font_color); theme->set_color("font_color_pressed", "MenuButton", control_font_color_pressed); @@ -332,7 +287,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("radio_checked", "CheckBox", make_icon(radio_checked_png)); theme->set_icon("radio_unchecked", "CheckBox", make_icon(radio_unchecked_png)); - theme->set_font("font", "CheckBox", default_font); + theme->set_font("font", "CheckBox", Ref<Font>()); theme->set_color("font_color", "CheckBox", control_font_color); theme->set_color("font_color_pressed", "CheckBox", control_font_color_pressed); @@ -363,7 +318,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("off", "CheckButton", make_icon(toggle_off_png)); theme->set_icon("off_disabled", "CheckButton", make_icon(toggle_off_disabled_png)); - theme->set_font("font", "CheckButton", default_font); + theme->set_font("font", "CheckButton", Ref<Font>()); theme->set_color("font_color", "CheckButton", control_font_color); theme->set_color("font_color_pressed", "CheckButton", control_font_color_pressed); @@ -377,7 +332,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // Label theme->set_stylebox("normal", "Label", memnew(StyleBoxEmpty)); - theme->set_font("font", "Label", default_font); + theme->set_font("font", "Label", Ref<Font>()); theme->set_color("font_color", "Label", Color(1, 1, 1)); theme->set_color("font_color_shadow", "Label", Color(0, 0, 0, 0)); @@ -394,7 +349,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("focus", "LineEdit", focus); theme->set_stylebox("read_only", "LineEdit", make_stylebox(line_edit_disabled_png, 6, 6, 6, 6)); - theme->set_font("font", "LineEdit", default_font); + theme->set_font("font", "LineEdit", Ref<Font>()); theme->set_color("font_color", "LineEdit", control_font_color); theme->set_color("font_color_selected", "LineEdit", Color(0, 0, 0)); @@ -413,7 +368,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("bg", "ProgressBar", make_stylebox(progress_bar_png, 4, 4, 4, 4, 0, 0, 0, 0)); theme->set_stylebox("fg", "ProgressBar", make_stylebox(progress_fill_png, 6, 6, 6, 6, 2, 1, 2, 1)); - theme->set_font("font", "ProgressBar", default_font); + theme->set_font("font", "ProgressBar", Ref<Font>()); theme->set_color("font_color", "ProgressBar", control_font_color_hover); theme->set_color("font_color_shadow", "ProgressBar", Color(0, 0, 0)); @@ -427,10 +382,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("tab", "TextEdit", make_icon(tab_png)); theme->set_icon("space", "TextEdit", make_icon(space_png)); - theme->set_icon("folded", "TextEdit", make_icon(arrow_right_png)); - theme->set_icon("fold", "TextEdit", make_icon(arrow_down_png)); - theme->set_font("font", "TextEdit", default_font); + theme->set_font("font", "TextEdit", Ref<Font>()); theme->set_color("background_color", "TextEdit", Color(0, 0, 0, 0)); theme->set_color("completion_background_color", "TextEdit", Color(0.17, 0.16, 0.2)); @@ -443,20 +396,11 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_color("font_color_readonly", "TextEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f)); theme->set_color("selection_color", "TextEdit", font_color_selection); theme->set_color("mark_color", "TextEdit", Color(1.0, 0.4, 0.4, 0.4)); - theme->set_color("bookmark_color", "TextEdit", Color(0.08, 0.49, 0.98)); - theme->set_color("breakpoint_color", "TextEdit", Color(0.8, 0.8, 0.4, 0.2)); - theme->set_color("executing_line_color", "TextEdit", Color(0.2, 0.8, 0.2, 0.4)); theme->set_color("code_folding_color", "TextEdit", Color(0.8, 0.8, 0.8, 0.8)); theme->set_color("current_line_color", "TextEdit", Color(0.25, 0.25, 0.26, 0.8)); theme->set_color("caret_color", "TextEdit", control_font_color); theme->set_color("caret_background_color", "TextEdit", Color(0, 0, 0)); - theme->set_color("symbol_color", "TextEdit", control_font_color_hover); theme->set_color("brace_mismatch_color", "TextEdit", Color(1, 0.2, 0.2)); - theme->set_color("line_number_color", "TextEdit", Color(0.67, 0.67, 0.67, 0.4)); - theme->set_color("safe_line_number_color", "TextEdit", Color(0.67, 0.78, 0.67, 0.6)); - theme->set_color("function_color", "TextEdit", Color(0.4, 0.64, 0.81)); - theme->set_color("member_variable_color", "TextEdit", Color(0.9, 0.31, 0.35)); - theme->set_color("number_color", "TextEdit", Color(0.92, 0.58, 0.2)); theme->set_color("word_highlighted_color", "TextEdit", Color(0.8, 0.9, 0.9, 0.15)); theme->set_constant("completion_lines", "TextEdit", 7); @@ -464,7 +408,51 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("completion_scroll_width", "TextEdit", 3); theme->set_constant("line_spacing", "TextEdit", 4 * scale); - Ref<Texture> empty_icon = memnew(ImageTexture); + // CodeEdit + theme->set_stylebox("normal", "CodeEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3, 0, 0, 0, 0)); + theme->set_stylebox("focus", "CodeEdit", focus); + theme->set_stylebox("read_only", "CodeEdit", make_stylebox(tree_bg_disabled_png, 4, 4, 4, 4, 0, 0, 0, 0)); + theme->set_stylebox("completion", "CodeEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3, 0, 0, 0, 0)); + + theme->set_icon("tab", "CodeEdit", make_icon(tab_png)); + theme->set_icon("space", "CodeEdit", make_icon(space_png)); + theme->set_icon("breakpoint", "CodeEdit", make_icon(graph_port_png)); + theme->set_icon("bookmark", "CodeEdit", make_icon(bookmark_png)); + theme->set_icon("executing_line", "CodeEdit", make_icon(arrow_right_png)); + theme->set_icon("can_fold", "CodeEdit", make_icon(arrow_down_png)); + theme->set_icon("folded", "CodeEdit", make_icon(arrow_right_png)); + + theme->set_font("font", "CodeEdit", Ref<Font>()); + + theme->set_color("background_color", "CodeEdit", Color(0, 0, 0, 0)); + theme->set_color("completion_background_color", "CodeEdit", Color(0.17, 0.16, 0.2)); + theme->set_color("completion_selected_color", "CodeEdit", Color(0.26, 0.26, 0.27)); + theme->set_color("completion_existing_color", "CodeEdit", Color(0.87, 0.87, 0.87, 0.13)); + theme->set_color("completion_scroll_color", "CodeEdit", control_font_color_pressed); + theme->set_color("completion_font_color", "CodeEdit", Color(0.67, 0.67, 0.67)); + theme->set_color("font_color", "CodeEdit", control_font_color); + theme->set_color("font_color_selected", "CodeEdit", Color(0, 0, 0)); + theme->set_color("font_color_readonly", "CodeEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f)); + theme->set_color("selection_color", "CodeEdit", font_color_selection); + theme->set_color("mark_color", "CodeEdit", Color(1.0, 0.4, 0.4, 0.4)); + theme->set_color("bookmark_color", "CodeEdit", Color(0.5, 0.64, 1, 0.8)); + theme->set_color("breakpoint_color", "CodeEdit", Color(0.9, 0.29, 0.3)); + theme->set_color("executing_line_color", "CodeEdit", Color(0.98, 0.89, 0.27)); + theme->set_color("code_folding_color", "CodeEdit", Color(0.8, 0.8, 0.8, 0.8)); + theme->set_color("current_line_color", "CodeEdit", Color(0.25, 0.25, 0.26, 0.8)); + theme->set_color("caret_color", "CodeEdit", control_font_color); + theme->set_color("caret_background_color", "CodeEdit", Color(0, 0, 0)); + theme->set_color("brace_mismatch_color", "CodeEdit", Color(1, 0.2, 0.2)); + theme->set_color("line_number_color", "CodeEdit", Color(0.67, 0.67, 0.67, 0.4)); + theme->set_color("safe_line_number_color", "CodeEdit", Color(0.67, 0.78, 0.67, 0.6)); + theme->set_color("word_highlighted_color", "CodeEdit", Color(0.8, 0.9, 0.9, 0.15)); + + theme->set_constant("completion_lines", "CodeEdit", 7); + theme->set_constant("completion_max_width", "CodeEdit", 50); + theme->set_constant("completion_scroll_width", "CodeEdit", 3); + theme->set_constant("line_spacing", "CodeEdit", 4 * scale); + + Ref<Texture2D> empty_icon = memnew(ImageTexture); // HScrollBar @@ -496,6 +484,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("slider", "HSlider", make_stylebox(hslider_bg_png, 4, 4, 4, 4)); theme->set_stylebox("grabber_area", "HSlider", make_stylebox(hslider_bg_png, 4, 4, 4, 4)); + theme->set_stylebox("grabber_area_highlight", "HSlider", make_stylebox(hslider_bg_png, 4, 4, 4, 4)); theme->set_icon("grabber", "HSlider", make_icon(hslider_grabber_png)); theme->set_icon("grabber_highlight", "HSlider", make_icon(hslider_grabber_hl_png)); @@ -506,6 +495,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("slider", "VSlider", make_stylebox(vslider_bg_png, 4, 4, 4, 4)); theme->set_stylebox("grabber_area", "VSlider", make_stylebox(vslider_bg_png, 4, 4, 4, 4)); + theme->set_stylebox("grabber_area_highlight", "VSlider", make_stylebox(vslider_bg_png, 4, 4, 4, 4)); theme->set_icon("grabber", "VSlider", make_icon(vslider_grabber_png)); theme->set_icon("grabber_highlight", "VSlider", make_icon(vslider_grabber_hl_png)); @@ -523,17 +513,19 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // WindowDialog - theme->set_stylebox("panel", "WindowDialog", sb_expand(make_stylebox(popup_window_png, 10, 26, 10, 8), 8, 24, 8, 6)); - theme->set_constant("scaleborder_size", "WindowDialog", 4 * scale); + theme->set_stylebox("panel", "Window", default_style); + theme->set_stylebox("window_panel", "Window", sb_expand(make_stylebox(popup_window_png, 10, 26, 10, 8), 8, 24, 8, 6)); + theme->set_constant("scaleborder_size", "Window", 4 * scale); - theme->set_font("title_font", "WindowDialog", large_font); - theme->set_color("title_color", "WindowDialog", Color(0, 0, 0)); - theme->set_constant("title_height", "WindowDialog", 20 * scale); + theme->set_font("title_font", "Window", large_font); + theme->set_color("title_color", "Window", Color(0, 0, 0)); + theme->set_constant("title_height", "Window", 20 * scale); + theme->set_constant("resize_margin", "Window", 4 * scale); - theme->set_icon("close", "WindowDialog", make_icon(close_png)); - theme->set_icon("close_highlight", "WindowDialog", make_icon(close_hl_png)); - theme->set_constant("close_h_ofs", "WindowDialog", 18 * scale); - theme->set_constant("close_v_ofs", "WindowDialog", 18 * scale); + theme->set_icon("close", "Window", make_icon(close_png)); + theme->set_icon("close_highlight", "Window", make_icon(close_hl_png)); + theme->set_constant("close_h_ofs", "Window", 18 * scale); + theme->set_constant("close_v_ofs", "Window", 18 * scale); // File Dialog @@ -572,7 +564,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("radio_unchecked", "PopupMenu", make_icon(radio_unchecked_png)); theme->set_icon("submenu", "PopupMenu", make_icon(submenu_png)); - theme->set_font("font", "PopupMenu", default_font); + theme->set_font("font", "PopupMenu", Ref<Font>()); theme->set_color("font_color", "PopupMenu", control_font_color); theme->set_color("font_color_accel", "PopupMenu", Color(0.7, 0.7, 0.7, 0.8)); @@ -607,7 +599,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("port", "GraphNode", make_icon(graph_port_png)); theme->set_icon("close", "GraphNode", make_icon(graph_node_close_png)); theme->set_icon("resizer", "GraphNode", make_icon(window_resizer_png)); - theme->set_font("title_font", "GraphNode", default_font); + theme->set_font("title_font", "GraphNode", Ref<Font>()); theme->set_color("title_color", "GraphNode", Color(0, 0, 0, 1)); theme->set_color("close_color", "GraphNode", Color(0, 0, 0, 1)); theme->set_color("resizer_color", "GraphNode", Color(0, 0, 0, 1)); @@ -641,14 +633,12 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("arrow", "Tree", make_icon(arrow_down_png)); theme->set_icon("arrow_collapsed", "Tree", make_icon(arrow_right_png)); - theme->set_font("title_button_font", "Tree", default_font); - theme->set_font("font", "Tree", default_font); + theme->set_font("title_button_font", "Tree", Ref<Font>()); + theme->set_font("font", "Tree", Ref<Font>()); theme->set_color("title_button_color", "Tree", control_font_color); theme->set_color("font_color", "Tree", control_font_color_low); theme->set_color("font_color_selected", "Tree", control_font_color_pressed); - theme->set_color("selection_color", "Tree", Color(0.1, 0.1, 1, 0.8)); - theme->set_color("cursor_color", "Tree", Color(0, 0, 0)); theme->set_color("guide_color", "Tree", Color(0, 0, 0, 0.1)); theme->set_color("drop_position_color", "Tree", Color(1, 0.3, 0.2)); theme->set_color("relationship_line_color", "Tree", Color(0.27, 0.27, 0.27)); @@ -673,7 +663,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("vseparation", "ItemList", 2); theme->set_constant("icon_margin", "ItemList", 4); theme->set_constant("line_separation", "ItemList", 2 * scale); - theme->set_font("font", "ItemList", default_font); + theme->set_font("font", "ItemList", Ref<Font>()); theme->set_color("font_color", "ItemList", control_font_color_lower); theme->set_color("font_color_selected", "ItemList", control_font_color_pressed); theme->set_color("guide_color", "ItemList", Color(0, 0, 0, 0.1)); @@ -701,17 +691,14 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("menu", "TabContainer", make_icon(tab_menu_png)); theme->set_icon("menu_highlight", "TabContainer", make_icon(tab_menu_hl_png)); - theme->set_font("font", "TabContainer", default_font); + theme->set_font("font", "TabContainer", Ref<Font>()); theme->set_color("font_color_fg", "TabContainer", control_font_color_hover); theme->set_color("font_color_bg", "TabContainer", control_font_color_low); theme->set_color("font_color_disabled", "TabContainer", control_font_color_disabled); theme->set_constant("side_margin", "TabContainer", 8 * scale); - theme->set_constant("top_margin", "TabContainer", 24 * scale); - theme->set_constant("label_valign_fg", "TabContainer", 0 * scale); - theme->set_constant("label_valign_bg", "TabContainer", 2 * scale); - theme->set_constant("hseparation", "TabContainer", 4 * scale); + theme->set_constant("icon_separation", "TabContainer", 4 * scale); // Tabs @@ -728,15 +715,12 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("decrement_highlight", "Tabs", make_icon(scroll_button_left_hl_png)); theme->set_icon("close", "Tabs", make_icon(tab_close_png)); - theme->set_font("font", "Tabs", default_font); + theme->set_font("font", "Tabs", Ref<Font>()); theme->set_color("font_color_fg", "Tabs", control_font_color_hover); theme->set_color("font_color_bg", "Tabs", control_font_color_low); theme->set_color("font_color_disabled", "Tabs", control_font_color_disabled); - theme->set_constant("top_margin", "Tabs", 24 * scale); - theme->set_constant("label_valign_fg", "Tabs", 0 * scale); - theme->set_constant("label_valign_bg", "Tabs", 2 * scale); theme->set_constant("hseparation", "Tabs", 4 * scale); // Separators @@ -745,7 +729,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("separator", "VSeparator", make_stylebox(hseparator_png, 3, 3, 3, 3)); theme->set_icon("close", "Icons", make_icon(icon_close_png)); - theme->set_font("normal", "Fonts", default_font); + theme->set_font("normal", "Fonts", Ref<Font>()); theme->set_font("large", "Fonts", large_font); theme->set_constant("separation", "HSeparator", 4 * scale); @@ -759,7 +743,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // FileDialog theme->set_icon("folder", "FileDialog", make_icon(icon_folder_png)); + theme->set_icon("file", "FileDialog", make_icon(icon_file_png)); theme->set_color("folder_icon_modulate", "FileDialog", Color(1, 1, 1)); + theme->set_color("file_icon_modulate", "FileDialog", Color(1, 1, 1)); theme->set_color("files_disabled", "FileDialog", Color(0, 0, 0, 0.7)); // ColorPicker @@ -782,12 +768,13 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const // TooltipPanel Ref<StyleBoxTexture> style_tt = make_stylebox(tooltip_bg_png, 4, 4, 4, 4); - for (int i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) { style_tt->set_expand_margin_size((Margin)i, 4 * scale); + } theme->set_stylebox("panel", "TooltipPanel", style_tt); - theme->set_font("font", "TooltipLabel", default_font); + theme->set_font("font", "TooltipLabel", Ref<Font>()); theme->set_color("font_color", "TooltipLabel", Color(0, 0, 0)); theme->set_color("font_color_shadow", "TooltipLabel", Color(0, 0, 0, 0.1)); @@ -800,11 +787,11 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_stylebox("focus", "RichTextLabel", focus); theme->set_stylebox("normal", "RichTextLabel", make_empty_stylebox(0, 0, 0, 0)); - theme->set_font("normal_font", "RichTextLabel", default_font); - theme->set_font("bold_font", "RichTextLabel", default_font); - theme->set_font("italics_font", "RichTextLabel", default_font); - theme->set_font("bold_italics_font", "RichTextLabel", default_font); - theme->set_font("mono_font", "RichTextLabel", default_font); + theme->set_font("normal_font", "RichTextLabel", Ref<Font>()); + theme->set_font("bold_font", "RichTextLabel", Ref<Font>()); + theme->set_font("italics_font", "RichTextLabel", Ref<Font>()); + theme->set_font("bold_italics_font", "RichTextLabel", Ref<Font>()); + theme->set_font("mono_font", "RichTextLabel", Ref<Font>()); theme->set_color("default_color", "RichTextLabel", Color(1, 1, 1)); theme->set_color("font_color_selected", "RichTextLabel", font_color_selection); @@ -870,12 +857,11 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const } void make_default_theme(bool p_hidpi, Ref<Font> p_font) { - Ref<Theme> t; t.instance(); Ref<StyleBox> default_style; - Ref<Texture> default_icon; + Ref<Texture2D> default_icon; Ref<Font> default_font; if (p_font.is_valid()) { default_font = p_font; @@ -894,10 +880,9 @@ void make_default_theme(bool p_hidpi, Ref<Font> p_font) { } void clear_default_theme() { - - Theme::set_project_default(NULL); - Theme::set_default(NULL); - Theme::set_default_icon(NULL); - Theme::set_default_style(NULL); - Theme::set_default_font(NULL); + Theme::set_project_default(nullptr); + Theme::set_default(nullptr); + Theme::set_default_icon(nullptr); + Theme::set_default_style(nullptr); + Theme::set_default_font(nullptr); } diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h index 1807770ff4..46f89a9b50 100644 --- a/scene/resources/default_theme/default_theme.h +++ b/scene/resources/default_theme/default_theme.h @@ -33,7 +33,7 @@ #include "scene/resources/theme.h" -void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &large_font, Ref<Texture> &default_icon, Ref<StyleBox> &default_style, float p_scale); +void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &large_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale); void make_default_theme(bool p_hidpi, Ref<Font> p_font); void clear_default_theme(); diff --git a/scene/resources/default_theme/icon_file.png b/scene/resources/default_theme/icon_file.png Binary files differnew file mode 100644 index 0000000000..bb4c361a8d --- /dev/null +++ b/scene/resources/default_theme/icon_file.png diff --git a/scene/resources/default_theme/make_header.py b/scene/resources/default_theme/make_header.py index cf0ccf1c3a..efad3b2815 100755 --- a/scene/resources/default_theme/make_header.py +++ b/scene/resources/default_theme/make_header.py @@ -13,7 +13,7 @@ os.chdir(os.path.dirname(os.path.realpath(__file__))) f = open("theme_data.h", "wb") -f.write(b"// THIS FILE HAS BEEN AUTOGENERATED, DON\'T EDIT!!\n") +f.write(b"// THIS FILE HAS BEEN AUTOGENERATED, DON'T EDIT!!\n") # Generate png image block f.write(b"\n// png image block\n") @@ -31,17 +31,17 @@ for x in pixmaps: pngf = open(x, "rb") b = pngf.read(1) - while(len(b) == 1): + while len(b) == 1: f.write(hex(ord(b)).encode(enc)) b = pngf.read(1) - if (len(b) == 1): + if len(b) == 1: f.write(b", ") f.write(b"\n};\n") pngf.close() # Generate shaders block -f.write(b"\n// shaders block\n"); +f.write(b"\n// shaders block\n") shaders = glob.glob("*.gsl") shaders.sort() @@ -56,15 +56,15 @@ for x in shaders: sf = open(x, "rb") b = sf.readline() - while(b != ""): - if (b.endswith("\r\n")): + while b != "": + if b.endswith("\r\n"): b = b[:-2] - if (b.endswith("\n")): + if b.endswith("\n"): b = b[:-1] - s = ' \"' + b + s = ' "' + b f.write(s.encode(enc)) b = sf.readline() - if (b != ""): + if b != "": f.write(b'"\n') f.write(b'";\n') diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index 0a4e557451..a15efb593a 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -10,6 +10,10 @@ static const unsigned char arrow_right_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x4, 0x0, 0x0, 0x0, 0xfc, 0x7c, 0x94, 0x6c, 0x0, 0x0, 0x0, 0x2e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x17, 0x3c, 0xf8, 0xf, 0x82, 0xf7, 0x13, 0x70, 0x48, 0x3c, 0xf8, 0xf2, 0x50, 0x1b, 0x43, 0x2, 0xa, 0xaf, 0xbe, 0xe0, 0xc6, 0x2e, 0xf1, 0xff, 0xe1, 0x7c, 0x12, 0x24, 0x10, 0x46, 0x11, 0xb6, 0x1c, 0xe1, 0x5c, 0xa, 0x0, 0x0, 0xe0, 0x14, 0x48, 0xb1, 0x3d, 0x1b, 0x7a, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; +static const unsigned char bookmark_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x4, 0x73, 0x42, 0x49, 0x54, 0x8, 0x8, 0x8, 0x8, 0x7c, 0x8, 0x64, 0x88, 0x0, 0x0, 0x0, 0x57, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xed, 0x93, 0x31, 0xa, 0xc0, 0x30, 0xc, 0x3, 0xa5, 0xd0, 0xff, 0x7f, 0x59, 0x1d, 0x8a, 0x42, 0x8, 0x9, 0x95, 0xc9, 0xd2, 0xa1, 0x9a, 0x8c, 0xf1, 0xdd, 0x62, 0x1b, 0x38, 0xc, 0x87, 0x5a, 0x5, 0xae, 0x79, 0xde, 0x2, 0x1, 0x80, 0x94, 0x39, 0x48, 0x76, 0x49, 0x17, 0xa4, 0xf0, 0x24, 0x61, 0x2b, 0x51, 0x8b, 0xfc, 0x82, 0xcf, 0xb, 0x48, 0x7a, 0xdf, 0x75, 0x81, 0xf, 0xe5, 0x29, 0xf7, 0x92, 0x6b, 0x3, 0x1a, 0x1e, 0xda, 0x7c, 0x3d, 0x77, 0x21, 0x7b, 0xa8, 0x74, 0x2e, 0xcb, 0xd, 0xc8, 0x75, 0x13, 0x28, 0x9, 0xed, 0xc2, 0xc8, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 +}; + static const unsigned char button_disabled_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0xc7, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x6c, 0xd0, 0x81, 0x66, 0x43, 0x31, 0x14, 0x87, 0xf1, 0xf, 0x5, 0x17, 0xb8, 0x28, 0x2e, 0x8, 0x71, 0xf3, 0x6, 0x19, 0xb6, 0xb9, 0xcb, 0xac, 0x95, 0xa4, 0xb7, 0xad, 0x6a, 0xd5, 0x68, 0x5f, 0xe4, 0x3e, 0x76, 0x1e, 0xe1, 0xbf, 0x21, 0xa6, 0xab, 0xf8, 0x1, 0x7c, 0x9c, 0x73, 0xe, 0xac, 0xe8, 0xe8, 0x19, 0x30, 0x58, 0xc6, 0xca, 0x62, 0x18, 0xe8, 0xe9, 0x58, 0x41, 0xc7, 0x1a, 0x87, 0x27, 0x10, 0x49, 0xe4, 0x5f, 0x89, 0x48, 0xc0, 0xe3, 0x58, 0xd3, 0x41, 0x8f, 0xb, 0xcb, 0xbd, 0x7c, 0xeb, 0xbf, 0x7b, 0x9, 0xb, 0x8e, 0x1e, 0x6, 0xfc, 0xad, 0x64, 0x6d, 0xb5, 0x79, 0xb0, 0x55, 0xd6, 0xad, 0xe0, 0x19, 0xc0, 0x10, 0xae, 0xda, 0x34, 0x5c, 0x45, 0xc0, 0x80, 0x25, 0x5e, 0xf4, 0xd5, 0x70, 0x11, 0x11, 0xb, 0x23, 0xe9, 0xac, 0xcf, 0x86, 0xb3, 0x48, 0x8c, 0x30, 0x92, 0x4f, 0xa, 0xd, 0x27, 0x91, 0x6b, 0x70, 0xd4, 0x47, 0xc3, 0xf1, 0x2f, 0x48, 0x7, 0x4d, 0xd, 0x87, 0x3a, 0xc2, 0x12, 0x67, 0xbd, 0x37, 0xcc, 0x75, 0x49, 0x43, 0xd8, 0xe9, 0xad, 0x61, 0x57, 0xcf, 0x1c, 0xf0, 0xfb, 0x32, 0xe9, 0xf5, 0xc9, 0xa4, 0x7d, 0x7d, 0x54, 0x8f, 0x7b, 0x59, 0xe6, 0x92, 0x14, 0x1f, 0x24, 0xcd, 0x3f, 0x7b, 0x6b, 0xa, 0xe, 0x6a, 0x82, 0x91, 0x45, 0x30, 0xba, 0x1, 0x4a, 0x51, 0xc4, 0x35, 0x1f, 0xe5, 0xa1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; @@ -150,6 +154,10 @@ static const unsigned char icon_color_pick_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0xaa, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x9d, 0x8e, 0x35, 0x82, 0x2, 0x41, 0x10, 0x45, 0x3b, 0xda, 0x3d, 0xca, 0xba, 0x44, 0x2b, 0x70, 0x9, 0xdc, 0xe1, 0x20, 0xe8, 0x91, 0x90, 0x78, 0x6e, 0x40, 0x4c, 0x82, 0x74, 0xff, 0xc2, 0x9d, 0x18, 0xa7, 0x6, 0x77, 0x7b, 0x23, 0x2d, 0xaf, 0x4c, 0xdc, 0xc, 0xbd, 0x65, 0x1e, 0x84, 0x80, 0x19, 0x55, 0x34, 0x60, 0x3e, 0xd0, 0xea, 0x17, 0x3d, 0x4a, 0xc8, 0x80, 0x1a, 0x60, 0xc2, 0x4f, 0xfd, 0x30, 0xe0, 0x1b, 0x2d, 0x16, 0xab, 0xa7, 0x2c, 0xe, 0x41, 0x68, 0xa5, 0xb9, 0xca, 0x91, 0x16, 0x2e, 0x54, 0xe0, 0x59, 0x54, 0x91, 0xfe, 0xa3, 0x3a, 0xff, 0xce, 0xab, 0x5b, 0xf, 0xa0, 0x4, 0x8f, 0x7b, 0x4c, 0xd3, 0x1b, 0xca, 0x32, 0xcc, 0x55, 0x7a, 0xf4, 0x76, 0x42, 0x2b, 0x97, 0x3e, 0xae, 0xfa, 0xdd, 0xd2, 0xd2, 0x8e, 0x72, 0xe1, 0x83, 0xaf, 0x9f, 0xa9, 0x28, 0x7d, 0x5b, 0xe2, 0x2a, 0xd, 0xc3, 0xa2, 0x78, 0xfe, 0x7d, 0x51, 0xfc, 0x0, 0x8a, 0x41, 0xcb, 0x3d, 0xb2, 0xae, 0x1c, 0xd3, 0xc, 0xa5, 0x30, 0x81, 0xc6, 0xda, 0x29, 0x8e, 0x83, 0x34, 0x25, 0x29, 0x4a, 0x46, 0x71, 0x1f, 0x33, 0xbe, 0x51, 0x89, 0xaf, 0x78, 0xe3, 0x97, 0x7e, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; +static const unsigned char icon_file_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x2, 0x3, 0x0, 0x0, 0x0, 0x62, 0x9d, 0x17, 0xf2, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xe, 0xc3, 0x0, 0x0, 0xe, 0xc3, 0x1, 0xc7, 0x6f, 0xa8, 0x64, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x0, 0x0, 0x0, 0x9, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0x42, 0xf, 0xc7, 0x49, 0x0, 0x0, 0x0, 0x2, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x88, 0x95, 0xf0, 0xc6, 0x2a, 0x0, 0x0, 0x0, 0x21, 0x49, 0x44, 0x41, 0x54, 0x8, 0xd7, 0x63, 0x60, 0x0, 0x1, 0xae, 0x55, 0x2d, 0x20, 0xa2, 0x13, 0x44, 0x74, 0x39, 0x80, 0x88, 0x9, 0x40, 0xa2, 0x1, 0xc4, 0x5d, 0xb5, 0x80, 0x68, 0x2, 0x4, 0x0, 0x95, 0x34, 0x18, 0xe4, 0x5e, 0x46, 0xf7, 0x27, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 +}; + static const unsigned char icon_folder_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x2e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x6, 0x78, 0x70, 0xf4, 0xc1, 0x7f, 0x24, 0x78, 0x18, 0x53, 0xc1, 0x7f, 0x54, 0x48, 0x50, 0xc1, 0x43, 0x1b, 0xbc, 0xa, 0x50, 0xad, 0x23, 0xa4, 0xe0, 0xff, 0x70, 0x52, 0x70, 0x18, 0x97, 0xf4, 0xfd, 0x43, 0xd4, 0x88, 0x4a, 0x0, 0x5a, 0xcb, 0x18, 0xab, 0x5e, 0xd9, 0x1a, 0x53, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index d19d82d252..bc983c1d7e 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -28,8 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef FREETYPE_ENABLED +#include "modules/modules_enabled.gen.h" +#ifdef MODULE_FREETYPE_ENABLED + #include "dynamic_font.h" + #include "core/os/file_access.h" #include "core/os/os.h" @@ -43,7 +46,6 @@ bool DynamicFontData::CacheID::operator<(CacheID right) const { } Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(CacheID p_cache_id) { - if (size_cache.has(p_cache_id)) { return Ref<DynamicFontAtSize>(size_cache[p_cache_id]); } @@ -62,13 +64,11 @@ Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(CacheID p_cach } void DynamicFontData::set_font_ptr(const uint8_t *p_font_mem, int p_font_mem_size) { - font_mem = p_font_mem; font_mem_size = p_font_mem_size; } void DynamicFontData::set_font_path(const String &p_path) { - font_path = p_path; } @@ -77,7 +77,6 @@ String DynamicFontData::get_font_path() const { } void DynamicFontData::set_force_autohinter(bool p_force) { - force_autohinter = p_force; } @@ -100,11 +99,10 @@ void DynamicFontData::_bind_methods() { } DynamicFontData::DynamicFontData() { - antialiased = true; force_autohinter = false; hinting = DynamicFontData::HINTING_NORMAL; - font_mem = NULL; + font_mem = nullptr; font_mem_size = 0; } @@ -112,23 +110,20 @@ DynamicFontData::~DynamicFontData() { } //////////////////// -HashMap<String, Vector<uint8_t> > DynamicFontAtSize::_fontdata; +HashMap<String, Vector<uint8_t>> DynamicFontAtSize::_fontdata; Error DynamicFontAtSize::_load() { - int error = FT_Init_FreeType(&library); ERR_FAIL_COND_V_MSG(error != 0, ERR_CANT_CREATE, "Error initializing FreeType."); // FT_OPEN_STREAM is extremely slow only on Android. - if (OS::get_singleton()->get_name() == "Android" && font->font_mem == NULL && font->font_path != String()) { + if (OS::get_singleton()->get_name() == "Android" && font->font_mem == nullptr && font->font_path != String()) { // cache font only once for each font->font_path if (_fontdata.has(font->font_path)) { - font->set_font_ptr(_fontdata[font->font_path].ptr(), _fontdata[font->font_path].size()); } else { - FileAccess *f = FileAccess::open(font->font_path, FileAccess::READ); if (!f) { FT_Done_FreeType(library); @@ -145,8 +140,7 @@ Error DynamicFontAtSize::_load() { } } - if (font->font_mem == NULL && font->font_path != String()) { - + if (font->font_mem == nullptr && font->font_path != String()) { FileAccess *f = FileAccess::open(font->font_path, FileAccess::READ); if (!f) { FT_Done_FreeType(library); @@ -154,7 +148,7 @@ Error DynamicFontAtSize::_load() { } memset(&stream, 0, sizeof(FT_StreamRec)); - stream.base = NULL; + stream.base = nullptr; stream.size = f->get_len(); stream.pos = 0; stream.descriptor.pointer = f; @@ -167,7 +161,6 @@ Error DynamicFontAtSize::_load() { fargs.stream = &stream; error = FT_Open_Face(library, &fargs, 0, &face); } else if (font->font_mem) { - memset(&stream, 0, sizeof(FT_StreamRec)); stream.base = (unsigned char *)font->font_mem; stream.size = font->font_mem_size; @@ -189,12 +182,10 @@ Error DynamicFontAtSize::_load() { //error = FT_New_Face( library, src_path.utf8().get_data(),0,&face ); if (error == FT_Err_Unknown_File_Format) { - FT_Done_FreeType(library); ERR_FAIL_V_MSG(ERR_FILE_CANT_OPEN, "Unknown font format."); } else if (error) { - FT_Done_FreeType(library); ERR_FAIL_V_MSG(ERR_FILE_CANT_OPEN, "Error loading font."); } @@ -218,12 +209,9 @@ Error DynamicFontAtSize::_load() { ascent = (face->size->metrics.ascender / 64.0) / oversampling * scale_color_font; descent = (-face->size->metrics.descender / 64.0) / oversampling * scale_color_font; + underline_position = -face->underline_position / 64.0 / oversampling * scale_color_font; + underline_thickness = face->underline_thickness / 64.0 / oversampling * scale_color_font; linegap = 0; - texture_flags = 0; - if (id.mipmaps) - texture_flags |= Texture::FLAG_MIPMAPS; - if (id.filter) - texture_flags |= Texture::FLAG_FILTER; valid = true; return OK; @@ -232,38 +220,44 @@ Error DynamicFontAtSize::_load() { float DynamicFontAtSize::font_oversampling = 1.0; float DynamicFontAtSize::get_height() const { - return ascent + descent; } float DynamicFontAtSize::get_ascent() const { - return ascent; } -float DynamicFontAtSize::get_descent() const { +float DynamicFontAtSize::get_descent() const { return descent; } -const Pair<const DynamicFontAtSize::Character *, DynamicFontAtSize *> DynamicFontAtSize::_find_char_with_font(CharType p_char, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks) const { +float DynamicFontAtSize::get_underline_position() const { + return underline_position; +} + +float DynamicFontAtSize::get_underline_thickness() const { + return underline_thickness; +} + +const Pair<const DynamicFontAtSize::Character *, DynamicFontAtSize *> DynamicFontAtSize::_find_char_with_font(char32_t p_char, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const { const Character *chr = char_map.getptr(p_char); - ERR_FAIL_COND_V(!chr, (Pair<const Character *, DynamicFontAtSize *>(NULL, NULL))); + ERR_FAIL_COND_V(!chr, (Pair<const Character *, DynamicFontAtSize *>(nullptr, nullptr))); if (!chr->found) { - //not found, try in fallbacks for (int i = 0; i < p_fallbacks.size(); i++) { - DynamicFontAtSize *fb = const_cast<DynamicFontAtSize *>(p_fallbacks[i].ptr()); - if (!fb->valid) + if (!fb->valid) { continue; + } fb->_update_char(p_char); const Character *fallback_chr = fb->char_map.getptr(p_char); ERR_CONTINUE(!fallback_chr); - if (!fallback_chr->found) + if (!fallback_chr->found) { continue; + } return Pair<const Character *, DynamicFontAtSize *>(fallback_chr, fb); } @@ -271,16 +265,16 @@ const Pair<const DynamicFontAtSize::Character *, DynamicFontAtSize *> DynamicFon //not found, try 0xFFFD to display 'not found'. const_cast<DynamicFontAtSize *>(this)->_update_char(0xFFFD); chr = char_map.getptr(0xFFFD); - ERR_FAIL_COND_V(!chr, (Pair<const Character *, DynamicFontAtSize *>(NULL, NULL))); + ERR_FAIL_COND_V(!chr, (Pair<const Character *, DynamicFontAtSize *>(nullptr, nullptr))); } return Pair<const Character *, DynamicFontAtSize *>(chr, const_cast<DynamicFontAtSize *>(this)); } -Size2 DynamicFontAtSize::get_char_size(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks) const { - - if (!valid) +Size2 DynamicFontAtSize::get_char_size(char32_t p_char, char32_t p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const { + if (!valid) { return Size2(1, 1); + } const_cast<DynamicFontAtSize *>(this)->_update_char(p_char); Pair<const Character *, DynamicFontAtSize *> char_pair_with_font = _find_char_with_font(p_char, p_fallbacks); @@ -296,20 +290,25 @@ Size2 DynamicFontAtSize::get_char_size(CharType p_char, CharType p_next, const V return ret; } -void DynamicFontAtSize::set_texture_flags(uint32_t p_flags) { +String DynamicFontAtSize::get_available_chars() const { + String chars; - texture_flags = p_flags; - for (int i = 0; i < textures.size(); i++) { - Ref<ImageTexture> &tex = textures.write[i].texture; - if (!tex.is_null()) - tex->set_flags(p_flags); + FT_UInt gindex; + FT_ULong charcode = FT_Get_First_Char(face, &gindex); + while (gindex != 0) { + if (charcode != 0) { + chars += char32_t(charcode); + } + charcode = FT_Get_Next_Char(face, charcode, &gindex); } -} -float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks, bool p_advance_only, bool p_outline) const { + return chars; +} - if (!valid) +float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks, bool p_advance_only, bool p_outline) const { + if (!valid) { return 0; + } const_cast<DynamicFontAtSize *>(this)->_update_char(p_char); @@ -348,7 +347,7 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT modulate.r = modulate.g = modulate.b = 1.0; } RID texture = font->textures[ch->texture_idx].texture->get_rid(); - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, ch->rect.size), texture, ch->rect_uv, modulate, false, RID(), false); + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, ch->rect.size), texture, ch->rect_uv, modulate, false, RID(), RID(), Color(1, 1, 1, 1), false); } advance = ch->advance; @@ -358,20 +357,20 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT } unsigned long DynamicFontAtSize::_ft_stream_io(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count) { - FileAccess *f = (FileAccess *)stream->descriptor.pointer; if (f->get_position() != offset) { f->seek(offset); } - if (count == 0) + if (count == 0) { return 0; + } return f->get_buffer(buffer, count); } -void DynamicFontAtSize::_ft_stream_close(FT_Stream stream) { +void DynamicFontAtSize::_ft_stream_close(FT_Stream stream) { FileAccess *f = (FileAccess *)stream->descriptor.pointer; f->close(); memdelete(f); @@ -397,27 +396,27 @@ DynamicFontAtSize::TexturePosition DynamicFontAtSize::_find_texture_pos_for_glyp int mh = p_height; for (int i = 0; i < textures.size(); i++) { - const CharTexture &ct = textures[i]; - if (ct.texture->get_format() != p_image_format) + if (ct.texture->get_format() != p_image_format) { continue; + } - if (mw > ct.texture_size || mh > ct.texture_size) //too big for this texture + if (mw > ct.texture_size || mh > ct.texture_size) { //too big for this texture continue; + } ret.y = 0x7FFFFFFF; ret.x = 0; for (int j = 0; j < ct.texture_size - mw; j++) { - int max_y = 0; for (int k = j; k < j + mw; k++) { - int y = ct.offsets[k]; - if (y > max_y) + if (y > max_y) { max_y = y; + } } if (max_y < ret.y) { @@ -426,8 +425,9 @@ DynamicFontAtSize::TexturePosition DynamicFontAtSize::_find_texture_pos_for_glyp } } - if (ret.y == 0x7FFFFFFF || ret.y + mh > ct.texture_size) + if (ret.y == 0x7FFFFFFF || ret.y + mh > ct.texture_size) { continue; //fail, could not fit it here + } ret.index = i; break; @@ -439,10 +439,12 @@ DynamicFontAtSize::TexturePosition DynamicFontAtSize::_find_texture_pos_for_glyp ret.y = 0; int texsize = MAX(id.size * oversampling * 8, 256); - if (mw > texsize) + if (mw > texsize) { texsize = mw; //special case, adapt to it? - if (mh > texsize) + } + if (mh > texsize) { texsize = mh; //special case, adapt to it? + } texsize = next_power_of_2(texsize); @@ -454,15 +456,16 @@ DynamicFontAtSize::TexturePosition DynamicFontAtSize::_find_texture_pos_for_glyp { //zero texture - PoolVector<uint8_t>::Write w = tex.imgdata.write(); + uint8_t *w = tex.imgdata.ptrw(); ERR_FAIL_COND_V(texsize * texsize * p_color_size > tex.imgdata.size(), ret); for (int i = 0; i < texsize * texsize * p_color_size; i++) { w[i] = 0; } } tex.offsets.resize(texsize); - for (int i = 0; i < texsize; i++) //zero offsets + for (int i = 0; i < texsize; i++) { //zero offsets tex.offsets.write[i] = 0; + } textures.push_back(tex); ret.index = textures.size() - 1; @@ -492,11 +495,10 @@ DynamicFontAtSize::Character DynamicFontAtSize::_bitmap_to_character(FT_Bitmap b CharTexture &tex = textures.write[tex_pos.index]; { - PoolVector<uint8_t>::Write wr = tex.imgdata.write(); + uint8_t *wr = tex.imgdata.ptrw(); for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { - int ofs = ((i + tex_pos.y + rect_margin) * tex.texture_size + j + tex_pos.x + rect_margin) * color_size; ERR_FAIL_COND_V(ofs >= tex.imgdata.size(), Character::not_found()); switch (bitmap.pixel_mode) { @@ -528,14 +530,13 @@ DynamicFontAtSize::Character DynamicFontAtSize::_bitmap_to_character(FT_Bitmap b //blit to image and texture { - Ref<Image> img = memnew(Image(tex.texture_size, tex.texture_size, 0, require_format, tex.imgdata)); if (tex.texture.is_null()) { tex.texture.instance(); - tex.texture->create_from_image(img, Texture::FLAG_VIDEO_SURFACE | texture_flags); + tex.texture->create_from_image(img); } else { - tex.texture->set_data(img); //update + tex.texture->update(img); //update } } @@ -559,26 +560,31 @@ DynamicFontAtSize::Character DynamicFontAtSize::_bitmap_to_character(FT_Bitmap b return chr; } -DynamicFontAtSize::Character DynamicFontAtSize::_make_outline_char(CharType p_char) { +DynamicFontAtSize::Character DynamicFontAtSize::_make_outline_char(char32_t p_char) { Character ret = Character::not_found(); - if (FT_Load_Char(face, p_char, FT_LOAD_NO_BITMAP | (font->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0)) != 0) + if (FT_Load_Char(face, p_char, FT_LOAD_NO_BITMAP | (font->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0)) != 0) { return ret; + } FT_Stroker stroker; - if (FT_Stroker_New(library, &stroker) != 0) + if (FT_Stroker_New(library, &stroker) != 0) { return ret; + } FT_Stroker_Set(stroker, (int)(id.outline_size * oversampling * 64.0), FT_STROKER_LINECAP_BUTT, FT_STROKER_LINEJOIN_ROUND, 0); FT_Glyph glyph; FT_BitmapGlyph glyph_bitmap; - if (FT_Get_Glyph(face->glyph, &glyph) != 0) + if (FT_Get_Glyph(face->glyph, &glyph) != 0) { goto cleanup_stroker; - if (FT_Glyph_Stroke(&glyph, stroker, 1) != 0) + } + if (FT_Glyph_Stroke(&glyph, stroker, 1) != 0) { goto cleanup_glyph; - if (FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1) != 0) + } + if (FT_Glyph_To_Bitmap(&glyph, font->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, nullptr, 1) != 0) { goto cleanup_glyph; + } glyph_bitmap = (FT_BitmapGlyph)glyph; ret = _bitmap_to_character(glyph_bitmap->bitmap, glyph_bitmap->top, glyph_bitmap->left, glyph->advance.x / 65536.0); @@ -590,10 +596,10 @@ cleanup_stroker: return ret; } -void DynamicFontAtSize::_update_char(CharType p_char) { - - if (char_map.has(p_char)) +void DynamicFontAtSize::_update_char(char32_t p_char) { + if (char_map.has(p_char)) { return; + } _THREAD_SAFE_METHOD_ @@ -630,16 +636,18 @@ void DynamicFontAtSize::_update_char(CharType p_char) { character = _make_outline_char(p_char); } else { error = FT_Render_Glyph(face->glyph, font->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); - if (!error) + if (!error) { character = _bitmap_to_character(slot->bitmap, slot->bitmap_top, slot->bitmap_left, slot->advance.x / 64.0); + } } char_map[p_char] = character; } void DynamicFontAtSize::update_oversampling() { - if (oversampling == font_oversampling || !valid) + if (oversampling == font_oversampling || !valid) { return; + } FT_Done_FreeType(library); textures.clear(); @@ -650,19 +658,16 @@ void DynamicFontAtSize::update_oversampling() { } DynamicFontAtSize::DynamicFontAtSize() { - valid = false; rect_margin = 1; ascent = 1; descent = 1; linegap = 1; - texture_flags = 0; oversampling = font_oversampling; scale_color_font = 1; } DynamicFontAtSize::~DynamicFontAtSize() { - if (valid) { FT_Done_FreeType(library); } @@ -673,7 +678,6 @@ DynamicFontAtSize::~DynamicFontAtSize() { ///////////////////////// void DynamicFont::_reload_cache() { - ERR_FAIL_COND(cache_id.size < 1); if (!data.is_valid()) { data_at_size.unref(); @@ -695,8 +699,9 @@ void DynamicFont::_reload_cache() { for (int i = 0; i < fallbacks.size(); i++) { fallback_data_at_size.write[i] = fallbacks.write[i]->_get_dynamic_font_at_size(cache_id); - if (outline_cache_id.outline_size > 0) + if (outline_cache_id.outline_size > 0) { fallback_outline_data_at_size.write[i] = fallbacks.write[i]->_get_dynamic_font_at_size(outline_cache_id); + } } emit_changed(); @@ -704,7 +709,6 @@ void DynamicFont::_reload_cache() { } void DynamicFont::set_font_data(const Ref<DynamicFontData> &p_data) { - data = p_data; _reload_cache(); @@ -713,27 +717,26 @@ void DynamicFont::set_font_data(const Ref<DynamicFontData> &p_data) { } Ref<DynamicFontData> DynamicFont::get_font_data() const { - return data; } void DynamicFont::set_size(int p_size) { - - if (cache_id.size == p_size) + if (cache_id.size == p_size) { return; + } cache_id.size = p_size; outline_cache_id.size = p_size; _reload_cache(); } int DynamicFont::get_size() const { - return cache_id.size; } void DynamicFont::set_outline_size(int p_size) { - if (outline_cache_id.outline_size == p_size) + if (outline_cache_id.outline_size == p_size) { return; + } ERR_FAIL_COND(p_size < 0 || p_size > UINT8_MAX); outline_cache_id.outline_size = p_size; _reload_cache(); @@ -755,60 +758,29 @@ Color DynamicFont::get_outline_color() const { return outline_color; } -bool DynamicFont::get_use_mipmaps() const { - - return cache_id.mipmaps; -} - -void DynamicFont::set_use_mipmaps(bool p_enable) { - - if (cache_id.mipmaps == p_enable) - return; - cache_id.mipmaps = p_enable; - outline_cache_id.mipmaps = p_enable; - _reload_cache(); -} - -bool DynamicFont::get_use_filter() const { - - return cache_id.filter; -} - -void DynamicFont::set_use_filter(bool p_enable) { - - if (cache_id.filter == p_enable) - return; - cache_id.filter = p_enable; - outline_cache_id.filter = p_enable; - _reload_cache(); -} - bool DynamicFontData::is_antialiased() const { - return antialiased; } void DynamicFontData::set_antialiased(bool p_antialiased) { - - if (antialiased == p_antialiased) + if (antialiased == p_antialiased) { return; + } antialiased = p_antialiased; } DynamicFontData::Hinting DynamicFontData::get_hinting() const { - return hinting; } void DynamicFontData::set_hinting(Hinting p_hinting) { - - if (hinting == p_hinting) + if (hinting == p_hinting) { return; + } hinting = p_hinting; } int DynamicFont::get_spacing(int p_type) const { - if (p_type == SPACING_TOP) { return spacing_top; } else if (p_type == SPACING_BOTTOM) { @@ -823,7 +795,6 @@ int DynamicFont::get_spacing(int p_type) const { } void DynamicFont::set_spacing(int p_type, int p_value) { - if (p_type == SPACING_TOP) { spacing_top = p_value; } else if (p_type == SPACING_BOTTOM) { @@ -839,45 +810,80 @@ void DynamicFont::set_spacing(int p_type, int p_value) { } float DynamicFont::get_height() const { - - if (!data_at_size.is_valid()) + if (!data_at_size.is_valid()) { return 1; + } return data_at_size->get_height() + spacing_top + spacing_bottom; } float DynamicFont::get_ascent() const { - - if (!data_at_size.is_valid()) + if (!data_at_size.is_valid()) { return 1; + } return data_at_size->get_ascent() + spacing_top; } float DynamicFont::get_descent() const { - - if (!data_at_size.is_valid()) + if (!data_at_size.is_valid()) { return 1; + } return data_at_size->get_descent() + spacing_bottom; } -Size2 DynamicFont::get_char_size(CharType p_char, CharType p_next) const { +float DynamicFont::get_underline_position() const { + if (!data_at_size.is_valid()) { + return 2; + } + + return data_at_size->get_underline_position(); +} + +float DynamicFont::get_underline_thickness() const { + if (!data_at_size.is_valid()) { + return 1; + } - if (!data_at_size.is_valid()) + return data_at_size->get_underline_thickness(); +} + +Size2 DynamicFont::get_char_size(char32_t p_char, char32_t p_next) const { + if (!data_at_size.is_valid()) { return Size2(1, 1); + } Size2 ret = data_at_size->get_char_size(p_char, p_next, fallback_data_at_size); - if (p_char == ' ') + if (p_char == ' ') { ret.width += spacing_space + spacing_char; - else if (p_next) + } else if (p_next) { ret.width += spacing_char; + } return ret; } -bool DynamicFont::is_distance_field_hint() const { +String DynamicFont::get_available_chars() const { + if (!data_at_size.is_valid()) { + return ""; + } + String chars = data_at_size->get_available_chars(); + + for (int i = 0; i < fallback_data_at_size.size(); i++) { + String fallback_chars = fallback_data_at_size[i]->get_available_chars(); + for (int j = 0; j < fallback_chars.length(); j++) { + if (chars.find_char(fallback_chars[j]) == -1) { + chars += fallback_chars[j]; + } + } + } + + return chars; +} + +bool DynamicFont::is_distance_field_hint() const { return false; } @@ -885,13 +891,14 @@ bool DynamicFont::has_outline() const { return outline_cache_id.outline_size > 0; } -float DynamicFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, bool p_outline) const { +float DynamicFont::draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, const Color &p_modulate, bool p_outline) const { const Ref<DynamicFontAtSize> &font_at_size = p_outline && outline_cache_id.outline_size > 0 ? outline_data_at_size : data_at_size; - if (!font_at_size.is_valid()) + if (!font_at_size.is_valid()) { return 0; + } - const Vector<Ref<DynamicFontAtSize> > &fallbacks = p_outline && outline_cache_id.outline_size > 0 ? fallback_outline_data_at_size : fallback_data_at_size; + const Vector<Ref<DynamicFontAtSize>> &fallbacks = p_outline && outline_cache_id.outline_size > 0 ? fallback_outline_data_at_size : fallback_data_at_size; Color color = p_outline && outline_cache_id.outline_size > 0 ? p_modulate * outline_color : p_modulate; // If requested outline draw, but no outline is present, simply return advance without drawing anything @@ -900,7 +907,6 @@ float DynamicFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_ } void DynamicFont::set_fallback(int p_idx, const Ref<DynamicFontData> &p_data) { - ERR_FAIL_COND(p_data.is_null()); ERR_FAIL_INDEX(p_idx, fallbacks.size()); fallbacks.write[p_idx] = p_data; @@ -908,12 +914,12 @@ void DynamicFont::set_fallback(int p_idx, const Ref<DynamicFontData> &p_data) { } void DynamicFont::add_fallback(const Ref<DynamicFontData> &p_data) { - ERR_FAIL_COND(p_data.is_null()); fallbacks.push_back(p_data); fallback_data_at_size.push_back(fallbacks.write[fallbacks.size() - 1]->_get_dynamic_font_at_size(cache_id)); //const.. - if (outline_cache_id.outline_size > 0) + if (outline_cache_id.outline_size > 0) { fallback_outline_data_at_size.push_back(fallbacks.write[fallbacks.size() - 1]->_get_dynamic_font_at_size(outline_cache_id)); + } _change_notify(); emit_changed(); @@ -923,14 +929,14 @@ void DynamicFont::add_fallback(const Ref<DynamicFontData> &p_data) { int DynamicFont::get_fallback_count() const { return fallbacks.size(); } -Ref<DynamicFontData> DynamicFont::get_fallback(int p_idx) const { +Ref<DynamicFontData> DynamicFont::get_fallback(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, fallbacks.size(), Ref<DynamicFontData>()); return fallbacks[p_idx]; } -void DynamicFont::remove_fallback(int p_idx) { +void DynamicFont::remove_fallback(int p_idx) { ERR_FAIL_INDEX(p_idx, fallbacks.size()); fallbacks.remove(p_idx); fallback_data_at_size.remove(p_idx); @@ -939,7 +945,6 @@ void DynamicFont::remove_fallback(int p_idx) { } bool DynamicFont::_set(const StringName &p_name, const Variant &p_value) { - String str = p_name; if (str.begins_with("fallback/")) { int idx = str.get_slicec('/', 1).to_int(); @@ -965,7 +970,6 @@ bool DynamicFont::_set(const StringName &p_name, const Variant &p_value) { } bool DynamicFont::_get(const StringName &p_name, Variant &r_ret) const { - String str = p_name; if (str.begins_with("fallback/")) { int idx = str.get_slicec('/', 1).to_int(); @@ -981,8 +985,8 @@ bool DynamicFont::_get(const StringName &p_name, Variant &r_ret) const { return false; } -void DynamicFont::_get_property_list(List<PropertyInfo> *p_list) const { +void DynamicFont::_get_property_list(List<PropertyInfo> *p_list) const { for (int i = 0; i < fallbacks.size(); i++) { p_list->push_back(PropertyInfo(Variant::OBJECT, "fallback/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "DynamicFontData")); } @@ -991,10 +995,11 @@ void DynamicFont::_get_property_list(List<PropertyInfo> *p_list) const { } void DynamicFont::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_font_data", "data"), &DynamicFont::set_font_data); ClassDB::bind_method(D_METHOD("get_font_data"), &DynamicFont::get_font_data); + ClassDB::bind_method(D_METHOD("get_available_chars"), &DynamicFont::get_available_chars); + ClassDB::bind_method(D_METHOD("set_size", "data"), &DynamicFont::set_size); ClassDB::bind_method(D_METHOD("get_size"), &DynamicFont::get_size); @@ -1004,10 +1009,6 @@ void DynamicFont::_bind_methods() { ClassDB::bind_method(D_METHOD("set_outline_color", "color"), &DynamicFont::set_outline_color); ClassDB::bind_method(D_METHOD("get_outline_color"), &DynamicFont::get_outline_color); - ClassDB::bind_method(D_METHOD("set_use_mipmaps", "enable"), &DynamicFont::set_use_mipmaps); - ClassDB::bind_method(D_METHOD("get_use_mipmaps"), &DynamicFont::get_use_mipmaps); - ClassDB::bind_method(D_METHOD("set_use_filter", "enable"), &DynamicFont::set_use_filter); - ClassDB::bind_method(D_METHOD("get_use_filter"), &DynamicFont::get_use_filter); ClassDB::bind_method(D_METHOD("set_spacing", "type", "value"), &DynamicFont::set_spacing); ClassDB::bind_method(D_METHOD("get_spacing", "type"), &DynamicFont::get_spacing); @@ -1021,8 +1022,6 @@ void DynamicFont::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "size", PROPERTY_HINT_RANGE, "1,1024,1"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "outline_size", PROPERTY_HINT_RANGE, "0,1024,1"), "set_outline_size", "get_outline_size"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "outline_color"), "set_outline_color", "get_outline_color"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_mipmaps"), "set_use_mipmaps", "get_use_mipmaps"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_filter"), "set_use_filter", "get_use_filter"); ADD_GROUP("Extra Spacing", "extra_spacing"); ADD_PROPERTYI(PropertyInfo(Variant::INT, "extra_spacing_top"), "set_spacing", "get_spacing", SPACING_TOP); ADD_PROPERTYI(PropertyInfo(Variant::INT, "extra_spacing_bottom"), "set_spacing", "get_spacing", SPACING_BOTTOM); @@ -1037,13 +1036,13 @@ void DynamicFont::_bind_methods() { BIND_ENUM_CONSTANT(SPACING_SPACE); } -Mutex *DynamicFont::dynamic_font_mutex = NULL; +Mutex DynamicFont::dynamic_font_mutex; -SelfList<DynamicFont>::List *DynamicFont::dynamic_fonts = NULL; +SelfList<DynamicFont>::List *DynamicFont::dynamic_fonts = nullptr; DynamicFont::DynamicFont() : font_list(this) { - + valid = false; cache_id.size = 16; outline_cache_id.size = 16; spacing_top = 0; @@ -1051,69 +1050,56 @@ DynamicFont::DynamicFont() : spacing_char = 0; spacing_space = 0; outline_color = Color(1, 1, 1); - if (dynamic_font_mutex) { - dynamic_font_mutex->lock(); - dynamic_fonts->add(&font_list); - dynamic_font_mutex->unlock(); - } + + MutexLock lock(dynamic_font_mutex); + dynamic_fonts->add(&font_list); } DynamicFont::~DynamicFont() { - if (dynamic_font_mutex) { - dynamic_font_mutex->lock(); - dynamic_fonts->remove(&font_list); - dynamic_font_mutex->unlock(); - } + MutexLock lock(dynamic_font_mutex); + dynamic_fonts->remove(&font_list); } void DynamicFont::initialize_dynamic_fonts() { dynamic_fonts = memnew(SelfList<DynamicFont>::List()); - dynamic_font_mutex = Mutex::create(); } void DynamicFont::finish_dynamic_fonts() { - memdelete(dynamic_font_mutex); - dynamic_font_mutex = NULL; memdelete(dynamic_fonts); - dynamic_fonts = NULL; + dynamic_fonts = nullptr; } void DynamicFont::update_oversampling() { + Vector<Ref<DynamicFont>> changed; + { + MutexLock lock(dynamic_font_mutex); - Vector<Ref<DynamicFont> > changed; - - if (dynamic_font_mutex) - dynamic_font_mutex->lock(); - - SelfList<DynamicFont> *E = dynamic_fonts->first(); - while (E) { - - if (E->self()->data_at_size.is_valid()) { - E->self()->data_at_size->update_oversampling(); + SelfList<DynamicFont> *E = dynamic_fonts->first(); + while (E) { + if (E->self()->data_at_size.is_valid()) { + E->self()->data_at_size->update_oversampling(); - if (E->self()->outline_data_at_size.is_valid()) { - E->self()->outline_data_at_size->update_oversampling(); - } + if (E->self()->outline_data_at_size.is_valid()) { + E->self()->outline_data_at_size->update_oversampling(); + } - for (int i = 0; i < E->self()->fallback_data_at_size.size(); i++) { - if (E->self()->fallback_data_at_size[i].is_valid()) { - E->self()->fallback_data_at_size.write[i]->update_oversampling(); + for (int i = 0; i < E->self()->fallback_data_at_size.size(); i++) { + if (E->self()->fallback_data_at_size[i].is_valid()) { + E->self()->fallback_data_at_size.write[i]->update_oversampling(); - if (E->self()->has_outline() && E->self()->fallback_outline_data_at_size[i].is_valid()) { - E->self()->fallback_outline_data_at_size.write[i]->update_oversampling(); + if (E->self()->has_outline() && E->self()->fallback_outline_data_at_size[i].is_valid()) { + E->self()->fallback_outline_data_at_size.write[i]->update_oversampling(); + } } } + + changed.push_back(Ref<DynamicFont>(E->self())); } - changed.push_back(Ref<DynamicFont>(E->self())); + E = E->next(); } - - E = E->next(); } - if (dynamic_font_mutex) - dynamic_font_mutex->unlock(); - for (int i = 0; i < changed.size(); i++) { changed.write[i]->emit_changed(); } @@ -1121,37 +1107,36 @@ void DynamicFont::update_oversampling() { ///////////////////////// -RES ResourceFormatLoaderDynamicFont::load(const String &p_path, const String &p_original_path, Error *r_error) { - - if (r_error) +RES ResourceFormatLoaderDynamicFont::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { + if (r_error) { *r_error = ERR_FILE_CANT_OPEN; + } Ref<DynamicFontData> dfont; dfont.instance(); dfont->set_font_path(p_path); - if (r_error) + if (r_error) { *r_error = OK; + } return dfont; } void ResourceFormatLoaderDynamicFont::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("ttf"); p_extensions->push_back("otf"); } bool ResourceFormatLoaderDynamicFont::handles_type(const String &p_type) const { - return (p_type == "DynamicFontData"); } String ResourceFormatLoaderDynamicFont::get_resource_type(const String &p_path) const { - String el = p_path.get_extension().to_lower(); - if (el == "ttf" || el == "otf") + if (el == "ttf" || el == "otf") { return "DynamicFontData"; + } return ""; } diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h index 2dafd3ce4f..a881e21da8 100644 --- a/scene/resources/dynamic_font.h +++ b/scene/resources/dynamic_font.h @@ -31,7 +31,9 @@ #ifndef DYNAMIC_FONT_H #define DYNAMIC_FONT_H -#ifdef FREETYPE_ENABLED +#include "modules/modules_enabled.gen.h" +#ifdef MODULE_FREETYPE_ENABLED + #include "core/io/resource_loader.h" #include "core/os/mutex.h" #include "core/os/thread_safe.h" @@ -45,7 +47,6 @@ class DynamicFontAtSize; class DynamicFont; class DynamicFontData : public Resource { - GDCLASS(DynamicFontData, Resource); public: @@ -54,9 +55,7 @@ public: struct { uint32_t size : 16; uint32_t outline_size : 8; - uint32_t mipmaps : 1; - uint32_t filter : 1; - uint32_t unused : 6; + uint32_t unused : 8; }; uint32_t key; }; @@ -109,7 +108,6 @@ public: VARIANT_ENUM_CAST(DynamicFontData::Hinting); class DynamicFontAtSize : public Reference { - GDCLASS(DynamicFontAtSize, Reference); _THREAD_SAFE_CLASS_ @@ -124,14 +122,13 @@ class DynamicFontAtSize : public Reference { float rect_margin; float oversampling; float scale_color_font; - - uint32_t texture_flags; + float underline_position; + float underline_thickness; bool valid; struct CharTexture { - - PoolVector<uint8_t> imgdata; + Vector<uint8_t> imgdata; int texture_size; Vector<int> offsets; Ref<ImageTexture> texture; @@ -140,7 +137,6 @@ class DynamicFontAtSize : public Reference { Vector<CharTexture> textures; struct Character { - bool found; int texture_idx; Rect2 rect; @@ -163,23 +159,23 @@ class DynamicFontAtSize : public Reference { int y; }; - const Pair<const Character *, DynamicFontAtSize *> _find_char_with_font(CharType p_char, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks) const; - Character _make_outline_char(CharType p_char); + const Pair<const Character *, DynamicFontAtSize *> _find_char_with_font(char32_t p_char, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const; + Character _make_outline_char(char32_t p_char); TexturePosition _find_texture_pos_for_glyph(int p_color_size, Image::Format p_image_format, int p_width, int p_height); Character _bitmap_to_character(FT_Bitmap bitmap, int yofs, int xofs, float advance); static unsigned long _ft_stream_io(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count); static void _ft_stream_close(FT_Stream stream); - HashMap<CharType, Character> char_map; + HashMap<char32_t, Character> char_map; - _FORCE_INLINE_ void _update_char(CharType p_char); + _FORCE_INLINE_ void _update_char(char32_t p_char); friend class DynamicFontData; Ref<DynamicFontData> font; DynamicFontData::CacheID id; - static HashMap<String, Vector<uint8_t> > _fontdata; + static HashMap<String, Vector<uint8_t>> _fontdata; Error _load(); public: @@ -189,10 +185,13 @@ public: float get_ascent() const; float get_descent() const; + float get_underline_position() const; + float get_underline_thickness() const; - Size2 get_char_size(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks) const; + Size2 get_char_size(char32_t p_char, char32_t p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const; + String get_available_chars() const; - float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize> > &p_fallbacks, bool p_advance_only = false, bool p_outline = false) const; + float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks, bool p_advance_only = false, bool p_outline = false) const; void set_texture_flags(uint32_t p_flags); void update_oversampling(); @@ -204,7 +203,6 @@ public: /////////////// class DynamicFont : public Font { - GDCLASS(DynamicFont, Font); public: @@ -220,9 +218,9 @@ private: Ref<DynamicFontAtSize> data_at_size; Ref<DynamicFontAtSize> outline_data_at_size; - Vector<Ref<DynamicFontData> > fallbacks; - Vector<Ref<DynamicFontAtSize> > fallback_data_at_size; - Vector<Ref<DynamicFontAtSize> > fallback_outline_data_at_size; + Vector<Ref<DynamicFontData>> fallbacks; + Vector<Ref<DynamicFontAtSize>> fallback_data_at_size; + Vector<Ref<DynamicFontAtSize>> fallback_outline_data_at_size; DynamicFontData::CacheID cache_id; DynamicFontData::CacheID outline_cache_id; @@ -272,22 +270,25 @@ public: Ref<DynamicFontData> get_fallback(int p_idx) const; void remove_fallback(int p_idx); - virtual float get_height() const; + virtual float get_height() const override; - virtual float get_ascent() const; - virtual float get_descent() const; + virtual float get_ascent() const override; + virtual float get_descent() const override; + virtual float get_underline_position() const override; + virtual float get_underline_thickness() const override; - virtual Size2 get_char_size(CharType p_char, CharType p_next = 0) const; + virtual Size2 get_char_size(char32_t p_char, char32_t p_next = 0) const override; + String get_available_chars() const; - virtual bool is_distance_field_hint() const; + virtual bool is_distance_field_hint() const override; - virtual bool has_outline() const; + virtual bool has_outline() const override; - virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const; + virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const override; SelfList<DynamicFont> font_list; - static Mutex *dynamic_font_mutex; + static Mutex dynamic_font_mutex; static SelfList<DynamicFont>::List *dynamic_fonts; static void initialize_dynamic_fonts(); @@ -304,7 +305,7 @@ VARIANT_ENUM_CAST(DynamicFont::SpacingType); class ResourceFormatLoaderDynamicFont : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 7597cd636e..ee8e63266d 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -29,1390 +29,1318 @@ /*************************************************************************/ #include "environment.h" + #include "core/project_settings.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" #include "texture.h" RID Environment::get_rid() const { - return environment; } -void Environment::set_background(BGMode p_bg) { +// Background +void Environment::set_background(BGMode p_bg) { bg_mode = p_bg; - VS::get_singleton()->environment_set_background(environment, VS::EnvironmentBG(p_bg)); + RS::get_singleton()->environment_set_background(environment, RS::EnvironmentBG(p_bg)); _change_notify(); } -void Environment::set_sky(const Ref<Sky> &p_sky) { +Environment::BGMode Environment::get_background() const { + return bg_mode; +} +void Environment::set_sky(const Ref<Sky> &p_sky) { bg_sky = p_sky; - RID sb_rid; - if (bg_sky.is_valid()) + if (bg_sky.is_valid()) { sb_rid = bg_sky->get_rid(); + } + RS::get_singleton()->environment_set_sky(environment, sb_rid); +} - VS::get_singleton()->environment_set_sky(environment, sb_rid); +Ref<Sky> Environment::get_sky() const { + return bg_sky; } void Environment::set_sky_custom_fov(float p_scale) { - bg_sky_custom_fov = p_scale; - VS::get_singleton()->environment_set_sky_custom_fov(environment, p_scale); + RS::get_singleton()->environment_set_sky_custom_fov(environment, p_scale); } -void Environment::set_sky_orientation(const Basis &p_orientation) { - bg_sky_orientation = p_orientation; - _change_notify("background_sky_rotation"); - _change_notify("background_sky_rotation_degrees"); - VS::get_singleton()->environment_set_sky_orientation(environment, bg_sky_orientation); +float Environment::get_sky_custom_fov() const { + return bg_sky_custom_fov; } -void Environment::set_sky_rotation(const Vector3 &p_euler_rad) { - bg_sky_orientation.set_euler(p_euler_rad); - _change_notify("background_sky_orientation"); - _change_notify("background_sky_rotation_degrees"); - VS::get_singleton()->environment_set_sky_orientation(environment, bg_sky_orientation); +void Environment::set_sky_rotation(const Vector3 &p_rotation) { + bg_sky_rotation = p_rotation; + RS::get_singleton()->environment_set_sky_orientation(environment, Basis(p_rotation)); } -void Environment::set_sky_rotation_degrees(const Vector3 &p_euler_deg) { - set_sky_rotation(p_euler_deg * Math_PI / 180.0); - _change_notify("background_sky_rotation"); +Vector3 Environment::get_sky_rotation() const { + return bg_sky_rotation; } -void Environment::set_bg_color(const Color &p_color) { +void Environment::set_bg_color(const Color &p_color) { bg_color = p_color; - VS::get_singleton()->environment_set_bg_color(environment, p_color); + RS::get_singleton()->environment_set_bg_color(environment, p_color); } -void Environment::set_bg_energy(float p_energy) { - bg_energy = p_energy; - VS::get_singleton()->environment_set_bg_energy(environment, p_energy); +Color Environment::get_bg_color() const { + return bg_color; } -void Environment::set_canvas_max_layer(int p_max_layer) { - bg_canvas_max_layer = p_max_layer; - VS::get_singleton()->environment_set_canvas_max_layer(environment, p_max_layer); +void Environment::set_bg_energy(float p_energy) { + bg_energy = p_energy; + RS::get_singleton()->environment_set_bg_energy(environment, p_energy); } -void Environment::set_ambient_light_color(const Color &p_color) { - ambient_color = p_color; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, ambient_energy, ambient_sky_contribution); +float Environment::get_bg_energy() const { + return bg_energy; } -void Environment::set_ambient_light_energy(float p_energy) { - ambient_energy = p_energy; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, ambient_energy, ambient_sky_contribution); +void Environment::set_canvas_max_layer(int p_max_layer) { + bg_canvas_max_layer = p_max_layer; + RS::get_singleton()->environment_set_canvas_max_layer(environment, p_max_layer); } -void Environment::set_ambient_light_sky_contribution(float p_energy) { - ambient_sky_contribution = p_energy; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, ambient_energy, ambient_sky_contribution); +int Environment::get_canvas_max_layer() const { + return bg_canvas_max_layer; } -void Environment::set_camera_feed_id(int p_camera_feed_id) { - camera_feed_id = p_camera_feed_id; - VS::get_singleton()->environment_set_camera_feed_id(environment, camera_feed_id); -}; - -Environment::BGMode Environment::get_background() const { - - return bg_mode; +void Environment::set_camera_feed_id(int p_id) { + bg_camera_feed_id = p_id; +// FIXME: Disabled during Vulkan refactoring, should be ported. +#if 0 + RS::get_singleton()->environment_set_camera_feed_id(environment, camera_feed_id); +#endif } -Ref<Sky> Environment::get_sky() const { - return bg_sky; +int Environment::get_camera_feed_id() const { + return bg_camera_feed_id; } -float Environment::get_sky_custom_fov() const { +// Ambient light - return bg_sky_custom_fov; +void Environment::set_ambient_light_color(const Color &p_color) { + ambient_color = p_color; + _update_ambient_light(); } -Basis Environment::get_sky_orientation() const { - - return bg_sky_orientation; +Color Environment::get_ambient_light_color() const { + return ambient_color; } -Vector3 Environment::get_sky_rotation() const { - - // should we cache this? maybe overkill - return bg_sky_orientation.get_euler(); +void Environment::set_ambient_source(AmbientSource p_source) { + ambient_source = p_source; + _update_ambient_light(); + _change_notify(); } -Vector3 Environment::get_sky_rotation_degrees() const { +Environment::AmbientSource Environment::get_ambient_source() const { + return ambient_source; +} - return get_sky_rotation() * 180.0 / Math_PI; +void Environment::set_ambient_light_energy(float p_energy) { + ambient_energy = p_energy; + _update_ambient_light(); } -Color Environment::get_bg_color() const { +float Environment::get_ambient_light_energy() const { + return ambient_energy; +} - return bg_color; +void Environment::set_ambient_light_sky_contribution(float p_ratio) { + ambient_sky_contribution = p_ratio; + _update_ambient_light(); } -float Environment::get_bg_energy() const { - return bg_energy; +float Environment::get_ambient_light_sky_contribution() const { + return ambient_sky_contribution; } -int Environment::get_canvas_max_layer() const { - return bg_canvas_max_layer; +void Environment::set_reflection_source(ReflectionSource p_source) { + reflection_source = p_source; + _update_ambient_light(); + _change_notify(); } -Color Environment::get_ambient_light_color() const { - return ambient_color; +Environment::ReflectionSource Environment::get_reflection_source() const { + return reflection_source; } -float Environment::get_ambient_light_energy() const { - return ambient_energy; +void Environment::set_ao_color(const Color &p_color) { + ao_color = p_color; + _update_ambient_light(); } -float Environment::get_ambient_light_sky_contribution() const { - return ambient_sky_contribution; +Color Environment::get_ao_color() const { + return ao_color; } -int Environment::get_camera_feed_id(void) const { - return camera_feed_id; +void Environment::_update_ambient_light() { + RS::get_singleton()->environment_set_ambient_light( + environment, + ambient_color, + RS::EnvironmentAmbientSource(ambient_source), + ambient_energy, + ambient_sky_contribution, RS::EnvironmentReflectionSource(reflection_source), + ao_color); } -void Environment::set_tonemapper(ToneMapper p_tone_mapper) { +// Tonemap +void Environment::set_tonemapper(ToneMapper p_tone_mapper) { tone_mapper = p_tone_mapper; - VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + _update_tonemap(); } Environment::ToneMapper Environment::get_tonemapper() const { - return tone_mapper; } void Environment::set_tonemap_exposure(float p_exposure) { - tonemap_exposure = p_exposure; - VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + _update_tonemap(); } float Environment::get_tonemap_exposure() const { - return tonemap_exposure; } void Environment::set_tonemap_white(float p_white) { - tonemap_white = p_white; - VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + _update_tonemap(); } -float Environment::get_tonemap_white() const { +float Environment::get_tonemap_white() const { return tonemap_white; } -void Environment::set_tonemap_auto_exposure(bool p_enabled) { - - tonemap_auto_exposure = p_enabled; - VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); +void Environment::set_tonemap_auto_exposure_enabled(bool p_enabled) { + tonemap_auto_exposure_enabled = p_enabled; + _update_tonemap(); _change_notify(); } -bool Environment::get_tonemap_auto_exposure() const { - return tonemap_auto_exposure; +bool Environment::is_tonemap_auto_exposure_enabled() const { + return tonemap_auto_exposure_enabled; } -void Environment::set_tonemap_auto_exposure_max(float p_auto_exposure_max) { - - tonemap_auto_exposure_max = p_auto_exposure_max; - VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); +void Environment::set_tonemap_auto_exposure_min(float p_auto_exposure_min) { + tonemap_auto_exposure_min = p_auto_exposure_min; + _update_tonemap(); } -float Environment::get_tonemap_auto_exposure_max() const { - return tonemap_auto_exposure_max; +float Environment::get_tonemap_auto_exposure_min() const { + return tonemap_auto_exposure_min; } -void Environment::set_tonemap_auto_exposure_min(float p_auto_exposure_min) { - - tonemap_auto_exposure_min = p_auto_exposure_min; - VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); +void Environment::set_tonemap_auto_exposure_max(float p_auto_exposure_max) { + tonemap_auto_exposure_max = p_auto_exposure_max; + _update_tonemap(); } -float Environment::get_tonemap_auto_exposure_min() const { - return tonemap_auto_exposure_min; +float Environment::get_tonemap_auto_exposure_max() const { + return tonemap_auto_exposure_max; } void Environment::set_tonemap_auto_exposure_speed(float p_auto_exposure_speed) { - tonemap_auto_exposure_speed = p_auto_exposure_speed; - VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + _update_tonemap(); } -float Environment::get_tonemap_auto_exposure_speed() const { +float Environment::get_tonemap_auto_exposure_speed() const { return tonemap_auto_exposure_speed; } void Environment::set_tonemap_auto_exposure_grey(float p_auto_exposure_grey) { - tonemap_auto_exposure_grey = p_auto_exposure_grey; - VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + _update_tonemap(); } -float Environment::get_tonemap_auto_exposure_grey() const { +float Environment::get_tonemap_auto_exposure_grey() const { return tonemap_auto_exposure_grey; } -void Environment::set_adjustment_enable(bool p_enable) { - - adjustment_enabled = p_enable; - VS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); - _change_notify(); -} - -bool Environment::is_adjustment_enabled() const { - - return adjustment_enabled; -} - -void Environment::set_adjustment_brightness(float p_brightness) { - - adjustment_brightness = p_brightness; - VS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); -} -float Environment::get_adjustment_brightness() const { - - return adjustment_brightness; -} - -void Environment::set_adjustment_contrast(float p_contrast) { - - adjustment_contrast = p_contrast; - VS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); -} -float Environment::get_adjustment_contrast() const { - - return adjustment_contrast; -} - -void Environment::set_adjustment_saturation(float p_saturation) { - - adjustment_saturation = p_saturation; - VS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); -} -float Environment::get_adjustment_saturation() const { - - return adjustment_saturation; +void Environment::_update_tonemap() { + RS::get_singleton()->environment_set_tonemap( + environment, + RS::EnvironmentToneMapper(tone_mapper), + tonemap_exposure, + tonemap_white, + tonemap_auto_exposure_enabled, + tonemap_auto_exposure_min, + tonemap_auto_exposure_max, + tonemap_auto_exposure_speed, + tonemap_auto_exposure_grey); } -void Environment::set_adjustment_color_correction(const Ref<Texture> &p_ramp) { +// SSR - adjustment_color_correction = p_ramp; - VS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); -} -Ref<Texture> Environment::get_adjustment_color_correction() const { - - return adjustment_color_correction; -} - -void Environment::_validate_property(PropertyInfo &property) const { - - if (property.name == "background_sky" || property.name == "background_sky_custom_fov" || property.name == "background_sky_orientation" || property.name == "background_sky_rotation" || property.name == "background_sky_rotation_degrees" || property.name == "ambient_light/sky_contribution") { - if (bg_mode != BG_SKY && bg_mode != BG_COLOR_SKY) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; - } - } - - if (property.name == "background_color") { - if (bg_mode != BG_COLOR && bg_mode != BG_COLOR_SKY) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; - } - } - - if (property.name == "background_canvas_max_layer") { - if (bg_mode != BG_CANVAS) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; - } - } - - if (property.name == "background_camera_feed_id") { - if (bg_mode != BG_CAMERA_FEED) { - property.usage = PROPERTY_USAGE_NOEDITOR; - } - } - - static const char *hide_prefixes[] = { - "fog_", - "auto_exposure_", - "ss_reflections_", - "ssao_", - "dof_blur_far_", - "dof_blur_near_", - "glow_", - "adjustment_", - NULL - - }; - - static const char *high_end_prefixes[] = { - "auto_exposure_", - "tonemap_", - "ss_reflections_", - "ssao_", - NULL - - }; - - const char **prefixes = hide_prefixes; - while (*prefixes) { - String prefix = String(*prefixes); - - String enabled = prefix + "enabled"; - if (property.name.begins_with(prefix) && property.name != enabled && !bool(get(enabled))) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; - return; - } - - prefixes++; - } - - if (VisualServer::get_singleton()->is_low_end()) { - prefixes = high_end_prefixes; - while (*prefixes) { - String prefix = String(*prefixes); - - if (property.name.begins_with(prefix)) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; - return; - } - - prefixes++; - } - } -} - -void Environment::set_ssr_enabled(bool p_enable) { - - ssr_enabled = p_enable; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); +void Environment::set_ssr_enabled(bool p_enabled) { + ssr_enabled = p_enabled; + _update_ssr(); _change_notify(); } bool Environment::is_ssr_enabled() const { - return ssr_enabled; } void Environment::set_ssr_max_steps(int p_steps) { - ssr_max_steps = p_steps; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); + _update_ssr(); } -int Environment::get_ssr_max_steps() const { +int Environment::get_ssr_max_steps() const { return ssr_max_steps; } void Environment::set_ssr_fade_in(float p_fade_in) { - ssr_fade_in = p_fade_in; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); + _update_ssr(); } -float Environment::get_ssr_fade_in() const { +float Environment::get_ssr_fade_in() const { return ssr_fade_in; } void Environment::set_ssr_fade_out(float p_fade_out) { - ssr_fade_out = p_fade_out; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); + _update_ssr(); } -float Environment::get_ssr_fade_out() const { +float Environment::get_ssr_fade_out() const { return ssr_fade_out; } void Environment::set_ssr_depth_tolerance(float p_depth_tolerance) { - ssr_depth_tolerance = p_depth_tolerance; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); + _update_ssr(); } -float Environment::get_ssr_depth_tolerance() const { +float Environment::get_ssr_depth_tolerance() const { return ssr_depth_tolerance; } -void Environment::set_ssr_rough(bool p_enable) { - - ssr_roughness = p_enable; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); +void Environment::_update_ssr() { + RS::get_singleton()->environment_set_ssr( + environment, + ssr_enabled, + ssr_max_steps, + ssr_fade_in, + ssr_fade_out, + ssr_depth_tolerance); } -bool Environment::is_ssr_rough() const { - return ssr_roughness; -} +// SSAO -void Environment::set_ssao_enabled(bool p_enable) { - - ssao_enabled = p_enable; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); +void Environment::set_ssao_enabled(bool p_enabled) { + ssao_enabled = p_enabled; + _update_ssao(); _change_notify(); } bool Environment::is_ssao_enabled() const { - return ssao_enabled; } void Environment::set_ssao_radius(float p_radius) { - ssao_radius = p_radius; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + _update_ssao(); } -float Environment::get_ssao_radius() const { +float Environment::get_ssao_radius() const { return ssao_radius; } void Environment::set_ssao_intensity(float p_intensity) { - ssao_intensity = p_intensity; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + _update_ssao(); } float Environment::get_ssao_intensity() const { - return ssao_intensity; } -void Environment::set_ssao_radius2(float p_radius) { +void Environment::set_ssao_bias(float p_bias) { + ssao_bias = p_bias; + _update_ssao(); +} - ssao_radius2 = p_radius; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); +float Environment::get_ssao_bias() const { + return ssao_bias; } -float Environment::get_ssao_radius2() const { - return ssao_radius2; +void Environment::set_ssao_direct_light_affect(float p_direct_light_affect) { + ssao_direct_light_affect = p_direct_light_affect; + _update_ssao(); } -void Environment::set_ssao_intensity2(float p_intensity) { +float Environment::get_ssao_direct_light_affect() const { + return ssao_direct_light_affect; +} - ssao_intensity2 = p_intensity; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); +void Environment::set_ssao_ao_channel_affect(float p_ao_channel_affect) { + ssao_ao_channel_affect = p_ao_channel_affect; + _update_ssao(); } -float Environment::get_ssao_intensity2() const { - return ssao_intensity2; +float Environment::get_ssao_ao_channel_affect() const { + return ssao_ao_channel_affect; } -void Environment::set_ssao_bias(float p_bias) { +void Environment::set_ssao_blur(SSAOBlur p_blur) { + ssao_blur = p_blur; + _update_ssao(); +} - ssao_bias = p_bias; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); +Environment::SSAOBlur Environment::get_ssao_blur() const { + return ssao_blur; } -float Environment::get_ssao_bias() const { - return ssao_bias; +void Environment::set_ssao_edge_sharpness(float p_edge_sharpness) { + ssao_edge_sharpness = p_edge_sharpness; + _update_ssao(); } -void Environment::set_ssao_direct_light_affect(float p_direct_light_affect) { +float Environment::get_ssao_edge_sharpness() const { + return ssao_edge_sharpness; +} - ssao_direct_light_affect = p_direct_light_affect; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); +void Environment::_update_ssao() { + RS::get_singleton()->environment_set_ssao( + environment, + ssao_enabled, + ssao_radius, + ssao_intensity, + ssao_bias, + ssao_direct_light_affect, + ssao_ao_channel_affect, + RS::EnvironmentSSAOBlur(ssao_blur), + ssao_edge_sharpness); } -float Environment::get_ssao_direct_light_affect() const { - return ssao_direct_light_affect; +// SDFGI + +void Environment::set_sdfgi_enabled(bool p_enabled) { + sdfgi_enabled = p_enabled; + _update_sdfgi(); } -void Environment::set_ssao_ao_channel_affect(float p_ao_channel_affect) { +bool Environment::is_sdfgi_enabled() const { + return sdfgi_enabled; +} - ssao_ao_channel_affect = p_ao_channel_affect; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); +void Environment::set_sdfgi_cascades(SDFGICascades p_cascades) { + sdfgi_cascades = p_cascades; + _update_sdfgi(); } -float Environment::get_ssao_ao_channel_affect() const { - return ssao_ao_channel_affect; +Environment::SDFGICascades Environment::get_sdfgi_cascades() const { + return sdfgi_cascades; } -void Environment::set_ssao_color(const Color &p_color) { +void Environment::set_sdfgi_min_cell_size(float p_size) { + sdfgi_min_cell_size = p_size; + _change_notify("sdfgi_max_distance"); + _change_notify("sdfgi_cascade0_distance"); + _update_sdfgi(); +} - ssao_color = p_color; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); +float Environment::get_sdfgi_min_cell_size() const { + return sdfgi_min_cell_size; } -Color Environment::get_ssao_color() const { +void Environment::set_sdfgi_max_distance(float p_distance) { + p_distance /= 64.0; + int cc[3] = { 4, 6, 8 }; + int cascades = cc[sdfgi_cascades]; + for (int i = 0; i < cascades; i++) { + p_distance *= 0.5; //halve for each cascade + } + sdfgi_min_cell_size = p_distance; + _change_notify("sdfgi_min_cell_size"); + _change_notify("sdfgi_cascade0_distance"); + _update_sdfgi(); +} + +float Environment::get_sdfgi_max_distance() const { + float md = sdfgi_min_cell_size; + md *= 64.0; + int cc[3] = { 4, 6, 8 }; + int cascades = cc[sdfgi_cascades]; + for (int i = 0; i < cascades; i++) { + md *= 2.0; + } + return md; +} - return ssao_color; +void Environment::set_sdfgi_cascade0_distance(float p_distance) { + sdfgi_min_cell_size = p_distance / 64.0; + _change_notify("sdfgi_min_cell_size"); + _change_notify("sdfgi_max_distance"); + _update_sdfgi(); } -void Environment::set_ssao_blur(SSAOBlur p_blur) { +float Environment::get_sdfgi_cascade0_distance() const { + return sdfgi_min_cell_size * 64.0; +} - ssao_blur = p_blur; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); +void Environment::set_sdfgi_y_scale(SDFGIYScale p_y_scale) { + sdfgi_y_scale = p_y_scale; + _update_sdfgi(); } -Environment::SSAOBlur Environment::get_ssao_blur() const { - return ssao_blur; +Environment::SDFGIYScale Environment::get_sdfgi_y_scale() const { + return sdfgi_y_scale; } -void Environment::set_ssao_quality(SSAOQuality p_quality) { +void Environment::set_sdfgi_use_occlusion(bool p_enabled) { + sdfgi_use_occlusion = p_enabled; + _update_sdfgi(); +} - ssao_quality = p_quality; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); +bool Environment::is_sdfgi_using_occlusion() const { + return sdfgi_use_occlusion; } -Environment::SSAOQuality Environment::get_ssao_quality() const { +void Environment::set_sdfgi_use_multi_bounce(bool p_enabled) { + sdfgi_use_multibounce = p_enabled; + _update_sdfgi(); +} - return ssao_quality; +bool Environment::is_sdfgi_using_multi_bounce() const { + return sdfgi_use_multibounce; } -void Environment::set_ssao_edge_sharpness(float p_edge_sharpness) { +void Environment::set_sdfgi_read_sky_light(bool p_enabled) { + sdfgi_read_sky_light = p_enabled; + _update_sdfgi(); +} - ssao_edge_sharpness = p_edge_sharpness; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_radius2, ssao_intensity2, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, ssao_color, VS::EnvironmentSSAOQuality(ssao_quality), VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); +bool Environment::is_sdfgi_reading_sky_light() const { + return sdfgi_read_sky_light; } -float Environment::get_ssao_edge_sharpness() const { +void Environment::set_sdfgi_energy(float p_energy) { + sdfgi_energy = p_energy; + _update_sdfgi(); +} - return ssao_edge_sharpness; +float Environment::get_sdfgi_energy() const { + return sdfgi_energy; } -void Environment::set_glow_enabled(bool p_enabled) { +void Environment::set_sdfgi_normal_bias(float p_bias) { + sdfgi_normal_bias = p_bias; + _update_sdfgi(); +} + +float Environment::get_sdfgi_normal_bias() const { + return sdfgi_normal_bias; +} + +void Environment::set_sdfgi_probe_bias(float p_bias) { + sdfgi_probe_bias = p_bias; + _update_sdfgi(); +} + +float Environment::get_sdfgi_probe_bias() const { + return sdfgi_probe_bias; +} + +void Environment::_update_sdfgi() { + RS::get_singleton()->environment_set_sdfgi( + environment, + sdfgi_enabled, + RS::EnvironmentSDFGICascades(sdfgi_cascades), + sdfgi_min_cell_size, + RS::EnvironmentSDFGIYScale(sdfgi_y_scale), + sdfgi_use_occlusion, + sdfgi_use_multibounce, + sdfgi_read_sky_light, + sdfgi_energy, + sdfgi_normal_bias, + sdfgi_probe_bias); +} + +// Glow +void Environment::set_glow_enabled(bool p_enabled) { glow_enabled = p_enabled; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + _update_glow(); _change_notify(); } bool Environment::is_glow_enabled() const { - return glow_enabled; } -void Environment::set_glow_level(int p_level, bool p_enabled) { - - ERR_FAIL_INDEX(p_level, VS::MAX_GLOW_LEVELS); +void Environment::set_glow_level_enabled(int p_level, bool p_enabled) { + ERR_FAIL_INDEX(p_level, RS::MAX_GLOW_LEVELS); - if (p_enabled) + if (p_enabled) { glow_levels |= (1 << p_level); - else + } else { glow_levels &= ~(1 << p_level); + } - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + _update_glow(); } -bool Environment::is_glow_level_enabled(int p_level) const { - ERR_FAIL_INDEX_V(p_level, VS::MAX_GLOW_LEVELS, false); +bool Environment::is_glow_level_enabled(int p_level) const { + ERR_FAIL_INDEX_V(p_level, RS::MAX_GLOW_LEVELS, false); return glow_levels & (1 << p_level); } void Environment::set_glow_intensity(float p_intensity) { - glow_intensity = p_intensity; - - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + _update_glow(); } -float Environment::get_glow_intensity() const { +float Environment::get_glow_intensity() const { return glow_intensity; } void Environment::set_glow_strength(float p_strength) { - glow_strength = p_strength; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + _update_glow(); } -float Environment::get_glow_strength() const { +float Environment::get_glow_strength() const { return glow_strength; } -void Environment::set_glow_bloom(float p_threshold) { +void Environment::set_glow_mix(float p_mix) { + glow_mix = p_mix; + _update_glow(); +} - glow_bloom = p_threshold; +float Environment::get_glow_mix() const { + return glow_mix; +} - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); +void Environment::set_glow_bloom(float p_threshold) { + glow_bloom = p_threshold; + _update_glow(); } -float Environment::get_glow_bloom() const { +float Environment::get_glow_bloom() const { return glow_bloom; } void Environment::set_glow_blend_mode(GlowBlendMode p_mode) { - glow_blend_mode = p_mode; - - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + _update_glow(); + _change_notify(); } -Environment::GlowBlendMode Environment::get_glow_blend_mode() const { +Environment::GlowBlendMode Environment::get_glow_blend_mode() const { return glow_blend_mode; } void Environment::set_glow_hdr_bleed_threshold(float p_threshold) { - glow_hdr_bleed_threshold = p_threshold; - - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + _update_glow(); } -float Environment::get_glow_hdr_bleed_threshold() const { +float Environment::get_glow_hdr_bleed_threshold() const { return glow_hdr_bleed_threshold; } -void Environment::set_glow_hdr_luminance_cap(float p_amount) { - - glow_hdr_luminance_cap = p_amount; - - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); -} -float Environment::get_glow_hdr_luminance_cap() const { - - return glow_hdr_luminance_cap; -} - void Environment::set_glow_hdr_bleed_scale(float p_scale) { - glow_hdr_bleed_scale = p_scale; - - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + _update_glow(); } -float Environment::get_glow_hdr_bleed_scale() const { +float Environment::get_glow_hdr_bleed_scale() const { return glow_hdr_bleed_scale; } -void Environment::set_glow_bicubic_upscale(bool p_enable) { - - glow_bicubic_upscale = p_enable; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); +void Environment::set_glow_hdr_luminance_cap(float p_amount) { + glow_hdr_luminance_cap = p_amount; + _update_glow(); } -bool Environment::is_glow_bicubic_upscale_enabled() const { +float Environment::get_glow_hdr_luminance_cap() const { + return glow_hdr_luminance_cap; +} - return glow_bicubic_upscale; +void Environment::_update_glow() { + RS::get_singleton()->environment_set_glow( + environment, + glow_enabled, + glow_levels, + glow_intensity, + glow_strength, + glow_mix, + glow_bloom, + RS::EnvironmentGlowBlendMode(glow_blend_mode), + glow_hdr_bleed_threshold, + glow_hdr_bleed_scale, + glow_hdr_luminance_cap); } -void Environment::set_dof_blur_far_enabled(bool p_enable) { +// Fog - dof_blur_far_enabled = p_enable; - VS::get_singleton()->environment_set_dof_blur_far(environment, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_far_amount, VS::EnvironmentDOFBlurQuality(dof_blur_far_quality)); +void Environment::set_fog_enabled(bool p_enabled) { + fog_enabled = p_enabled; + _update_fog(); _change_notify(); } -bool Environment::is_dof_blur_far_enabled() const { - - return dof_blur_far_enabled; +bool Environment::is_fog_enabled() const { + return fog_enabled; } -void Environment::set_dof_blur_far_distance(float p_distance) { - - dof_blur_far_distance = p_distance; - VS::get_singleton()->environment_set_dof_blur_far(environment, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_far_amount, VS::EnvironmentDOFBlurQuality(dof_blur_far_quality)); +void Environment::set_fog_light_color(const Color &p_light_color) { + fog_light_color = p_light_color; + _update_fog(); } -float Environment::get_dof_blur_far_distance() const { - - return dof_blur_far_distance; +Color Environment::get_fog_light_color() const { + return fog_light_color; } - -void Environment::set_dof_blur_far_transition(float p_distance) { - - dof_blur_far_transition = p_distance; - VS::get_singleton()->environment_set_dof_blur_far(environment, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_far_amount, VS::EnvironmentDOFBlurQuality(dof_blur_far_quality)); +void Environment::set_fog_light_energy(float p_amount) { + fog_light_energy = p_amount; + _update_fog(); } -float Environment::get_dof_blur_far_transition() const { - - return dof_blur_far_transition; +float Environment::get_fog_light_energy() const { + return fog_light_energy; } - -void Environment::set_dof_blur_far_amount(float p_amount) { - - dof_blur_far_amount = p_amount; - VS::get_singleton()->environment_set_dof_blur_far(environment, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_far_amount, VS::EnvironmentDOFBlurQuality(dof_blur_far_quality)); +void Environment::set_fog_sun_scatter(float p_amount) { + fog_sun_scatter = p_amount; + _update_fog(); } -float Environment::get_dof_blur_far_amount() const { - - return dof_blur_far_amount; +float Environment::get_fog_sun_scatter() const { + return fog_sun_scatter; +} +void Environment::set_fog_density(float p_amount) { + fog_density = p_amount; + _update_fog(); +} +float Environment::get_fog_density() const { + return fog_density; +} +void Environment::set_fog_height(float p_amount) { + fog_height = p_amount; + _update_fog(); +} +float Environment::get_fog_height() const { + return fog_height; +} +void Environment::set_fog_height_density(float p_amount) { + fog_height_density = p_amount; + _update_fog(); +} +float Environment::get_fog_height_density() const { + return fog_height_density; } -void Environment::set_dof_blur_far_quality(DOFBlurQuality p_quality) { - - dof_blur_far_quality = p_quality; - VS::get_singleton()->environment_set_dof_blur_far(environment, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_far_amount, VS::EnvironmentDOFBlurQuality(dof_blur_far_quality)); +void Environment::_update_fog() { + RS::get_singleton()->environment_set_fog( + environment, + fog_enabled, + fog_light_color, + fog_light_energy, + fog_sun_scatter, + fog_density, + fog_height, + fog_height_density); } -Environment::DOFBlurQuality Environment::get_dof_blur_far_quality() const { +// Volumetric Fog - return dof_blur_far_quality; +void Environment::_update_volumetric_fog() { + RS::get_singleton()->environment_set_volumetric_fog(environment, volumetric_fog_enabled, volumetric_fog_density, volumetric_fog_light, volumetric_fog_light_energy, volumetric_fog_length, volumetric_fog_detail_spread, volumetric_fog_gi_inject, RS::EnvVolumetricFogShadowFilter(volumetric_fog_shadow_filter)); } -void Environment::set_dof_blur_near_enabled(bool p_enable) { - - dof_blur_near_enabled = p_enable; - VS::get_singleton()->environment_set_dof_blur_near(environment, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_near_amount, VS::EnvironmentDOFBlurQuality(dof_blur_near_quality)); +void Environment::set_volumetric_fog_enabled(bool p_enable) { + volumetric_fog_enabled = p_enable; + _update_volumetric_fog(); _change_notify(); } -bool Environment::is_dof_blur_near_enabled() const { - - return dof_blur_near_enabled; +bool Environment::is_volumetric_fog_enabled() const { + return volumetric_fog_enabled; } - -void Environment::set_dof_blur_near_distance(float p_distance) { - - dof_blur_near_distance = p_distance; - VS::get_singleton()->environment_set_dof_blur_near(environment, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_near_amount, VS::EnvironmentDOFBlurQuality(dof_blur_near_quality)); +void Environment::set_volumetric_fog_density(float p_density) { + p_density = CLAMP(p_density, 0.0000001, 1.0); + volumetric_fog_density = p_density; + _update_volumetric_fog(); } - -float Environment::get_dof_blur_near_distance() const { - - return dof_blur_near_distance; +float Environment::get_volumetric_fog_density() const { + return volumetric_fog_density; } - -void Environment::set_dof_blur_near_transition(float p_distance) { - - dof_blur_near_transition = p_distance; - VS::get_singleton()->environment_set_dof_blur_near(environment, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_near_amount, VS::EnvironmentDOFBlurQuality(dof_blur_near_quality)); +void Environment::set_volumetric_fog_light(Color p_color) { + volumetric_fog_light = p_color; + _update_volumetric_fog(); } - -float Environment::get_dof_blur_near_transition() const { - - return dof_blur_near_transition; +Color Environment::get_volumetric_fog_light() const { + return volumetric_fog_light; } - -void Environment::set_dof_blur_near_amount(float p_amount) { - - dof_blur_near_amount = p_amount; - VS::get_singleton()->environment_set_dof_blur_near(environment, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_near_amount, VS::EnvironmentDOFBlurQuality(dof_blur_near_quality)); +void Environment::set_volumetric_fog_light_energy(float p_begin) { + volumetric_fog_light_energy = p_begin; + _update_volumetric_fog(); } - -float Environment::get_dof_blur_near_amount() const { - - return dof_blur_near_amount; +float Environment::get_volumetric_fog_light_energy() const { + return volumetric_fog_light_energy; } - -void Environment::set_dof_blur_near_quality(DOFBlurQuality p_quality) { - - dof_blur_near_quality = p_quality; - VS::get_singleton()->environment_set_dof_blur_near(environment, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_near_amount, VS::EnvironmentDOFBlurQuality(dof_blur_near_quality)); +void Environment::set_volumetric_fog_length(float p_length) { + volumetric_fog_length = p_length; + _update_volumetric_fog(); } - -Environment::DOFBlurQuality Environment::get_dof_blur_near_quality() const { - - return dof_blur_near_quality; +float Environment::get_volumetric_fog_length() const { + return volumetric_fog_length; } - -void Environment::set_fog_enabled(bool p_enabled) { - - fog_enabled = p_enabled; - VS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); - _change_notify(); +void Environment::set_volumetric_fog_detail_spread(float p_detail_spread) { + volumetric_fog_detail_spread = p_detail_spread; + _update_volumetric_fog(); } - -bool Environment::is_fog_enabled() const { - - return fog_enabled; +float Environment::get_volumetric_fog_detail_spread() const { + return volumetric_fog_detail_spread; } -void Environment::set_fog_color(const Color &p_color) { - - fog_color = p_color; - VS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); +void Environment::set_volumetric_fog_gi_inject(float p_gi_inject) { + volumetric_fog_gi_inject = p_gi_inject; + _update_volumetric_fog(); } -Color Environment::get_fog_color() const { - - return fog_color; +float Environment::get_volumetric_fog_gi_inject() const { + return volumetric_fog_gi_inject; } -void Environment::set_fog_sun_color(const Color &p_color) { - - fog_sun_color = p_color; - VS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); +void Environment::set_volumetric_fog_shadow_filter(VolumetricFogShadowFilter p_filter) { + volumetric_fog_shadow_filter = p_filter; + _update_volumetric_fog(); } -Color Environment::get_fog_sun_color() const { - return fog_sun_color; +Environment::VolumetricFogShadowFilter Environment::get_volumetric_fog_shadow_filter() const { + return volumetric_fog_shadow_filter; } -void Environment::set_fog_sun_amount(float p_amount) { +// Adjustment - fog_sun_amount = p_amount; - VS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); +void Environment::set_adjustment_enabled(bool p_enabled) { + adjustment_enabled = p_enabled; + _update_adjustment(); + _change_notify(); } -float Environment::get_fog_sun_amount() const { - return fog_sun_amount; +bool Environment::is_adjustment_enabled() const { + return adjustment_enabled; } -void Environment::set_fog_depth_enabled(bool p_enabled) { - - fog_depth_enabled = p_enabled; - VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); +void Environment::set_adjustment_brightness(float p_brightness) { + adjustment_brightness = p_brightness; + _update_adjustment(); } -bool Environment::is_fog_depth_enabled() const { - return fog_depth_enabled; +float Environment::get_adjustment_brightness() const { + return adjustment_brightness; } -void Environment::set_fog_depth_begin(float p_distance) { - - fog_depth_begin = p_distance; - VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); +void Environment::set_adjustment_contrast(float p_contrast) { + adjustment_contrast = p_contrast; + _update_adjustment(); } -float Environment::get_fog_depth_begin() const { - return fog_depth_begin; +float Environment::get_adjustment_contrast() const { + return adjustment_contrast; } -void Environment::set_fog_depth_end(float p_distance) { - - fog_depth_end = p_distance; - VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); +void Environment::set_adjustment_saturation(float p_saturation) { + adjustment_saturation = p_saturation; + _update_adjustment(); } -float Environment::get_fog_depth_end() const { - - return fog_depth_end; +float Environment::get_adjustment_saturation() const { + return adjustment_saturation; } -void Environment::set_fog_depth_curve(float p_curve) { +void Environment::set_adjustment_color_correction(const Ref<Texture2D> &p_ramp) { + adjustment_color_correction = p_ramp; + _update_adjustment(); +} - fog_depth_curve = p_curve; - VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); +Ref<Texture2D> Environment::get_adjustment_color_correction() const { + return adjustment_color_correction; } -float Environment::get_fog_depth_curve() const { - return fog_depth_curve; +void Environment::_update_adjustment() { + RS::get_singleton()->environment_set_adjustment( + environment, + adjustment_enabled, + adjustment_brightness, + adjustment_contrast, + adjustment_saturation, + adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); } -void Environment::set_fog_transmit_enabled(bool p_enabled) { +// Private methods, constructor and destructor - fog_transmit_enabled = p_enabled; - VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); -} -bool Environment::is_fog_transmit_enabled() const { +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") { + if (bg_mode != BG_SKY && ambient_source != AMBIENT_SOURCE_SKY && reflection_source != REFLECTION_SOURCE_SKY) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + } + } - return fog_transmit_enabled; -} + if (property.name == "glow_intensity" && glow_blend_mode == GLOW_BLEND_MODE_MIX) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + } -void Environment::set_fog_transmit_curve(float p_curve) { + if (property.name == "glow_mix" && glow_blend_mode != GLOW_BLEND_MODE_MIX) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + } - fog_transmit_curve = p_curve; - VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); -} -float Environment::get_fog_transmit_curve() const { + if (property.name == "background_color") { + if (bg_mode != BG_COLOR && ambient_source != AMBIENT_SOURCE_COLOR) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + } + } - return fog_transmit_curve; -} + if (property.name == "background_canvas_max_layer") { + if (bg_mode != BG_CANVAS) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + } + } -void Environment::set_fog_height_enabled(bool p_enabled) { + if (property.name == "background_camera_feed_id") { + if (bg_mode != BG_CAMERA_FEED) { + property.usage = PROPERTY_USAGE_NOEDITOR; + } + } - fog_height_enabled = p_enabled; - VS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); -} -bool Environment::is_fog_height_enabled() const { + static const char *hide_prefixes[] = { + "fog_", + "volumetric_fog_", + "auto_exposure_", + "ss_reflections_", + "ssao_", + "glow_", + "adjustment_", + nullptr - return fog_height_enabled; -} + }; -void Environment::set_fog_height_min(float p_distance) { + static const char *high_end_prefixes[] = { + "auto_exposure_", + "tonemap_", + "ss_reflections_", + "ssao_", + nullptr - fog_height_min = p_distance; - VS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); -} -float Environment::get_fog_height_min() const { + }; - return fog_height_min; -} + const char **prefixes = hide_prefixes; + while (*prefixes) { + String prefix = String(*prefixes); -void Environment::set_fog_height_max(float p_distance) { + String enabled = prefix + "enabled"; + if (property.name.begins_with(prefix) && property.name != enabled && !bool(get(enabled))) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + return; + } - fog_height_max = p_distance; - VS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); -} -float Environment::get_fog_height_max() const { + prefixes++; + } - return fog_height_max; -} + if (RenderingServer::get_singleton()->is_low_end()) { + prefixes = high_end_prefixes; + while (*prefixes) { + String prefix = String(*prefixes); -void Environment::set_fog_height_curve(float p_distance) { + if (property.name.begins_with(prefix)) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + return; + } - fog_height_curve = p_distance; - VS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); + prefixes++; + } + } } -float Environment::get_fog_height_curve() const { - return fog_height_curve; +#ifndef DISABLE_DEPRECATED +// Kept for compatibility from 3.x to 4.0. +bool Environment::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "background_sky") { + set_sky(p_value); + return true; + } else if (p_name == "background_sky_custom_fov") { + set_sky_custom_fov(p_value); + return true; + } else if (p_name == "background_sky_orientation") { + Vector3 euler = p_value.operator Basis().get_euler(); + set_sky_rotation(euler); + return true; + } else { + return false; + } } +#endif void Environment::_bind_methods() { + // Background ClassDB::bind_method(D_METHOD("set_background", "mode"), &Environment::set_background); - ClassDB::bind_method(D_METHOD("set_sky", "sky"), &Environment::set_sky); - ClassDB::bind_method(D_METHOD("set_sky_custom_fov", "scale"), &Environment::set_sky_custom_fov); - ClassDB::bind_method(D_METHOD("set_sky_orientation", "orientation"), &Environment::set_sky_orientation); - ClassDB::bind_method(D_METHOD("set_sky_rotation", "euler_radians"), &Environment::set_sky_rotation); - ClassDB::bind_method(D_METHOD("set_sky_rotation_degrees", "euler_degrees"), &Environment::set_sky_rotation_degrees); - ClassDB::bind_method(D_METHOD("set_bg_color", "color"), &Environment::set_bg_color); - ClassDB::bind_method(D_METHOD("set_bg_energy", "energy"), &Environment::set_bg_energy); - ClassDB::bind_method(D_METHOD("set_canvas_max_layer", "layer"), &Environment::set_canvas_max_layer); - ClassDB::bind_method(D_METHOD("set_ambient_light_color", "color"), &Environment::set_ambient_light_color); - ClassDB::bind_method(D_METHOD("set_ambient_light_energy", "energy"), &Environment::set_ambient_light_energy); - ClassDB::bind_method(D_METHOD("set_ambient_light_sky_contribution", "energy"), &Environment::set_ambient_light_sky_contribution); - ClassDB::bind_method(D_METHOD("set_camera_feed_id", "camera_feed_id"), &Environment::set_camera_feed_id); - ClassDB::bind_method(D_METHOD("get_background"), &Environment::get_background); + ClassDB::bind_method(D_METHOD("set_sky", "sky"), &Environment::set_sky); ClassDB::bind_method(D_METHOD("get_sky"), &Environment::get_sky); + ClassDB::bind_method(D_METHOD("set_sky_custom_fov", "scale"), &Environment::set_sky_custom_fov); ClassDB::bind_method(D_METHOD("get_sky_custom_fov"), &Environment::get_sky_custom_fov); - ClassDB::bind_method(D_METHOD("get_sky_orientation"), &Environment::get_sky_orientation); + ClassDB::bind_method(D_METHOD("set_sky_rotation", "euler_radians"), &Environment::set_sky_rotation); ClassDB::bind_method(D_METHOD("get_sky_rotation"), &Environment::get_sky_rotation); - ClassDB::bind_method(D_METHOD("get_sky_rotation_degrees"), &Environment::get_sky_rotation_degrees); + ClassDB::bind_method(D_METHOD("set_bg_color", "color"), &Environment::set_bg_color); ClassDB::bind_method(D_METHOD("get_bg_color"), &Environment::get_bg_color); + ClassDB::bind_method(D_METHOD("set_bg_energy", "energy"), &Environment::set_bg_energy); ClassDB::bind_method(D_METHOD("get_bg_energy"), &Environment::get_bg_energy); + ClassDB::bind_method(D_METHOD("set_canvas_max_layer", "layer"), &Environment::set_canvas_max_layer); ClassDB::bind_method(D_METHOD("get_canvas_max_layer"), &Environment::get_canvas_max_layer); - ClassDB::bind_method(D_METHOD("get_ambient_light_color"), &Environment::get_ambient_light_color); - ClassDB::bind_method(D_METHOD("get_ambient_light_energy"), &Environment::get_ambient_light_energy); - ClassDB::bind_method(D_METHOD("get_ambient_light_sky_contribution"), &Environment::get_ambient_light_sky_contribution); + ClassDB::bind_method(D_METHOD("set_camera_feed_id", "id"), &Environment::set_camera_feed_id); ClassDB::bind_method(D_METHOD("get_camera_feed_id"), &Environment::get_camera_feed_id); ADD_GROUP("Background", "background_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "background_mode", PROPERTY_HINT_ENUM, "Clear Color,Custom Color,Sky,Color+Sky,Canvas,Keep,Camera Feed"), "set_background", "get_background"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "background_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_sky", "get_sky"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "background_sky_custom_fov", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_sky_custom_fov", "get_sky_custom_fov"); - ADD_PROPERTY(PropertyInfo(Variant::BASIS, "background_sky_orientation"), "set_sky_orientation", "get_sky_orientation"); - // Only display rotation in degrees in the inspector (like in Spatial). - // This avoids displaying the same information twice. - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "background_sky_rotation", PROPERTY_HINT_NONE, "", 0), "set_sky_rotation", "get_sky_rotation"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "background_sky_rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_sky_rotation_degrees", "get_sky_rotation_degrees"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "background_mode", PROPERTY_HINT_ENUM, "Clear Color,Custom Color,Sky,Canvas,Keep,Camera Feed"), "set_background", "get_background"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "background_color"), "set_bg_color", "get_bg_color"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "background_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_bg_energy", "get_bg_energy"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "background_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_bg_energy", "get_bg_energy"); ADD_PROPERTY(PropertyInfo(Variant::INT, "background_canvas_max_layer", PROPERTY_HINT_RANGE, "-1000,1000,1"), "set_canvas_max_layer", "get_canvas_max_layer"); ADD_PROPERTY(PropertyInfo(Variant::INT, "background_camera_feed_id", PROPERTY_HINT_RANGE, "1,10,1"), "set_camera_feed_id", "get_camera_feed_id"); - ADD_GROUP("Ambient Light", "ambient_light_"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ambient_light_color"), "set_ambient_light_color", "get_ambient_light_color"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ambient_light_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_ambient_light_energy", "get_ambient_light_energy"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ambient_light_sky_contribution", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ambient_light_sky_contribution", "get_ambient_light_sky_contribution"); - - ClassDB::bind_method(D_METHOD("set_fog_enabled", "enabled"), &Environment::set_fog_enabled); - ClassDB::bind_method(D_METHOD("is_fog_enabled"), &Environment::is_fog_enabled); - - ClassDB::bind_method(D_METHOD("set_fog_color", "color"), &Environment::set_fog_color); - ClassDB::bind_method(D_METHOD("get_fog_color"), &Environment::get_fog_color); - - ClassDB::bind_method(D_METHOD("set_fog_sun_color", "color"), &Environment::set_fog_sun_color); - ClassDB::bind_method(D_METHOD("get_fog_sun_color"), &Environment::get_fog_sun_color); - - ClassDB::bind_method(D_METHOD("set_fog_sun_amount", "amount"), &Environment::set_fog_sun_amount); - ClassDB::bind_method(D_METHOD("get_fog_sun_amount"), &Environment::get_fog_sun_amount); - - ClassDB::bind_method(D_METHOD("set_fog_depth_enabled", "enabled"), &Environment::set_fog_depth_enabled); - ClassDB::bind_method(D_METHOD("is_fog_depth_enabled"), &Environment::is_fog_depth_enabled); - ClassDB::bind_method(D_METHOD("set_fog_depth_begin", "distance"), &Environment::set_fog_depth_begin); - ClassDB::bind_method(D_METHOD("get_fog_depth_begin"), &Environment::get_fog_depth_begin); + ADD_GROUP("Sky", "sky_"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_sky", "get_sky"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_custom_fov", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_sky_custom_fov", "get_sky_custom_fov"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "sky_rotation"), "set_sky_rotation", "get_sky_rotation"); - ClassDB::bind_method(D_METHOD("set_fog_depth_end", "distance"), &Environment::set_fog_depth_end); - ClassDB::bind_method(D_METHOD("get_fog_depth_end"), &Environment::get_fog_depth_end); + // Ambient light - ClassDB::bind_method(D_METHOD("set_fog_depth_curve", "curve"), &Environment::set_fog_depth_curve); - ClassDB::bind_method(D_METHOD("get_fog_depth_curve"), &Environment::get_fog_depth_curve); - - ClassDB::bind_method(D_METHOD("set_fog_transmit_enabled", "enabled"), &Environment::set_fog_transmit_enabled); - ClassDB::bind_method(D_METHOD("is_fog_transmit_enabled"), &Environment::is_fog_transmit_enabled); - - ClassDB::bind_method(D_METHOD("set_fog_transmit_curve", "curve"), &Environment::set_fog_transmit_curve); - ClassDB::bind_method(D_METHOD("get_fog_transmit_curve"), &Environment::get_fog_transmit_curve); - - ClassDB::bind_method(D_METHOD("set_fog_height_enabled", "enabled"), &Environment::set_fog_height_enabled); - ClassDB::bind_method(D_METHOD("is_fog_height_enabled"), &Environment::is_fog_height_enabled); - - ClassDB::bind_method(D_METHOD("set_fog_height_min", "height"), &Environment::set_fog_height_min); - ClassDB::bind_method(D_METHOD("get_fog_height_min"), &Environment::get_fog_height_min); + ClassDB::bind_method(D_METHOD("set_ambient_light_color", "color"), &Environment::set_ambient_light_color); + ClassDB::bind_method(D_METHOD("get_ambient_light_color"), &Environment::get_ambient_light_color); + ClassDB::bind_method(D_METHOD("set_ambient_source", "source"), &Environment::set_ambient_source); + ClassDB::bind_method(D_METHOD("get_ambient_source"), &Environment::get_ambient_source); + ClassDB::bind_method(D_METHOD("set_ambient_light_energy", "energy"), &Environment::set_ambient_light_energy); + ClassDB::bind_method(D_METHOD("get_ambient_light_energy"), &Environment::get_ambient_light_energy); + ClassDB::bind_method(D_METHOD("set_ambient_light_sky_contribution", "ratio"), &Environment::set_ambient_light_sky_contribution); + ClassDB::bind_method(D_METHOD("get_ambient_light_sky_contribution"), &Environment::get_ambient_light_sky_contribution); + ClassDB::bind_method(D_METHOD("set_reflection_source", "source"), &Environment::set_reflection_source); + ClassDB::bind_method(D_METHOD("get_reflection_source"), &Environment::get_reflection_source); + ClassDB::bind_method(D_METHOD("set_ao_color", "color"), &Environment::set_ao_color); + ClassDB::bind_method(D_METHOD("get_ao_color"), &Environment::get_ao_color); - ClassDB::bind_method(D_METHOD("set_fog_height_max", "height"), &Environment::set_fog_height_max); - ClassDB::bind_method(D_METHOD("get_fog_height_max"), &Environment::get_fog_height_max); + ADD_GROUP("Ambient Light", "ambient_light_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "ambient_light_source", PROPERTY_HINT_ENUM, "Background,Disabled,Color,Sky"), "set_ambient_source", "get_ambient_source"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ambient_light_color"), "set_ambient_light_color", "get_ambient_light_color"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ambient_light_sky_contribution", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ambient_light_sky_contribution", "get_ambient_light_sky_contribution"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ambient_light_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_ambient_light_energy", "get_ambient_light_energy"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ambient_light_occlusion_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ao_color", "get_ao_color"); - ClassDB::bind_method(D_METHOD("set_fog_height_curve", "curve"), &Environment::set_fog_height_curve); - ClassDB::bind_method(D_METHOD("get_fog_height_curve"), &Environment::get_fog_height_curve); + ADD_GROUP("Reflected Light", "reflected_light_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "reflected_light_source", PROPERTY_HINT_ENUM, "Background,Disabled,Sky"), "set_reflection_source", "get_reflection_source"); - ADD_GROUP("Fog", "fog_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_enabled"), "set_fog_enabled", "is_fog_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "fog_color"), "set_fog_color", "get_fog_color"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "fog_sun_color"), "set_fog_sun_color", "get_fog_sun_color"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_sun_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_fog_sun_amount", "get_fog_sun_amount"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_depth_enabled"), "set_fog_depth_enabled", "is_fog_depth_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_depth_begin", PROPERTY_HINT_RANGE, "0,4000,0.1"), "set_fog_depth_begin", "get_fog_depth_begin"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_depth_end", PROPERTY_HINT_RANGE, "0,4000,0.1,or_greater"), "set_fog_depth_end", "get_fog_depth_end"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_depth_curve", PROPERTY_HINT_EXP_EASING), "set_fog_depth_curve", "get_fog_depth_curve"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_transmit_enabled"), "set_fog_transmit_enabled", "is_fog_transmit_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_transmit_curve", PROPERTY_HINT_EXP_EASING), "set_fog_transmit_curve", "get_fog_transmit_curve"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_height_enabled"), "set_fog_height_enabled", "is_fog_height_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_height_min", PROPERTY_HINT_RANGE, "-4000,4000,0.1,or_lesser,or_greater"), "set_fog_height_min", "get_fog_height_min"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_height_max", PROPERTY_HINT_RANGE, "-4000,4000,0.1,or_lesser,or_greater"), "set_fog_height_max", "get_fog_height_max"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "fog_height_curve", PROPERTY_HINT_EXP_EASING), "set_fog_height_curve", "get_fog_height_curve"); + // Tonemap ClassDB::bind_method(D_METHOD("set_tonemapper", "mode"), &Environment::set_tonemapper); ClassDB::bind_method(D_METHOD("get_tonemapper"), &Environment::get_tonemapper); - ClassDB::bind_method(D_METHOD("set_tonemap_exposure", "exposure"), &Environment::set_tonemap_exposure); ClassDB::bind_method(D_METHOD("get_tonemap_exposure"), &Environment::get_tonemap_exposure); - ClassDB::bind_method(D_METHOD("set_tonemap_white", "white"), &Environment::set_tonemap_white); ClassDB::bind_method(D_METHOD("get_tonemap_white"), &Environment::get_tonemap_white); - - ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure", "auto_exposure"), &Environment::set_tonemap_auto_exposure); - ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure"), &Environment::get_tonemap_auto_exposure); - + ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_enabled", "enabled"), &Environment::set_tonemap_auto_exposure_enabled); + ClassDB::bind_method(D_METHOD("is_tonemap_auto_exposure_enabled"), &Environment::is_tonemap_auto_exposure_enabled); ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_max", "exposure_max"), &Environment::set_tonemap_auto_exposure_max); ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_max"), &Environment::get_tonemap_auto_exposure_max); - ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_min", "exposure_min"), &Environment::set_tonemap_auto_exposure_min); ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_min"), &Environment::get_tonemap_auto_exposure_min); - ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_speed", "exposure_speed"), &Environment::set_tonemap_auto_exposure_speed); ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_speed"), &Environment::get_tonemap_auto_exposure_speed); - ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_grey", "exposure_grey"), &Environment::set_tonemap_auto_exposure_grey); ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_grey"), &Environment::get_tonemap_auto_exposure_grey); ADD_GROUP("Tonemap", "tonemap_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "tonemap_mode", PROPERTY_HINT_ENUM, "Linear,Reinhard,Filmic,Aces"), "set_tonemapper", "get_tonemapper"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "tonemap_exposure", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_exposure", "get_tonemap_exposure"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "tonemap_white", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_white", "get_tonemap_white"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "tonemap_mode", PROPERTY_HINT_ENUM, "Linear,Reinhard,Filmic,ACES"), "set_tonemapper", "get_tonemapper"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_exposure", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_exposure", "get_tonemap_exposure"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_white", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_white", "get_tonemap_white"); ADD_GROUP("Auto Exposure", "auto_exposure_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_exposure_enabled"), "set_tonemap_auto_exposure", "get_tonemap_auto_exposure"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "auto_exposure_scale", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_tonemap_auto_exposure_grey", "get_tonemap_auto_exposure_grey"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "auto_exposure_min_luma", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_auto_exposure_min", "get_tonemap_auto_exposure_min"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "auto_exposure_max_luma", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_auto_exposure_max", "get_tonemap_auto_exposure_max"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "auto_exposure_speed", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_tonemap_auto_exposure_speed", "get_tonemap_auto_exposure_speed"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_exposure_enabled"), "set_tonemap_auto_exposure_enabled", "is_tonemap_auto_exposure_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_scale", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_tonemap_auto_exposure_grey", "get_tonemap_auto_exposure_grey"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_min_luma", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_auto_exposure_min", "get_tonemap_auto_exposure_min"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_max_luma", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_auto_exposure_max", "get_tonemap_auto_exposure_max"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_speed", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_tonemap_auto_exposure_speed", "get_tonemap_auto_exposure_speed"); + + // SSR ClassDB::bind_method(D_METHOD("set_ssr_enabled", "enabled"), &Environment::set_ssr_enabled); ClassDB::bind_method(D_METHOD("is_ssr_enabled"), &Environment::is_ssr_enabled); - ClassDB::bind_method(D_METHOD("set_ssr_max_steps", "max_steps"), &Environment::set_ssr_max_steps); ClassDB::bind_method(D_METHOD("get_ssr_max_steps"), &Environment::get_ssr_max_steps); - ClassDB::bind_method(D_METHOD("set_ssr_fade_in", "fade_in"), &Environment::set_ssr_fade_in); ClassDB::bind_method(D_METHOD("get_ssr_fade_in"), &Environment::get_ssr_fade_in); - ClassDB::bind_method(D_METHOD("set_ssr_fade_out", "fade_out"), &Environment::set_ssr_fade_out); ClassDB::bind_method(D_METHOD("get_ssr_fade_out"), &Environment::get_ssr_fade_out); - ClassDB::bind_method(D_METHOD("set_ssr_depth_tolerance", "depth_tolerance"), &Environment::set_ssr_depth_tolerance); ClassDB::bind_method(D_METHOD("get_ssr_depth_tolerance"), &Environment::get_ssr_depth_tolerance); - ClassDB::bind_method(D_METHOD("set_ssr_rough", "rough"), &Environment::set_ssr_rough); - ClassDB::bind_method(D_METHOD("is_ssr_rough"), &Environment::is_ssr_rough); - ADD_GROUP("SS Reflections", "ss_reflections_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ss_reflections_enabled"), "set_ssr_enabled", "is_ssr_enabled"); ADD_PROPERTY(PropertyInfo(Variant::INT, "ss_reflections_max_steps", PROPERTY_HINT_RANGE, "1,512,1"), "set_ssr_max_steps", "get_ssr_max_steps"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ss_reflections_fade_in", PROPERTY_HINT_EXP_EASING), "set_ssr_fade_in", "get_ssr_fade_in"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ss_reflections_fade_out", PROPERTY_HINT_EXP_EASING), "set_ssr_fade_out", "get_ssr_fade_out"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ss_reflections_depth_tolerance", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_ssr_depth_tolerance", "get_ssr_depth_tolerance"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ss_reflections_roughness"), "set_ssr_rough", "is_ssr_rough"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ss_reflections_fade_in", PROPERTY_HINT_EXP_EASING), "set_ssr_fade_in", "get_ssr_fade_in"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ss_reflections_fade_out", PROPERTY_HINT_EXP_EASING), "set_ssr_fade_out", "get_ssr_fade_out"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ss_reflections_depth_tolerance", PROPERTY_HINT_RANGE, "0.01,128,0.1"), "set_ssr_depth_tolerance", "get_ssr_depth_tolerance"); + + // SSAO ClassDB::bind_method(D_METHOD("set_ssao_enabled", "enabled"), &Environment::set_ssao_enabled); ClassDB::bind_method(D_METHOD("is_ssao_enabled"), &Environment::is_ssao_enabled); - ClassDB::bind_method(D_METHOD("set_ssao_radius", "radius"), &Environment::set_ssao_radius); ClassDB::bind_method(D_METHOD("get_ssao_radius"), &Environment::get_ssao_radius); - ClassDB::bind_method(D_METHOD("set_ssao_intensity", "intensity"), &Environment::set_ssao_intensity); ClassDB::bind_method(D_METHOD("get_ssao_intensity"), &Environment::get_ssao_intensity); - - ClassDB::bind_method(D_METHOD("set_ssao_radius2", "radius"), &Environment::set_ssao_radius2); - ClassDB::bind_method(D_METHOD("get_ssao_radius2"), &Environment::get_ssao_radius2); - - ClassDB::bind_method(D_METHOD("set_ssao_intensity2", "intensity"), &Environment::set_ssao_intensity2); - ClassDB::bind_method(D_METHOD("get_ssao_intensity2"), &Environment::get_ssao_intensity2); - ClassDB::bind_method(D_METHOD("set_ssao_bias", "bias"), &Environment::set_ssao_bias); ClassDB::bind_method(D_METHOD("get_ssao_bias"), &Environment::get_ssao_bias); - ClassDB::bind_method(D_METHOD("set_ssao_direct_light_affect", "amount"), &Environment::set_ssao_direct_light_affect); ClassDB::bind_method(D_METHOD("get_ssao_direct_light_affect"), &Environment::get_ssao_direct_light_affect); - ClassDB::bind_method(D_METHOD("set_ssao_ao_channel_affect", "amount"), &Environment::set_ssao_ao_channel_affect); ClassDB::bind_method(D_METHOD("get_ssao_ao_channel_affect"), &Environment::get_ssao_ao_channel_affect); - - ClassDB::bind_method(D_METHOD("set_ssao_color", "color"), &Environment::set_ssao_color); - ClassDB::bind_method(D_METHOD("get_ssao_color"), &Environment::get_ssao_color); - ClassDB::bind_method(D_METHOD("set_ssao_blur", "mode"), &Environment::set_ssao_blur); ClassDB::bind_method(D_METHOD("get_ssao_blur"), &Environment::get_ssao_blur); - - ClassDB::bind_method(D_METHOD("set_ssao_quality", "quality"), &Environment::set_ssao_quality); - ClassDB::bind_method(D_METHOD("get_ssao_quality"), &Environment::get_ssao_quality); - ClassDB::bind_method(D_METHOD("set_ssao_edge_sharpness", "edge_sharpness"), &Environment::set_ssao_edge_sharpness); ClassDB::bind_method(D_METHOD("get_ssao_edge_sharpness"), &Environment::get_ssao_edge_sharpness); ADD_GROUP("SSAO", "ssao_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ssao_enabled"), "set_ssao_enabled", "is_ssao_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_radius", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_ssao_radius", "get_ssao_radius"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_intensity", PROPERTY_HINT_RANGE, "0.0,128,0.1"), "set_ssao_intensity", "get_ssao_intensity"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_radius2", PROPERTY_HINT_RANGE, "0.0,128,0.1"), "set_ssao_radius2", "get_ssao_radius2"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_intensity2", PROPERTY_HINT_RANGE, "0.0,128,0.1"), "set_ssao_intensity2", "get_ssao_intensity2"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_bias", PROPERTY_HINT_RANGE, "0.001,8,0.001"), "set_ssao_bias", "get_ssao_bias"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_light_affect", PROPERTY_HINT_RANGE, "0.00,1,0.01"), "set_ssao_direct_light_affect", "get_ssao_direct_light_affect"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_ao_channel_affect", PROPERTY_HINT_RANGE, "0.00,1,0.01"), "set_ssao_ao_channel_affect", "get_ssao_ao_channel_affect"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ssao_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ssao_color", "get_ssao_color"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "ssao_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), "set_ssao_quality", "get_ssao_quality"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_radius", PROPERTY_HINT_RANGE, "0.1,128,0.01"), "set_ssao_radius", "get_ssao_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_intensity", PROPERTY_HINT_RANGE, "0.0,128,0.01"), "set_ssao_intensity", "get_ssao_intensity"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_bias", PROPERTY_HINT_RANGE, "0.001,8,0.001"), "set_ssao_bias", "get_ssao_bias"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_light_affect", PROPERTY_HINT_RANGE, "0.00,1,0.01"), "set_ssao_direct_light_affect", "get_ssao_direct_light_affect"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_ao_channel_affect", PROPERTY_HINT_RANGE, "0.00,1,0.01"), "set_ssao_ao_channel_affect", "get_ssao_ao_channel_affect"); ADD_PROPERTY(PropertyInfo(Variant::INT, "ssao_blur", PROPERTY_HINT_ENUM, "Disabled,1x1,2x2,3x3"), "set_ssao_blur", "get_ssao_blur"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ssao_edge_sharpness", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_ssao_edge_sharpness", "get_ssao_edge_sharpness"); - - ClassDB::bind_method(D_METHOD("set_dof_blur_far_enabled", "enabled"), &Environment::set_dof_blur_far_enabled); - ClassDB::bind_method(D_METHOD("is_dof_blur_far_enabled"), &Environment::is_dof_blur_far_enabled); - - ClassDB::bind_method(D_METHOD("set_dof_blur_far_distance", "intensity"), &Environment::set_dof_blur_far_distance); - ClassDB::bind_method(D_METHOD("get_dof_blur_far_distance"), &Environment::get_dof_blur_far_distance); - - ClassDB::bind_method(D_METHOD("set_dof_blur_far_transition", "intensity"), &Environment::set_dof_blur_far_transition); - ClassDB::bind_method(D_METHOD("get_dof_blur_far_transition"), &Environment::get_dof_blur_far_transition); - - ClassDB::bind_method(D_METHOD("set_dof_blur_far_amount", "intensity"), &Environment::set_dof_blur_far_amount); - ClassDB::bind_method(D_METHOD("get_dof_blur_far_amount"), &Environment::get_dof_blur_far_amount); - - ClassDB::bind_method(D_METHOD("set_dof_blur_far_quality", "intensity"), &Environment::set_dof_blur_far_quality); - ClassDB::bind_method(D_METHOD("get_dof_blur_far_quality"), &Environment::get_dof_blur_far_quality); - - ClassDB::bind_method(D_METHOD("set_dof_blur_near_enabled", "enabled"), &Environment::set_dof_blur_near_enabled); - ClassDB::bind_method(D_METHOD("is_dof_blur_near_enabled"), &Environment::is_dof_blur_near_enabled); - - ClassDB::bind_method(D_METHOD("set_dof_blur_near_distance", "intensity"), &Environment::set_dof_blur_near_distance); - ClassDB::bind_method(D_METHOD("get_dof_blur_near_distance"), &Environment::get_dof_blur_near_distance); - - ClassDB::bind_method(D_METHOD("set_dof_blur_near_transition", "intensity"), &Environment::set_dof_blur_near_transition); - ClassDB::bind_method(D_METHOD("get_dof_blur_near_transition"), &Environment::get_dof_blur_near_transition); - - ClassDB::bind_method(D_METHOD("set_dof_blur_near_amount", "intensity"), &Environment::set_dof_blur_near_amount); - ClassDB::bind_method(D_METHOD("get_dof_blur_near_amount"), &Environment::get_dof_blur_near_amount); - - ClassDB::bind_method(D_METHOD("set_dof_blur_near_quality", "level"), &Environment::set_dof_blur_near_quality); - ClassDB::bind_method(D_METHOD("get_dof_blur_near_quality"), &Environment::get_dof_blur_near_quality); - - ADD_GROUP("DOF Far Blur", "dof_blur_far_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_far_enabled"), "set_dof_blur_far_enabled", "is_dof_blur_far_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "dof_blur_far_distance", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_far_distance", "get_dof_blur_far_distance"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "dof_blur_far_transition", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_far_transition", "get_dof_blur_far_transition"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "dof_blur_far_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dof_blur_far_amount", "get_dof_blur_far_amount"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "dof_blur_far_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), "set_dof_blur_far_quality", "get_dof_blur_far_quality"); - - ADD_GROUP("DOF Near Blur", "dof_blur_near_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_near_enabled"), "set_dof_blur_near_enabled", "is_dof_blur_near_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "dof_blur_near_distance", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_near_distance", "get_dof_blur_near_distance"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "dof_blur_near_transition", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_near_transition", "get_dof_blur_near_transition"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "dof_blur_near_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dof_blur_near_amount", "get_dof_blur_near_amount"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "dof_blur_near_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), "set_dof_blur_near_quality", "get_dof_blur_near_quality"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_edge_sharpness", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_ssao_edge_sharpness", "get_ssao_edge_sharpness"); + + // SDFGI + + ClassDB::bind_method(D_METHOD("set_sdfgi_enabled", "enabled"), &Environment::set_sdfgi_enabled); + ClassDB::bind_method(D_METHOD("is_sdfgi_enabled"), &Environment::is_sdfgi_enabled); + ClassDB::bind_method(D_METHOD("set_sdfgi_cascades", "amount"), &Environment::set_sdfgi_cascades); + ClassDB::bind_method(D_METHOD("get_sdfgi_cascades"), &Environment::get_sdfgi_cascades); + ClassDB::bind_method(D_METHOD("set_sdfgi_min_cell_size", "size"), &Environment::set_sdfgi_min_cell_size); + ClassDB::bind_method(D_METHOD("get_sdfgi_min_cell_size"), &Environment::get_sdfgi_min_cell_size); + ClassDB::bind_method(D_METHOD("set_sdfgi_max_distance", "distance"), &Environment::set_sdfgi_max_distance); + ClassDB::bind_method(D_METHOD("get_sdfgi_max_distance"), &Environment::get_sdfgi_max_distance); + ClassDB::bind_method(D_METHOD("set_sdfgi_cascade0_distance", "distance"), &Environment::set_sdfgi_cascade0_distance); + ClassDB::bind_method(D_METHOD("get_sdfgi_cascade0_distance"), &Environment::get_sdfgi_cascade0_distance); + ClassDB::bind_method(D_METHOD("set_sdfgi_y_scale", "scale"), &Environment::set_sdfgi_y_scale); + ClassDB::bind_method(D_METHOD("get_sdfgi_y_scale"), &Environment::get_sdfgi_y_scale); + ClassDB::bind_method(D_METHOD("set_sdfgi_use_occlusion", "enable"), &Environment::set_sdfgi_use_occlusion); + ClassDB::bind_method(D_METHOD("is_sdfgi_using_occlusion"), &Environment::is_sdfgi_using_occlusion); + ClassDB::bind_method(D_METHOD("set_sdfgi_use_multi_bounce", "enable"), &Environment::set_sdfgi_use_multi_bounce); + ClassDB::bind_method(D_METHOD("is_sdfgi_using_multi_bounce"), &Environment::is_sdfgi_using_multi_bounce); + ClassDB::bind_method(D_METHOD("set_sdfgi_read_sky_light", "enable"), &Environment::set_sdfgi_read_sky_light); + ClassDB::bind_method(D_METHOD("is_sdfgi_reading_sky_light"), &Environment::is_sdfgi_reading_sky_light); + ClassDB::bind_method(D_METHOD("set_sdfgi_energy", "amount"), &Environment::set_sdfgi_energy); + ClassDB::bind_method(D_METHOD("get_sdfgi_energy"), &Environment::get_sdfgi_energy); + ClassDB::bind_method(D_METHOD("set_sdfgi_normal_bias", "bias"), &Environment::set_sdfgi_normal_bias); + ClassDB::bind_method(D_METHOD("get_sdfgi_normal_bias"), &Environment::get_sdfgi_normal_bias); + ClassDB::bind_method(D_METHOD("set_sdfgi_probe_bias", "bias"), &Environment::set_sdfgi_probe_bias); + ClassDB::bind_method(D_METHOD("get_sdfgi_probe_bias"), &Environment::get_sdfgi_probe_bias); + + ADD_GROUP("SDFGI", "sdfgi_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_enabled"), "set_sdfgi_enabled", "is_sdfgi_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_use_multi_bounce"), "set_sdfgi_use_multi_bounce", "is_sdfgi_using_multi_bounce"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_use_occlusion"), "set_sdfgi_use_occlusion", "is_sdfgi_using_occlusion"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_read_sky_light"), "set_sdfgi_read_sky_light", "is_sdfgi_reading_sky_light"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "sdfgi_cascades", PROPERTY_HINT_ENUM, "4 Cascades,6 Cascades,8 Cascades"), "set_sdfgi_cascades", "get_sdfgi_cascades"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_min_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_sdfgi_min_cell_size", "get_sdfgi_min_cell_size"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_cascade0_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater"), "set_sdfgi_cascade0_distance", "get_sdfgi_cascade0_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_max_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater"), "set_sdfgi_max_distance", "get_sdfgi_max_distance"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "sdfgi_y_scale", PROPERTY_HINT_ENUM, "Disable,75%,50%"), "set_sdfgi_y_scale", "get_sdfgi_y_scale"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_energy"), "set_sdfgi_energy", "get_sdfgi_energy"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_normal_bias"), "set_sdfgi_normal_bias", "get_sdfgi_normal_bias"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_probe_bias"), "set_sdfgi_probe_bias", "get_sdfgi_probe_bias"); + + // Glow ClassDB::bind_method(D_METHOD("set_glow_enabled", "enabled"), &Environment::set_glow_enabled); ClassDB::bind_method(D_METHOD("is_glow_enabled"), &Environment::is_glow_enabled); - - ClassDB::bind_method(D_METHOD("set_glow_level", "idx", "enabled"), &Environment::set_glow_level); + ClassDB::bind_method(D_METHOD("set_glow_level_enabled", "idx", "enabled"), &Environment::set_glow_level_enabled); ClassDB::bind_method(D_METHOD("is_glow_level_enabled", "idx"), &Environment::is_glow_level_enabled); - ClassDB::bind_method(D_METHOD("set_glow_intensity", "intensity"), &Environment::set_glow_intensity); ClassDB::bind_method(D_METHOD("get_glow_intensity"), &Environment::get_glow_intensity); - ClassDB::bind_method(D_METHOD("set_glow_strength", "strength"), &Environment::set_glow_strength); ClassDB::bind_method(D_METHOD("get_glow_strength"), &Environment::get_glow_strength); - + ClassDB::bind_method(D_METHOD("set_glow_mix", "mix"), &Environment::set_glow_mix); + ClassDB::bind_method(D_METHOD("get_glow_mix"), &Environment::get_glow_mix); ClassDB::bind_method(D_METHOD("set_glow_bloom", "amount"), &Environment::set_glow_bloom); ClassDB::bind_method(D_METHOD("get_glow_bloom"), &Environment::get_glow_bloom); - ClassDB::bind_method(D_METHOD("set_glow_blend_mode", "mode"), &Environment::set_glow_blend_mode); ClassDB::bind_method(D_METHOD("get_glow_blend_mode"), &Environment::get_glow_blend_mode); - ClassDB::bind_method(D_METHOD("set_glow_hdr_bleed_threshold", "threshold"), &Environment::set_glow_hdr_bleed_threshold); ClassDB::bind_method(D_METHOD("get_glow_hdr_bleed_threshold"), &Environment::get_glow_hdr_bleed_threshold); - - ClassDB::bind_method(D_METHOD("set_glow_hdr_luminance_cap", "amount"), &Environment::set_glow_hdr_luminance_cap); - ClassDB::bind_method(D_METHOD("get_glow_hdr_luminance_cap"), &Environment::get_glow_hdr_luminance_cap); - ClassDB::bind_method(D_METHOD("set_glow_hdr_bleed_scale", "scale"), &Environment::set_glow_hdr_bleed_scale); ClassDB::bind_method(D_METHOD("get_glow_hdr_bleed_scale"), &Environment::get_glow_hdr_bleed_scale); - - ClassDB::bind_method(D_METHOD("set_glow_bicubic_upscale", "enabled"), &Environment::set_glow_bicubic_upscale); - ClassDB::bind_method(D_METHOD("is_glow_bicubic_upscale_enabled"), &Environment::is_glow_bicubic_upscale_enabled); + ClassDB::bind_method(D_METHOD("set_glow_hdr_luminance_cap", "amount"), &Environment::set_glow_hdr_luminance_cap); + ClassDB::bind_method(D_METHOD("get_glow_hdr_luminance_cap"), &Environment::get_glow_hdr_luminance_cap); ADD_GROUP("Glow", "glow_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "glow_enabled"), "set_glow_enabled", "is_glow_enabled"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/1"), "set_glow_level", "is_glow_level_enabled", 0); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/2"), "set_glow_level", "is_glow_level_enabled", 1); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/3"), "set_glow_level", "is_glow_level_enabled", 2); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/4"), "set_glow_level", "is_glow_level_enabled", 3); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/5"), "set_glow_level", "is_glow_level_enabled", 4); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/6"), "set_glow_level", "is_glow_level_enabled", 5); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/7"), "set_glow_level", "is_glow_level_enabled", 6); - - ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_intensity", PROPERTY_HINT_RANGE, "0.0,8.0,0.01"), "set_glow_intensity", "get_glow_intensity"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_strength", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_glow_strength", "get_glow_strength"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_bloom", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_glow_bloom", "get_glow_bloom"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "glow_blend_mode", PROPERTY_HINT_ENUM, "Additive,Screen,Softlight,Replace"), "set_glow_blend_mode", "get_glow_blend_mode"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_hdr_threshold", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_threshold", "get_glow_hdr_bleed_threshold"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_hdr_luminance_cap", PROPERTY_HINT_RANGE, "0.0,256.0,0.01"), "set_glow_hdr_luminance_cap", "get_glow_hdr_luminance_cap"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "glow_hdr_scale", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_scale", "get_glow_hdr_bleed_scale"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "glow_bicubic_upscale"), "set_glow_bicubic_upscale", "is_glow_bicubic_upscale_enabled"); - - ClassDB::bind_method(D_METHOD("set_adjustment_enable", "enabled"), &Environment::set_adjustment_enable); - ClassDB::bind_method(D_METHOD("is_adjustment_enabled"), &Environment::is_adjustment_enabled); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/1"), "set_glow_level_enabled", "is_glow_level_enabled", 0); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/2"), "set_glow_level_enabled", "is_glow_level_enabled", 1); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/3"), "set_glow_level_enabled", "is_glow_level_enabled", 2); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/4"), "set_glow_level_enabled", "is_glow_level_enabled", 3); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/5"), "set_glow_level_enabled", "is_glow_level_enabled", 4); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/6"), "set_glow_level_enabled", "is_glow_level_enabled", 5); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/7"), "set_glow_level_enabled", "is_glow_level_enabled", 6); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_intensity", PROPERTY_HINT_RANGE, "0.0,8.0,0.01"), "set_glow_intensity", "get_glow_intensity"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_strength", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_glow_strength", "get_glow_strength"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_mix", PROPERTY_HINT_RANGE, "0.0,1.0,0.001"), "set_glow_mix", "get_glow_mix"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_bloom", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_glow_bloom", "get_glow_bloom"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "glow_blend_mode", PROPERTY_HINT_ENUM, "Additive,Screen,Softlight,Replace,Mix"), "set_glow_blend_mode", "get_glow_blend_mode"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_hdr_threshold", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_threshold", "get_glow_hdr_bleed_threshold"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_hdr_scale", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_scale", "get_glow_hdr_bleed_scale"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_hdr_luminance_cap", PROPERTY_HINT_RANGE, "0.0,256.0,0.01"), "set_glow_hdr_luminance_cap", "get_glow_hdr_luminance_cap"); + + // Fog + + ClassDB::bind_method(D_METHOD("set_fog_enabled", "enabled"), &Environment::set_fog_enabled); + ClassDB::bind_method(D_METHOD("is_fog_enabled"), &Environment::is_fog_enabled); + ClassDB::bind_method(D_METHOD("set_fog_light_color", "light_color"), &Environment::set_fog_light_color); + ClassDB::bind_method(D_METHOD("get_fog_light_color"), &Environment::get_fog_light_color); + ClassDB::bind_method(D_METHOD("set_fog_light_energy", "light_energy"), &Environment::set_fog_light_energy); + ClassDB::bind_method(D_METHOD("get_fog_light_energy"), &Environment::get_fog_light_energy); + ClassDB::bind_method(D_METHOD("set_fog_sun_scatter", "sun_scatter"), &Environment::set_fog_sun_scatter); + ClassDB::bind_method(D_METHOD("get_fog_sun_scatter"), &Environment::get_fog_sun_scatter); + ClassDB::bind_method(D_METHOD("set_fog_density", "density"), &Environment::set_fog_density); + ClassDB::bind_method(D_METHOD("get_fog_density"), &Environment::get_fog_density); + + ClassDB::bind_method(D_METHOD("set_fog_height", "height"), &Environment::set_fog_height); + ClassDB::bind_method(D_METHOD("get_fog_height"), &Environment::get_fog_height); + + ClassDB::bind_method(D_METHOD("set_fog_height_density", "height_density"), &Environment::set_fog_height_density); + ClassDB::bind_method(D_METHOD("get_fog_height_density"), &Environment::get_fog_height_density); + + ADD_GROUP("Fog", "fog_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_enabled"), "set_fog_enabled", "is_fog_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "fog_light_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_fog_light_color", "get_fog_light_color"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_light_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_fog_light_energy", "get_fog_light_energy"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_sun_scatter", PROPERTY_HINT_RANGE, "0,1,0.01,or_greater"), "set_fog_sun_scatter", "get_fog_sun_scatter"); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_density", PROPERTY_HINT_RANGE, "0,16,0.0001"), "set_fog_density", "get_fog_density"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height", PROPERTY_HINT_RANGE, "-1024,1024,0.01,or_lesser,or_greater"), "set_fog_height", "get_fog_height"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height_density", PROPERTY_HINT_RANGE, "0,128,0.001,or_greater"), "set_fog_height_density", "get_fog_height_density"); + + ClassDB::bind_method(D_METHOD("set_volumetric_fog_enabled", "enabled"), &Environment::set_volumetric_fog_enabled); + ClassDB::bind_method(D_METHOD("is_volumetric_fog_enabled"), &Environment::is_volumetric_fog_enabled); + ClassDB::bind_method(D_METHOD("set_volumetric_fog_light", "color"), &Environment::set_volumetric_fog_light); + ClassDB::bind_method(D_METHOD("get_volumetric_fog_light"), &Environment::get_volumetric_fog_light); + ClassDB::bind_method(D_METHOD("set_volumetric_fog_density", "density"), &Environment::set_volumetric_fog_density); + ClassDB::bind_method(D_METHOD("get_volumetric_fog_density"), &Environment::get_volumetric_fog_density); + ClassDB::bind_method(D_METHOD("set_volumetric_fog_light_energy", "begin"), &Environment::set_volumetric_fog_light_energy); + ClassDB::bind_method(D_METHOD("get_volumetric_fog_light_energy"), &Environment::get_volumetric_fog_light_energy); + ClassDB::bind_method(D_METHOD("set_volumetric_fog_length", "length"), &Environment::set_volumetric_fog_length); + ClassDB::bind_method(D_METHOD("get_volumetric_fog_length"), &Environment::get_volumetric_fog_length); + ClassDB::bind_method(D_METHOD("set_volumetric_fog_detail_spread", "detail_spread"), &Environment::set_volumetric_fog_detail_spread); + ClassDB::bind_method(D_METHOD("get_volumetric_fog_detail_spread"), &Environment::get_volumetric_fog_detail_spread); + ClassDB::bind_method(D_METHOD("set_volumetric_fog_gi_inject", "gi_inject"), &Environment::set_volumetric_fog_gi_inject); + ClassDB::bind_method(D_METHOD("get_volumetric_fog_gi_inject"), &Environment::get_volumetric_fog_gi_inject); + ClassDB::bind_method(D_METHOD("set_volumetric_fog_shadow_filter", "shadow_filter"), &Environment::set_volumetric_fog_shadow_filter); + ClassDB::bind_method(D_METHOD("get_volumetric_fog_shadow_filter"), &Environment::get_volumetric_fog_shadow_filter); + + ADD_GROUP("Volumetric Fog", "volumetric_fog_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "volumetric_fog_enabled"), "set_volumetric_fog_enabled", "is_volumetric_fog_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_density", PROPERTY_HINT_RANGE, "0,1,0.0001,or_greater"), "set_volumetric_fog_density", "get_volumetric_fog_density"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "volumetric_fog_light", PROPERTY_HINT_COLOR_NO_ALPHA), "set_volumetric_fog_light", "get_volumetric_fog_light"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_light_energy", PROPERTY_HINT_RANGE, "0,1024,0.01,or_greater"), "set_volumetric_fog_light_energy", "get_volumetric_fog_light_energy"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_gi_inject", PROPERTY_HINT_EXP_RANGE, "0.00,16,0.01"), "set_volumetric_fog_gi_inject", "get_volumetric_fog_gi_inject"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_length", PROPERTY_HINT_RANGE, "0,1024,0.01,or_greater"), "set_volumetric_fog_length", "get_volumetric_fog_length"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_detail_spread", PROPERTY_HINT_EXP_EASING, "0.01,16,0.01"), "set_volumetric_fog_detail_spread", "get_volumetric_fog_detail_spread"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "volumetric_fog_shadow_filter", PROPERTY_HINT_ENUM, "Disabled,Low,Medium,High"), "set_volumetric_fog_shadow_filter", "get_volumetric_fog_shadow_filter"); + + // Adjustment + + ClassDB::bind_method(D_METHOD("set_adjustment_enabled", "enabled"), &Environment::set_adjustment_enabled); + ClassDB::bind_method(D_METHOD("is_adjustment_enabled"), &Environment::is_adjustment_enabled); ClassDB::bind_method(D_METHOD("set_adjustment_brightness", "brightness"), &Environment::set_adjustment_brightness); ClassDB::bind_method(D_METHOD("get_adjustment_brightness"), &Environment::get_adjustment_brightness); - ClassDB::bind_method(D_METHOD("set_adjustment_contrast", "contrast"), &Environment::set_adjustment_contrast); ClassDB::bind_method(D_METHOD("get_adjustment_contrast"), &Environment::get_adjustment_contrast); - ClassDB::bind_method(D_METHOD("set_adjustment_saturation", "saturation"), &Environment::set_adjustment_saturation); ClassDB::bind_method(D_METHOD("get_adjustment_saturation"), &Environment::get_adjustment_saturation); - ClassDB::bind_method(D_METHOD("set_adjustment_color_correction", "color_correction"), &Environment::set_adjustment_color_correction); ClassDB::bind_method(D_METHOD("get_adjustment_color_correction"), &Environment::get_adjustment_color_correction); ADD_GROUP("Adjustments", "adjustment_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "adjustment_enabled"), "set_adjustment_enable", "is_adjustment_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "adjustment_brightness", PROPERTY_HINT_RANGE, "0.01,8,0.01"), "set_adjustment_brightness", "get_adjustment_brightness"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "adjustment_contrast", PROPERTY_HINT_RANGE, "0.01,8,0.01"), "set_adjustment_contrast", "get_adjustment_contrast"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "adjustment_saturation", PROPERTY_HINT_RANGE, "0.01,8,0.01"), "set_adjustment_saturation", "get_adjustment_saturation"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "adjustment_color_correction", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_adjustment_color_correction", "get_adjustment_color_correction"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "adjustment_enabled"), "set_adjustment_enabled", "is_adjustment_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "adjustment_brightness", PROPERTY_HINT_RANGE, "0.01,8,0.01"), "set_adjustment_brightness", "get_adjustment_brightness"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "adjustment_contrast", PROPERTY_HINT_RANGE, "0.01,8,0.01"), "set_adjustment_contrast", "get_adjustment_contrast"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "adjustment_saturation", PROPERTY_HINT_RANGE, "0.01,8,0.01"), "set_adjustment_saturation", "get_adjustment_saturation"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "adjustment_color_correction", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_adjustment_color_correction", "get_adjustment_color_correction"); + + // Constants - BIND_ENUM_CONSTANT(BG_KEEP); BIND_ENUM_CONSTANT(BG_CLEAR_COLOR); BIND_ENUM_CONSTANT(BG_COLOR); BIND_ENUM_CONSTANT(BG_SKY); - BIND_ENUM_CONSTANT(BG_COLOR_SKY); BIND_ENUM_CONSTANT(BG_CANVAS); + BIND_ENUM_CONSTANT(BG_KEEP); BIND_ENUM_CONSTANT(BG_CAMERA_FEED); BIND_ENUM_CONSTANT(BG_MAX); - BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_ADDITIVE); - BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_SCREEN); - BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_SOFTLIGHT); - BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_REPLACE); + BIND_ENUM_CONSTANT(AMBIENT_SOURCE_BG); + BIND_ENUM_CONSTANT(AMBIENT_SOURCE_DISABLED); + BIND_ENUM_CONSTANT(AMBIENT_SOURCE_COLOR); + BIND_ENUM_CONSTANT(AMBIENT_SOURCE_SKY); + + BIND_ENUM_CONSTANT(REFLECTION_SOURCE_BG); + BIND_ENUM_CONSTANT(REFLECTION_SOURCE_DISABLED); + BIND_ENUM_CONSTANT(REFLECTION_SOURCE_SKY); BIND_ENUM_CONSTANT(TONE_MAPPER_LINEAR); BIND_ENUM_CONSTANT(TONE_MAPPER_REINHARDT); BIND_ENUM_CONSTANT(TONE_MAPPER_FILMIC); BIND_ENUM_CONSTANT(TONE_MAPPER_ACES); - BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_LOW); - BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_MEDIUM); - BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_HIGH); + BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_ADDITIVE); + BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_SCREEN); + BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_SOFTLIGHT); + BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_REPLACE); + BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_MIX); BIND_ENUM_CONSTANT(SSAO_BLUR_DISABLED); BIND_ENUM_CONSTANT(SSAO_BLUR_1x1); BIND_ENUM_CONSTANT(SSAO_BLUR_2x2); BIND_ENUM_CONSTANT(SSAO_BLUR_3x3); - BIND_ENUM_CONSTANT(SSAO_QUALITY_LOW); - BIND_ENUM_CONSTANT(SSAO_QUALITY_MEDIUM); - BIND_ENUM_CONSTANT(SSAO_QUALITY_HIGH); -} - -Environment::Environment() : - bg_mode(BG_CLEAR_COLOR), - tone_mapper(TONE_MAPPER_LINEAR), - ssao_blur(SSAO_BLUR_3x3), - ssao_quality(SSAO_QUALITY_MEDIUM), - glow_blend_mode(GLOW_BLEND_MODE_ADDITIVE), - dof_blur_far_quality(DOF_BLUR_QUALITY_LOW), - dof_blur_near_quality(DOF_BLUR_QUALITY_LOW) { - - environment = VS::get_singleton()->environment_create(); - - bg_mode = BG_CLEAR_COLOR; - bg_sky_custom_fov = 0; - bg_sky_orientation = Basis(); - bg_energy = 1.0; - bg_canvas_max_layer = 0; - ambient_energy = 1.0; - //ambient_sky_contribution = 1.0; - set_ambient_light_sky_contribution(1.0); - set_camera_feed_id(1); - - tone_mapper = TONE_MAPPER_LINEAR; - tonemap_exposure = 1.0; - tonemap_white = 1.0; - tonemap_auto_exposure = false; - tonemap_auto_exposure_max = 8; - tonemap_auto_exposure_min = 0.05; - tonemap_auto_exposure_speed = 0.5; - tonemap_auto_exposure_grey = 0.4; - - set_tonemapper(tone_mapper); //update - - adjustment_enabled = false; - adjustment_contrast = 1.0; - adjustment_saturation = 1.0; - adjustment_brightness = 1.0; - - set_adjustment_enable(adjustment_enabled); //update - - ssr_enabled = false; - ssr_max_steps = 64; - ssr_fade_in = 0.15; - ssr_fade_out = 2.0; - ssr_depth_tolerance = 0.2; - ssr_roughness = true; - - ssao_enabled = false; - ssao_radius = 1; - ssao_intensity = 1; - ssao_radius2 = 0; - ssao_intensity2 = 1; - ssao_bias = 0.01; - ssao_direct_light_affect = 0.0; - ssao_ao_channel_affect = 0.0; - ssao_blur = SSAO_BLUR_3x3; - set_ssao_edge_sharpness(4); - set_ssao_quality(SSAO_QUALITY_MEDIUM); - - glow_enabled = false; - glow_levels = (1 << 2) | (1 << 4); - glow_intensity = 0.8; - glow_strength = 1.0; - glow_bloom = 0.0; - glow_blend_mode = GLOW_BLEND_MODE_SOFTLIGHT; - glow_hdr_bleed_threshold = 1.0; - glow_hdr_luminance_cap = 12.0; - glow_hdr_bleed_scale = 2.0; - glow_bicubic_upscale = false; - - dof_blur_far_enabled = false; - dof_blur_far_distance = 10; - dof_blur_far_transition = 5; - dof_blur_far_amount = 0.1; - dof_blur_far_quality = DOF_BLUR_QUALITY_MEDIUM; - - dof_blur_near_enabled = false; - dof_blur_near_distance = 2; - dof_blur_near_transition = 1; - dof_blur_near_amount = 0.1; - dof_blur_near_quality = DOF_BLUR_QUALITY_MEDIUM; - - fog_enabled = false; - fog_color = Color(0.5, 0.5, 0.5); - fog_sun_color = Color(0.8, 0.8, 0.0); - fog_sun_amount = 0; - - fog_depth_enabled = true; - - fog_depth_begin = 10; - fog_depth_end = 100; - fog_depth_curve = 1; - - fog_transmit_enabled = false; - fog_transmit_curve = 1; - - fog_height_enabled = false; - fog_height_min = 10; - fog_height_max = 0; - fog_height_curve = 1; - - set_fog_color(Color(0.5, 0.6, 0.7)); - set_fog_sun_color(Color(1.0, 0.9, 0.7)); + BIND_ENUM_CONSTANT(SDFGI_CASCADES_4); + BIND_ENUM_CONSTANT(SDFGI_CASCADES_6); + BIND_ENUM_CONSTANT(SDFGI_CASCADES_8); + + BIND_ENUM_CONSTANT(SDFGI_Y_SCALE_DISABLED); + BIND_ENUM_CONSTANT(SDFGI_Y_SCALE_75_PERCENT); + BIND_ENUM_CONSTANT(SDFGI_Y_SCALE_50_PERCENT); + + BIND_ENUM_CONSTANT(VOLUMETRIC_FOG_SHADOW_FILTER_DISABLED); + BIND_ENUM_CONSTANT(VOLUMETRIC_FOG_SHADOW_FILTER_LOW); + BIND_ENUM_CONSTANT(VOLUMETRIC_FOG_SHADOW_FILTER_MEDIUM); + BIND_ENUM_CONSTANT(VOLUMETRIC_FOG_SHADOW_FILTER_HIGH); +} + +Environment::Environment() { + environment = RS::get_singleton()->environment_create(); + + set_camera_feed_id(bg_camera_feed_id); + _update_ambient_light(); + _update_tonemap(); + _update_ssr(); + _update_ssao(); + _update_sdfgi(); + _update_glow(); + _update_fog(); + _update_adjustment(); + _update_volumetric_fog(); + _change_notify(); } Environment::~Environment() { - - VS::get_singleton()->free(environment); + RS::get_singleton()->free(environment); } diff --git a/scene/resources/environment.h b/scene/resources/environment.h index 62c6c5b4cd..d4d84f31aa 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -34,30 +34,59 @@ #include "core/resource.h" #include "scene/resources/sky.h" #include "scene/resources/texture.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" class Environment : public Resource { - GDCLASS(Environment, Resource); public: enum BGMode { - BG_CLEAR_COLOR, BG_COLOR, BG_SKY, - BG_COLOR_SKY, BG_CANVAS, BG_KEEP, BG_CAMERA_FEED, BG_MAX }; + enum AmbientSource { + AMBIENT_SOURCE_BG, + AMBIENT_SOURCE_DISABLED, + AMBIENT_SOURCE_COLOR, + AMBIENT_SOURCE_SKY, + }; + + enum ReflectionSource { + REFLECTION_SOURCE_BG, + REFLECTION_SOURCE_DISABLED, + REFLECTION_SOURCE_SKY, + }; + enum ToneMapper { TONE_MAPPER_LINEAR, TONE_MAPPER_REINHARDT, TONE_MAPPER_FILMIC, - TONE_MAPPER_ACES + TONE_MAPPER_ACES, + }; + + enum SSAOBlur { + SSAO_BLUR_DISABLED, + SSAO_BLUR_1x1, + SSAO_BLUR_2x2, + SSAO_BLUR_3x3, + }; + + enum SDFGICascades { + SDFGI_CASCADES_4, + SDFGI_CASCADES_6, + SDFGI_CASCADES_8, + }; + + enum SDFGIYScale { + SDFGI_Y_SCALE_DISABLED, + SDFGI_Y_SCALE_75_PERCENT, + SDFGI_Y_SCALE_50_PERCENT, }; enum GlowBlendMode { @@ -65,357 +94,323 @@ public: GLOW_BLEND_MODE_SCREEN, GLOW_BLEND_MODE_SOFTLIGHT, GLOW_BLEND_MODE_REPLACE, + GLOW_BLEND_MODE_MIX, }; - enum DOFBlurQuality { - DOF_BLUR_QUALITY_LOW, - DOF_BLUR_QUALITY_MEDIUM, - DOF_BLUR_QUALITY_HIGH, - }; - - enum SSAOBlur { - SSAO_BLUR_DISABLED, - SSAO_BLUR_1x1, - SSAO_BLUR_2x2, - SSAO_BLUR_3x3 - }; - - enum SSAOQuality { - SSAO_QUALITY_LOW, - SSAO_QUALITY_MEDIUM, - SSAO_QUALITY_HIGH + enum VolumetricFogShadowFilter { + VOLUMETRIC_FOG_SHADOW_FILTER_DISABLED, + VOLUMETRIC_FOG_SHADOW_FILTER_LOW, + VOLUMETRIC_FOG_SHADOW_FILTER_MEDIUM, + VOLUMETRIC_FOG_SHADOW_FILTER_HIGH, }; private: RID environment; - BGMode bg_mode; + // Background + BGMode bg_mode = BG_CLEAR_COLOR; Ref<Sky> bg_sky; - float bg_sky_custom_fov; - Basis bg_sky_orientation; + float bg_sky_custom_fov = 0; + Vector3 bg_sky_rotation; Color bg_color; - float bg_energy; - int bg_canvas_max_layer; + float bg_energy = 1.0; + int bg_canvas_max_layer = 0; + int bg_camera_feed_id = 1; + + // Ambient light Color ambient_color; - float ambient_energy; - float ambient_sky_contribution; - int camera_feed_id; - - ToneMapper tone_mapper; - float tonemap_exposure; - float tonemap_white; - bool tonemap_auto_exposure; - float tonemap_auto_exposure_max; - float tonemap_auto_exposure_min; - float tonemap_auto_exposure_speed; - float tonemap_auto_exposure_grey; - - bool adjustment_enabled; - float adjustment_contrast; - float adjustment_saturation; - float adjustment_brightness; - Ref<Texture> adjustment_color_correction; - - bool ssr_enabled; - int ssr_max_steps; - float ssr_fade_in; - float ssr_fade_out; - float ssr_depth_tolerance; - bool ssr_roughness; - - bool ssao_enabled; - float ssao_radius; - float ssao_intensity; - float ssao_radius2; - float ssao_intensity2; - float ssao_bias; - float ssao_direct_light_affect; - float ssao_ao_channel_affect; - Color ssao_color; - SSAOBlur ssao_blur; - float ssao_edge_sharpness; - SSAOQuality ssao_quality; - - bool glow_enabled; - int glow_levels; - float glow_intensity; - float glow_strength; - float glow_bloom; - GlowBlendMode glow_blend_mode; - float glow_hdr_bleed_threshold; - float glow_hdr_bleed_scale; - float glow_hdr_luminance_cap; - bool glow_bicubic_upscale; - - bool dof_blur_far_enabled; - float dof_blur_far_distance; - float dof_blur_far_transition; - float dof_blur_far_amount; - DOFBlurQuality dof_blur_far_quality; - - bool dof_blur_near_enabled; - float dof_blur_near_distance; - float dof_blur_near_transition; - float dof_blur_near_amount; - DOFBlurQuality dof_blur_near_quality; - - bool fog_enabled; - Color fog_color; - Color fog_sun_color; - float fog_sun_amount; - - bool fog_depth_enabled; - float fog_depth_begin; - float fog_depth_end; - float fog_depth_curve; - - bool fog_transmit_enabled; - float fog_transmit_curve; - - bool fog_height_enabled; - float fog_height_min; - float fog_height_max; - float fog_height_curve; + AmbientSource ambient_source = AMBIENT_SOURCE_BG; + float ambient_energy = 1.0; + float ambient_sky_contribution = 1.0; + ReflectionSource reflection_source = REFLECTION_SOURCE_BG; + Color ao_color; + void _update_ambient_light(); + + // Tonemap + ToneMapper tone_mapper = TONE_MAPPER_LINEAR; + float tonemap_exposure = 1.0; + float tonemap_white = 1.0; + bool tonemap_auto_exposure_enabled = false; + float tonemap_auto_exposure_min = 0.05; + float tonemap_auto_exposure_max = 8; + float tonemap_auto_exposure_speed = 0.5; + float tonemap_auto_exposure_grey = 0.4; + void _update_tonemap(); + + // SSR + bool ssr_enabled = false; + int ssr_max_steps = 64; + float ssr_fade_in = 0.15; + float ssr_fade_out = 2.0; + float ssr_depth_tolerance = 0.2; + void _update_ssr(); + + // SSAO + bool ssao_enabled = false; + float ssao_radius = 1.0; + float ssao_intensity = 1.0; + float ssao_bias = 0.01; + float ssao_direct_light_affect = 0.0; + float ssao_ao_channel_affect = 0.0; + SSAOBlur ssao_blur = SSAO_BLUR_3x3; + float ssao_edge_sharpness = 4.0; + void _update_ssao(); + + // SDFGI + bool sdfgi_enabled = false; + SDFGICascades sdfgi_cascades = SDFGI_CASCADES_6; + float sdfgi_min_cell_size = 0.2; + SDFGIYScale sdfgi_y_scale = SDFGI_Y_SCALE_DISABLED; + bool sdfgi_use_occlusion = false; + bool sdfgi_use_multibounce = false; + bool sdfgi_read_sky_light = false; + float sdfgi_energy = 1.0; + float sdfgi_normal_bias = 1.1; + float sdfgi_probe_bias = 1.1; + void _update_sdfgi(); + + // Glow + bool glow_enabled = false; + int glow_levels = (1 << 2) | (1 << 4); + float glow_intensity = 0.8; + float glow_strength = 1.0; + float glow_mix = 0.05; + float glow_bloom = 0.0; + GlowBlendMode glow_blend_mode = GLOW_BLEND_MODE_SOFTLIGHT; + float glow_hdr_bleed_threshold = 1.0; + float glow_hdr_bleed_scale = 2.0; + float glow_hdr_luminance_cap = 12.0; + void _update_glow(); + + // Fog + bool fog_enabled = false; + Color fog_light_color = Color(0.5, 0.6, 0.7); + float fog_light_energy = 1.0; + float fog_sun_scatter = 0.0; + float fog_density = 0.001; + float fog_height = 0.0; + float fog_height_density = 0.0; //can be negative to invert effect + + void _update_fog(); + + // Volumetric Fog + bool volumetric_fog_enabled = false; + float volumetric_fog_density = 0.01; + Color volumetric_fog_light = Color(0.0, 0.0, 0.0); + float volumetric_fog_light_energy = 1.0; + float volumetric_fog_length = 64.0; + float volumetric_fog_detail_spread = 2.0; + VolumetricFogShadowFilter volumetric_fog_shadow_filter = VOLUMETRIC_FOG_SHADOW_FILTER_LOW; + float volumetric_fog_gi_inject = 0.0; + void _update_volumetric_fog(); + + // Adjustment + bool adjustment_enabled = false; + float adjustment_brightness = 1.0; + float adjustment_contrast = 1.0; + float adjustment_saturation = 1.0; + Ref<Texture2D> adjustment_color_correction; + void _update_adjustment(); protected: static void _bind_methods(); - virtual void _validate_property(PropertyInfo &property) const; + virtual void _validate_property(PropertyInfo &property) const override; +#ifndef DISABLE_DEPRECATED + // Kept for compatibility from 3.x to 4.0. + bool _set(const StringName &p_name, const Variant &p_value); +#endif public: - void set_background(BGMode p_bg); - void set_sky(const Ref<Sky> &p_sky); - void set_sky_custom_fov(float p_scale); - void set_sky_orientation(const Basis &p_orientation); - void set_sky_rotation(const Vector3 &p_euler_rad); - void set_sky_rotation_degrees(const Vector3 &p_euler_deg); - void set_bg_color(const Color &p_color); - void set_bg_energy(float p_energy); - void set_canvas_max_layer(int p_max_layer); - void set_ambient_light_color(const Color &p_color); - void set_ambient_light_energy(float p_energy); - void set_ambient_light_sky_contribution(float p_energy); - void set_camera_feed_id(int p_camera_feed_id); + virtual RID get_rid() const override; + // Background + void set_background(BGMode p_bg); BGMode get_background() const; + void set_sky(const Ref<Sky> &p_sky); Ref<Sky> get_sky() const; + void set_sky_custom_fov(float p_scale); float get_sky_custom_fov() const; - Basis get_sky_orientation() const; + void set_sky_rotation(const Vector3 &p_rotation); Vector3 get_sky_rotation() const; - Vector3 get_sky_rotation_degrees() const; + void set_bg_color(const Color &p_color); Color get_bg_color() const; + void set_bg_energy(float p_energy); float get_bg_energy() const; + void set_canvas_max_layer(int p_max_layer); int get_canvas_max_layer() const; + void set_camera_feed_id(int p_id); + int get_camera_feed_id() const; + + // Ambient light + void set_ambient_light_color(const Color &p_color); Color get_ambient_light_color() const; + void set_ambient_source(AmbientSource p_source); + AmbientSource get_ambient_source() const; + void set_ambient_light_energy(float p_energy); float get_ambient_light_energy() const; + void set_ambient_light_sky_contribution(float p_ratio); float get_ambient_light_sky_contribution() const; - int get_camera_feed_id(void) const; + void set_reflection_source(ReflectionSource p_source); + ReflectionSource get_reflection_source() const; + void set_ao_color(const Color &p_color); + Color get_ao_color() const; + // Tonemap void set_tonemapper(ToneMapper p_tone_mapper); ToneMapper get_tonemapper() const; - void set_tonemap_exposure(float p_exposure); float get_tonemap_exposure() const; - void set_tonemap_white(float p_white); float get_tonemap_white() const; - - void set_tonemap_auto_exposure(bool p_enabled); - bool get_tonemap_auto_exposure() const; - - void set_tonemap_auto_exposure_max(float p_auto_exposure_max); - float get_tonemap_auto_exposure_max() const; - + void set_tonemap_auto_exposure_enabled(bool p_enabled); + bool is_tonemap_auto_exposure_enabled() const; void set_tonemap_auto_exposure_min(float p_auto_exposure_min); float get_tonemap_auto_exposure_min() const; - + void set_tonemap_auto_exposure_max(float p_auto_exposure_max); + float get_tonemap_auto_exposure_max() const; void set_tonemap_auto_exposure_speed(float p_auto_exposure_speed); float get_tonemap_auto_exposure_speed() const; - void set_tonemap_auto_exposure_grey(float p_auto_exposure_grey); float get_tonemap_auto_exposure_grey() const; - void set_adjustment_enable(bool p_enable); - bool is_adjustment_enabled() const; - - void set_adjustment_brightness(float p_brightness); - float get_adjustment_brightness() const; - - void set_adjustment_contrast(float p_contrast); - float get_adjustment_contrast() const; - - void set_adjustment_saturation(float p_saturation); - float get_adjustment_saturation() const; - - void set_adjustment_color_correction(const Ref<Texture> &p_ramp); - Ref<Texture> get_adjustment_color_correction() const; - - void set_ssr_enabled(bool p_enable); + // SSR + void set_ssr_enabled(bool p_enabled); bool is_ssr_enabled() const; - void set_ssr_max_steps(int p_steps); int get_ssr_max_steps() const; - void set_ssr_fade_in(float p_fade_in); float get_ssr_fade_in() const; - void set_ssr_fade_out(float p_fade_out); float get_ssr_fade_out() const; - void set_ssr_depth_tolerance(float p_depth_tolerance); float get_ssr_depth_tolerance() const; - void set_ssr_rough(bool p_enable); - bool is_ssr_rough() const; - - void set_ssao_enabled(bool p_enable); + // SSAO + void set_ssao_enabled(bool p_enabled); bool is_ssao_enabled() const; - void set_ssao_radius(float p_radius); float get_ssao_radius() const; - void set_ssao_intensity(float p_intensity); float get_ssao_intensity() const; - - void set_ssao_radius2(float p_radius); - float get_ssao_radius2() const; - - void set_ssao_intensity2(float p_intensity); - float get_ssao_intensity2() const; - void set_ssao_bias(float p_bias); float get_ssao_bias() const; - void set_ssao_direct_light_affect(float p_direct_light_affect); float get_ssao_direct_light_affect() const; - void set_ssao_ao_channel_affect(float p_ao_channel_affect); float get_ssao_ao_channel_affect() const; - - void set_ssao_color(const Color &p_color); - Color get_ssao_color() const; - void set_ssao_blur(SSAOBlur p_blur); SSAOBlur get_ssao_blur() const; - - void set_ssao_quality(SSAOQuality p_quality); - SSAOQuality get_ssao_quality() const; - void set_ssao_edge_sharpness(float p_edge_sharpness); float get_ssao_edge_sharpness() const; + // SDFGI + void set_sdfgi_enabled(bool p_enabled); + bool is_sdfgi_enabled() const; + void set_sdfgi_cascades(SDFGICascades p_cascades); + SDFGICascades get_sdfgi_cascades() const; + void set_sdfgi_min_cell_size(float p_size); + float get_sdfgi_min_cell_size() const; + void set_sdfgi_max_distance(float p_distance); + float get_sdfgi_max_distance() const; + void set_sdfgi_cascade0_distance(float p_distance); + float get_sdfgi_cascade0_distance() const; + void set_sdfgi_y_scale(SDFGIYScale p_y_scale); + SDFGIYScale get_sdfgi_y_scale() const; + void set_sdfgi_use_occlusion(bool p_enabled); + bool is_sdfgi_using_occlusion() const; + void set_sdfgi_use_multi_bounce(bool p_enabled); + bool is_sdfgi_using_multi_bounce() const; + void set_sdfgi_read_sky_light(bool p_enabled); + bool is_sdfgi_reading_sky_light() const; + void set_sdfgi_energy(float p_energy); + float get_sdfgi_energy() const; + void set_sdfgi_normal_bias(float p_bias); + float get_sdfgi_normal_bias() const; + void set_sdfgi_probe_bias(float p_bias); + float get_sdfgi_probe_bias() const; + + // Glow void set_glow_enabled(bool p_enabled); bool is_glow_enabled() const; - - void set_glow_level(int p_level, bool p_enabled); + void set_glow_level_enabled(int p_level, bool p_enabled); bool is_glow_level_enabled(int p_level) const; - void set_glow_intensity(float p_intensity); float get_glow_intensity() const; - void set_glow_strength(float p_strength); float get_glow_strength() const; - + void set_glow_mix(float p_mix); + float get_glow_mix() const; void set_glow_bloom(float p_threshold); float get_glow_bloom() const; - void set_glow_blend_mode(GlowBlendMode p_mode); GlowBlendMode get_glow_blend_mode() const; - void set_glow_hdr_bleed_threshold(float p_threshold); float get_glow_hdr_bleed_threshold() const; - - void set_glow_hdr_luminance_cap(float p_amount); - float get_glow_hdr_luminance_cap() const; - void set_glow_hdr_bleed_scale(float p_scale); float get_glow_hdr_bleed_scale() const; + void set_glow_hdr_luminance_cap(float p_amount); + float get_glow_hdr_luminance_cap() const; - void set_glow_bicubic_upscale(bool p_enable); - bool is_glow_bicubic_upscale_enabled() const; - - void set_dof_blur_far_enabled(bool p_enable); - bool is_dof_blur_far_enabled() const; - - void set_dof_blur_far_distance(float p_distance); - float get_dof_blur_far_distance() const; - - void set_dof_blur_far_transition(float p_distance); - float get_dof_blur_far_transition() const; - - void set_dof_blur_far_amount(float p_amount); - float get_dof_blur_far_amount() const; - - void set_dof_blur_far_quality(DOFBlurQuality p_quality); - DOFBlurQuality get_dof_blur_far_quality() const; - - void set_dof_blur_near_enabled(bool p_enable); - bool is_dof_blur_near_enabled() const; - - void set_dof_blur_near_distance(float p_distance); - float get_dof_blur_near_distance() const; - - void set_dof_blur_near_transition(float p_distance); - float get_dof_blur_near_transition() const; - - void set_dof_blur_near_amount(float p_amount); - float get_dof_blur_near_amount() const; - - void set_dof_blur_near_quality(DOFBlurQuality p_quality); - DOFBlurQuality get_dof_blur_near_quality() const; + // Fog void set_fog_enabled(bool p_enabled); bool is_fog_enabled() const; - - void set_fog_color(const Color &p_color); - Color get_fog_color() const; - - void set_fog_sun_color(const Color &p_color); - Color get_fog_sun_color() const; - - void set_fog_sun_amount(float p_amount); - float get_fog_sun_amount() const; - - void set_fog_depth_enabled(bool p_enabled); - bool is_fog_depth_enabled() const; - - void set_fog_depth_begin(float p_distance); - float get_fog_depth_begin() const; - - void set_fog_depth_end(float p_distance); - float get_fog_depth_end() const; - - void set_fog_depth_curve(float p_curve); - float get_fog_depth_curve() const; - - void set_fog_transmit_enabled(bool p_enabled); - bool is_fog_transmit_enabled() const; - - void set_fog_transmit_curve(float p_curve); - float get_fog_transmit_curve() const; - - void set_fog_height_enabled(bool p_enabled); - bool is_fog_height_enabled() const; - - void set_fog_height_min(float p_distance); - float get_fog_height_min() const; - - void set_fog_height_max(float p_distance); - float get_fog_height_max() const; - - void set_fog_height_curve(float p_distance); - float get_fog_height_curve() const; - - virtual RID get_rid() const; + void set_fog_light_color(const Color &p_light_color); + Color get_fog_light_color() const; + void set_fog_light_energy(float p_amount); + float get_fog_light_energy() const; + void set_fog_sun_scatter(float p_amount); + float get_fog_sun_scatter() const; + + void set_fog_density(float p_amount); + float get_fog_density() const; + void set_fog_height(float p_amount); + float get_fog_height() const; + void set_fog_height_density(float p_amount); + float get_fog_height_density() const; + + // Volumetric Fog + void set_volumetric_fog_enabled(bool p_enable); + bool is_volumetric_fog_enabled() const; + void set_volumetric_fog_density(float p_density); + float get_volumetric_fog_density() const; + void set_volumetric_fog_light(Color p_color); + Color get_volumetric_fog_light() const; + void set_volumetric_fog_light_energy(float p_begin); + float get_volumetric_fog_light_energy() const; + void set_volumetric_fog_length(float p_length); + float get_volumetric_fog_length() const; + void set_volumetric_fog_detail_spread(float p_detail_spread); + float get_volumetric_fog_detail_spread() const; + void set_volumetric_fog_shadow_filter(VolumetricFogShadowFilter p_filter); + VolumetricFogShadowFilter get_volumetric_fog_shadow_filter() const; + void set_volumetric_fog_gi_inject(float p_gi_inject); + float get_volumetric_fog_gi_inject() const; + + // Adjustment + void set_adjustment_enabled(bool p_enabled); + bool is_adjustment_enabled() const; + void set_adjustment_brightness(float p_brightness); + float get_adjustment_brightness() const; + void set_adjustment_contrast(float p_contrast); + float get_adjustment_contrast() const; + void set_adjustment_saturation(float p_saturation); + float get_adjustment_saturation() const; + void set_adjustment_color_correction(const Ref<Texture2D> &p_ramp); + Ref<Texture2D> get_adjustment_color_correction() const; Environment(); ~Environment(); }; VARIANT_ENUM_CAST(Environment::BGMode) +VARIANT_ENUM_CAST(Environment::AmbientSource) +VARIANT_ENUM_CAST(Environment::ReflectionSource) VARIANT_ENUM_CAST(Environment::ToneMapper) -VARIANT_ENUM_CAST(Environment::GlowBlendMode) -VARIANT_ENUM_CAST(Environment::DOFBlurQuality) -VARIANT_ENUM_CAST(Environment::SSAOQuality) VARIANT_ENUM_CAST(Environment::SSAOBlur) +VARIANT_ENUM_CAST(Environment::SDFGICascades) +VARIANT_ENUM_CAST(Environment::SDFGIYScale) +VARIANT_ENUM_CAST(Environment::GlowBlendMode) +VARIANT_ENUM_CAST(Environment::VolumetricFogShadowFilter) #endif // ENVIRONMENT_H diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 19c59b3817..7cc39f661d 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -65,11 +65,11 @@ void Font::draw(RID p_canvas_item, const Point2 &p_pos, const String &p_text, co int chars_drawn = 0; bool with_outline = has_outline(); for (int i = 0; i < p_text.length(); i++) { - int width = get_char_size(p_text[i]).width; - if (p_clip_w >= 0 && (ofs.x + width) > p_clip_w) + if (p_clip_w >= 0 && (ofs.x + width) > p_clip_w) { break; //clip + } ofs.x += draw_char(p_canvas_item, p_pos + ofs, p_text[i], p_text[i + 1], with_outline ? p_outline_modulate : p_modulate, with_outline); ++chars_drawn; @@ -84,17 +84,16 @@ void Font::draw(RID p_canvas_item, const Point2 &p_pos, const String &p_text, co } void Font::update_changes() { - emit_changed(); } void Font::_bind_methods() { - ClassDB::bind_method(D_METHOD("draw", "canvas_item", "position", "string", "modulate", "clip_w", "outline_modulate"), &Font::draw, DEFVAL(Color(1, 1, 1)), DEFVAL(-1), DEFVAL(Color(1, 1, 1))); ClassDB::bind_method(D_METHOD("get_ascent"), &Font::get_ascent); ClassDB::bind_method(D_METHOD("get_descent"), &Font::get_descent); ClassDB::bind_method(D_METHOD("get_height"), &Font::get_height); ClassDB::bind_method(D_METHOD("is_distance_field_hint"), &Font::is_distance_field_hint); + ClassDB::bind_method(D_METHOD("get_char_size", "char", "next"), &Font::get_char_size, DEFVAL(0)); ClassDB::bind_method(D_METHOD("get_string_size", "string"), &Font::get_string_size); ClassDB::bind_method(D_METHOD("get_wordwrap_string_size", "string", "width"), &Font::get_wordwrap_string_size); ClassDB::bind_method(D_METHOD("has_outline"), &Font::has_outline); @@ -107,33 +106,30 @@ Font::Font() { ///////////////////////////////////////////////////////////////// -void BitmapFont::_set_chars(const PoolVector<int> &p_chars) { - +void BitmapFont::_set_chars(const Vector<int> &p_chars) { int len = p_chars.size(); //char 1 charsize 1 texture, 4 rect, 2 align, advance 1 ERR_FAIL_COND(len % 9); - if (!len) + if (!len) { return; //none to do + } int chars = len / 9; - PoolVector<int>::Read r = p_chars.read(); + const int *r = p_chars.ptr(); for (int i = 0; i < chars; i++) { - const int *data = &r[i * 9]; add_char(data[0], data[1], Rect2(data[2], data[3], data[4], data[5]), Size2(data[6], data[7]), data[8]); } } -PoolVector<int> BitmapFont::_get_chars() const { +Vector<int> BitmapFont::_get_chars() const { + Vector<int> chars; - PoolVector<int> chars; - - const CharType *key = NULL; + const char32_t *key = nullptr; while ((key = char_map.next(key))) { - const Character *c = char_map.getptr(*key); - ERR_FAIL_COND_V(!c, PoolVector<int>()); + ERR_FAIL_COND_V(!c, Vector<int>()); chars.push_back(*key); chars.push_back(c->texture_idx); chars.push_back(c->rect.position.x); @@ -149,27 +145,24 @@ PoolVector<int> BitmapFont::_get_chars() const { return chars; } -void BitmapFont::_set_kernings(const PoolVector<int> &p_kernings) { - +void BitmapFont::_set_kernings(const Vector<int> &p_kernings) { int len = p_kernings.size(); ERR_FAIL_COND(len % 3); - if (!len) + if (!len) { return; - PoolVector<int>::Read r = p_kernings.read(); + } + const int *r = p_kernings.ptr(); for (int i = 0; i < len / 3; i++) { - const int *data = &r[i * 3]; add_kerning_pair(data[0], data[1], data[2]); } } -PoolVector<int> BitmapFont::_get_kernings() const { - - PoolVector<int> kernings; +Vector<int> BitmapFont::_get_kernings() const { + Vector<int> kernings; for (Map<KerningPairKey, int>::Element *E = kerning_map.front(); E; E = E->next()) { - kernings.push_back(E->key().A); kernings.push_back(E->key().B); kernings.push_back(E->get()); @@ -179,20 +172,19 @@ PoolVector<int> BitmapFont::_get_kernings() const { } void BitmapFont::_set_textures(const Vector<Variant> &p_textures) { - textures.clear(); for (int i = 0; i < p_textures.size(); i++) { - Ref<Texture> tex = p_textures[i]; + Ref<Texture2D> tex = p_textures[i]; ERR_CONTINUE(!tex.is_valid()); add_texture(tex); } } Vector<Variant> BitmapFont::_get_textures() const { - Vector<Variant> rtextures; - for (int i = 0; i < textures.size(); i++) - rtextures.push_back(textures[i].get_ref_ptr()); + for (int i = 0; i < textures.size(); i++) { + rtextures.push_back(textures[i]); + } return rtextures; } @@ -207,7 +199,6 @@ Error BitmapFont::create_from_fnt(const String &p_file) { clear(); while (true) { - String line = f->get_line(); int delimiter = line.find(" "); @@ -215,62 +206,65 @@ Error BitmapFont::create_from_fnt(const String &p_file) { int pos = delimiter + 1; Map<String, String> keys; - while (pos < line.size() && line[pos] == ' ') + while (pos < line.size() && line[pos] == ' ') { pos++; + } while (pos < line.size()) { - int eq = line.find("=", pos); - if (eq == -1) + if (eq == -1) { break; + } String key = line.substr(pos, eq - pos); int end = -1; String value; if (line[eq + 1] == '"') { end = line.find("\"", eq + 2); - if (end == -1) + if (end == -1) { break; + } value = line.substr(eq + 2, end - 1 - eq - 1); pos = end + 1; } else { end = line.find(" ", eq + 1); - if (end == -1) + if (end == -1) { end = line.size(); + } value = line.substr(eq + 1, end - eq); pos = end; } - while (pos < line.size() && line[pos] == ' ') + while (pos < line.size() && line[pos] == ' ') { pos++; + } keys[key] = value; } if (type == "info") { - - if (keys.has("face")) + if (keys.has("face")) { set_name(keys["face"]); + } /* if (keys.has("size")) font->set_height(keys["size"].to_int()); */ } else if (type == "common") { - - if (keys.has("lineHeight")) + if (keys.has("lineHeight")) { set_height(keys["lineHeight"].to_int()); - if (keys.has("base")) + } + if (keys.has("base")) { set_ascent(keys["base"].to_int()); + } } else if (type == "page") { - if (keys.has("file")) { - String base_dir = p_file.get_base_dir(); String file = base_dir.plus_file(keys["file"]); - Ref<Texture> tex = ResourceLoader::load(file); + Ref<Texture2D> tex = ResourceLoader::load(file); if (tex.is_null()) { ERR_PRINT("Can't load font texture!"); } else { @@ -278,55 +272,66 @@ Error BitmapFont::create_from_fnt(const String &p_file) { } } } else if (type == "char") { - - CharType idx = 0; - if (keys.has("id")) + char32_t idx = 0; + if (keys.has("id")) { idx = keys["id"].to_int(); + } Rect2 rect; - if (keys.has("x")) + if (keys.has("x")) { rect.position.x = keys["x"].to_int(); - if (keys.has("y")) + } + if (keys.has("y")) { rect.position.y = keys["y"].to_int(); - if (keys.has("width")) + } + if (keys.has("width")) { rect.size.width = keys["width"].to_int(); - if (keys.has("height")) + } + if (keys.has("height")) { rect.size.height = keys["height"].to_int(); + } Point2 ofs; - if (keys.has("xoffset")) + if (keys.has("xoffset")) { ofs.x = keys["xoffset"].to_int(); - if (keys.has("yoffset")) + } + if (keys.has("yoffset")) { ofs.y = keys["yoffset"].to_int(); + } int texture = 0; - if (keys.has("page")) + if (keys.has("page")) { texture = keys["page"].to_int(); + } int advance = -1; - if (keys.has("xadvance")) + if (keys.has("xadvance")) { advance = keys["xadvance"].to_int(); + } add_char(idx, texture, rect, ofs, advance); } else if (type == "kerning") { - - CharType first = 0, second = 0; + char32_t first = 0, second = 0; int k = 0; - if (keys.has("first")) + if (keys.has("first")) { first = keys["first"].to_int(); - if (keys.has("second")) + } + if (keys.has("second")) { second = keys["second"].to_int(); - if (keys.has("amount")) + } + if (keys.has("amount")) { k = keys["amount"].to_int(); + } add_kerning_pair(first, second, -k); } - if (f->eof_reached()) + if (f->eof_reached()) { break; + } } memdelete(f); @@ -335,65 +340,64 @@ Error BitmapFont::create_from_fnt(const String &p_file) { } void BitmapFont::set_height(float p_height) { - height = p_height; } -float BitmapFont::get_height() const { +float BitmapFont::get_height() const { return height; } void BitmapFont::set_ascent(float p_ascent) { - ascent = p_ascent; } -float BitmapFont::get_ascent() const { +float BitmapFont::get_ascent() const { return ascent; } -float BitmapFont::get_descent() const { +float BitmapFont::get_descent() const { return height - ascent; } -void BitmapFont::add_texture(const Ref<Texture> &p_texture) { +float BitmapFont::get_underline_position() const { + return 2; +} +float BitmapFont::get_underline_thickness() const { + return 1; +} + +void BitmapFont::add_texture(const Ref<Texture2D> &p_texture) { ERR_FAIL_COND_MSG(p_texture.is_null(), "It's not a reference to a valid Texture object."); textures.push_back(p_texture); } int BitmapFont::get_texture_count() const { - return textures.size(); }; -Ref<Texture> BitmapFont::get_texture(int p_idx) const { - - ERR_FAIL_INDEX_V(p_idx, textures.size(), Ref<Texture>()); +Ref<Texture2D> BitmapFont::get_texture(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, textures.size(), Ref<Texture2D>()); return textures[p_idx]; }; int BitmapFont::get_character_count() const { - return char_map.size(); }; -Vector<CharType> BitmapFont::get_char_keys() const { - - Vector<CharType> chars; +Vector<char32_t> BitmapFont::get_char_keys() const { + Vector<char32_t> chars; chars.resize(char_map.size()); - const CharType *ct = NULL; + const char32_t *ct = nullptr; int count = 0; while ((ct = char_map.next(ct))) { - chars.write[count++] = *ct; }; return chars; }; -BitmapFont::Character BitmapFont::get_character(CharType p_char) const { - +BitmapFont::Character BitmapFont::get_character(char32_t p_char) const { if (!char_map.has(p_char)) { ERR_FAIL_V(Character()); }; @@ -401,10 +405,10 @@ BitmapFont::Character BitmapFont::get_character(CharType p_char) const { return char_map[p_char]; }; -void BitmapFont::add_char(CharType p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) { - - if (p_advance < 0) +void BitmapFont::add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) { + if (p_advance < 0) { p_advance = p_rect.size.width; + } Character c; c.rect = p_rect; @@ -416,23 +420,19 @@ void BitmapFont::add_char(CharType p_char, int p_texture_idx, const Rect2 &p_rec char_map[p_char] = c; } -void BitmapFont::add_kerning_pair(CharType p_A, CharType p_B, int p_kerning) { - +void BitmapFont::add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning) { KerningPairKey kpk; kpk.A = p_A; kpk.B = p_B; if (p_kerning == 0 && kerning_map.has(kpk)) { - kerning_map.erase(kpk); } else { - kerning_map[kpk] = p_kerning; } } Vector<BitmapFont::KerningPairKey> BitmapFont::get_kerning_pair_keys() const { - Vector<BitmapFont::KerningPairKey> ret; ret.resize(kerning_map.size()); int i = 0; @@ -444,32 +444,29 @@ Vector<BitmapFont::KerningPairKey> BitmapFont::get_kerning_pair_keys() const { return ret; } -int BitmapFont::get_kerning_pair(CharType p_A, CharType p_B) const { - +int BitmapFont::get_kerning_pair(char32_t p_A, char32_t p_B) const { KerningPairKey kpk; kpk.A = p_A; kpk.B = p_B; const Map<KerningPairKey, int>::Element *E = kerning_map.find(kpk); - if (E) + if (E) { return E->get(); + } return 0; } void BitmapFont::set_distance_field_hint(bool p_distance_field) { - distance_field_hint = p_distance_field; emit_changed(); } bool BitmapFont::is_distance_field_hint() const { - return distance_field_hint; } void BitmapFont::clear() { - height = 1; ascent = 0; char_map.clear(); @@ -479,16 +476,15 @@ void BitmapFont::clear() { } Size2 Font::get_string_size(const String &p_string) const { - float w = 0; int l = p_string.length(); - if (l == 0) + if (l == 0) { return Size2(0, get_height()); - const CharType *sptr = &p_string[0]; + } + const char32_t *sptr = &p_string[0]; for (int i = 0; i < l; i++) { - w += get_char_size(sptr[i], sptr[i + 1]).width; } @@ -496,12 +492,12 @@ Size2 Font::get_string_size(const String &p_string) const { } Size2 Font::get_wordwrap_string_size(const String &p_string, float p_width) const { - ERR_FAIL_COND_V(p_width <= 0, Vector2(0, get_height())); int l = p_string.length(); - if (l == 0) + if (l == 0) { return Size2(p_width, get_height()); + } float line_w = 0; float h = 0; @@ -527,8 +523,7 @@ Size2 Font::get_wordwrap_string_size(const String &p_string, float p_width) cons } void BitmapFont::set_fallback(const Ref<BitmapFont> &p_fallback) { - - for (Ref<BitmapFont> fallback_child = p_fallback; fallback_child != NULL; fallback_child = fallback_child->get_fallback()) { + for (Ref<BitmapFont> fallback_child = p_fallback; fallback_child != nullptr; fallback_child = fallback_child->get_fallback()) { ERR_FAIL_COND_MSG(fallback_child == this, "Can't set as fallback one of its parents to prevent crashes due to recursive loop."); } @@ -536,17 +531,16 @@ void BitmapFont::set_fallback(const Ref<BitmapFont> &p_fallback) { } Ref<BitmapFont> BitmapFont::get_fallback() const { - return fallback; } -float BitmapFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, bool p_outline) const { - +float BitmapFont::draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, const Color &p_modulate, bool p_outline) const { const Character *c = char_map.getptr(p_char); if (!c) { - if (fallback.is_valid()) + if (fallback.is_valid()) { return fallback->draw_char(p_canvas_item, p_pos, p_char, p_next, p_modulate, p_outline); + } return 0; } @@ -556,33 +550,31 @@ float BitmapFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_c cpos.x += c->h_align; cpos.y -= ascent; cpos.y += c->v_align; - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx]->get_rid(), c->rect, p_modulate, false, RID(), false); + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx]->get_rid(), c->rect, p_modulate, false, RID(), RID(), Color(1, 1, 1, 1), false); } return get_char_size(p_char, p_next).width; } -Size2 BitmapFont::get_char_size(CharType p_char, CharType p_next) const { - +Size2 BitmapFont::get_char_size(char32_t p_char, char32_t p_next) const { const Character *c = char_map.getptr(p_char); if (!c) { - if (fallback.is_valid()) + if (fallback.is_valid()) { return fallback->get_char_size(p_char, p_next); + } return Size2(); } Size2 ret(c->advance, c->rect.size.y); if (p_next) { - KerningPairKey kpk; kpk.A = p_char; kpk.B = p_next; const Map<KerningPairKey, int>::Element *E = kerning_map.find(kpk); if (E) { - ret.width -= E->get(); } } @@ -591,7 +583,6 @@ Size2 BitmapFont::get_char_size(CharType p_char, CharType p_next) const { } void BitmapFont::_bind_methods() { - ClassDB::bind_method(D_METHOD("create_from_fnt", "path"), &BitmapFont::create_from_fnt); ClassDB::bind_method(D_METHOD("set_height", "px"), &BitmapFont::set_height); @@ -606,8 +597,6 @@ void BitmapFont::_bind_methods() { ClassDB::bind_method(D_METHOD("get_texture_count"), &BitmapFont::get_texture_count); ClassDB::bind_method(D_METHOD("get_texture", "idx"), &BitmapFont::get_texture); - ClassDB::bind_method(D_METHOD("get_char_size", "char", "next"), &BitmapFont::get_char_size, DEFVAL(0)); - ClassDB::bind_method(D_METHOD("set_distance_field_hint", "enable"), &BitmapFont::set_distance_field_hint); ClassDB::bind_method(D_METHOD("clear"), &BitmapFont::clear); @@ -625,31 +614,29 @@ void BitmapFont::_bind_methods() { ClassDB::bind_method(D_METHOD("get_fallback"), &BitmapFont::get_fallback); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_textures", "_get_textures"); - ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "chars", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_chars", "_get_chars"); - ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "kernings", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_kernings", "_get_kernings"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "chars", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_chars", "_get_chars"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "kernings", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_kernings", "_get_kernings"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "1,1024,1"), "set_height", "get_height"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ascent", PROPERTY_HINT_RANGE, "0,1024,1"), "set_ascent", "get_ascent"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "1,1024,1"), "set_height", "get_height"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ascent", PROPERTY_HINT_RANGE, "0,1024,1"), "set_ascent", "get_ascent"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_field"), "set_distance_field_hint", "is_distance_field_hint"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "fallback", PROPERTY_HINT_RESOURCE_TYPE, "BitmapFont"), "set_fallback", "get_fallback"); } BitmapFont::BitmapFont() { - clear(); } BitmapFont::~BitmapFont() { - clear(); } //////////// -RES ResourceFormatLoaderBMFont::load(const String &p_path, const String &p_original_path, Error *r_error) { - - if (r_error) +RES ResourceFormatLoaderBMFont::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { + if (r_error) { *r_error = ERR_FILE_CANT_OPEN; + } Ref<BitmapFont> font; font.instance(); @@ -657,8 +644,9 @@ RES ResourceFormatLoaderBMFont::load(const String &p_path, const String &p_origi Error err = font->create_from_fnt(p_path); if (err) { - if (r_error) + if (r_error) { *r_error = err; + } return RES(); } @@ -666,19 +654,17 @@ RES ResourceFormatLoaderBMFont::load(const String &p_path, const String &p_origi } void ResourceFormatLoaderBMFont::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("fnt"); } bool ResourceFormatLoaderBMFont::handles_type(const String &p_type) const { - return (p_type == "BitmapFont"); } String ResourceFormatLoaderBMFont::get_resource_type(const String &p_path) const { - String el = p_path.get_extension().to_lower(); - if (el == "fnt") + if (el == "fnt") { return "BitmapFont"; + } return ""; } diff --git a/scene/resources/font.h b/scene/resources/font.h index 411145c153..c739520da3 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -36,7 +36,6 @@ #include "scene/resources/texture.h" class Font : public Resource { - GDCLASS(Font, Resource); protected: @@ -47,8 +46,10 @@ public: virtual float get_ascent() const = 0; virtual float get_descent() const = 0; + virtual float get_underline_position() const = 0; + virtual float get_underline_thickness() const = 0; - virtual Size2 get_char_size(CharType p_char, CharType p_next = 0) const = 0; + virtual Size2 get_char_size(char32_t p_char, char32_t p_next = 0) const = 0; Size2 get_string_size(const String &p_string) const; Size2 get_wordwrap_string_size(const String &p_string, float p_width) const; @@ -58,7 +59,7 @@ public: void draw_halign(RID p_canvas_item, const Point2 &p_pos, HAlign p_align, float p_width, const String &p_text, const Color &p_modulate = Color(1, 1, 1), const Color &p_outline_modulate = Color(1, 1, 1)) const; virtual bool has_outline() const { return false; } - virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const = 0; + virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const = 0; void update_changes(); Font(); @@ -73,8 +74,8 @@ class FontDrawer { struct PendingDraw { RID canvas_item; Point2 pos; - CharType chr; - CharType next; + char32_t chr; + char32_t next; Color modulate; }; @@ -87,7 +88,7 @@ public: has_outline = p_font->has_outline(); } - float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1)) { + float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, const Color &p_modulate = Color(1, 1, 1)) { if (has_outline) { PendingDraw draw = { p_canvas_item, p_pos, p_char, p_next, p_modulate }; pending_draws.push_back(draw); @@ -104,15 +105,13 @@ public: }; class BitmapFont : public Font { - GDCLASS(BitmapFont, Font); RES_BASE_EXTENSION("font"); - Vector<Ref<Texture> > textures; + Vector<Ref<Texture2D>> textures; public: struct Character { - int texture_idx; Rect2 rect; float v_align; @@ -126,7 +125,6 @@ public: }; struct KerningPairKey { - union { struct { uint32_t A, B; @@ -139,17 +137,17 @@ public: }; private: - HashMap<CharType, Character> char_map; + HashMap<char32_t, Character> char_map; Map<KerningPairKey, int> kerning_map; float height; float ascent; bool distance_field_hint; - void _set_chars(const PoolVector<int> &p_chars); - PoolVector<int> _get_chars() const; - void _set_kernings(const PoolVector<int> &p_kernings); - PoolVector<int> _get_kernings() const; + void _set_chars(const Vector<int> &p_chars); + Vector<int> _get_chars() const; + void _set_kernings(const Vector<int> &p_kernings); + Vector<int> _get_kernings() const; void _set_textures(const Vector<Variant> &p_textures); Vector<Variant> _get_textures() const; @@ -162,27 +160,29 @@ public: Error create_from_fnt(const String &p_file); void set_height(float p_height); - float get_height() const; + float get_height() const override; void set_ascent(float p_ascent); - float get_ascent() const; - float get_descent() const; + float get_ascent() const override; + float get_descent() const override; + float get_underline_position() const override; + float get_underline_thickness() const override; - void add_texture(const Ref<Texture> &p_texture); - void add_char(CharType p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance = -1); + void add_texture(const Ref<Texture2D> &p_texture); + void add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance = -1); int get_character_count() const; - Vector<CharType> get_char_keys() const; - Character get_character(CharType p_char) const; + Vector<char32_t> get_char_keys() const; + Character get_character(char32_t p_char) const; int get_texture_count() const; - Ref<Texture> get_texture(int p_idx) const; + Ref<Texture2D> get_texture(int p_idx) const; - void add_kerning_pair(CharType p_A, CharType p_B, int p_kerning); - int get_kerning_pair(CharType p_A, CharType p_B) const; + void add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning); + int get_kerning_pair(char32_t p_A, char32_t p_B) const; Vector<KerningPairKey> get_kerning_pair_keys() const; - Size2 get_char_size(CharType p_char, CharType p_next = 0) const; + Size2 get_char_size(char32_t p_char, char32_t p_next = 0) const override; void set_fallback(const Ref<BitmapFont> &p_fallback); Ref<BitmapFont> get_fallback() const; @@ -190,9 +190,9 @@ public: void clear(); void set_distance_field_hint(bool p_distance_field); - bool is_distance_field_hint() const; + bool is_distance_field_hint() const override; - float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const; + float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const override; BitmapFont(); ~BitmapFont(); @@ -200,7 +200,7 @@ public: class ResourceFormatLoaderBMFont : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/scene/resources/gradient.cpp b/scene/resources/gradient.cpp index 6373436762..b720653f91 100644 --- a/scene/resources/gradient.cpp +++ b/scene/resources/gradient.cpp @@ -52,7 +52,6 @@ Gradient::~Gradient() { } void Gradient::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_point", "offset", "color"), &Gradient::add_point); ClassDB::bind_method(D_METHOD("remove_point", "offset"), &Gradient::remove_point); @@ -72,8 +71,8 @@ void Gradient::_bind_methods() { ClassDB::bind_method(D_METHOD(COLOR_RAMP_SET_COLORS, "colors"), &Gradient::set_colors); ClassDB::bind_method(D_METHOD(COLOR_RAMP_GET_COLORS), &Gradient::get_colors); - ADD_PROPERTY(PropertyInfo(Variant::POOL_REAL_ARRAY, "offsets"), COLOR_RAMP_SET_OFFSETS, COLOR_RAMP_GET_OFFSETS); - ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "colors"), COLOR_RAMP_SET_COLORS, COLOR_RAMP_GET_COLORS); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_FLOAT32_ARRAY, "offsets"), COLOR_RAMP_SET_OFFSETS, COLOR_RAMP_GET_OFFSETS); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "colors"), COLOR_RAMP_SET_COLORS, COLOR_RAMP_GET_COLORS); } Vector<float> Gradient::get_offsets() const { @@ -104,8 +103,9 @@ void Gradient::set_offsets(const Vector<float> &p_offsets) { } void Gradient::set_colors(const Vector<Color> &p_colors) { - if (points.size() < p_colors.size()) + if (points.size() < p_colors.size()) { is_sorted = false; + } points.resize(p_colors.size()); for (int i = 0; i < points.size(); i++) { points.write[i].color = p_colors[i]; @@ -118,7 +118,6 @@ Vector<Gradient::Point> &Gradient::get_points() { } void Gradient::add_point(float p_offset, const Color &p_color) { - Point p; p.offset = p_offset; p.color = p_color; @@ -129,7 +128,6 @@ void Gradient::add_point(float p_offset, const Color &p_color) { } void Gradient::remove_point(int p_index) { - ERR_FAIL_INDEX(p_index, points.size()); ERR_FAIL_COND(points.size() <= 1); points.remove(p_index); @@ -143,32 +141,29 @@ void Gradient::set_points(Vector<Gradient::Point> &p_points) { } void Gradient::set_offset(int pos, const float offset) { - - ERR_FAIL_COND(pos < 0); - if (points.size() <= pos) - points.resize(pos + 1); + ERR_FAIL_INDEX(pos, points.size()); + _update_sorting(); points.write[pos].offset = offset; is_sorted = false; emit_signal(CoreStringNames::get_singleton()->changed); } -float Gradient::get_offset(int pos) const { +float Gradient::get_offset(int pos) { ERR_FAIL_INDEX_V(pos, points.size(), 0.0); + _update_sorting(); return points[pos].offset; } void Gradient::set_color(int pos, const Color &color) { - ERR_FAIL_COND(pos < 0); - if (points.size() <= pos) { - points.resize(pos + 1); - is_sorted = false; - } + ERR_FAIL_INDEX(pos, points.size()); + _update_sorting(); points.write[pos].color = color; emit_signal(CoreStringNames::get_singleton()->changed); } -Color Gradient::get_color(int pos) const { +Color Gradient::get_color(int pos) { ERR_FAIL_INDEX_V(pos, points.size(), Color()); + _update_sorting(); return points[pos].color; } diff --git a/scene/resources/gradient.h b/scene/resources/gradient.h index 2d98f799e2..6518b13ee8 100644 --- a/scene/resources/gradient.h +++ b/scene/resources/gradient.h @@ -39,7 +39,6 @@ class Gradient : public Resource { public: struct Point { - float offset; Color color; bool operator<(const Point &p_ponit) const { @@ -50,6 +49,12 @@ public: private: Vector<Point> points; bool is_sorted; + _FORCE_INLINE_ void _update_sorting() { + if (!is_sorted) { + points.sort(); + is_sorted = true; + } + } protected: static void _bind_methods(); @@ -65,10 +70,10 @@ public: Vector<Point> &get_points(); void set_offset(int pos, const float offset); - float get_offset(int pos) const; + float get_offset(int pos); void set_color(int pos, const Color &color); - Color get_color(int pos) const; + Color get_color(int pos); void set_offsets(const Vector<float> &p_offsets); Vector<float> get_offsets() const; @@ -77,23 +82,21 @@ public: Vector<Color> get_colors() const; _FORCE_INLINE_ Color get_color_at_offset(float p_offset) { - - if (points.empty()) + if (points.empty()) { return Color(0, 0, 0, 1); - - if (!is_sorted) { - points.sort(); - is_sorted = true; } + _update_sorting(); + //binary search int low = 0; int high = points.size() - 1; int middle = 0; #ifdef DEBUG_ENABLED - if (low > high) + if (low > high) { ERR_PRINT("low > high, this may be a bug"); + } #endif while (low <= high) { @@ -114,13 +117,15 @@ public: } int first = middle; int second = middle + 1; - if (second >= points.size()) + if (second >= points.size()) { return points[points.size() - 1].color; - if (first < 0) + } + if (first < 0) { return points[0].color; + } const Point &pointFirst = points[first]; const Point &pointSecond = points[second]; - return pointFirst.color.linear_interpolate(pointSecond.color, (p_offset - pointFirst.offset) / (pointSecond.offset - pointFirst.offset)); + return pointFirst.color.lerp(pointSecond.color, (p_offset - pointFirst.offset) / (pointSecond.offset - pointFirst.offset)); } int get_points_count() const; diff --git a/scene/resources/height_map_shape.cpp b/scene/resources/height_map_shape_3d.cpp index 2b86d658d8..2ae47bcf3c 100644 --- a/scene/resources/height_map_shape.cpp +++ b/scene/resources/height_map_shape_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* height_map_shape.cpp */ +/* height_map_shape_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,21 +28,20 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "height_map_shape.h" -#include "servers/physics_server.h" +#include "height_map_shape_3d.h" +#include "servers/physics_server_3d.h" -Vector<Vector3> HeightMapShape::get_debug_mesh_lines() { +Vector<Vector3> HeightMapShape3D::get_debug_mesh_lines() const { Vector<Vector3> points; if ((map_width != 0) && (map_depth != 0)) { - // This will be slow for large maps... // also we'll have to figure out how well bullet centers this shape... Vector2 size(map_width - 1, map_depth - 1); Vector2 start = size * -0.5; - PoolRealArray::Read r = map_data.read(); + const real_t *r = map_data.ptr(); // reserve some memory for our points.. points.resize(((map_width - 1) * map_depth * 2) + (map_width * (map_depth - 1) * 2)); @@ -76,19 +75,22 @@ Vector<Vector3> HeightMapShape::get_debug_mesh_lines() { return points; } -void HeightMapShape::_update_shape() { +real_t HeightMapShape3D::get_enclosing_radius() const { + return Vector3(real_t(map_width), max_height - min_height, real_t(map_depth)).length(); +} +void HeightMapShape3D::_update_shape() { Dictionary d; d["width"] = map_width; d["depth"] = map_depth; d["heights"] = map_data; d["min_height"] = min_height; d["max_height"] = max_height; - PhysicsServer::get_singleton()->shape_set_data(get_shape(), d); - Shape::_update_shape(); + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), d); + Shape3D::_update_shape(); } -void HeightMapShape::set_map_width(int p_new) { +void HeightMapShape3D::set_map_width(int p_new) { if (p_new < 1) { // ignore } else if (map_width != p_new) { @@ -98,7 +100,7 @@ void HeightMapShape::set_map_width(int p_new) { int new_size = map_width * map_depth; map_data.resize(map_width * map_depth); - PoolRealArray::Write w = map_data.write(); + real_t *w = map_data.ptrw(); while (was_size < new_size) { w[was_size++] = 0.0; } @@ -110,11 +112,11 @@ void HeightMapShape::set_map_width(int p_new) { } } -int HeightMapShape::get_map_width() const { +int HeightMapShape3D::get_map_width() const { return map_width; } -void HeightMapShape::set_map_depth(int p_new) { +void HeightMapShape3D::set_map_depth(int p_new) { if (p_new < 1) { // ignore } else if (map_depth != p_new) { @@ -124,7 +126,7 @@ void HeightMapShape::set_map_depth(int p_new) { int new_size = map_width * map_depth; map_data.resize(new_size); - PoolRealArray::Write w = map_data.write(); + real_t *w = map_data.ptrw(); while (was_size < new_size) { w[was_size++] = 0.0; } @@ -136,11 +138,11 @@ void HeightMapShape::set_map_depth(int p_new) { } } -int HeightMapShape::get_map_depth() const { +int HeightMapShape3D::get_map_depth() const { return map_depth; } -void HeightMapShape::set_map_data(PoolRealArray p_new) { +void HeightMapShape3D::set_map_data(PackedFloat32Array p_new) { int size = (map_width * map_depth); if (p_new.size() != size) { // fail @@ -148,8 +150,8 @@ void HeightMapShape::set_map_data(PoolRealArray p_new) { } // copy - PoolRealArray::Write w = map_data.write(); - PoolRealArray::Read r = p_new.read(); + real_t *w = map_data.ptrw(); + const real_t *r = p_new.ptr(); for (int i = 0; i < size; i++) { float val = r[i]; w[i] = val; @@ -157,11 +159,13 @@ void HeightMapShape::set_map_data(PoolRealArray p_new) { min_height = val; max_height = val; } else { - if (min_height > val) + if (min_height > val) { min_height = val; + } - if (max_height < val) + if (max_height < val) { max_height = val; + } } } @@ -170,30 +174,29 @@ void HeightMapShape::set_map_data(PoolRealArray p_new) { _change_notify("map_data"); } -PoolRealArray HeightMapShape::get_map_data() const { +PackedFloat32Array HeightMapShape3D::get_map_data() const { return map_data; } -void HeightMapShape::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_map_width", "width"), &HeightMapShape::set_map_width); - ClassDB::bind_method(D_METHOD("get_map_width"), &HeightMapShape::get_map_width); - ClassDB::bind_method(D_METHOD("set_map_depth", "height"), &HeightMapShape::set_map_depth); - ClassDB::bind_method(D_METHOD("get_map_depth"), &HeightMapShape::get_map_depth); - ClassDB::bind_method(D_METHOD("set_map_data", "data"), &HeightMapShape::set_map_data); - ClassDB::bind_method(D_METHOD("get_map_data"), &HeightMapShape::get_map_data); +void HeightMapShape3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_map_width", "width"), &HeightMapShape3D::set_map_width); + ClassDB::bind_method(D_METHOD("get_map_width"), &HeightMapShape3D::get_map_width); + ClassDB::bind_method(D_METHOD("set_map_depth", "height"), &HeightMapShape3D::set_map_depth); + ClassDB::bind_method(D_METHOD("get_map_depth"), &HeightMapShape3D::get_map_depth); + ClassDB::bind_method(D_METHOD("set_map_data", "data"), &HeightMapShape3D::set_map_data); + ClassDB::bind_method(D_METHOD("get_map_data"), &HeightMapShape3D::get_map_data); ADD_PROPERTY(PropertyInfo(Variant::INT, "map_width", PROPERTY_HINT_RANGE, "1,4096,1"), "set_map_width", "get_map_width"); ADD_PROPERTY(PropertyInfo(Variant::INT, "map_depth", PROPERTY_HINT_RANGE, "1,4096,1"), "set_map_depth", "get_map_depth"); - ADD_PROPERTY(PropertyInfo(Variant::POOL_REAL_ARRAY, "map_data"), "set_map_data", "get_map_data"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_FLOAT32_ARRAY, "map_data"), "set_map_data", "get_map_data"); } -HeightMapShape::HeightMapShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_HEIGHTMAP)) { - +HeightMapShape3D::HeightMapShape3D() : + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_HEIGHTMAP)) { map_width = 2; map_depth = 2; map_data.resize(map_width * map_depth); - PoolRealArray::Write w = map_data.write(); + real_t *w = map_data.ptrw(); w[0] = 0.0; w[1] = 0.0; w[2] = 0.0; diff --git a/scene/resources/height_map_shape.h b/scene/resources/height_map_shape_3d.h index 3a976e3add..9ee8b49689 100644 --- a/scene/resources/height_map_shape.h +++ b/scene/resources/height_map_shape_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* height_map_shape.h */ +/* height_map_shape_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -31,32 +31,33 @@ #ifndef HEIGHT_MAP_SHAPE_H #define HEIGHT_MAP_SHAPE_H -#include "scene/resources/shape.h" +#include "scene/resources/shape_3d.h" -class HeightMapShape : public Shape { - GDCLASS(HeightMapShape, Shape); +class HeightMapShape3D : public Shape3D { + GDCLASS(HeightMapShape3D, Shape3D); int map_width; int map_depth; - PoolRealArray map_data; + PackedFloat32Array map_data; float min_height; float max_height; protected: static void _bind_methods(); - virtual void _update_shape(); + virtual void _update_shape() override; public: void set_map_width(int p_new); int get_map_width() const; void set_map_depth(int p_new); int get_map_depth() const; - void set_map_data(PoolRealArray p_new); - PoolRealArray get_map_data() const; + void set_map_data(PackedFloat32Array p_new); + PackedFloat32Array get_map_data() const; - virtual Vector<Vector3> get_debug_mesh_lines(); + virtual Vector<Vector3> get_debug_mesh_lines() const override; + virtual real_t get_enclosing_radius() const override; - HeightMapShape(); + HeightMapShape3D(); }; #endif /* !HEIGHT_MAP_SHAPE_H */ diff --git a/scene/resources/line_shape_2d.cpp b/scene/resources/line_shape_2d.cpp index 7f39467403..58653c5f4a 100644 --- a/scene/resources/line_shape_2d.cpp +++ b/scene/resources/line_shape_2d.cpp @@ -30,65 +30,61 @@ #include "line_shape_2d.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "core/math/geometry_2d.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" bool LineShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { - - Vector2 point = get_d() * get_normal(); + Vector2 point = get_distance() * get_normal(); Vector2 l[2][2] = { { point - get_normal().tangent() * 100, point + get_normal().tangent() * 100 }, { point, point + get_normal() * 30 } }; for (int i = 0; i < 2; i++) { - Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point, l[i]); - if (p_point.distance_to(closest) < p_tolerance) + Vector2 closest = Geometry2D::get_closest_point_to_segment(p_point, l[i]); + if (p_point.distance_to(closest) < p_tolerance) { return true; + } } return false; } void LineShape2D::_update_shape() { - Array arr; arr.push_back(normal); - arr.push_back(d); - Physics2DServer::get_singleton()->shape_set_data(get_rid(), arr); + arr.push_back(distance); + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), arr); emit_changed(); } void LineShape2D::set_normal(const Vector2 &p_normal) { - normal = p_normal; _update_shape(); } -void LineShape2D::set_d(real_t p_d) { - - d = p_d; +void LineShape2D::set_distance(real_t p_distance) { + distance = p_distance; _update_shape(); } Vector2 LineShape2D::get_normal() const { - return normal; } -real_t LineShape2D::get_d() const { - return d; +real_t LineShape2D::get_distance() const { + return distance; } void LineShape2D::draw(const RID &p_to_rid, const Color &p_color) { - - Vector2 point = get_d() * get_normal(); + Vector2 point = get_distance() * get_normal(); Vector2 l1[2] = { point - get_normal().tangent() * 100, point + get_normal().tangent() * 100 }; - VS::get_singleton()->canvas_item_add_line(p_to_rid, l1[0], l1[1], p_color, 3); + RS::get_singleton()->canvas_item_add_line(p_to_rid, l1[0], l1[1], p_color, 3); Vector2 l2[2] = { point, point + get_normal() * 30 }; - VS::get_singleton()->canvas_item_add_line(p_to_rid, l2[0], l2[1], p_color, 3); + RS::get_singleton()->canvas_item_add_line(p_to_rid, l2[0], l2[1], p_color, 3); } -Rect2 LineShape2D::get_rect() const { - Vector2 point = get_d() * get_normal(); +Rect2 LineShape2D::get_rect() const { + Vector2 point = get_distance() * get_normal(); Vector2 l1[2] = { point - get_normal().tangent() * 100, point + get_normal().tangent() * 100 }; Vector2 l2[2] = { point, point + get_normal() * 30 }; @@ -100,22 +96,24 @@ Rect2 LineShape2D::get_rect() const { return rect; } -void LineShape2D::_bind_methods() { +real_t LineShape2D::get_enclosing_radius() const { + return distance; +} +void LineShape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_normal", "normal"), &LineShape2D::set_normal); ClassDB::bind_method(D_METHOD("get_normal"), &LineShape2D::get_normal); - ClassDB::bind_method(D_METHOD("set_d", "d"), &LineShape2D::set_d); - ClassDB::bind_method(D_METHOD("get_d"), &LineShape2D::get_d); + ClassDB::bind_method(D_METHOD("set_distance", "distance"), &LineShape2D::set_distance); + ClassDB::bind_method(D_METHOD("get_distance"), &LineShape2D::get_distance); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "normal"), "set_normal", "get_normal"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "d"), "set_d", "get_d"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance"), "set_distance", "get_distance"); } LineShape2D::LineShape2D() : - Shape2D(Physics2DServer::get_singleton()->line_shape_create()) { - - normal = Vector2(0, -1); - d = 0; + Shape2D(PhysicsServer2D::get_singleton()->line_shape_create()) { + normal = Vector2(0, 1); + distance = 0; _update_shape(); } diff --git a/scene/resources/line_shape_2d.h b/scene/resources/line_shape_2d.h index 7babfe12f6..7e67a8f67c 100644 --- a/scene/resources/line_shape_2d.h +++ b/scene/resources/line_shape_2d.h @@ -37,7 +37,7 @@ class LineShape2D : public Shape2D { GDCLASS(LineShape2D, Shape2D); Vector2 normal; - real_t d; + real_t distance; void _update_shape(); @@ -45,16 +45,17 @@ protected: static void _bind_methods(); public: - virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override; void set_normal(const Vector2 &p_normal); - void set_d(real_t p_d); + void set_distance(real_t p_distance); Vector2 get_normal() const; - real_t get_d() const; + real_t get_distance() const; - virtual void draw(const RID &p_to_rid, const Color &p_color); - virtual Rect2 get_rect() const; + virtual void draw(const RID &p_to_rid, const Color &p_color) override; + virtual Rect2 get_rect() const override; + virtual real_t get_enclosing_radius() const override; LineShape2D(); }; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index ab4dbb758a..1e95a35726 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -39,52 +39,48 @@ #include "scene/scene_string_names.h" void Material::set_next_pass(const Ref<Material> &p_pass) { - - for (Ref<Material> pass_child = p_pass; pass_child != NULL; pass_child = pass_child->get_next_pass()) { + for (Ref<Material> pass_child = p_pass; pass_child != nullptr; pass_child = pass_child->get_next_pass()) { ERR_FAIL_COND_MSG(pass_child == this, "Can't set as next_pass one of its parents to prevent crashes due to recursive loop."); } - if (next_pass == p_pass) + if (next_pass == p_pass) { return; + } next_pass = p_pass; RID next_pass_rid; - if (next_pass.is_valid()) + if (next_pass.is_valid()) { next_pass_rid = next_pass->get_rid(); - VS::get_singleton()->material_set_next_pass(material, next_pass_rid); + } + RS::get_singleton()->material_set_next_pass(material, next_pass_rid); } Ref<Material> Material::get_next_pass() const { - return next_pass; } void Material::set_render_priority(int p_priority) { - ERR_FAIL_COND(p_priority < RENDER_PRIORITY_MIN); ERR_FAIL_COND(p_priority > RENDER_PRIORITY_MAX); render_priority = p_priority; - VS::get_singleton()->material_set_render_priority(material, p_priority); + RS::get_singleton()->material_set_render_priority(material, p_priority); } int Material::get_render_priority() const { - return render_priority; } RID Material::get_rid() const { - return material; } -void Material::_validate_property(PropertyInfo &property) const { +void Material::_validate_property(PropertyInfo &property) const { if (!_can_do_next_pass() && property.name == "next_pass") { property.usage = 0; } } void Material::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_next_pass", "next_pass"), &Material::set_next_pass); ClassDB::bind_method(D_METHOD("get_next_pass"), &Material::get_next_pass); @@ -99,22 +95,18 @@ void Material::_bind_methods() { } Material::Material() { - - material = VisualServer::get_singleton()->material_create(); + material = RenderingServer::get_singleton()->material_create(); render_priority = 0; } Material::~Material() { - - VisualServer::get_singleton()->free(material); + RenderingServer::get_singleton()->free(material); } /////////////////////////////////// bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) { - if (shader.is_valid()) { - StringName pr = shader->remap_param(p_name); if (!pr) { String n = p_name; @@ -126,7 +118,7 @@ bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) { } } if (pr) { - VisualServer::get_singleton()->material_set_param(_get_material(), pr, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), pr, p_value); return true; } } @@ -135,9 +127,7 @@ bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) { } bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const { - if (shader.is_valid()) { - StringName pr = shader->remap_param(p_name); if (!pr) { String n = p_name; @@ -150,7 +140,7 @@ bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const { } if (pr) { - r_ret = VisualServer::get_singleton()->material_get_param(_get_material(), pr); + r_ret = RenderingServer::get_singleton()->material_get_param(_get_material(), pr); return true; } } @@ -159,19 +149,16 @@ bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const { } void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const { - if (!shader.is_null()) { - shader->get_param_list(p_list); } } bool ShaderMaterial::property_can_revert(const String &p_name) { if (shader.is_valid()) { - StringName pr = shader->remap_param(p_name); if (pr) { - Variant default_value = VisualServer::get_singleton()->material_get_param_default(_get_material(), pr); + Variant default_value = RenderingServer::get_singleton()->shader_get_param_default(shader->get_rid(), pr); Variant current_value; _get(p_name, current_value); return default_value.get_type() != Variant::NIL && default_value != current_value; @@ -185,19 +172,18 @@ Variant ShaderMaterial::property_get_revert(const String &p_name) { if (shader.is_valid()) { StringName pr = shader->remap_param(p_name); if (pr) { - r_ret = VisualServer::get_singleton()->material_get_param_default(_get_material(), pr); + r_ret = RenderingServer::get_singleton()->shader_get_param_default(shader->get_rid(), pr); } } return r_ret; } void ShaderMaterial::set_shader(const Ref<Shader> &p_shader) { - // Only connect/disconnect the signal when running in the editor. // This can be a slow operation, and `_change_notify()` (which is called by `_shader_changed()`) // does nothing in non-editor builds anyway. See GH-34741 for details. if (shader.is_valid() && Engine::get_singleton()->is_editor_hint()) { - shader->disconnect("changed", this, "_shader_changed"); + shader->disconnect("changed", callable_mp(this, &ShaderMaterial::_shader_changed)); } shader = p_shader; @@ -207,28 +193,25 @@ void ShaderMaterial::set_shader(const Ref<Shader> &p_shader) { rid = shader->get_rid(); if (Engine::get_singleton()->is_editor_hint()) { - shader->connect("changed", this, "_shader_changed"); + shader->connect("changed", callable_mp(this, &ShaderMaterial::_shader_changed)); } } - VS::get_singleton()->material_set_shader(_get_material(), rid); + RS::get_singleton()->material_set_shader(_get_material(), rid); _change_notify(); //properties for shader exposed emit_changed(); } Ref<Shader> ShaderMaterial::get_shader() const { - return shader; } void ShaderMaterial::set_shader_param(const StringName &p_param, const Variant &p_value) { - - VS::get_singleton()->material_set_param(_get_material(), p_param, p_value); + RS::get_singleton()->material_set_param(_get_material(), p_param, p_value); } Variant ShaderMaterial::get_shader_param(const StringName &p_param) const { - - return VS::get_singleton()->material_get_param(_get_material(), p_param); + return RS::get_singleton()->material_get_param(_get_material(), p_param); } void ShaderMaterial::_shader_changed() { @@ -236,12 +219,10 @@ void ShaderMaterial::_shader_changed() { } void ShaderMaterial::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_shader", "shader"), &ShaderMaterial::set_shader); ClassDB::bind_method(D_METHOD("get_shader"), &ShaderMaterial::get_shader); ClassDB::bind_method(D_METHOD("set_shader_param", "param", "value"), &ShaderMaterial::set_shader_param); ClassDB::bind_method(D_METHOD("get_shader_param", "param"), &ShaderMaterial::get_shader_param); - ClassDB::bind_method(D_METHOD("_shader_changed"), &ShaderMaterial::_shader_changed); 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); @@ -249,7 +230,6 @@ void ShaderMaterial::_bind_methods() { } void ShaderMaterial::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { - #ifdef TOOLS_ENABLED const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", 0) ? "'" : "\""; #else @@ -258,7 +238,6 @@ void ShaderMaterial::get_argument_options(const StringName &p_function, int p_id String f = p_function.operator String(); if ((f == "get_shader_param" || f == "set_shader_param") && p_idx == 0) { - if (shader.is_valid()) { List<PropertyInfo> pl; shader->get_param_list(&pl); @@ -271,15 +250,15 @@ void ShaderMaterial::get_argument_options(const StringName &p_function, int p_id } bool ShaderMaterial::_can_do_next_pass() const { - return shader.is_valid() && shader->get_mode() == Shader::MODE_SPATIAL; } Shader::Mode ShaderMaterial::get_shader_mode() const { - if (shader.is_valid()) + if (shader.is_valid()) { return shader->get_mode(); - else + } else { return Shader::MODE_SPATIAL; + } } ShaderMaterial::ShaderMaterial() { @@ -290,18 +269,13 @@ ShaderMaterial::~ShaderMaterial() { ///////////////////////////////// -Mutex *SpatialMaterial::material_mutex = NULL; -SelfList<SpatialMaterial>::List *SpatialMaterial::dirty_materials = NULL; -Map<SpatialMaterial::MaterialKey, SpatialMaterial::ShaderData> SpatialMaterial::shader_map; -SpatialMaterial::ShaderNames *SpatialMaterial::shader_names = NULL; - -void SpatialMaterial::init_shaders() { +Mutex BaseMaterial3D::material_mutex; +SelfList<BaseMaterial3D>::List *BaseMaterial3D::dirty_materials = nullptr; +Map<BaseMaterial3D::MaterialKey, BaseMaterial3D::ShaderData> BaseMaterial3D::shader_map; +BaseMaterial3D::ShaderNames *BaseMaterial3D::shader_names = nullptr; -#ifndef NO_THREADS - material_mutex = Mutex::create(); -#endif - - dirty_materials = memnew(SelfList<SpatialMaterial>::List); +void BaseMaterial3D::init_shaders() { + dirty_materials = memnew(SelfList<BaseMaterial3D>::List); shader_names = memnew(ShaderNames); @@ -317,9 +291,9 @@ void SpatialMaterial::init_shaders() { shader_names->clearcoat = "clearcoat"; shader_names->clearcoat_gloss = "clearcoat_gloss"; shader_names->anisotropy = "anisotropy_ratio"; - shader_names->depth_scale = "depth_scale"; + shader_names->heightmap_scale = "heightmap_scale"; shader_names->subsurface_scattering_strength = "subsurface_scattering_strength"; - shader_names->transmission = "transmission"; + shader_names->backlight = "backlight"; shader_names->refraction = "refraction"; shader_names->point_size = "point_size"; shader_names->uv1_scale = "uv1_scale"; @@ -332,9 +306,9 @@ void SpatialMaterial::init_shaders() { shader_names->particles_anim_h_frames = "particles_anim_h_frames"; shader_names->particles_anim_v_frames = "particles_anim_v_frames"; shader_names->particles_anim_loop = "particles_anim_loop"; - shader_names->depth_min_layers = "depth_min_layers"; - shader_names->depth_max_layers = "depth_max_layers"; - shader_names->depth_flip = "depth_flip"; + shader_names->heightmap_min_layers = "heightmap_min_layers"; + shader_names->heightmap_max_layers = "heightmap_max_layers"; + shader_names->heightmap_flip = "heightmap_flip"; shader_names->grow = "grow"; @@ -345,14 +319,18 @@ void SpatialMaterial::init_shaders() { shader_names->distance_fade_max = "distance_fade_max"; shader_names->metallic_texture_channel = "metallic_texture_channel"; - shader_names->roughness_texture_channel = "roughness_texture_channel"; shader_names->ao_texture_channel = "ao_texture_channel"; shader_names->clearcoat_texture_channel = "clearcoat_texture_channel"; shader_names->rim_texture_channel = "rim_texture_channel"; - shader_names->depth_texture_channel = "depth_texture_channel"; + shader_names->heightmap_texture_channel = "heightmap_texture_channel"; shader_names->refraction_texture_channel = "refraction_texture_channel"; shader_names->alpha_scissor_threshold = "alpha_scissor_threshold"; + shader_names->transmittance_color = "transmittance_color"; + shader_names->transmittance_curve = "transmittance_curve"; + shader_names->transmittance_depth = "transmittance_depth"; + shader_names->transmittance_boost = "transmittance_boost"; + shader_names->texture_names[TEXTURE_ALBEDO] = "texture_albedo"; shader_names->texture_names[TEXTURE_METALLIC] = "texture_metallic"; shader_names->texture_names[TEXTURE_ROUGHNESS] = "texture_roughness"; @@ -362,46 +340,43 @@ void SpatialMaterial::init_shaders() { shader_names->texture_names[TEXTURE_CLEARCOAT] = "texture_clearcoat"; shader_names->texture_names[TEXTURE_FLOWMAP] = "texture_flowmap"; shader_names->texture_names[TEXTURE_AMBIENT_OCCLUSION] = "texture_ambient_occlusion"; - shader_names->texture_names[TEXTURE_DEPTH] = "texture_depth"; + shader_names->texture_names[TEXTURE_HEIGHTMAP] = "texture_heightmap"; shader_names->texture_names[TEXTURE_SUBSURFACE_SCATTERING] = "texture_subsurface_scattering"; - shader_names->texture_names[TEXTURE_TRANSMISSION] = "texture_transmission"; + shader_names->texture_names[TEXTURE_SUBSURFACE_TRANSMITTANCE] = "texture_subsurface_transmittance"; + shader_names->texture_names[TEXTURE_BACKLIGHT] = "texture_backlight"; shader_names->texture_names[TEXTURE_REFRACTION] = "texture_refraction"; shader_names->texture_names[TEXTURE_DETAIL_MASK] = "texture_detail_mask"; shader_names->texture_names[TEXTURE_DETAIL_ALBEDO] = "texture_detail_albedo"; shader_names->texture_names[TEXTURE_DETAIL_NORMAL] = "texture_detail_normal"; + shader_names->texture_names[TEXTURE_ORM] = "texture_orm"; } -Ref<SpatialMaterial> SpatialMaterial::materials_for_2d[SpatialMaterial::MAX_MATERIALS_FOR_2D]; - -void SpatialMaterial::finish_shaders() { +Ref<StandardMaterial3D> BaseMaterial3D::materials_for_2d[BaseMaterial3D::MAX_MATERIALS_FOR_2D]; +void BaseMaterial3D::finish_shaders() { for (int i = 0; i < MAX_MATERIALS_FOR_2D; i++) { materials_for_2d[i].unref(); } -#ifndef NO_THREADS - memdelete(material_mutex); -#endif - memdelete(dirty_materials); - dirty_materials = NULL; + dirty_materials = nullptr; memdelete(shader_names); } -void SpatialMaterial::_update_shader() { - +void BaseMaterial3D::_update_shader() { dirty_materials->remove(&element); MaterialKey mk = _compute_key(); - if (mk.key == current_key.key) + if (mk == current_key) { return; //no update required in the end + } if (shader_map.has(current_key)) { shader_map[current_key].users--; if (shader_map[current_key].users == 0) { //deallocate shader, as it's no longer in use - VS::get_singleton()->free(shader_map[current_key].shader); + RS::get_singleton()->free(shader_map[current_key].shader); shader_map.erase(current_key); } } @@ -409,20 +384,57 @@ void SpatialMaterial::_update_shader() { current_key = mk; if (shader_map.has(mk)) { - - VS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); + RS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); shader_map[mk].users++; return; } + String texfilter_str; + switch (texture_filter) { + case TEXTURE_FILTER_NEAREST: + texfilter_str = "filter_nearest"; + break; + case TEXTURE_FILTER_LINEAR: + texfilter_str = "filter_linear"; + break; + case TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: + texfilter_str = "filter_nearest_mipmap"; + break; + case TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: + texfilter_str = "filter_linear_mipmap"; + break; + case TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: + texfilter_str = "filter_nearest_mipmap_aniso"; + break; + case TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: + texfilter_str = "filter_linear_mipmap_aniso"; + break; + case TEXTURE_FILTER_MAX: + break; // Internal value, skip. + } + + if (flags[FLAG_USE_TEXTURE_REPEAT]) { + texfilter_str += ",repeat_enable"; + } else { + texfilter_str += ",repeat_disable"; + } + //must create a shader! String code = "shader_type spatial;\nrender_mode "; switch (blend_mode) { - case BLEND_MODE_MIX: code += "blend_mix"; break; - case BLEND_MODE_ADD: code += "blend_add"; break; - case BLEND_MODE_SUB: code += "blend_sub"; break; - case BLEND_MODE_MUL: code += "blend_mul"; break; + case BLEND_MODE_MIX: + code += "blend_mix"; + break; + case BLEND_MODE_ADD: + code += "blend_add"; + break; + case BLEND_MODE_SUB: + code += "blend_sub"; + break; + case BLEND_MODE_MUL: + code += "blend_mul"; + break; } DepthDrawMode ddm = depth_draw_mode; @@ -431,62 +443,92 @@ void SpatialMaterial::_update_shader() { } switch (ddm) { - case DEPTH_DRAW_OPAQUE_ONLY: code += ",depth_draw_opaque"; break; - case DEPTH_DRAW_ALWAYS: code += ",depth_draw_always"; break; - case DEPTH_DRAW_DISABLED: code += ",depth_draw_never"; break; - case DEPTH_DRAW_ALPHA_OPAQUE_PREPASS: code += ",depth_draw_alpha_prepass"; break; + case DEPTH_DRAW_OPAQUE_ONLY: + code += ",depth_draw_opaque"; + break; + case DEPTH_DRAW_ALWAYS: + code += ",depth_draw_always"; + break; + case DEPTH_DRAW_DISABLED: + code += ",depth_draw_never"; + break; + } + + if (transparency == TRANSPARENCY_ALPHA_DEPTH_PRE_PASS) { + code += ",depth_prepass_alpha"; } switch (cull_mode) { - case CULL_BACK: code += ",cull_back"; break; - case CULL_FRONT: code += ",cull_front"; break; - case CULL_DISABLED: code += ",cull_disabled"; break; + case CULL_BACK: + code += ",cull_back"; + break; + case CULL_FRONT: + code += ",cull_front"; + break; + case CULL_DISABLED: + code += ",cull_disabled"; + break; } switch (diffuse_mode) { - case DIFFUSE_BURLEY: code += ",diffuse_burley"; break; - case DIFFUSE_LAMBERT: code += ",diffuse_lambert"; break; - case DIFFUSE_LAMBERT_WRAP: code += ",diffuse_lambert_wrap"; break; - case DIFFUSE_OREN_NAYAR: code += ",diffuse_oren_nayar"; break; - case DIFFUSE_TOON: code += ",diffuse_toon"; break; + case DIFFUSE_BURLEY: + code += ",diffuse_burley"; + break; + case DIFFUSE_LAMBERT: + code += ",diffuse_lambert"; + break; + case DIFFUSE_LAMBERT_WRAP: + code += ",diffuse_lambert_wrap"; + break; + case DIFFUSE_OREN_NAYAR: + code += ",diffuse_oren_nayar"; + break; + case DIFFUSE_TOON: + code += ",diffuse_toon"; + break; } switch (specular_mode) { - case SPECULAR_SCHLICK_GGX: code += ",specular_schlick_ggx"; break; - case SPECULAR_BLINN: code += ",specular_blinn"; break; - case SPECULAR_PHONG: code += ",specular_phong"; break; - case SPECULAR_TOON: code += ",specular_toon"; break; - case SPECULAR_DISABLED: code += ",specular_disabled"; break; - } - - if (flags[FLAG_UNSHADED]) { + case SPECULAR_SCHLICK_GGX: + code += ",specular_schlick_ggx"; + break; + case SPECULAR_BLINN: + code += ",specular_blinn"; + break; + case SPECULAR_PHONG: + code += ",specular_phong"; + break; + case SPECULAR_TOON: + code += ",specular_toon"; + break; + case SPECULAR_DISABLED: + code += ",specular_disabled"; + break; + } + if (features[FEATURE_SUBSURFACE_SCATTERING] && flags[FLAG_SUBSURFACE_MODE_SKIN]) { + code += ",sss_mode_skin"; + } + + if (shading_mode == SHADING_MODE_UNSHADED) { code += ",unshaded"; } if (flags[FLAG_DISABLE_DEPTH_TEST]) { - code += ",depth_test_disable"; + code += ",depth_test_disabled"; } - if (flags[FLAG_USE_VERTEX_LIGHTING]) { + if (shading_mode == SHADING_MODE_PER_VERTEX) { code += ",vertex_lighting"; } - if (flags[FLAG_TRIPLANAR_USE_WORLD] && (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR])) { - code += ",world_vertex_coords"; - } if (flags[FLAG_DONT_RECEIVE_SHADOWS]) { code += ",shadows_disabled"; } if (flags[FLAG_DISABLE_AMBIENT_LIGHT]) { code += ",ambient_light_disabled"; } - if (flags[FLAG_ENSURE_CORRECT_NORMALS]) { - code += ",ensure_correct_normals"; - } if (flags[FLAG_USE_SHADOW_TO_OPACITY]) { code += ",shadow_to_opacity"; } code += ";\n"; code += "uniform vec4 albedo : hint_color;\n"; - code += "uniform sampler2D texture_albedo : hint_albedo;\n"; - code += "uniform float specular;\n"; - code += "uniform float metallic;\n"; + code += "uniform sampler2D texture_albedo : hint_albedo," + texfilter_str + ";\n"; if (grow_enabled) { code += "uniform float grow;\n"; } @@ -499,21 +541,41 @@ void SpatialMaterial::_update_shader() { code += "uniform float distance_fade_max;\n"; } - if (flags[FLAG_USE_ALPHA_SCISSOR]) { + if (transparency == TRANSPARENCY_ALPHA_SCISSOR) { code += "uniform float alpha_scissor_threshold;\n"; } - code += "uniform float roughness : hint_range(0,1);\n"; + code += "uniform float point_size : hint_range(0,128);\n"; - if (textures[TEXTURE_METALLIC] != NULL) { - code += "uniform sampler2D texture_metallic : hint_white;\n"; + //TODO ALL HINTS + if (!orm) { + code += "uniform float roughness : hint_range(0,1);\n"; + code += "uniform sampler2D texture_metallic : hint_white," + texfilter_str + ";\n"; code += "uniform vec4 metallic_texture_channel;\n"; - } + switch (roughness_texture_channel) { + case TEXTURE_CHANNEL_RED: { + code += "uniform sampler2D texture_roughness : hint_roughness_r," + texfilter_str + ";\n"; + } break; + case TEXTURE_CHANNEL_GREEN: { + code += "uniform sampler2D texture_roughness : hint_roughness_g," + texfilter_str + ";\n"; + } break; + case TEXTURE_CHANNEL_BLUE: { + code += "uniform sampler2D texture_roughness : hint_roughness_b," + texfilter_str + ";\n"; + } break; + case TEXTURE_CHANNEL_ALPHA: { + code += "uniform sampler2D texture_roughness : hint_roughness_a," + texfilter_str + ";\n"; + } break; + case TEXTURE_CHANNEL_GRAYSCALE: { + code += "uniform sampler2D texture_roughness : hint_roughness_gray," + texfilter_str + ";\n"; + } break; + } - if (textures[TEXTURE_ROUGHNESS] != NULL) { - code += "uniform sampler2D texture_roughness : hint_white;\n"; - code += "uniform vec4 roughness_texture_channel;\n"; + code += "uniform float specular;\n"; + code += "uniform float metallic;\n"; + } else { + code += "uniform sampler2D texture_orm : hint_roughness_g," + texfilter_str + ";\n"; } + if (billboard_mode == BILLBOARD_PARTICLES) { code += "uniform int particles_anim_h_frames;\n"; code += "uniform int particles_anim_v_frames;\n"; @@ -521,35 +583,34 @@ void SpatialMaterial::_update_shader() { } if (features[FEATURE_EMISSION]) { - - code += "uniform sampler2D texture_emission : hint_black_albedo;\n"; + code += "uniform sampler2D texture_emission : hint_black_albedo," + texfilter_str + ";\n"; code += "uniform vec4 emission : hint_color;\n"; code += "uniform float emission_energy;\n"; } if (features[FEATURE_REFRACTION]) { - code += "uniform sampler2D texture_refraction;\n"; + code += "uniform sampler2D texture_refraction : " + texfilter_str + ";\n"; code += "uniform float refraction : hint_range(-16,16);\n"; code += "uniform vec4 refraction_texture_channel;\n"; } if (features[FEATURE_NORMAL_MAPPING]) { - code += "uniform sampler2D texture_normal : hint_normal;\n"; + code += "uniform sampler2D texture_normal : hint_roughness_normal," + texfilter_str + ";\n"; code += "uniform float normal_scale : hint_range(-16,16);\n"; } if (features[FEATURE_RIM]) { code += "uniform float rim : hint_range(0,1);\n"; code += "uniform float rim_tint : hint_range(0,1);\n"; - code += "uniform sampler2D texture_rim : hint_white;\n"; + code += "uniform sampler2D texture_rim : hint_white," + texfilter_str + ";\n"; } if (features[FEATURE_CLEARCOAT]) { code += "uniform float clearcoat : hint_range(0,1);\n"; code += "uniform float clearcoat_gloss : hint_range(0,1);\n"; - code += "uniform sampler2D texture_clearcoat : hint_white;\n"; + code += "uniform sampler2D texture_clearcoat : hint_white," + texfilter_str + ";\n"; } if (features[FEATURE_ANISOTROPY]) { code += "uniform float anisotropy_ratio : hint_range(0,256);\n"; - code += "uniform sampler2D texture_flowmap : hint_aniso;\n"; + code += "uniform sampler2D texture_flowmap : hint_aniso," + texfilter_str + ";\n"; } if (features[FEATURE_AMBIENT_OCCLUSION]) { code += "uniform sampler2D texture_ambient_occlusion : hint_white;\n"; @@ -558,29 +619,35 @@ void SpatialMaterial::_update_shader() { } if (features[FEATURE_DETAIL]) { - code += "uniform sampler2D texture_detail_albedo : hint_albedo;\n"; - code += "uniform sampler2D texture_detail_normal : hint_normal;\n"; - code += "uniform sampler2D texture_detail_mask : hint_white;\n"; + code += "uniform sampler2D texture_detail_albedo : hint_albedo," + texfilter_str + ";\n"; + code += "uniform sampler2D texture_detail_normal : hint_normal," + texfilter_str + ";\n"; + code += "uniform sampler2D texture_detail_mask : hint_white," + texfilter_str + ";\n"; } - if (features[FEATURE_SUBSURACE_SCATTERING]) { - + if (features[FEATURE_SUBSURFACE_SCATTERING]) { code += "uniform float subsurface_scattering_strength : hint_range(0,1);\n"; - code += "uniform sampler2D texture_subsurface_scattering : hint_white;\n"; + code += "uniform sampler2D texture_subsurface_scattering : hint_white," + texfilter_str + ";\n"; } - if (features[FEATURE_TRANSMISSION]) { + if (features[FEATURE_SUBSURFACE_TRANSMITTANCE]) { + code += "uniform vec4 transmittance_color : hint_color;\n"; + code += "uniform float transmittance_depth;\n"; + code += "uniform sampler2D texture_subsurface_transmittance : hint_white," + texfilter_str + ";\n"; + code += "uniform float transmittance_curve;\n"; + code += "uniform float transmittance_boost;\n"; + } - code += "uniform vec4 transmission : hint_color;\n"; - code += "uniform sampler2D texture_transmission : hint_black;\n"; + if (features[FEATURE_BACKLIGHT]) { + code += "uniform vec4 backlight : hint_color;\n"; + code += "uniform sampler2D texture_backlight : hint_black," + texfilter_str + ";\n"; } - if (features[FEATURE_DEPTH_MAPPING]) { - code += "uniform sampler2D texture_depth : hint_black;\n"; - code += "uniform float depth_scale;\n"; - code += "uniform int depth_min_layers;\n"; - code += "uniform int depth_max_layers;\n"; - code += "uniform vec2 depth_flip;\n"; + if (features[FEATURE_HEIGHT_MAPPING]) { + code += "uniform sampler2D texture_heightmap : hint_black," + texfilter_str + ";\n"; + code += "uniform float heightmap_scale;\n"; + code += "uniform int heightmap_min_layers;\n"; + code += "uniform int heightmap_max_layers;\n"; + code += "uniform vec2 heightmap_flip;\n"; } if (flags[FLAG_UV1_USE_TRIPLANAR]) { code += "varying vec3 uv1_triplanar_pos;\n"; @@ -608,18 +675,15 @@ void SpatialMaterial::_update_shader() { code += "void vertex() {\n"; if (flags[FLAG_SRGB_VERTEX_COLOR]) { - code += "\tif (!OUTPUT_IS_SRGB) {\n"; code += "\t\tCOLOR.rgb = mix( pow((COLOR.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), COLOR.rgb* (1.0 / 12.92), lessThan(COLOR.rgb,vec3(0.04045)) );\n"; code += "\t}\n"; } if (flags[FLAG_USE_POINT_SIZE]) { - code += "\tPOINT_SIZE=point_size;\n"; } - if (flags[FLAG_USE_VERTEX_LIGHTING]) { - + if (shading_mode == SHADING_MODE_PER_VERTEX) { code += "\tROUGHNESS=roughness;\n"; } @@ -629,10 +693,8 @@ void SpatialMaterial::_update_shader() { switch (billboard_mode) { case BILLBOARD_DISABLED: { - } break; case BILLBOARD_ENABLED: { - code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],CAMERA_MATRIX[1],CAMERA_MATRIX[2],WORLD_MATRIX[3]);\n"; if (flags[FLAG_BILLBOARD_KEEP_SCALE]) { @@ -640,7 +702,6 @@ void SpatialMaterial::_update_shader() { } } break; case BILLBOARD_FIXED_Y: { - code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],WORLD_MATRIX[1],vec4(normalize(cross(CAMERA_MATRIX[0].xyz,WORLD_MATRIX[1].xyz)), 0.0),WORLD_MATRIX[3]);\n"; if (flags[FLAG_BILLBOARD_KEEP_SCALE]) { @@ -650,7 +711,6 @@ void SpatialMaterial::_update_shader() { } } break; case BILLBOARD_PARTICLES: { - //make billboard code += "\tmat4 mat_world = mat4(normalize(CAMERA_MATRIX[0])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[1])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[2])*length(WORLD_MATRIX[2]),WORLD_MATRIX[3]);\n"; //rotate by rotation @@ -674,7 +734,6 @@ void SpatialMaterial::_update_shader() { } if (flags[FLAG_FIXED_SIZE]) { - code += "\tif (PROJECTION_MATRIX[3][3] != 0.0) {\n"; //orthogonal matrix, try to do about the same //with viewport size @@ -709,7 +768,6 @@ void SpatialMaterial::_update_shader() { } if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tuv1_power_normal=pow(abs(NORMAL),vec3(uv1_blend_sharpness));\n"; code += "\tuv1_power_normal/=dot(uv1_power_normal,vec3(1.0));\n"; code += "\tuv1_triplanar_pos = VERTEX * uv1_scale + uv1_offset;\n"; @@ -717,7 +775,6 @@ void SpatialMaterial::_update_shader() { } if (flags[FLAG_UV2_USE_TRIPLANAR]) { - code += "\tuv2_power_normal=pow(abs(NORMAL), vec3(uv2_blend_sharpness));\n"; code += "\tuv2_power_normal/=dot(uv2_power_normal,vec3(1.0));\n"; code += "\tuv2_triplanar_pos = VERTEX * uv2_scale + uv2_offset;\n"; @@ -750,33 +807,49 @@ void SpatialMaterial::_update_shader() { code += "\tvec2 base_uv2 = UV2;\n"; } - if (!VisualServer::get_singleton()->is_low_end() && features[FEATURE_DEPTH_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //depthmap not supported with triplanar + if (!RenderingServer::get_singleton()->is_low_end() && features[FEATURE_HEIGHT_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //heightmap not supported with triplanar code += "\t{\n"; - code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT*depth_flip.x,-BINORMAL*depth_flip.y,NORMAL));\n"; // binormal is negative due to mikktspace, flip 'unflips' it ;-) + code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT*heightmap_flip.x,-BINORMAL*heightmap_flip.y,NORMAL));\n"; // binormal is negative due to mikktspace, flip 'unflips' it ;-) if (deep_parallax) { - code += "\t\tfloat num_layers = mix(float(depth_max_layers),float(depth_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));\n"; + code += "\t\tfloat num_layers = mix(float(heightmap_max_layers),float(heightmap_min_layers), abs(dot(vec3(0.0, 0.0, 1.0), view_dir)));\n"; code += "\t\tfloat layer_depth = 1.0 / num_layers;\n"; code += "\t\tfloat current_layer_depth = 0.0;\n"; - code += "\t\tvec2 P = view_dir.xy * depth_scale;\n"; + code += "\t\tvec2 P = view_dir.xy * heightmap_scale;\n"; code += "\t\tvec2 delta = P / num_layers;\n"; code += "\t\tvec2 ofs = base_uv;\n"; - code += "\t\tfloat depth = textureLod(texture_depth, ofs,0.0).r;\n"; + if (flags[FLAG_INVERT_HEIGHTMAP]) { + code += "\t\tfloat depth = texture(texture_heightmap, ofs).r;\n"; + } else { + code += "\t\tfloat depth = 1.0 - texture(texture_heightmap, ofs).r;\n"; + } code += "\t\tfloat current_depth = 0.0;\n"; code += "\t\twhile(current_depth < depth) {\n"; code += "\t\t\tofs -= delta;\n"; - code += "\t\t\tdepth = textureLod(texture_depth, ofs,0.0).r;\n"; + if (flags[FLAG_INVERT_HEIGHTMAP]) { + code += "\t\t\tdepth = texture(texture_heightmap, ofs).r;\n"; + } else { + code += "\t\t\tdepth = 1.0 - texture(texture_heightmap, ofs).r;\n"; + } code += "\t\t\tcurrent_depth += layer_depth;\n"; code += "\t\t}\n"; code += "\t\tvec2 prev_ofs = ofs + delta;\n"; code += "\t\tfloat after_depth = depth - current_depth;\n"; - code += "\t\tfloat before_depth = textureLod(texture_depth, prev_ofs, 0.0).r - current_depth + layer_depth;\n"; + if (flags[FLAG_INVERT_HEIGHTMAP]) { + code += "\t\tfloat before_depth = texture(texture_heightmap, prev_ofs).r - current_depth + layer_depth;\n"; + } else { + code += "\t\tfloat before_depth = ( 1.0 - texture(texture_heightmap, prev_ofs).r ) - current_depth + layer_depth;\n"; + } code += "\t\tfloat weight = after_depth / (after_depth - before_depth);\n"; code += "\t\tofs = mix(ofs,prev_ofs,weight);\n"; } else { - code += "\t\tfloat depth = texture(texture_depth, base_uv).r;\n"; - code += "\t\tvec2 ofs = base_uv - view_dir.xy / view_dir.z * (depth * depth_scale);\n"; + if (flags[FLAG_INVERT_HEIGHTMAP]) { + code += "\t\tfloat depth = texture(texture_heightmap, base_uv).r;\n"; + } else { + code += "\t\tfloat depth = 1.0 - texture(texture_heightmap, base_uv).r;\n"; + } + code += "\t\tvec2 ofs = base_uv - view_dir.xy / view_dir.z * (depth * heightmap_scale);\n"; } code += "\t\tbase_uv=ofs;\n"; @@ -806,29 +879,49 @@ void SpatialMaterial::_update_shader() { } code += "\tALBEDO = albedo.rgb * albedo_tex.rgb;\n"; - if (textures[TEXTURE_METALLIC] != NULL) { + if (!orm) { if (flags[FLAG_UV1_USE_TRIPLANAR]) { code += "\tfloat metallic_tex = dot(triplanar_texture(texture_metallic,uv1_power_normal,uv1_triplanar_pos),metallic_texture_channel);\n"; } else { code += "\tfloat metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel);\n"; } code += "\tMETALLIC = metallic_tex * metallic;\n"; - } else { - code += "\tMETALLIC = metallic;\n"; - } - if (textures[TEXTURE_ROUGHNESS] != NULL) { + switch (roughness_texture_channel) { + case TEXTURE_CHANNEL_RED: { + code += "\tvec4 roughness_texture_channel = vec4(1.0,0.0,0.0,0.0);\n"; + } break; + case TEXTURE_CHANNEL_GREEN: { + code += "\tvec4 roughness_texture_channel = vec4(0.0,1.0,0.0,0.0);\n"; + } break; + case TEXTURE_CHANNEL_BLUE: { + code += "\tvec4 roughness_texture_channel = vec4(0.0,0.0,1.0,0.0);\n"; + } break; + case TEXTURE_CHANNEL_ALPHA: { + code += "\tvec4 roughness_texture_channel = vec4(0.0,0.0,0.0,1.0);\n"; + } break; + case TEXTURE_CHANNEL_GRAYSCALE: { + code += "\tvec4 roughness_texture_channel = vec4(0.333333,0.333333,0.333333,0.0);\n"; + } break; + } + if (flags[FLAG_UV1_USE_TRIPLANAR]) { code += "\tfloat roughness_tex = dot(triplanar_texture(texture_roughness,uv1_power_normal,uv1_triplanar_pos),roughness_texture_channel);\n"; } else { code += "\tfloat roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);\n"; } code += "\tROUGHNESS = roughness_tex * roughness;\n"; + code += "\tSPECULAR = specular;\n"; } else { - code += "\tROUGHNESS = roughness;\n"; - } + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tfloat orm_tex = triplanar_texture(texture_orm,uv1_power_normal,uv1_triplanar_pos);\n"; + } else { + code += "\tfloat orm_tex = texture(texture_orm,base_uv);\n"; + } - code += "\tSPECULAR = specular;\n"; + code += "\tROUGHNESS = orm_tex.g;\n"; + code += "\tMETALLIC = orm_tex.b;\n"; + } if (features[FEATURE_NORMAL_MAPPING]) { if (flags[FLAG_UV1_USE_TRIPLANAR]) { @@ -862,7 +955,6 @@ void SpatialMaterial::_update_shader() { } if (features[FEATURE_REFRACTION]) { - if (features[FEATURE_NORMAL_MAPPING]) { code += "\tvec3 ref_normal = normalize( mix(NORMAL,TANGENT * NORMALMAP.x + BINORMAL * NORMALMAP.y + NORMAL * NORMALMAP.z,NORMALMAP_DEPTH) );\n"; } else { @@ -878,8 +970,10 @@ void SpatialMaterial::_update_shader() { code += "\tALBEDO *= 1.0 - ref_amount;\n"; code += "\tALPHA = 1.0;\n"; - } else if (features[FEATURE_TRANSPARENT] || flags[FLAG_USE_ALPHA_SCISSOR] || flags[FLAG_USE_SHADOW_TO_OPACITY] || (distance_fade == DISTANCE_FADE_PIXEL_ALPHA) || proximity_fade_enabled) { + } else if (transparency == TRANSPARENCY_ALPHA || transparency == TRANSPARENCY_ALPHA_DEPTH_PRE_PASS || flags[FLAG_USE_SHADOW_TO_OPACITY] || (distance_fade == DISTANCE_FADE_PIXEL_ALPHA) || proximity_fade_enabled) { code += "\tALPHA = albedo.a * albedo_tex.a;\n"; + } else if (transparency == TRANSPARENCY_ALPHA_SCISSOR) { + code += "\tif (albedo.a * albedo_tex.a < alpha_scissor_threshold) discard;\n"; } if (proximity_fade_enabled) { @@ -891,8 +985,7 @@ void SpatialMaterial::_update_shader() { if (distance_fade != DISTANCE_FADE_DISABLED) { if ((distance_fade == DISTANCE_FADE_OBJECT_DITHER || distance_fade == DISTANCE_FADE_PIXEL_DITHER)) { - - if (!VisualServer::get_singleton()->is_low_end()) { + if (!RenderingServer::get_singleton()->is_low_end()) { code += "\t{\n"; if (distance_fade == DISTANCE_FADE_OBJECT_DITHER) { code += "\t\tfloat fade_distance = abs((INV_CAMERA_MATRIX * WORLD_MATRIX[3]).z);\n"; @@ -965,25 +1058,28 @@ void SpatialMaterial::_update_shader() { } if (features[FEATURE_AMBIENT_OCCLUSION]) { - if (flags[FLAG_AO_ON_UV2]) { - if (flags[FLAG_UV2_USE_TRIPLANAR]) { - code += "\tAO = dot(triplanar_texture(texture_ambient_occlusion,uv2_power_normal,uv2_triplanar_pos),ao_texture_channel);\n"; + if (!orm) { + if (flags[FLAG_AO_ON_UV2]) { + if (flags[FLAG_UV2_USE_TRIPLANAR]) { + code += "\tAO = dot(triplanar_texture(texture_ambient_occlusion,uv2_power_normal,uv2_triplanar_pos),ao_texture_channel);\n"; + } else { + code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv2),ao_texture_channel);\n"; + } } else { - code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv2),ao_texture_channel);\n"; + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tAO = dot(triplanar_texture(texture_ambient_occlusion,uv1_power_normal,uv1_triplanar_pos),ao_texture_channel);\n"; + } else { + code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv),ao_texture_channel);\n"; + } } } else { - if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tAO = dot(triplanar_texture(texture_ambient_occlusion,uv1_power_normal,uv1_triplanar_pos),ao_texture_channel);\n"; - } else { - code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv),ao_texture_channel);\n"; - } + code += "\tAO = orm_tex.r;\n"; } code += "\tAO_LIGHT_AFFECT = ao_light_affect;\n"; } - if (features[FEATURE_SUBSURACE_SCATTERING]) { - + if (features[FEATURE_SUBSURFACE_SCATTERING]) { if (flags[FLAG_UV1_USE_TRIPLANAR]) { code += "\tfloat sss_tex = triplanar_texture(texture_subsurface_scattering,uv1_power_normal,uv1_triplanar_pos).r;\n"; } else { @@ -992,17 +1088,29 @@ void SpatialMaterial::_update_shader() { code += "\tSSS_STRENGTH=subsurface_scattering_strength*sss_tex;\n"; } - if (features[FEATURE_TRANSMISSION]) { + if (features[FEATURE_SUBSURFACE_TRANSMITTANCE]) { if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tvec3 transmission_tex = triplanar_texture(texture_transmission,uv1_power_normal,uv1_triplanar_pos).rgb;\n"; + code += "\tvec4 trans_color_tex = triplanar_texture(texture_subsurface_transmittance,uv1_power_normal,uv1_triplanar_pos);\n"; } else { - code += "\tvec3 transmission_tex = texture(texture_transmission,base_uv).rgb;\n"; + code += "\tvec4 trans_color_tex = texture(texture_subsurface_transmittance,base_uv);\n"; } - code += "\tTRANSMISSION = (transmission.rgb+transmission_tex);\n"; + code += "\tSSS_TRANSMITTANCE_COLOR=transmittance_color*trans_color_tex;\n"; + + code += "\tSSS_TRANSMITTANCE_DEPTH=transmittance_depth;\n"; + code += "\tSSS_TRANSMITTANCE_CURVE=transmittance_curve;\n"; + code += "\tSSS_TRANSMITTANCE_BOOST=transmittance_boost;\n"; } - if (features[FEATURE_DETAIL]) { + if (features[FEATURE_BACKLIGHT]) { + if (flags[FLAG_UV1_USE_TRIPLANAR]) { + code += "\tvec3 backlight_tex = triplanar_texture(texture_backlight,uv1_power_normal,uv1_triplanar_pos).rgb;\n"; + } else { + code += "\tvec3 backlight_tex = texture(texture_backlight,base_uv).rgb;\n"; + } + code += "\tBACKLIGHT = (backlight.rgb+backlight_tex);\n"; + } + if (features[FEATURE_DETAIL]) { bool triplanar = (flags[FLAG_UV1_USE_TRIPLANAR] && detail_uv == DETAIL_UV_1) || (flags[FLAG_UV2_USE_TRIPLANAR] && detail_uv == DETAIL_UV_2); if (triplanar) { @@ -1017,7 +1125,6 @@ void SpatialMaterial::_update_shader() { } if (flags[FLAG_UV1_USE_TRIPLANAR]) { - code += "\tvec4 detail_mask_tex = triplanar_texture(texture_detail_mask,uv1_power_normal,uv1_triplanar_pos);\n"; } else { code += "\tvec4 detail_mask_tex = texture(texture_detail_mask,base_uv);\n"; @@ -1043,417 +1150,436 @@ void SpatialMaterial::_update_shader() { code += "\tALBEDO.rgb = mix(ALBEDO.rgb,detail,detail_mask_tex.r);\n"; } - if (flags[FLAG_USE_ALPHA_SCISSOR]) { - code += "\tALPHA_SCISSOR=alpha_scissor_threshold;\n"; - } - code += "}\n"; ShaderData shader_data; - shader_data.shader = VS::get_singleton()->shader_create(); + shader_data.shader = RS::get_singleton()->shader_create(); shader_data.users = 1; - VS::get_singleton()->shader_set_code(shader_data.shader, code); + RS::get_singleton()->shader_set_code(shader_data.shader, code); shader_map[mk] = shader_data; - VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); + RS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); } -void SpatialMaterial::flush_changes() { - - if (material_mutex) - material_mutex->lock(); +void BaseMaterial3D::flush_changes() { + MutexLock lock(material_mutex); while (dirty_materials->first()) { - dirty_materials->first()->self()->_update_shader(); } - - if (material_mutex) - material_mutex->unlock(); } -void SpatialMaterial::_queue_shader_change() { - - if (material_mutex) - material_mutex->lock(); +void BaseMaterial3D::_queue_shader_change() { + MutexLock lock(material_mutex); if (!element.in_list()) { dirty_materials->add(&element); } - - if (material_mutex) - material_mutex->unlock(); } -bool SpatialMaterial::_is_shader_dirty() const { - - bool dirty = false; - - if (material_mutex) - material_mutex->lock(); - - dirty = element.in_list(); +bool BaseMaterial3D::_is_shader_dirty() const { + MutexLock lock(material_mutex); - if (material_mutex) - material_mutex->unlock(); - - return dirty; + return element.in_list(); } -void SpatialMaterial::set_albedo(const Color &p_albedo) { +void BaseMaterial3D::set_albedo(const Color &p_albedo) { albedo = p_albedo; - VS::get_singleton()->material_set_param(_get_material(), shader_names->albedo, p_albedo); + RS::get_singleton()->material_set_param(_get_material(), shader_names->albedo, p_albedo); } -Color SpatialMaterial::get_albedo() const { - +Color BaseMaterial3D::get_albedo() const { return albedo; } -void SpatialMaterial::set_specular(float p_specular) { - +void BaseMaterial3D::set_specular(float p_specular) { specular = p_specular; - VS::get_singleton()->material_set_param(_get_material(), shader_names->specular, p_specular); + RS::get_singleton()->material_set_param(_get_material(), shader_names->specular, p_specular); } -float SpatialMaterial::get_specular() const { - +float BaseMaterial3D::get_specular() const { return specular; } -void SpatialMaterial::set_roughness(float p_roughness) { - +void BaseMaterial3D::set_roughness(float p_roughness) { roughness = p_roughness; - VS::get_singleton()->material_set_param(_get_material(), shader_names->roughness, p_roughness); + RS::get_singleton()->material_set_param(_get_material(), shader_names->roughness, p_roughness); } -float SpatialMaterial::get_roughness() const { - +float BaseMaterial3D::get_roughness() const { return roughness; } -void SpatialMaterial::set_metallic(float p_metallic) { - +void BaseMaterial3D::set_metallic(float p_metallic) { metallic = p_metallic; - VS::get_singleton()->material_set_param(_get_material(), shader_names->metallic, p_metallic); + RS::get_singleton()->material_set_param(_get_material(), shader_names->metallic, p_metallic); } -float SpatialMaterial::get_metallic() const { - +float BaseMaterial3D::get_metallic() const { return metallic; } -void SpatialMaterial::set_emission(const Color &p_emission) { - +void BaseMaterial3D::set_emission(const Color &p_emission) { emission = p_emission; - VS::get_singleton()->material_set_param(_get_material(), shader_names->emission, p_emission); + RS::get_singleton()->material_set_param(_get_material(), shader_names->emission, p_emission); } -Color SpatialMaterial::get_emission() const { +Color BaseMaterial3D::get_emission() const { return emission; } -void SpatialMaterial::set_emission_energy(float p_emission_energy) { - +void BaseMaterial3D::set_emission_energy(float p_emission_energy) { emission_energy = p_emission_energy; - VS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy); + RS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy); } -float SpatialMaterial::get_emission_energy() const { +float BaseMaterial3D::get_emission_energy() const { return emission_energy; } -void SpatialMaterial::set_normal_scale(float p_normal_scale) { - +void BaseMaterial3D::set_normal_scale(float p_normal_scale) { normal_scale = p_normal_scale; - VS::get_singleton()->material_set_param(_get_material(), shader_names->normal_scale, p_normal_scale); + RS::get_singleton()->material_set_param(_get_material(), shader_names->normal_scale, p_normal_scale); } -float SpatialMaterial::get_normal_scale() const { +float BaseMaterial3D::get_normal_scale() const { return normal_scale; } -void SpatialMaterial::set_rim(float p_rim) { - +void BaseMaterial3D::set_rim(float p_rim) { rim = p_rim; - VS::get_singleton()->material_set_param(_get_material(), shader_names->rim, p_rim); + RS::get_singleton()->material_set_param(_get_material(), shader_names->rim, p_rim); } -float SpatialMaterial::get_rim() const { +float BaseMaterial3D::get_rim() const { return rim; } -void SpatialMaterial::set_rim_tint(float p_rim_tint) { - +void BaseMaterial3D::set_rim_tint(float p_rim_tint) { rim_tint = p_rim_tint; - VS::get_singleton()->material_set_param(_get_material(), shader_names->rim_tint, p_rim_tint); + RS::get_singleton()->material_set_param(_get_material(), shader_names->rim_tint, p_rim_tint); } -float SpatialMaterial::get_rim_tint() const { +float BaseMaterial3D::get_rim_tint() const { return rim_tint; } -void SpatialMaterial::set_ao_light_affect(float p_ao_light_affect) { - +void BaseMaterial3D::set_ao_light_affect(float p_ao_light_affect) { ao_light_affect = p_ao_light_affect; - VS::get_singleton()->material_set_param(_get_material(), shader_names->ao_light_affect, p_ao_light_affect); + RS::get_singleton()->material_set_param(_get_material(), shader_names->ao_light_affect, p_ao_light_affect); } -float SpatialMaterial::get_ao_light_affect() const { +float BaseMaterial3D::get_ao_light_affect() const { return ao_light_affect; } -void SpatialMaterial::set_clearcoat(float p_clearcoat) { - +void BaseMaterial3D::set_clearcoat(float p_clearcoat) { clearcoat = p_clearcoat; - VS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat, p_clearcoat); + RS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat, p_clearcoat); } -float SpatialMaterial::get_clearcoat() const { - +float BaseMaterial3D::get_clearcoat() const { return clearcoat; } -void SpatialMaterial::set_clearcoat_gloss(float p_clearcoat_gloss) { - +void BaseMaterial3D::set_clearcoat_gloss(float p_clearcoat_gloss) { clearcoat_gloss = p_clearcoat_gloss; - VS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat_gloss, p_clearcoat_gloss); + RS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat_gloss, p_clearcoat_gloss); } -float SpatialMaterial::get_clearcoat_gloss() const { - +float BaseMaterial3D::get_clearcoat_gloss() const { return clearcoat_gloss; } -void SpatialMaterial::set_anisotropy(float p_anisotropy) { - +void BaseMaterial3D::set_anisotropy(float p_anisotropy) { anisotropy = p_anisotropy; - VS::get_singleton()->material_set_param(_get_material(), shader_names->anisotropy, p_anisotropy); + RS::get_singleton()->material_set_param(_get_material(), shader_names->anisotropy, p_anisotropy); } -float SpatialMaterial::get_anisotropy() const { +float BaseMaterial3D::get_anisotropy() const { return anisotropy; } -void SpatialMaterial::set_depth_scale(float p_depth_scale) { +void BaseMaterial3D::set_heightmap_scale(float p_heightmap_scale) { + heightmap_scale = p_heightmap_scale; + RS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_scale, p_heightmap_scale); +} + +float BaseMaterial3D::get_heightmap_scale() const { + return heightmap_scale; +} - depth_scale = p_depth_scale; - VS::get_singleton()->material_set_param(_get_material(), shader_names->depth_scale, p_depth_scale); +void BaseMaterial3D::set_subsurface_scattering_strength(float p_subsurface_scattering_strength) { + subsurface_scattering_strength = p_subsurface_scattering_strength; + RS::get_singleton()->material_set_param(_get_material(), shader_names->subsurface_scattering_strength, subsurface_scattering_strength); } -float SpatialMaterial::get_depth_scale() const { +float BaseMaterial3D::get_subsurface_scattering_strength() const { + return subsurface_scattering_strength; +} - return depth_scale; +void BaseMaterial3D::set_transmittance_color(const Color &p_color) { + transmittance_color = p_color; + RS::get_singleton()->material_set_param(_get_material(), shader_names->transmittance_color, p_color); } -void SpatialMaterial::set_subsurface_scattering_strength(float p_subsurface_scattering_strength) { +Color BaseMaterial3D::get_transmittance_color() const { + return transmittance_color; +} - subsurface_scattering_strength = p_subsurface_scattering_strength; - VS::get_singleton()->material_set_param(_get_material(), shader_names->subsurface_scattering_strength, subsurface_scattering_strength); +void BaseMaterial3D::set_transmittance_depth(float p_depth) { + transmittance_depth = p_depth; + RS::get_singleton()->material_set_param(_get_material(), shader_names->transmittance_depth, p_depth); } -float SpatialMaterial::get_subsurface_scattering_strength() const { +float BaseMaterial3D::get_transmittance_depth() const { + return transmittance_depth; +} - return subsurface_scattering_strength; +void BaseMaterial3D::set_transmittance_curve(float p_curve) { + transmittance_curve = p_curve; + RS::get_singleton()->material_set_param(_get_material(), shader_names->transmittance_curve, p_curve); } -void SpatialMaterial::set_transmission(const Color &p_transmission) { +float BaseMaterial3D::get_transmittance_curve() const { + return transmittance_curve; +} - transmission = p_transmission; - VS::get_singleton()->material_set_param(_get_material(), shader_names->transmission, transmission); +void BaseMaterial3D::set_transmittance_boost(float p_boost) { + transmittance_boost = p_boost; + RS::get_singleton()->material_set_param(_get_material(), shader_names->transmittance_boost, p_boost); } -Color SpatialMaterial::get_transmission() const { +float BaseMaterial3D::get_transmittance_boost() const { + return transmittance_boost; +} - return transmission; +void BaseMaterial3D::set_backlight(const Color &p_backlight) { + backlight = p_backlight; + RS::get_singleton()->material_set_param(_get_material(), shader_names->backlight, backlight); } -void SpatialMaterial::set_refraction(float p_refraction) { +Color BaseMaterial3D::get_backlight() const { + return backlight; +} +void BaseMaterial3D::set_refraction(float p_refraction) { refraction = p_refraction; - VS::get_singleton()->material_set_param(_get_material(), shader_names->refraction, refraction); + RS::get_singleton()->material_set_param(_get_material(), shader_names->refraction, refraction); } -float SpatialMaterial::get_refraction() const { - +float BaseMaterial3D::get_refraction() const { return refraction; } -void SpatialMaterial::set_detail_uv(DetailUV p_detail_uv) { - - if (detail_uv == p_detail_uv) +void BaseMaterial3D::set_detail_uv(DetailUV p_detail_uv) { + if (detail_uv == p_detail_uv) { return; + } detail_uv = p_detail_uv; _queue_shader_change(); } -SpatialMaterial::DetailUV SpatialMaterial::get_detail_uv() const { +BaseMaterial3D::DetailUV BaseMaterial3D::get_detail_uv() const { return detail_uv; } -void SpatialMaterial::set_blend_mode(BlendMode p_mode) { - - if (blend_mode == p_mode) +void BaseMaterial3D::set_blend_mode(BlendMode p_mode) { + if (blend_mode == p_mode) { return; + } blend_mode = p_mode; _queue_shader_change(); } -SpatialMaterial::BlendMode SpatialMaterial::get_blend_mode() const { +BaseMaterial3D::BlendMode BaseMaterial3D::get_blend_mode() const { return blend_mode; } -void SpatialMaterial::set_detail_blend_mode(BlendMode p_mode) { - +void BaseMaterial3D::set_detail_blend_mode(BlendMode p_mode) { detail_blend_mode = p_mode; _queue_shader_change(); } -SpatialMaterial::BlendMode SpatialMaterial::get_detail_blend_mode() const { +BaseMaterial3D::BlendMode BaseMaterial3D::get_detail_blend_mode() const { return detail_blend_mode; } -void SpatialMaterial::set_depth_draw_mode(DepthDrawMode p_mode) { +void BaseMaterial3D::set_transparency(Transparency p_transparency) { + if (transparency == p_transparency) { + return; + } + + transparency = p_transparency; + _queue_shader_change(); + _change_notify(); +} + +BaseMaterial3D::Transparency BaseMaterial3D::get_transparency() const { + return transparency; +} - if (depth_draw_mode == p_mode) +void BaseMaterial3D::set_shading_mode(ShadingMode p_shading_mode) { + if (shading_mode == p_shading_mode) { return; + } + + shading_mode = p_shading_mode; + _queue_shader_change(); + _change_notify(); +} + +BaseMaterial3D::ShadingMode BaseMaterial3D::get_shading_mode() const { + return shading_mode; +} + +void BaseMaterial3D::set_depth_draw_mode(DepthDrawMode p_mode) { + if (depth_draw_mode == p_mode) { + return; + } depth_draw_mode = p_mode; _queue_shader_change(); } -SpatialMaterial::DepthDrawMode SpatialMaterial::get_depth_draw_mode() const { +BaseMaterial3D::DepthDrawMode BaseMaterial3D::get_depth_draw_mode() const { return depth_draw_mode; } -void SpatialMaterial::set_cull_mode(CullMode p_mode) { - - if (cull_mode == p_mode) +void BaseMaterial3D::set_cull_mode(CullMode p_mode) { + if (cull_mode == p_mode) { return; + } cull_mode = p_mode; _queue_shader_change(); } -SpatialMaterial::CullMode SpatialMaterial::get_cull_mode() const { +BaseMaterial3D::CullMode BaseMaterial3D::get_cull_mode() const { return cull_mode; } -void SpatialMaterial::set_diffuse_mode(DiffuseMode p_mode) { - - if (diffuse_mode == p_mode) +void BaseMaterial3D::set_diffuse_mode(DiffuseMode p_mode) { + if (diffuse_mode == p_mode) { return; + } diffuse_mode = p_mode; _queue_shader_change(); } -SpatialMaterial::DiffuseMode SpatialMaterial::get_diffuse_mode() const { +BaseMaterial3D::DiffuseMode BaseMaterial3D::get_diffuse_mode() const { return diffuse_mode; } -void SpatialMaterial::set_specular_mode(SpecularMode p_mode) { - - if (specular_mode == p_mode) +void BaseMaterial3D::set_specular_mode(SpecularMode p_mode) { + if (specular_mode == p_mode) { return; + } specular_mode = p_mode; _queue_shader_change(); } -SpatialMaterial::SpecularMode SpatialMaterial::get_specular_mode() const { +BaseMaterial3D::SpecularMode BaseMaterial3D::get_specular_mode() const { return specular_mode; } -void SpatialMaterial::set_flag(Flags p_flag, bool p_enabled) { - +void BaseMaterial3D::set_flag(Flags p_flag, bool p_enabled) { ERR_FAIL_INDEX(p_flag, FLAG_MAX); - if (flags[p_flag] == p_enabled) + if (flags[p_flag] == p_enabled) { return; + } flags[p_flag] = p_enabled; - if ((p_flag == FLAG_USE_ALPHA_SCISSOR) || (p_flag == FLAG_UNSHADED) || (p_flag == FLAG_USE_SHADOW_TO_OPACITY)) { + if (p_flag == FLAG_USE_SHADOW_TO_OPACITY || p_flag == FLAG_USE_TEXTURE_REPEAT || p_flag == FLAG_SUBSURFACE_MODE_SKIN) { _change_notify(); } _queue_shader_change(); } -bool SpatialMaterial::get_flag(Flags p_flag) const { - +bool BaseMaterial3D::get_flag(Flags p_flag) const { ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); return flags[p_flag]; } -void SpatialMaterial::set_feature(Feature p_feature, bool p_enabled) { - +void BaseMaterial3D::set_feature(Feature p_feature, bool p_enabled) { ERR_FAIL_INDEX(p_feature, FEATURE_MAX); - if (features[p_feature] == p_enabled) + if (features[p_feature] == p_enabled) { return; + } features[p_feature] = p_enabled; _change_notify(); _queue_shader_change(); } -bool SpatialMaterial::get_feature(Feature p_feature) const { - +bool BaseMaterial3D::get_feature(Feature p_feature) const { ERR_FAIL_INDEX_V(p_feature, FEATURE_MAX, false); return features[p_feature]; } -void SpatialMaterial::set_texture(TextureParam p_param, const Ref<Texture> &p_texture) { - +void BaseMaterial3D::set_texture(TextureParam p_param, const Ref<Texture2D> &p_texture) { ERR_FAIL_INDEX(p_param, TEXTURE_MAX); textures[p_param] = p_texture; RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); - VS::get_singleton()->material_set_param(_get_material(), shader_names->texture_names[p_param], rid); + RS::get_singleton()->material_set_param(_get_material(), shader_names->texture_names[p_param], rid); _change_notify(); _queue_shader_change(); } -Ref<Texture> SpatialMaterial::get_texture(TextureParam p_param) const { - - ERR_FAIL_INDEX_V(p_param, TEXTURE_MAX, Ref<Texture>()); +Ref<Texture2D> BaseMaterial3D::get_texture(TextureParam p_param) const { + ERR_FAIL_INDEX_V(p_param, TEXTURE_MAX, Ref<Texture2D>()); return textures[p_param]; } -Ref<Texture> SpatialMaterial::get_texture_by_name(StringName p_name) const { - for (int i = 0; i < (int)SpatialMaterial::TEXTURE_MAX; i++) { +Ref<Texture2D> BaseMaterial3D::get_texture_by_name(StringName p_name) const { + for (int i = 0; i < (int)BaseMaterial3D::TEXTURE_MAX; i++) { TextureParam param = TextureParam(i); - if (p_name == shader_names->texture_names[param]) + if (p_name == shader_names->texture_names[param]) { return textures[param]; + } } - return Ref<Texture>(); + return Ref<Texture2D>(); } -void SpatialMaterial::_validate_feature(const String &text, Feature feature, PropertyInfo &property) const { +void BaseMaterial3D::set_texture_filter(TextureFilter p_filter) { + texture_filter = p_filter; + _queue_shader_change(); +} + +BaseMaterial3D::TextureFilter BaseMaterial3D::get_texture_filter() const { + return texture_filter; +} + +void BaseMaterial3D::_validate_feature(const String &text, Feature feature, PropertyInfo &property) const { if (property.name.begins_with(text) && property.name != text + "_enabled" && !features[feature]) { property.usage = 0; } } -void SpatialMaterial::_validate_high_end(const String &text, PropertyInfo &property) const { +void BaseMaterial3D::_validate_high_end(const String &text, PropertyInfo &property) const { if (property.name.begins_with(text)) { property.usage |= PROPERTY_USAGE_HIGH_END_GFX; } } -void SpatialMaterial::_validate_property(PropertyInfo &property) const { +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("depth", FEATURE_DEPTH_MAPPING, property); - _validate_feature("subsurf_scatter", FEATURE_SUBSURACE_SCATTERING, property); - _validate_feature("transmission", FEATURE_TRANSMISSION, 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); @@ -1461,7 +1587,7 @@ void SpatialMaterial::_validate_property(PropertyInfo &property) const { _validate_high_end("subsurf_scatter", property); _validate_high_end("anisotropy", property); _validate_high_end("clearcoat", property); - _validate_high_end("depth", property); + _validate_high_end("heightmap", property); if (property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) { property.usage = 0; @@ -1479,273 +1605,256 @@ void SpatialMaterial::_validate_property(PropertyInfo &property) const { property.usage = 0; } - if (property.name == "params_alpha_scissor_threshold" && !flags[FLAG_USE_ALPHA_SCISSOR]) { + if (property.name == "alpha_scissor_threshold" && transparency != TRANSPARENCY_ALPHA_SCISSOR) { property.usage = 0; } - if ((property.name == "depth_min_layers" || property.name == "depth_max_layers") && !deep_parallax) { + if ((property.name == "heightmap_min_layers" || property.name == "heightmap_max_layers") && !deep_parallax) { property.usage = 0; } - if (flags[FLAG_UNSHADED]) { - if (property.name.begins_with("anisotropy")) { - property.usage = 0; - } + if (flags[FLAG_SUBSURFACE_MODE_SKIN] && (property.name == "subsurf_scatter_transmittance_color" || property.name == "subsurf_scatter_transmittance_texture" || property.name == "subsurf_scatter_transmittance_curve")) { + property.usage = 0; + } - if (property.name.begins_with("ao")) { - property.usage = 0; + if (orm) { + if (property.name == "shading_mode") { + property.hint_string = "Unshaded,PerPixel"; //vertex not supported in ORM mode, since no individual roughness. } - - if (property.name.begins_with("clearcoat")) { + if (property.name.begins_with("roughness") || property.name.begins_with("metallic") || property.name.begins_with("ao_texture")) { property.usage = 0; } - if (property.name.begins_with("emission")) { + } else { + if (property.name == "orm_texture") { property.usage = 0; } + } - if (property.name.begins_with("metallic")) { - property.usage = 0; + 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 = 0; + } + if (property.name.begins_with("emission")) { + property.usage = 0; + } + + if (property.name.begins_with("metallic")) { + property.usage = 0; + } + if (property.name.begins_with("rim")) { + property.usage = 0; + } + + if (property.name.begins_with("roughness")) { + property.usage = 0; + } + + if (property.name.begins_with("subsurf_scatter")) { + property.usage = 0; + } } - if (property.name.begins_with("normal")) { + //these definitely only need per pixel + if (property.name.begins_with("anisotropy")) { property.usage = 0; } - if (property.name.begins_with("rim")) { + if (property.name.begins_with("clearcoat")) { property.usage = 0; } - if (property.name.begins_with("roughness")) { + if (property.name.begins_with("normal")) { property.usage = 0; } - if (property.name.begins_with("subsurf_scatter")) { + if (property.name.begins_with("backlight")) { property.usage = 0; } - if (property.name.begins_with("transmission")) { + if (property.name.begins_with("transmittance")) { property.usage = 0; } } } -void SpatialMaterial::set_line_width(float p_line_width) { - - line_width = p_line_width; - VS::get_singleton()->material_set_line_width(_get_material(), line_width); -} - -float SpatialMaterial::get_line_width() const { - - return line_width; -} - -void SpatialMaterial::set_point_size(float p_point_size) { - +void BaseMaterial3D::set_point_size(float p_point_size) { point_size = p_point_size; - VS::get_singleton()->material_set_param(_get_material(), shader_names->point_size, p_point_size); + RS::get_singleton()->material_set_param(_get_material(), shader_names->point_size, p_point_size); } -float SpatialMaterial::get_point_size() const { - +float BaseMaterial3D::get_point_size() const { return point_size; } -void SpatialMaterial::set_uv1_scale(const Vector3 &p_scale) { - +void BaseMaterial3D::set_uv1_scale(const Vector3 &p_scale) { uv1_scale = p_scale; - VS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_scale, p_scale); + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_scale, p_scale); } -Vector3 SpatialMaterial::get_uv1_scale() const { - +Vector3 BaseMaterial3D::get_uv1_scale() const { return uv1_scale; } -void SpatialMaterial::set_uv1_offset(const Vector3 &p_offset) { - +void BaseMaterial3D::set_uv1_offset(const Vector3 &p_offset) { uv1_offset = p_offset; - VS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_offset, p_offset); + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_offset, p_offset); } -Vector3 SpatialMaterial::get_uv1_offset() const { +Vector3 BaseMaterial3D::get_uv1_offset() const { return uv1_offset; } -void SpatialMaterial::set_uv1_triplanar_blend_sharpness(float p_sharpness) { - +void BaseMaterial3D::set_uv1_triplanar_blend_sharpness(float p_sharpness) { uv1_triplanar_sharpness = p_sharpness; - VS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_blend_sharpness, p_sharpness); + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_blend_sharpness, p_sharpness); } -float SpatialMaterial::get_uv1_triplanar_blend_sharpness() const { - +float BaseMaterial3D::get_uv1_triplanar_blend_sharpness() const { return uv1_triplanar_sharpness; } -void SpatialMaterial::set_uv2_scale(const Vector3 &p_scale) { - +void BaseMaterial3D::set_uv2_scale(const Vector3 &p_scale) { uv2_scale = p_scale; - VS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_scale, p_scale); + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_scale, p_scale); } -Vector3 SpatialMaterial::get_uv2_scale() const { - +Vector3 BaseMaterial3D::get_uv2_scale() const { return uv2_scale; } -void SpatialMaterial::set_uv2_offset(const Vector3 &p_offset) { - +void BaseMaterial3D::set_uv2_offset(const Vector3 &p_offset) { uv2_offset = p_offset; - VS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_offset, p_offset); + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_offset, p_offset); } -Vector3 SpatialMaterial::get_uv2_offset() const { - +Vector3 BaseMaterial3D::get_uv2_offset() const { return uv2_offset; } -void SpatialMaterial::set_uv2_triplanar_blend_sharpness(float p_sharpness) { - +void BaseMaterial3D::set_uv2_triplanar_blend_sharpness(float p_sharpness) { uv2_triplanar_sharpness = p_sharpness; - VS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_blend_sharpness, p_sharpness); + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_blend_sharpness, p_sharpness); } -float SpatialMaterial::get_uv2_triplanar_blend_sharpness() const { - +float BaseMaterial3D::get_uv2_triplanar_blend_sharpness() const { return uv2_triplanar_sharpness; } -void SpatialMaterial::set_billboard_mode(BillboardMode p_mode) { - +void BaseMaterial3D::set_billboard_mode(BillboardMode p_mode) { billboard_mode = p_mode; _queue_shader_change(); _change_notify(); } -SpatialMaterial::BillboardMode SpatialMaterial::get_billboard_mode() const { - +BaseMaterial3D::BillboardMode BaseMaterial3D::get_billboard_mode() const { return billboard_mode; } -void SpatialMaterial::set_particles_anim_h_frames(int p_frames) { - +void BaseMaterial3D::set_particles_anim_h_frames(int p_frames) { particles_anim_h_frames = p_frames; - VS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_h_frames, p_frames); + RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_h_frames, p_frames); } -int SpatialMaterial::get_particles_anim_h_frames() const { - +int BaseMaterial3D::get_particles_anim_h_frames() const { return particles_anim_h_frames; } -void SpatialMaterial::set_particles_anim_v_frames(int p_frames) { +void BaseMaterial3D::set_particles_anim_v_frames(int p_frames) { particles_anim_v_frames = p_frames; - VS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_v_frames, p_frames); + RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_v_frames, p_frames); } -int SpatialMaterial::get_particles_anim_v_frames() const { - +int BaseMaterial3D::get_particles_anim_v_frames() const { return particles_anim_v_frames; } -void SpatialMaterial::set_particles_anim_loop(bool p_loop) { - +void BaseMaterial3D::set_particles_anim_loop(bool p_loop) { particles_anim_loop = p_loop; - VS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_loop, particles_anim_loop); + RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_loop, particles_anim_loop); } -bool SpatialMaterial::get_particles_anim_loop() const { - +bool BaseMaterial3D::get_particles_anim_loop() const { return particles_anim_loop; } -void SpatialMaterial::set_depth_deep_parallax(bool p_enable) { - +void BaseMaterial3D::set_heightmap_deep_parallax(bool p_enable) { deep_parallax = p_enable; _queue_shader_change(); _change_notify(); } -bool SpatialMaterial::is_depth_deep_parallax_enabled() const { - +bool BaseMaterial3D::is_heightmap_deep_parallax_enabled() const { return deep_parallax; } -void SpatialMaterial::set_depth_deep_parallax_min_layers(int p_layer) { - +void BaseMaterial3D::set_heightmap_deep_parallax_min_layers(int p_layer) { deep_parallax_min_layers = p_layer; - VS::get_singleton()->material_set_param(_get_material(), shader_names->depth_min_layers, p_layer); + RS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_min_layers, p_layer); } -int SpatialMaterial::get_depth_deep_parallax_min_layers() const { +int BaseMaterial3D::get_heightmap_deep_parallax_min_layers() const { return deep_parallax_min_layers; } -void SpatialMaterial::set_depth_deep_parallax_max_layers(int p_layer) { - +void BaseMaterial3D::set_heightmap_deep_parallax_max_layers(int p_layer) { deep_parallax_max_layers = p_layer; - VS::get_singleton()->material_set_param(_get_material(), shader_names->depth_max_layers, p_layer); + RS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_max_layers, p_layer); } -int SpatialMaterial::get_depth_deep_parallax_max_layers() const { +int BaseMaterial3D::get_heightmap_deep_parallax_max_layers() const { return deep_parallax_max_layers; } -void SpatialMaterial::set_depth_deep_parallax_flip_tangent(bool p_flip) { - - depth_parallax_flip_tangent = p_flip; - VS::get_singleton()->material_set_param(_get_material(), shader_names->depth_flip, Vector2(depth_parallax_flip_tangent ? -1 : 1, depth_parallax_flip_binormal ? -1 : 1)); +void BaseMaterial3D::set_heightmap_deep_parallax_flip_tangent(bool p_flip) { + heightmap_parallax_flip_tangent = p_flip; + RS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_flip, Vector2(heightmap_parallax_flip_tangent ? -1 : 1, heightmap_parallax_flip_binormal ? -1 : 1)); } -bool SpatialMaterial::get_depth_deep_parallax_flip_tangent() const { - - return depth_parallax_flip_tangent; +bool BaseMaterial3D::get_heightmap_deep_parallax_flip_tangent() const { + return heightmap_parallax_flip_tangent; } -void SpatialMaterial::set_depth_deep_parallax_flip_binormal(bool p_flip) { - - depth_parallax_flip_binormal = p_flip; - VS::get_singleton()->material_set_param(_get_material(), shader_names->depth_flip, Vector2(depth_parallax_flip_tangent ? -1 : 1, depth_parallax_flip_binormal ? -1 : 1)); +void BaseMaterial3D::set_heightmap_deep_parallax_flip_binormal(bool p_flip) { + heightmap_parallax_flip_binormal = p_flip; + RS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_flip, Vector2(heightmap_parallax_flip_tangent ? -1 : 1, heightmap_parallax_flip_binormal ? -1 : 1)); } -bool SpatialMaterial::get_depth_deep_parallax_flip_binormal() const { - - return depth_parallax_flip_binormal; +bool BaseMaterial3D::get_heightmap_deep_parallax_flip_binormal() const { + return heightmap_parallax_flip_binormal; } -void SpatialMaterial::set_grow_enabled(bool p_enable) { +void BaseMaterial3D::set_grow_enabled(bool p_enable) { grow_enabled = p_enable; _queue_shader_change(); _change_notify(); } -bool SpatialMaterial::is_grow_enabled() const { +bool BaseMaterial3D::is_grow_enabled() const { return grow_enabled; } -void SpatialMaterial::set_alpha_scissor_threshold(float p_threshold) { +void BaseMaterial3D::set_alpha_scissor_threshold(float p_threshold) { alpha_scissor_threshold = p_threshold; - VS::get_singleton()->material_set_param(_get_material(), shader_names->alpha_scissor_threshold, p_threshold); + RS::get_singleton()->material_set_param(_get_material(), shader_names->alpha_scissor_threshold, p_threshold); } -float SpatialMaterial::get_alpha_scissor_threshold() const { - +float BaseMaterial3D::get_alpha_scissor_threshold() const { return alpha_scissor_threshold; } -void SpatialMaterial::set_grow(float p_grow) { +void BaseMaterial3D::set_grow(float p_grow) { grow = p_grow; - VS::get_singleton()->material_set_param(_get_material(), shader_names->grow, p_grow); + RS::get_singleton()->material_set_param(_get_material(), shader_names->grow, p_grow); } -float SpatialMaterial::get_grow() const { - +float BaseMaterial3D::get_grow() const { return grow; } -static Plane _get_texture_mask(SpatialMaterial::TextureChannel p_channel) { +static Plane _get_texture_mask(BaseMaterial3D::TextureChannel p_channel) { static const Plane masks[5] = { Plane(1, 0, 0, 0), Plane(0, 1, 0, 0), @@ -1757,81 +1866,82 @@ static Plane _get_texture_mask(SpatialMaterial::TextureChannel p_channel) { return masks[p_channel]; } -void SpatialMaterial::set_metallic_texture_channel(TextureChannel p_channel) { +void BaseMaterial3D::set_metallic_texture_channel(TextureChannel p_channel) { ERR_FAIL_INDEX(p_channel, 5); metallic_texture_channel = p_channel; - VS::get_singleton()->material_set_param(_get_material(), shader_names->metallic_texture_channel, _get_texture_mask(p_channel)); + RS::get_singleton()->material_set_param(_get_material(), shader_names->metallic_texture_channel, _get_texture_mask(p_channel)); } -SpatialMaterial::TextureChannel SpatialMaterial::get_metallic_texture_channel() const { +BaseMaterial3D::TextureChannel BaseMaterial3D::get_metallic_texture_channel() const { return metallic_texture_channel; } -void SpatialMaterial::set_roughness_texture_channel(TextureChannel p_channel) { - +void BaseMaterial3D::set_roughness_texture_channel(TextureChannel p_channel) { ERR_FAIL_INDEX(p_channel, 5); roughness_texture_channel = p_channel; - VS::get_singleton()->material_set_param(_get_material(), shader_names->roughness_texture_channel, _get_texture_mask(p_channel)); + _queue_shader_change(); } -SpatialMaterial::TextureChannel SpatialMaterial::get_roughness_texture_channel() const { +BaseMaterial3D::TextureChannel BaseMaterial3D::get_roughness_texture_channel() const { return roughness_texture_channel; } -void SpatialMaterial::set_ao_texture_channel(TextureChannel p_channel) { - +void BaseMaterial3D::set_ao_texture_channel(TextureChannel p_channel) { ERR_FAIL_INDEX(p_channel, 5); ao_texture_channel = p_channel; - VS::get_singleton()->material_set_param(_get_material(), shader_names->ao_texture_channel, _get_texture_mask(p_channel)); + RS::get_singleton()->material_set_param(_get_material(), shader_names->ao_texture_channel, _get_texture_mask(p_channel)); } -SpatialMaterial::TextureChannel SpatialMaterial::get_ao_texture_channel() const { +BaseMaterial3D::TextureChannel BaseMaterial3D::get_ao_texture_channel() const { return ao_texture_channel; } -void SpatialMaterial::set_refraction_texture_channel(TextureChannel p_channel) { - +void BaseMaterial3D::set_refraction_texture_channel(TextureChannel p_channel) { ERR_FAIL_INDEX(p_channel, 5); refraction_texture_channel = p_channel; - VS::get_singleton()->material_set_param(_get_material(), shader_names->refraction_texture_channel, _get_texture_mask(p_channel)); + RS::get_singleton()->material_set_param(_get_material(), shader_names->refraction_texture_channel, _get_texture_mask(p_channel)); } -SpatialMaterial::TextureChannel SpatialMaterial::get_refraction_texture_channel() const { +BaseMaterial3D::TextureChannel BaseMaterial3D::get_refraction_texture_channel() const { return refraction_texture_channel; } -RID SpatialMaterial::get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard, bool p_billboard_y) { - +RID BaseMaterial3D::get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard, bool p_billboard_y) { int version = 0; - if (p_shaded) + if (p_shaded) { version = 1; - if (p_transparent) + } + if (p_transparent) { version |= 2; - if (p_cut_alpha) + } + if (p_cut_alpha) { version |= 4; - if (p_opaque_prepass) + } + if (p_opaque_prepass) { version |= 8; - if (p_double_sided) + } + if (p_double_sided) { version |= 16; - if (p_billboard) + } + if (p_billboard) { version |= 32; - if (p_billboard_y) + } + if (p_billboard_y) { version |= 64; + } if (materials_for_2d[version].is_valid()) { return materials_for_2d[version]->get_rid(); } - Ref<SpatialMaterial> material; + Ref<StandardMaterial3D> material; material.instance(); - material->set_flag(FLAG_UNSHADED, !p_shaded); - material->set_feature(FEATURE_TRANSPARENT, p_transparent); + material->set_shading_mode(p_shaded ? SHADING_MODE_PER_PIXEL : SHADING_MODE_UNSHADED); + material->set_transparency(p_transparent ? (p_opaque_prepass ? TRANSPARENCY_ALPHA_DEPTH_PRE_PASS : (p_cut_alpha ? TRANSPARENCY_ALPHA_SCISSOR : TRANSPARENCY_ALPHA)) : TRANSPARENCY_DISABLED); material->set_cull_mode(p_double_sided ? CULL_DISABLED : CULL_BACK); - material->set_depth_draw_mode(p_opaque_prepass ? DEPTH_DRAW_ALPHA_OPAQUE_PREPASS : DEPTH_DRAW_OPAQUE_ONLY); material->set_flag(FLAG_SRGB_VERTEX_COLOR, true); material->set_flag(FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - material->set_flag(FLAG_USE_ALPHA_SCISSOR, p_cut_alpha); if (p_billboard || p_billboard_y) { material->set_flag(FLAG_BILLBOARD_KEEP_SCALE, true); material->set_billboard_mode(p_billboard_y ? BILLBOARD_FIXED_Y : BILLBOARD_ENABLED); @@ -1842,404 +1952,433 @@ RID SpatialMaterial::get_material_rid_for_2d(bool p_shaded, bool p_transparent, return materials_for_2d[version]->get_rid(); } -void SpatialMaterial::set_on_top_of_alpha() { - set_feature(FEATURE_TRANSPARENT, true); +void BaseMaterial3D::set_on_top_of_alpha() { + set_transparency(TRANSPARENCY_DISABLED); set_render_priority(RENDER_PRIORITY_MAX); set_flag(FLAG_DISABLE_DEPTH_TEST, true); } -void SpatialMaterial::set_proximity_fade(bool p_enable) { - +void BaseMaterial3D::set_proximity_fade(bool p_enable) { proximity_fade_enabled = p_enable; _queue_shader_change(); _change_notify(); } -bool SpatialMaterial::is_proximity_fade_enabled() const { - +bool BaseMaterial3D::is_proximity_fade_enabled() const { return proximity_fade_enabled; } -void SpatialMaterial::set_proximity_fade_distance(float p_distance) { - +void BaseMaterial3D::set_proximity_fade_distance(float p_distance) { proximity_fade_distance = p_distance; - VS::get_singleton()->material_set_param(_get_material(), shader_names->proximity_fade_distance, p_distance); + RS::get_singleton()->material_set_param(_get_material(), shader_names->proximity_fade_distance, p_distance); } -float SpatialMaterial::get_proximity_fade_distance() const { +float BaseMaterial3D::get_proximity_fade_distance() const { return proximity_fade_distance; } -void SpatialMaterial::set_distance_fade(DistanceFadeMode p_mode) { - +void BaseMaterial3D::set_distance_fade(DistanceFadeMode p_mode) { distance_fade = p_mode; _queue_shader_change(); _change_notify(); } -SpatialMaterial::DistanceFadeMode SpatialMaterial::get_distance_fade() const { +BaseMaterial3D::DistanceFadeMode BaseMaterial3D::get_distance_fade() const { return distance_fade; } -void SpatialMaterial::set_distance_fade_max_distance(float p_distance) { - +void BaseMaterial3D::set_distance_fade_max_distance(float p_distance) { distance_fade_max_distance = p_distance; - VS::get_singleton()->material_set_param(_get_material(), shader_names->distance_fade_max, distance_fade_max_distance); + RS::get_singleton()->material_set_param(_get_material(), shader_names->distance_fade_max, distance_fade_max_distance); } -float SpatialMaterial::get_distance_fade_max_distance() const { +float BaseMaterial3D::get_distance_fade_max_distance() const { return distance_fade_max_distance; } -void SpatialMaterial::set_distance_fade_min_distance(float p_distance) { - +void BaseMaterial3D::set_distance_fade_min_distance(float p_distance) { distance_fade_min_distance = p_distance; - VS::get_singleton()->material_set_param(_get_material(), shader_names->distance_fade_min, distance_fade_min_distance); + RS::get_singleton()->material_set_param(_get_material(), shader_names->distance_fade_min, distance_fade_min_distance); } -float SpatialMaterial::get_distance_fade_min_distance() const { - +float BaseMaterial3D::get_distance_fade_min_distance() const { return distance_fade_min_distance; } -void SpatialMaterial::set_emission_operator(EmissionOperator p_op) { - - if (emission_op == p_op) +void BaseMaterial3D::set_emission_operator(EmissionOperator p_op) { + if (emission_op == p_op) { return; + } emission_op = p_op; _queue_shader_change(); } -SpatialMaterial::EmissionOperator SpatialMaterial::get_emission_operator() const { - +BaseMaterial3D::EmissionOperator BaseMaterial3D::get_emission_operator() const { return emission_op; } -RID SpatialMaterial::get_shader_rid() const { - +RID BaseMaterial3D::get_shader_rid() const { ERR_FAIL_COND_V(!shader_map.has(current_key), RID()); return shader_map[current_key].shader; } -Shader::Mode SpatialMaterial::get_shader_mode() const { - +Shader::Mode BaseMaterial3D::get_shader_mode() const { return Shader::MODE_SPATIAL; } -void SpatialMaterial::_bind_methods() { +void BaseMaterial3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_albedo", "albedo"), &BaseMaterial3D::set_albedo); + ClassDB::bind_method(D_METHOD("get_albedo"), &BaseMaterial3D::get_albedo); + + ClassDB::bind_method(D_METHOD("set_transparency", "transparency"), &BaseMaterial3D::set_transparency); + ClassDB::bind_method(D_METHOD("get_transparency"), &BaseMaterial3D::get_transparency); + + ClassDB::bind_method(D_METHOD("set_shading_mode", "shading_mode"), &BaseMaterial3D::set_shading_mode); + ClassDB::bind_method(D_METHOD("get_shading_mode"), &BaseMaterial3D::get_shading_mode); + + ClassDB::bind_method(D_METHOD("set_specular", "specular"), &BaseMaterial3D::set_specular); + ClassDB::bind_method(D_METHOD("get_specular"), &BaseMaterial3D::get_specular); - ClassDB::bind_method(D_METHOD("set_albedo", "albedo"), &SpatialMaterial::set_albedo); - ClassDB::bind_method(D_METHOD("get_albedo"), &SpatialMaterial::get_albedo); + ClassDB::bind_method(D_METHOD("set_metallic", "metallic"), &BaseMaterial3D::set_metallic); + ClassDB::bind_method(D_METHOD("get_metallic"), &BaseMaterial3D::get_metallic); - ClassDB::bind_method(D_METHOD("set_specular", "specular"), &SpatialMaterial::set_specular); - ClassDB::bind_method(D_METHOD("get_specular"), &SpatialMaterial::get_specular); + ClassDB::bind_method(D_METHOD("set_roughness", "roughness"), &BaseMaterial3D::set_roughness); + ClassDB::bind_method(D_METHOD("get_roughness"), &BaseMaterial3D::get_roughness); - ClassDB::bind_method(D_METHOD("set_metallic", "metallic"), &SpatialMaterial::set_metallic); - ClassDB::bind_method(D_METHOD("get_metallic"), &SpatialMaterial::get_metallic); + ClassDB::bind_method(D_METHOD("set_emission", "emission"), &BaseMaterial3D::set_emission); + ClassDB::bind_method(D_METHOD("get_emission"), &BaseMaterial3D::get_emission); - ClassDB::bind_method(D_METHOD("set_roughness", "roughness"), &SpatialMaterial::set_roughness); - ClassDB::bind_method(D_METHOD("get_roughness"), &SpatialMaterial::get_roughness); + ClassDB::bind_method(D_METHOD("set_emission_energy", "emission_energy"), &BaseMaterial3D::set_emission_energy); + ClassDB::bind_method(D_METHOD("get_emission_energy"), &BaseMaterial3D::get_emission_energy); - ClassDB::bind_method(D_METHOD("set_emission", "emission"), &SpatialMaterial::set_emission); - ClassDB::bind_method(D_METHOD("get_emission"), &SpatialMaterial::get_emission); + ClassDB::bind_method(D_METHOD("set_normal_scale", "normal_scale"), &BaseMaterial3D::set_normal_scale); + ClassDB::bind_method(D_METHOD("get_normal_scale"), &BaseMaterial3D::get_normal_scale); - ClassDB::bind_method(D_METHOD("set_emission_energy", "emission_energy"), &SpatialMaterial::set_emission_energy); - ClassDB::bind_method(D_METHOD("get_emission_energy"), &SpatialMaterial::get_emission_energy); + ClassDB::bind_method(D_METHOD("set_rim", "rim"), &BaseMaterial3D::set_rim); + ClassDB::bind_method(D_METHOD("get_rim"), &BaseMaterial3D::get_rim); - ClassDB::bind_method(D_METHOD("set_normal_scale", "normal_scale"), &SpatialMaterial::set_normal_scale); - ClassDB::bind_method(D_METHOD("get_normal_scale"), &SpatialMaterial::get_normal_scale); + ClassDB::bind_method(D_METHOD("set_rim_tint", "rim_tint"), &BaseMaterial3D::set_rim_tint); + ClassDB::bind_method(D_METHOD("get_rim_tint"), &BaseMaterial3D::get_rim_tint); - ClassDB::bind_method(D_METHOD("set_rim", "rim"), &SpatialMaterial::set_rim); - ClassDB::bind_method(D_METHOD("get_rim"), &SpatialMaterial::get_rim); + ClassDB::bind_method(D_METHOD("set_clearcoat", "clearcoat"), &BaseMaterial3D::set_clearcoat); + ClassDB::bind_method(D_METHOD("get_clearcoat"), &BaseMaterial3D::get_clearcoat); - ClassDB::bind_method(D_METHOD("set_rim_tint", "rim_tint"), &SpatialMaterial::set_rim_tint); - ClassDB::bind_method(D_METHOD("get_rim_tint"), &SpatialMaterial::get_rim_tint); + ClassDB::bind_method(D_METHOD("set_clearcoat_gloss", "clearcoat_gloss"), &BaseMaterial3D::set_clearcoat_gloss); + ClassDB::bind_method(D_METHOD("get_clearcoat_gloss"), &BaseMaterial3D::get_clearcoat_gloss); - ClassDB::bind_method(D_METHOD("set_clearcoat", "clearcoat"), &SpatialMaterial::set_clearcoat); - ClassDB::bind_method(D_METHOD("get_clearcoat"), &SpatialMaterial::get_clearcoat); + ClassDB::bind_method(D_METHOD("set_anisotropy", "anisotropy"), &BaseMaterial3D::set_anisotropy); + ClassDB::bind_method(D_METHOD("get_anisotropy"), &BaseMaterial3D::get_anisotropy); - ClassDB::bind_method(D_METHOD("set_clearcoat_gloss", "clearcoat_gloss"), &SpatialMaterial::set_clearcoat_gloss); - ClassDB::bind_method(D_METHOD("get_clearcoat_gloss"), &SpatialMaterial::get_clearcoat_gloss); + ClassDB::bind_method(D_METHOD("set_heightmap_scale", "heightmap_scale"), &BaseMaterial3D::set_heightmap_scale); + ClassDB::bind_method(D_METHOD("get_heightmap_scale"), &BaseMaterial3D::get_heightmap_scale); - ClassDB::bind_method(D_METHOD("set_anisotropy", "anisotropy"), &SpatialMaterial::set_anisotropy); - ClassDB::bind_method(D_METHOD("get_anisotropy"), &SpatialMaterial::get_anisotropy); + ClassDB::bind_method(D_METHOD("set_subsurface_scattering_strength", "strength"), &BaseMaterial3D::set_subsurface_scattering_strength); + ClassDB::bind_method(D_METHOD("get_subsurface_scattering_strength"), &BaseMaterial3D::get_subsurface_scattering_strength); - ClassDB::bind_method(D_METHOD("set_depth_scale", "depth_scale"), &SpatialMaterial::set_depth_scale); - ClassDB::bind_method(D_METHOD("get_depth_scale"), &SpatialMaterial::get_depth_scale); + ClassDB::bind_method(D_METHOD("set_transmittance_color", "color"), &BaseMaterial3D::set_transmittance_color); + ClassDB::bind_method(D_METHOD("get_transmittance_color"), &BaseMaterial3D::get_transmittance_color); - ClassDB::bind_method(D_METHOD("set_subsurface_scattering_strength", "strength"), &SpatialMaterial::set_subsurface_scattering_strength); - ClassDB::bind_method(D_METHOD("get_subsurface_scattering_strength"), &SpatialMaterial::get_subsurface_scattering_strength); + ClassDB::bind_method(D_METHOD("set_transmittance_depth", "depth"), &BaseMaterial3D::set_transmittance_depth); + ClassDB::bind_method(D_METHOD("get_transmittance_depth"), &BaseMaterial3D::get_transmittance_depth); - ClassDB::bind_method(D_METHOD("set_transmission", "transmission"), &SpatialMaterial::set_transmission); - ClassDB::bind_method(D_METHOD("get_transmission"), &SpatialMaterial::get_transmission); + ClassDB::bind_method(D_METHOD("set_transmittance_curve", "curve"), &BaseMaterial3D::set_transmittance_curve); + ClassDB::bind_method(D_METHOD("get_transmittance_curve"), &BaseMaterial3D::get_transmittance_curve); - ClassDB::bind_method(D_METHOD("set_refraction", "refraction"), &SpatialMaterial::set_refraction); - ClassDB::bind_method(D_METHOD("get_refraction"), &SpatialMaterial::get_refraction); + ClassDB::bind_method(D_METHOD("set_transmittance_boost", "boost"), &BaseMaterial3D::set_transmittance_boost); + ClassDB::bind_method(D_METHOD("get_transmittance_boost"), &BaseMaterial3D::get_transmittance_boost); - ClassDB::bind_method(D_METHOD("set_line_width", "line_width"), &SpatialMaterial::set_line_width); - ClassDB::bind_method(D_METHOD("get_line_width"), &SpatialMaterial::get_line_width); + ClassDB::bind_method(D_METHOD("set_backlight", "backlight"), &BaseMaterial3D::set_backlight); + ClassDB::bind_method(D_METHOD("get_backlight"), &BaseMaterial3D::get_backlight); - ClassDB::bind_method(D_METHOD("set_point_size", "point_size"), &SpatialMaterial::set_point_size); - ClassDB::bind_method(D_METHOD("get_point_size"), &SpatialMaterial::get_point_size); + ClassDB::bind_method(D_METHOD("set_refraction", "refraction"), &BaseMaterial3D::set_refraction); + ClassDB::bind_method(D_METHOD("get_refraction"), &BaseMaterial3D::get_refraction); - ClassDB::bind_method(D_METHOD("set_detail_uv", "detail_uv"), &SpatialMaterial::set_detail_uv); - ClassDB::bind_method(D_METHOD("get_detail_uv"), &SpatialMaterial::get_detail_uv); + ClassDB::bind_method(D_METHOD("set_point_size", "point_size"), &BaseMaterial3D::set_point_size); + ClassDB::bind_method(D_METHOD("get_point_size"), &BaseMaterial3D::get_point_size); - ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &SpatialMaterial::set_blend_mode); - ClassDB::bind_method(D_METHOD("get_blend_mode"), &SpatialMaterial::get_blend_mode); + ClassDB::bind_method(D_METHOD("set_detail_uv", "detail_uv"), &BaseMaterial3D::set_detail_uv); + ClassDB::bind_method(D_METHOD("get_detail_uv"), &BaseMaterial3D::get_detail_uv); - ClassDB::bind_method(D_METHOD("set_depth_draw_mode", "depth_draw_mode"), &SpatialMaterial::set_depth_draw_mode); - ClassDB::bind_method(D_METHOD("get_depth_draw_mode"), &SpatialMaterial::get_depth_draw_mode); + ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &BaseMaterial3D::set_blend_mode); + ClassDB::bind_method(D_METHOD("get_blend_mode"), &BaseMaterial3D::get_blend_mode); - ClassDB::bind_method(D_METHOD("set_cull_mode", "cull_mode"), &SpatialMaterial::set_cull_mode); - ClassDB::bind_method(D_METHOD("get_cull_mode"), &SpatialMaterial::get_cull_mode); + ClassDB::bind_method(D_METHOD("set_depth_draw_mode", "depth_draw_mode"), &BaseMaterial3D::set_depth_draw_mode); + ClassDB::bind_method(D_METHOD("get_depth_draw_mode"), &BaseMaterial3D::get_depth_draw_mode); - ClassDB::bind_method(D_METHOD("set_diffuse_mode", "diffuse_mode"), &SpatialMaterial::set_diffuse_mode); - ClassDB::bind_method(D_METHOD("get_diffuse_mode"), &SpatialMaterial::get_diffuse_mode); + ClassDB::bind_method(D_METHOD("set_cull_mode", "cull_mode"), &BaseMaterial3D::set_cull_mode); + ClassDB::bind_method(D_METHOD("get_cull_mode"), &BaseMaterial3D::get_cull_mode); - ClassDB::bind_method(D_METHOD("set_specular_mode", "specular_mode"), &SpatialMaterial::set_specular_mode); - ClassDB::bind_method(D_METHOD("get_specular_mode"), &SpatialMaterial::get_specular_mode); + ClassDB::bind_method(D_METHOD("set_diffuse_mode", "diffuse_mode"), &BaseMaterial3D::set_diffuse_mode); + ClassDB::bind_method(D_METHOD("get_diffuse_mode"), &BaseMaterial3D::get_diffuse_mode); - ClassDB::bind_method(D_METHOD("set_flag", "flag", "enable"), &SpatialMaterial::set_flag); - ClassDB::bind_method(D_METHOD("get_flag", "flag"), &SpatialMaterial::get_flag); + ClassDB::bind_method(D_METHOD("set_specular_mode", "specular_mode"), &BaseMaterial3D::set_specular_mode); + ClassDB::bind_method(D_METHOD("get_specular_mode"), &BaseMaterial3D::get_specular_mode); - ClassDB::bind_method(D_METHOD("set_feature", "feature", "enable"), &SpatialMaterial::set_feature); - ClassDB::bind_method(D_METHOD("get_feature", "feature"), &SpatialMaterial::get_feature); + ClassDB::bind_method(D_METHOD("set_flag", "flag", "enable"), &BaseMaterial3D::set_flag); + ClassDB::bind_method(D_METHOD("get_flag", "flag"), &BaseMaterial3D::get_flag); - ClassDB::bind_method(D_METHOD("set_texture", "param", "texture"), &SpatialMaterial::set_texture); - ClassDB::bind_method(D_METHOD("get_texture", "param"), &SpatialMaterial::get_texture); + ClassDB::bind_method(D_METHOD("set_texture_filter", "mode"), &BaseMaterial3D::set_texture_filter); + ClassDB::bind_method(D_METHOD("get_texture_filter"), &BaseMaterial3D::get_texture_filter); - ClassDB::bind_method(D_METHOD("set_detail_blend_mode", "detail_blend_mode"), &SpatialMaterial::set_detail_blend_mode); - ClassDB::bind_method(D_METHOD("get_detail_blend_mode"), &SpatialMaterial::get_detail_blend_mode); + ClassDB::bind_method(D_METHOD("set_feature", "feature", "enable"), &BaseMaterial3D::set_feature); + ClassDB::bind_method(D_METHOD("get_feature", "feature"), &BaseMaterial3D::get_feature); - ClassDB::bind_method(D_METHOD("set_uv1_scale", "scale"), &SpatialMaterial::set_uv1_scale); - ClassDB::bind_method(D_METHOD("get_uv1_scale"), &SpatialMaterial::get_uv1_scale); + ClassDB::bind_method(D_METHOD("set_texture", "param", "texture"), &BaseMaterial3D::set_texture); + ClassDB::bind_method(D_METHOD("get_texture", "param"), &BaseMaterial3D::get_texture); - ClassDB::bind_method(D_METHOD("set_uv1_offset", "offset"), &SpatialMaterial::set_uv1_offset); - ClassDB::bind_method(D_METHOD("get_uv1_offset"), &SpatialMaterial::get_uv1_offset); + ClassDB::bind_method(D_METHOD("set_detail_blend_mode", "detail_blend_mode"), &BaseMaterial3D::set_detail_blend_mode); + ClassDB::bind_method(D_METHOD("get_detail_blend_mode"), &BaseMaterial3D::get_detail_blend_mode); - ClassDB::bind_method(D_METHOD("set_uv1_triplanar_blend_sharpness", "sharpness"), &SpatialMaterial::set_uv1_triplanar_blend_sharpness); - ClassDB::bind_method(D_METHOD("get_uv1_triplanar_blend_sharpness"), &SpatialMaterial::get_uv1_triplanar_blend_sharpness); + ClassDB::bind_method(D_METHOD("set_uv1_scale", "scale"), &BaseMaterial3D::set_uv1_scale); + ClassDB::bind_method(D_METHOD("get_uv1_scale"), &BaseMaterial3D::get_uv1_scale); - ClassDB::bind_method(D_METHOD("set_uv2_scale", "scale"), &SpatialMaterial::set_uv2_scale); - ClassDB::bind_method(D_METHOD("get_uv2_scale"), &SpatialMaterial::get_uv2_scale); + ClassDB::bind_method(D_METHOD("set_uv1_offset", "offset"), &BaseMaterial3D::set_uv1_offset); + ClassDB::bind_method(D_METHOD("get_uv1_offset"), &BaseMaterial3D::get_uv1_offset); - ClassDB::bind_method(D_METHOD("set_uv2_offset", "offset"), &SpatialMaterial::set_uv2_offset); - ClassDB::bind_method(D_METHOD("get_uv2_offset"), &SpatialMaterial::get_uv2_offset); + ClassDB::bind_method(D_METHOD("set_uv1_triplanar_blend_sharpness", "sharpness"), &BaseMaterial3D::set_uv1_triplanar_blend_sharpness); + ClassDB::bind_method(D_METHOD("get_uv1_triplanar_blend_sharpness"), &BaseMaterial3D::get_uv1_triplanar_blend_sharpness); - ClassDB::bind_method(D_METHOD("set_uv2_triplanar_blend_sharpness", "sharpness"), &SpatialMaterial::set_uv2_triplanar_blend_sharpness); - ClassDB::bind_method(D_METHOD("get_uv2_triplanar_blend_sharpness"), &SpatialMaterial::get_uv2_triplanar_blend_sharpness); + ClassDB::bind_method(D_METHOD("set_uv2_scale", "scale"), &BaseMaterial3D::set_uv2_scale); + ClassDB::bind_method(D_METHOD("get_uv2_scale"), &BaseMaterial3D::get_uv2_scale); - ClassDB::bind_method(D_METHOD("set_billboard_mode", "mode"), &SpatialMaterial::set_billboard_mode); - ClassDB::bind_method(D_METHOD("get_billboard_mode"), &SpatialMaterial::get_billboard_mode); + ClassDB::bind_method(D_METHOD("set_uv2_offset", "offset"), &BaseMaterial3D::set_uv2_offset); + ClassDB::bind_method(D_METHOD("get_uv2_offset"), &BaseMaterial3D::get_uv2_offset); - ClassDB::bind_method(D_METHOD("set_particles_anim_h_frames", "frames"), &SpatialMaterial::set_particles_anim_h_frames); - ClassDB::bind_method(D_METHOD("get_particles_anim_h_frames"), &SpatialMaterial::get_particles_anim_h_frames); + ClassDB::bind_method(D_METHOD("set_uv2_triplanar_blend_sharpness", "sharpness"), &BaseMaterial3D::set_uv2_triplanar_blend_sharpness); + ClassDB::bind_method(D_METHOD("get_uv2_triplanar_blend_sharpness"), &BaseMaterial3D::get_uv2_triplanar_blend_sharpness); - ClassDB::bind_method(D_METHOD("set_particles_anim_v_frames", "frames"), &SpatialMaterial::set_particles_anim_v_frames); - ClassDB::bind_method(D_METHOD("get_particles_anim_v_frames"), &SpatialMaterial::get_particles_anim_v_frames); + ClassDB::bind_method(D_METHOD("set_billboard_mode", "mode"), &BaseMaterial3D::set_billboard_mode); + ClassDB::bind_method(D_METHOD("get_billboard_mode"), &BaseMaterial3D::get_billboard_mode); - ClassDB::bind_method(D_METHOD("set_particles_anim_loop", "loop"), &SpatialMaterial::set_particles_anim_loop); - ClassDB::bind_method(D_METHOD("get_particles_anim_loop"), &SpatialMaterial::get_particles_anim_loop); + ClassDB::bind_method(D_METHOD("set_particles_anim_h_frames", "frames"), &BaseMaterial3D::set_particles_anim_h_frames); + ClassDB::bind_method(D_METHOD("get_particles_anim_h_frames"), &BaseMaterial3D::get_particles_anim_h_frames); - ClassDB::bind_method(D_METHOD("set_depth_deep_parallax", "enable"), &SpatialMaterial::set_depth_deep_parallax); - ClassDB::bind_method(D_METHOD("is_depth_deep_parallax_enabled"), &SpatialMaterial::is_depth_deep_parallax_enabled); + ClassDB::bind_method(D_METHOD("set_particles_anim_v_frames", "frames"), &BaseMaterial3D::set_particles_anim_v_frames); + ClassDB::bind_method(D_METHOD("get_particles_anim_v_frames"), &BaseMaterial3D::get_particles_anim_v_frames); - ClassDB::bind_method(D_METHOD("set_depth_deep_parallax_min_layers", "layer"), &SpatialMaterial::set_depth_deep_parallax_min_layers); - ClassDB::bind_method(D_METHOD("get_depth_deep_parallax_min_layers"), &SpatialMaterial::get_depth_deep_parallax_min_layers); + ClassDB::bind_method(D_METHOD("set_particles_anim_loop", "loop"), &BaseMaterial3D::set_particles_anim_loop); + ClassDB::bind_method(D_METHOD("get_particles_anim_loop"), &BaseMaterial3D::get_particles_anim_loop); - ClassDB::bind_method(D_METHOD("set_depth_deep_parallax_max_layers", "layer"), &SpatialMaterial::set_depth_deep_parallax_max_layers); - ClassDB::bind_method(D_METHOD("get_depth_deep_parallax_max_layers"), &SpatialMaterial::get_depth_deep_parallax_max_layers); + ClassDB::bind_method(D_METHOD("set_heightmap_deep_parallax", "enable"), &BaseMaterial3D::set_heightmap_deep_parallax); + ClassDB::bind_method(D_METHOD("is_heightmap_deep_parallax_enabled"), &BaseMaterial3D::is_heightmap_deep_parallax_enabled); - ClassDB::bind_method(D_METHOD("set_depth_deep_parallax_flip_tangent", "flip"), &SpatialMaterial::set_depth_deep_parallax_flip_tangent); - ClassDB::bind_method(D_METHOD("get_depth_deep_parallax_flip_tangent"), &SpatialMaterial::get_depth_deep_parallax_flip_tangent); + ClassDB::bind_method(D_METHOD("set_heightmap_deep_parallax_min_layers", "layer"), &BaseMaterial3D::set_heightmap_deep_parallax_min_layers); + ClassDB::bind_method(D_METHOD("get_heightmap_deep_parallax_min_layers"), &BaseMaterial3D::get_heightmap_deep_parallax_min_layers); - ClassDB::bind_method(D_METHOD("set_depth_deep_parallax_flip_binormal", "flip"), &SpatialMaterial::set_depth_deep_parallax_flip_binormal); - ClassDB::bind_method(D_METHOD("get_depth_deep_parallax_flip_binormal"), &SpatialMaterial::get_depth_deep_parallax_flip_binormal); + ClassDB::bind_method(D_METHOD("set_heightmap_deep_parallax_max_layers", "layer"), &BaseMaterial3D::set_heightmap_deep_parallax_max_layers); + ClassDB::bind_method(D_METHOD("get_heightmap_deep_parallax_max_layers"), &BaseMaterial3D::get_heightmap_deep_parallax_max_layers); - ClassDB::bind_method(D_METHOD("set_grow", "amount"), &SpatialMaterial::set_grow); - ClassDB::bind_method(D_METHOD("get_grow"), &SpatialMaterial::get_grow); + ClassDB::bind_method(D_METHOD("set_heightmap_deep_parallax_flip_tangent", "flip"), &BaseMaterial3D::set_heightmap_deep_parallax_flip_tangent); + ClassDB::bind_method(D_METHOD("get_heightmap_deep_parallax_flip_tangent"), &BaseMaterial3D::get_heightmap_deep_parallax_flip_tangent); - ClassDB::bind_method(D_METHOD("set_emission_operator", "operator"), &SpatialMaterial::set_emission_operator); - ClassDB::bind_method(D_METHOD("get_emission_operator"), &SpatialMaterial::get_emission_operator); + ClassDB::bind_method(D_METHOD("set_heightmap_deep_parallax_flip_binormal", "flip"), &BaseMaterial3D::set_heightmap_deep_parallax_flip_binormal); + ClassDB::bind_method(D_METHOD("get_heightmap_deep_parallax_flip_binormal"), &BaseMaterial3D::get_heightmap_deep_parallax_flip_binormal); - ClassDB::bind_method(D_METHOD("set_ao_light_affect", "amount"), &SpatialMaterial::set_ao_light_affect); - ClassDB::bind_method(D_METHOD("get_ao_light_affect"), &SpatialMaterial::get_ao_light_affect); + ClassDB::bind_method(D_METHOD("set_grow", "amount"), &BaseMaterial3D::set_grow); + ClassDB::bind_method(D_METHOD("get_grow"), &BaseMaterial3D::get_grow); - ClassDB::bind_method(D_METHOD("set_alpha_scissor_threshold", "threshold"), &SpatialMaterial::set_alpha_scissor_threshold); - ClassDB::bind_method(D_METHOD("get_alpha_scissor_threshold"), &SpatialMaterial::get_alpha_scissor_threshold); + ClassDB::bind_method(D_METHOD("set_emission_operator", "operator"), &BaseMaterial3D::set_emission_operator); + ClassDB::bind_method(D_METHOD("get_emission_operator"), &BaseMaterial3D::get_emission_operator); - ClassDB::bind_method(D_METHOD("set_grow_enabled", "enable"), &SpatialMaterial::set_grow_enabled); - ClassDB::bind_method(D_METHOD("is_grow_enabled"), &SpatialMaterial::is_grow_enabled); + ClassDB::bind_method(D_METHOD("set_ao_light_affect", "amount"), &BaseMaterial3D::set_ao_light_affect); + ClassDB::bind_method(D_METHOD("get_ao_light_affect"), &BaseMaterial3D::get_ao_light_affect); - ClassDB::bind_method(D_METHOD("set_metallic_texture_channel", "channel"), &SpatialMaterial::set_metallic_texture_channel); - ClassDB::bind_method(D_METHOD("get_metallic_texture_channel"), &SpatialMaterial::get_metallic_texture_channel); + ClassDB::bind_method(D_METHOD("set_alpha_scissor_threshold", "threshold"), &BaseMaterial3D::set_alpha_scissor_threshold); + ClassDB::bind_method(D_METHOD("get_alpha_scissor_threshold"), &BaseMaterial3D::get_alpha_scissor_threshold); - ClassDB::bind_method(D_METHOD("set_roughness_texture_channel", "channel"), &SpatialMaterial::set_roughness_texture_channel); - ClassDB::bind_method(D_METHOD("get_roughness_texture_channel"), &SpatialMaterial::get_roughness_texture_channel); + ClassDB::bind_method(D_METHOD("set_grow_enabled", "enable"), &BaseMaterial3D::set_grow_enabled); + ClassDB::bind_method(D_METHOD("is_grow_enabled"), &BaseMaterial3D::is_grow_enabled); - ClassDB::bind_method(D_METHOD("set_ao_texture_channel", "channel"), &SpatialMaterial::set_ao_texture_channel); - ClassDB::bind_method(D_METHOD("get_ao_texture_channel"), &SpatialMaterial::get_ao_texture_channel); + ClassDB::bind_method(D_METHOD("set_metallic_texture_channel", "channel"), &BaseMaterial3D::set_metallic_texture_channel); + ClassDB::bind_method(D_METHOD("get_metallic_texture_channel"), &BaseMaterial3D::get_metallic_texture_channel); - ClassDB::bind_method(D_METHOD("set_refraction_texture_channel", "channel"), &SpatialMaterial::set_refraction_texture_channel); - ClassDB::bind_method(D_METHOD("get_refraction_texture_channel"), &SpatialMaterial::get_refraction_texture_channel); + ClassDB::bind_method(D_METHOD("set_roughness_texture_channel", "channel"), &BaseMaterial3D::set_roughness_texture_channel); + ClassDB::bind_method(D_METHOD("get_roughness_texture_channel"), &BaseMaterial3D::get_roughness_texture_channel); - ClassDB::bind_method(D_METHOD("set_proximity_fade", "enabled"), &SpatialMaterial::set_proximity_fade); - ClassDB::bind_method(D_METHOD("is_proximity_fade_enabled"), &SpatialMaterial::is_proximity_fade_enabled); + ClassDB::bind_method(D_METHOD("set_ao_texture_channel", "channel"), &BaseMaterial3D::set_ao_texture_channel); + ClassDB::bind_method(D_METHOD("get_ao_texture_channel"), &BaseMaterial3D::get_ao_texture_channel); - ClassDB::bind_method(D_METHOD("set_proximity_fade_distance", "distance"), &SpatialMaterial::set_proximity_fade_distance); - ClassDB::bind_method(D_METHOD("get_proximity_fade_distance"), &SpatialMaterial::get_proximity_fade_distance); + ClassDB::bind_method(D_METHOD("set_refraction_texture_channel", "channel"), &BaseMaterial3D::set_refraction_texture_channel); + ClassDB::bind_method(D_METHOD("get_refraction_texture_channel"), &BaseMaterial3D::get_refraction_texture_channel); - ClassDB::bind_method(D_METHOD("set_distance_fade", "mode"), &SpatialMaterial::set_distance_fade); - ClassDB::bind_method(D_METHOD("get_distance_fade"), &SpatialMaterial::get_distance_fade); + ClassDB::bind_method(D_METHOD("set_proximity_fade", "enabled"), &BaseMaterial3D::set_proximity_fade); + ClassDB::bind_method(D_METHOD("is_proximity_fade_enabled"), &BaseMaterial3D::is_proximity_fade_enabled); - ClassDB::bind_method(D_METHOD("set_distance_fade_max_distance", "distance"), &SpatialMaterial::set_distance_fade_max_distance); - ClassDB::bind_method(D_METHOD("get_distance_fade_max_distance"), &SpatialMaterial::get_distance_fade_max_distance); + ClassDB::bind_method(D_METHOD("set_proximity_fade_distance", "distance"), &BaseMaterial3D::set_proximity_fade_distance); + ClassDB::bind_method(D_METHOD("get_proximity_fade_distance"), &BaseMaterial3D::get_proximity_fade_distance); - ClassDB::bind_method(D_METHOD("set_distance_fade_min_distance", "distance"), &SpatialMaterial::set_distance_fade_min_distance); - ClassDB::bind_method(D_METHOD("get_distance_fade_min_distance"), &SpatialMaterial::get_distance_fade_min_distance); + ClassDB::bind_method(D_METHOD("set_distance_fade", "mode"), &BaseMaterial3D::set_distance_fade); + ClassDB::bind_method(D_METHOD("get_distance_fade"), &BaseMaterial3D::get_distance_fade); + + ClassDB::bind_method(D_METHOD("set_distance_fade_max_distance", "distance"), &BaseMaterial3D::set_distance_fade_max_distance); + ClassDB::bind_method(D_METHOD("get_distance_fade_max_distance"), &BaseMaterial3D::get_distance_fade_max_distance); + + ClassDB::bind_method(D_METHOD("set_distance_fade_min_distance", "distance"), &BaseMaterial3D::set_distance_fade_min_distance); + ClassDB::bind_method(D_METHOD("get_distance_fade_min_distance"), &BaseMaterial3D::get_distance_fade_min_distance); + + ADD_GROUP("Transparency", ""); + ADD_PROPERTY(PropertyInfo(Variant::INT, "transparency", PROPERTY_HINT_ENUM, "Disabled,Alpha,AlphaScissor,DepthPrePass"), "set_transparency", "get_transparency"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), "set_blend_mode", "get_blend_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mode", PROPERTY_HINT_ENUM, "Back,Front,Disabled"), "set_cull_mode", "get_cull_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_draw_mode", PROPERTY_HINT_ENUM, "Opaque Only,Always,Never"), "set_depth_draw_mode", "get_depth_draw_mode"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_flag", "get_flag", FLAG_DISABLE_DEPTH_TEST); + + ADD_GROUP("Shading", ""); + ADD_PROPERTY(PropertyInfo(Variant::INT, "shading_mode", PROPERTY_HINT_ENUM, "Unshaded,PerPixel,PerVertex"), "set_shading_mode", "get_shading_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "diffuse_mode", PROPERTY_HINT_ENUM, "Burley,Lambert,Lambert Wrap,Oren Nayar,Toon"), "set_diffuse_mode", "get_diffuse_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "specular_mode", PROPERTY_HINT_ENUM, "SchlickGGX,Blinn,Phong,Toon,Disabled"), "set_specular_mode", "get_specular_mode"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "disable_ambient_light"), "set_flag", "get_flag", FLAG_DISABLE_AMBIENT_LIGHT); - ADD_GROUP("Flags", "flags_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_transparent"), "set_feature", "get_feature", FEATURE_TRANSPARENT); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_use_shadow_to_opacity"), "set_flag", "get_flag", FLAG_USE_SHADOW_TO_OPACITY); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_unshaded"), "set_flag", "get_flag", FLAG_UNSHADED); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_vertex_lighting"), "set_flag", "get_flag", FLAG_USE_VERTEX_LIGHTING); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_no_depth_test"), "set_flag", "get_flag", FLAG_DISABLE_DEPTH_TEST); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_use_point_size"), "set_flag", "get_flag", FLAG_USE_POINT_SIZE); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_world_triplanar"), "set_flag", "get_flag", FLAG_TRIPLANAR_USE_WORLD); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_fixed_size"), "set_flag", "get_flag", FLAG_FIXED_SIZE); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_albedo_tex_force_srgb"), "set_flag", "get_flag", FLAG_ALBEDO_TEXTURE_FORCE_SRGB); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_do_not_receive_shadows"), "set_flag", "get_flag", FLAG_DONT_RECEIVE_SHADOWS); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_disable_ambient_light"), "set_flag", "get_flag", FLAG_DISABLE_AMBIENT_LIGHT); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_ensure_correct_normals"), "set_flag", "get_flag", FLAG_ENSURE_CORRECT_NORMALS); ADD_GROUP("Vertex Color", "vertex_color"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_use_as_albedo"), "set_flag", "get_flag", FLAG_ALBEDO_FROM_VERTEX_COLOR); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_is_srgb"), "set_flag", "get_flag", FLAG_SRGB_VERTEX_COLOR); - ADD_GROUP("Parameters", "params_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "params_diffuse_mode", PROPERTY_HINT_ENUM, "Burley,Lambert,Lambert Wrap,Oren Nayar,Toon"), "set_diffuse_mode", "get_diffuse_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "params_specular_mode", PROPERTY_HINT_ENUM, "SchlickGGX,Blinn,Phong,Toon,Disabled"), "set_specular_mode", "get_specular_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "params_blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), "set_blend_mode", "get_blend_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "params_cull_mode", PROPERTY_HINT_ENUM, "Back,Front,Disabled"), "set_cull_mode", "get_cull_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "params_depth_draw_mode", PROPERTY_HINT_ENUM, "Opaque Only,Always,Never,Opaque Pre-Pass"), "set_depth_draw_mode", "get_depth_draw_mode"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_line_width", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_line_width", "get_line_width"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_point_size", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_point_size", "get_point_size"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "params_billboard_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard,Particle Billboard"), "set_billboard_mode", "get_billboard_mode"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "params_billboard_keep_scale"), "set_flag", "get_flag", FLAG_BILLBOARD_KEEP_SCALE); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "params_grow"), "set_grow_enabled", "is_grow_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_grow_amount", PROPERTY_HINT_RANGE, "-16,16,0.001"), "set_grow", "get_grow"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "params_use_alpha_scissor"), "set_flag", "get_flag", FLAG_USE_ALPHA_SCISSOR); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold"); - ADD_GROUP("Particles Anim", "particles_anim_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_h_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_h_frames", "get_particles_anim_h_frames"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_v_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_v_frames", "get_particles_anim_v_frames"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "particles_anim_loop"), "set_particles_anim_loop", "get_particles_anim_loop"); - ADD_GROUP("Albedo", "albedo_"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "albedo_color"), "set_albedo", "get_albedo"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "albedo_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ALBEDO); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "albedo_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_ALBEDO); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "albedo_tex_force_srgb"), "set_flag", "get_flag", FLAG_ALBEDO_TEXTURE_FORCE_SRGB); + + ADD_GROUP("ORM", "orm_"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "orm_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_ORM); ADD_GROUP("Metallic", "metallic_"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "metallic", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_metallic", "get_metallic"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "metallic_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_specular", "get_specular"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "metallic_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_METALLIC); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "metallic", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_metallic", "get_metallic"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "metallic_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_specular", "get_specular"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "metallic_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_METALLIC); ADD_PROPERTY(PropertyInfo(Variant::INT, "metallic_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_metallic_texture_channel", "get_metallic_texture_channel"); ADD_GROUP("Roughness", "roughness_"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "roughness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_roughness", "get_roughness"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "roughness_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_ROUGHNESS); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "roughness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_roughness", "get_roughness"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "roughness_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_ROUGHNESS); ADD_PROPERTY(PropertyInfo(Variant::INT, "roughness_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_roughness_texture_channel", "get_roughness_texture_channel"); ADD_GROUP("Emission", "emission_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "emission_enabled"), "set_feature", "get_feature", FEATURE_EMISSION); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "emission", PROPERTY_HINT_COLOR_NO_ALPHA), "set_emission", "get_emission"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_emission_energy", "get_emission_energy"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_emission_energy", "get_emission_energy"); ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_operator", PROPERTY_HINT_ENUM, "Add,Multiply"), "set_emission_operator", "get_emission_operator"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "emission_on_uv2"), "set_flag", "get_flag", FLAG_EMISSION_ON_UV2); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "emission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_EMISSION); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "emission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_EMISSION); ADD_GROUP("NormalMap", "normal_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "normal_enabled"), "set_feature", "get_feature", FEATURE_NORMAL_MAPPING); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_scale", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_normal_scale", "get_normal_scale"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_NORMAL); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "normal_scale", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_normal_scale", "get_normal_scale"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_NORMAL); ADD_GROUP("Rim", "rim_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "rim_enabled"), "set_feature", "get_feature", FEATURE_RIM); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "rim", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_rim", "get_rim"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "rim_tint", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_rim_tint", "get_rim_tint"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "rim_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_RIM); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rim", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_rim", "get_rim"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rim_tint", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_rim_tint", "get_rim_tint"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "rim_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_RIM); ADD_GROUP("Clearcoat", "clearcoat_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "clearcoat_enabled"), "set_feature", "get_feature", FEATURE_CLEARCOAT); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "clearcoat", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_clearcoat", "get_clearcoat"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "clearcoat_gloss", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_clearcoat_gloss", "get_clearcoat_gloss"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "clearcoat_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_CLEARCOAT); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "clearcoat", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_clearcoat", "get_clearcoat"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "clearcoat_gloss", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_clearcoat_gloss", "get_clearcoat_gloss"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "clearcoat_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_CLEARCOAT); ADD_GROUP("Anisotropy", "anisotropy_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "anisotropy_enabled"), "set_feature", "get_feature", FEATURE_ANISOTROPY); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "anisotropy", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_anisotropy", "get_anisotropy"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anisotropy_flowmap", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_FLOWMAP); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "anisotropy", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_anisotropy", "get_anisotropy"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anisotropy_flowmap", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_FLOWMAP); ADD_GROUP("Ambient Occlusion", "ao_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "ao_enabled"), "set_feature", "get_feature", FEATURE_AMBIENT_OCCLUSION); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ao_light_affect", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao_light_affect", "get_ao_light_affect"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "ao_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_AMBIENT_OCCLUSION); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ao_light_affect", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao_light_affect", "get_ao_light_affect"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "ao_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_AMBIENT_OCCLUSION); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "ao_on_uv2"), "set_flag", "get_flag", FLAG_AO_ON_UV2); ADD_PROPERTY(PropertyInfo(Variant::INT, "ao_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_ao_texture_channel", "get_ao_texture_channel"); - ADD_GROUP("Depth", "depth_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "depth_enabled"), "set_feature", "get_feature", FEATURE_DEPTH_MAPPING); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "depth_scale", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_depth_scale", "get_depth_scale"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "depth_deep_parallax"), "set_depth_deep_parallax", "is_depth_deep_parallax_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_min_layers", PROPERTY_HINT_RANGE, "1,32,1"), "set_depth_deep_parallax_min_layers", "get_depth_deep_parallax_min_layers"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_max_layers", PROPERTY_HINT_RANGE, "1,32,1"), "set_depth_deep_parallax_max_layers", "get_depth_deep_parallax_max_layers"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "depth_flip_tangent"), "set_depth_deep_parallax_flip_tangent", "get_depth_deep_parallax_flip_tangent"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "depth_flip_binormal"), "set_depth_deep_parallax_flip_binormal", "get_depth_deep_parallax_flip_binormal"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "depth_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_DEPTH); + ADD_GROUP("Height", "heightmap_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "heightmap_enabled"), "set_feature", "get_feature", FEATURE_HEIGHT_MAPPING); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "heightmap_scale", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_heightmap_scale", "get_heightmap_scale"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "heightmap_deep_parallax"), "set_heightmap_deep_parallax", "is_heightmap_deep_parallax_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "heightmap_min_layers", PROPERTY_HINT_RANGE, "1,32,1"), "set_heightmap_deep_parallax_min_layers", "get_heightmap_deep_parallax_min_layers"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "heightmap_max_layers", PROPERTY_HINT_RANGE, "1,32,1"), "set_heightmap_deep_parallax_max_layers", "get_heightmap_deep_parallax_max_layers"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "heightmap_flip_tangent"), "set_heightmap_deep_parallax_flip_tangent", "get_heightmap_deep_parallax_flip_tangent"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "heightmap_flip_binormal"), "set_heightmap_deep_parallax_flip_binormal", "get_heightmap_deep_parallax_flip_binormal"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "heightmap_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_HEIGHTMAP); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "heightmap_flip_texture"), "set_flag", "get_flag", FLAG_INVERT_HEIGHTMAP); ADD_GROUP("Subsurf Scatter", "subsurf_scatter_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_enabled"), "set_feature", "get_feature", FEATURE_SUBSURACE_SCATTERING); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "subsurf_scatter_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_subsurface_scattering_strength", "get_subsurface_scattering_strength"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "subsurf_scatter_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_SUBSURFACE_SCATTERING); - - ADD_GROUP("Transmission", "transmission_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "transmission_enabled"), "set_feature", "get_feature", FEATURE_TRANSMISSION); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "transmission", PROPERTY_HINT_COLOR_NO_ALPHA), "set_transmission", "get_transmission"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "transmission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_TRANSMISSION); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_enabled"), "set_feature", "get_feature", FEATURE_SUBSURFACE_SCATTERING); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_subsurface_scattering_strength", "get_subsurface_scattering_strength"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_skin_mode"), "set_flag", "get_flag", FLAG_SUBSURFACE_MODE_SKIN); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "subsurf_scatter_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_SUBSURFACE_SCATTERING); + + ADD_SUBGROUP("Transmittance", "subsurf_scatter_transmittance_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "subsurf_scatter_transmittance_enabled"), "set_feature", "get_feature", FEATURE_SUBSURFACE_TRANSMITTANCE); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "subsurf_scatter_transmittance_color"), "set_transmittance_color", "get_transmittance_color"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "subsurf_scatter_transmittance_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_SUBSURFACE_TRANSMITTANCE); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_transmittance_depth", PROPERTY_HINT_RANGE, "0.001,8,0.001,or_greater"), "set_transmittance_depth", "get_transmittance_depth"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_transmittance_curve", PROPERTY_HINT_EXP_EASING, "0.01,16,0.01"), "set_transmittance_curve", "get_transmittance_curve"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "subsurf_scatter_transmittance_boost", PROPERTY_HINT_RANGE, "0.00,1.0,0.01"), "set_transmittance_boost", "get_transmittance_boost"); + + ADD_GROUP("Back Lighting", "backlight_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "backlight_enabled"), "set_feature", "get_feature", FEATURE_BACKLIGHT); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "backlight", PROPERTY_HINT_COLOR_NO_ALPHA), "set_backlight", "get_backlight"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "backlight_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_BACKLIGHT); ADD_GROUP("Refraction", "refraction_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "refraction_enabled"), "set_feature", "get_feature", FEATURE_REFRACTION); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "refraction_scale", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_refraction", "get_refraction"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "refraction_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_REFRACTION); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "refraction_scale", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_refraction", "get_refraction"); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "refraction_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_REFRACTION); ADD_PROPERTY(PropertyInfo(Variant::INT, "refraction_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_refraction_texture_channel", "get_refraction_texture_channel"); ADD_GROUP("Detail", "detail_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "detail_enabled"), "set_feature", "get_feature", FEATURE_DETAIL); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_mask", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_DETAIL_MASK); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_mask", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_DETAIL_MASK); ADD_PROPERTY(PropertyInfo(Variant::INT, "detail_blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), "set_detail_blend_mode", "get_detail_blend_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "detail_uv_layer", PROPERTY_HINT_ENUM, "UV1,UV2"), "set_detail_uv", "get_detail_uv"); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_albedo", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_DETAIL_ALBEDO); - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_DETAIL_NORMAL); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_albedo", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_DETAIL_ALBEDO); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_DETAIL_NORMAL); ADD_GROUP("UV1", "uv1_"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv1_scale"), "set_uv1_scale", "get_uv1_scale"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv1_offset"), "set_uv1_offset", "get_uv1_offset"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv1_triplanar"), "set_flag", "get_flag", FLAG_UV1_USE_TRIPLANAR); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "uv1_triplanar_sharpness", PROPERTY_HINT_EXP_EASING), "set_uv1_triplanar_blend_sharpness", "get_uv1_triplanar_blend_sharpness"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "uv1_triplanar_sharpness", PROPERTY_HINT_EXP_EASING), "set_uv1_triplanar_blend_sharpness", "get_uv1_triplanar_blend_sharpness"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv1_world_triplanar"), "set_flag", "get_flag", FLAG_UV1_USE_WORLD_TRIPLANAR); ADD_GROUP("UV2", "uv2_"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv2_scale"), "set_uv2_scale", "get_uv2_scale"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "uv2_offset"), "set_uv2_offset", "get_uv2_offset"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv2_triplanar"), "set_flag", "get_flag", FLAG_UV2_USE_TRIPLANAR); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "uv2_triplanar_sharpness", PROPERTY_HINT_EXP_EASING), "set_uv2_triplanar_blend_sharpness", "get_uv2_triplanar_blend_sharpness"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "uv2_triplanar_sharpness", PROPERTY_HINT_EXP_EASING), "set_uv2_triplanar_blend_sharpness", "get_uv2_triplanar_blend_sharpness"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv2_world_triplanar"), "set_flag", "get_flag", FLAG_UV2_USE_WORLD_TRIPLANAR); + + ADD_GROUP("Sampling", "texture_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,MipmapNearest,MipmapLinear,MipmapNearestAniso,MipmapLinearAniso"), "set_texture_filter", "get_texture_filter"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "texture_repeat"), "set_flag", "get_flag", FLAG_USE_TEXTURE_REPEAT); + + ADD_GROUP("Shadows", ""); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "disable_receive_shadows"), "set_flag", "get_flag", FLAG_DONT_RECEIVE_SHADOWS); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "shadow_to_opacity"), "set_flag", "get_flag", FLAG_USE_SHADOW_TO_OPACITY); + + ADD_GROUP("Billboard", "billboard_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "billboard_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard,Particle Billboard"), "set_billboard_mode", "get_billboard_mode"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "billboard_keep_scale"), "set_flag", "get_flag", FLAG_BILLBOARD_KEEP_SCALE); + + ADD_GROUP("Particles Anim", "particles_anim_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_h_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_h_frames", "get_particles_anim_h_frames"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_v_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_v_frames", "get_particles_anim_v_frames"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "particles_anim_loop"), "set_particles_anim_loop", "get_particles_anim_loop"); + ADD_GROUP("Grow", "grow_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "grow"), "set_grow_enabled", "is_grow_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "grow_amount", PROPERTY_HINT_RANGE, "-16,16,0.001"), "set_grow", "get_grow"); + ADD_GROUP("Transform", ""); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "fixed_size"), "set_flag", "get_flag", FLAG_FIXED_SIZE); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_point_size"), "set_flag", "get_flag", FLAG_USE_POINT_SIZE); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "point_size", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_point_size", "get_point_size"); ADD_GROUP("Proximity Fade", "proximity_fade_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "proximity_fade_enable"), "set_proximity_fade", "is_proximity_fade_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "proximity_fade_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_proximity_fade_distance", "get_proximity_fade_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "proximity_fade_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_proximity_fade_distance", "get_proximity_fade_distance"); ADD_GROUP("Distance Fade", "distance_fade_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "distance_fade_mode", PROPERTY_HINT_ENUM, "Disabled,PixelAlpha,PixelDither,ObjectDither"), "set_distance_fade", "get_distance_fade"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "distance_fade_min_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_distance_fade_min_distance", "get_distance_fade_min_distance"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "distance_fade_max_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_distance_fade_max_distance", "get_distance_fade_max_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_min_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_distance_fade_min_distance", "get_distance_fade_min_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_max_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_distance_fade_max_distance", "get_distance_fade_max_distance"); BIND_ENUM_CONSTANT(TEXTURE_ALBEDO); BIND_ENUM_CONSTANT(TEXTURE_METALLIC); @@ -2250,28 +2389,49 @@ void SpatialMaterial::_bind_methods() { BIND_ENUM_CONSTANT(TEXTURE_CLEARCOAT); BIND_ENUM_CONSTANT(TEXTURE_FLOWMAP); BIND_ENUM_CONSTANT(TEXTURE_AMBIENT_OCCLUSION); - BIND_ENUM_CONSTANT(TEXTURE_DEPTH); + BIND_ENUM_CONSTANT(TEXTURE_HEIGHTMAP); BIND_ENUM_CONSTANT(TEXTURE_SUBSURFACE_SCATTERING); - BIND_ENUM_CONSTANT(TEXTURE_TRANSMISSION); + BIND_ENUM_CONSTANT(TEXTURE_SUBSURFACE_TRANSMITTANCE); + BIND_ENUM_CONSTANT(TEXTURE_BACKLIGHT); BIND_ENUM_CONSTANT(TEXTURE_REFRACTION); BIND_ENUM_CONSTANT(TEXTURE_DETAIL_MASK); BIND_ENUM_CONSTANT(TEXTURE_DETAIL_ALBEDO); BIND_ENUM_CONSTANT(TEXTURE_DETAIL_NORMAL); + BIND_ENUM_CONSTANT(TEXTURE_ORM); BIND_ENUM_CONSTANT(TEXTURE_MAX); + BIND_ENUM_CONSTANT(TEXTURE_FILTER_NEAREST); + BIND_ENUM_CONSTANT(TEXTURE_FILTER_LINEAR); + BIND_ENUM_CONSTANT(TEXTURE_FILTER_NEAREST_WITH_MIPMAPS); + BIND_ENUM_CONSTANT(TEXTURE_FILTER_LINEAR_WITH_MIPMAPS); + BIND_ENUM_CONSTANT(TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC); + BIND_ENUM_CONSTANT(TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC); + BIND_ENUM_CONSTANT(TEXTURE_FILTER_MAX); + BIND_ENUM_CONSTANT(DETAIL_UV_1); BIND_ENUM_CONSTANT(DETAIL_UV_2); - BIND_ENUM_CONSTANT(FEATURE_TRANSPARENT); + BIND_ENUM_CONSTANT(TRANSPARENCY_DISABLED); + BIND_ENUM_CONSTANT(TRANSPARENCY_ALPHA); + BIND_ENUM_CONSTANT(TRANSPARENCY_ALPHA_SCISSOR); + BIND_ENUM_CONSTANT(TRANSPARENCY_ALPHA_DEPTH_PRE_PASS); + BIND_ENUM_CONSTANT(TRANSPARENCY_MAX); + + BIND_ENUM_CONSTANT(SHADING_MODE_UNSHADED); + BIND_ENUM_CONSTANT(SHADING_MODE_PER_PIXEL); + BIND_ENUM_CONSTANT(SHADING_MODE_PER_VERTEX); + BIND_ENUM_CONSTANT(SHADING_MODE_MAX); + BIND_ENUM_CONSTANT(FEATURE_EMISSION); BIND_ENUM_CONSTANT(FEATURE_NORMAL_MAPPING); BIND_ENUM_CONSTANT(FEATURE_RIM); BIND_ENUM_CONSTANT(FEATURE_CLEARCOAT); BIND_ENUM_CONSTANT(FEATURE_ANISOTROPY); BIND_ENUM_CONSTANT(FEATURE_AMBIENT_OCCLUSION); - BIND_ENUM_CONSTANT(FEATURE_DEPTH_MAPPING); - BIND_ENUM_CONSTANT(FEATURE_SUBSURACE_SCATTERING); - BIND_ENUM_CONSTANT(FEATURE_TRANSMISSION); + BIND_ENUM_CONSTANT(FEATURE_HEIGHT_MAPPING); + BIND_ENUM_CONSTANT(FEATURE_SUBSURFACE_SCATTERING); + BIND_ENUM_CONSTANT(FEATURE_SUBSURFACE_TRANSMITTANCE); + BIND_ENUM_CONSTANT(FEATURE_BACKLIGHT); BIND_ENUM_CONSTANT(FEATURE_REFRACTION); BIND_ENUM_CONSTANT(FEATURE_DETAIL); BIND_ENUM_CONSTANT(FEATURE_MAX); @@ -2284,14 +2444,11 @@ void SpatialMaterial::_bind_methods() { BIND_ENUM_CONSTANT(DEPTH_DRAW_OPAQUE_ONLY); BIND_ENUM_CONSTANT(DEPTH_DRAW_ALWAYS); BIND_ENUM_CONSTANT(DEPTH_DRAW_DISABLED); - BIND_ENUM_CONSTANT(DEPTH_DRAW_ALPHA_OPAQUE_PREPASS); BIND_ENUM_CONSTANT(CULL_BACK); BIND_ENUM_CONSTANT(CULL_FRONT); BIND_ENUM_CONSTANT(CULL_DISABLED); - BIND_ENUM_CONSTANT(FLAG_UNSHADED); - BIND_ENUM_CONSTANT(FLAG_USE_VERTEX_LIGHTING); BIND_ENUM_CONSTANT(FLAG_DISABLE_DEPTH_TEST); BIND_ENUM_CONSTANT(FLAG_ALBEDO_FROM_VERTEX_COLOR); BIND_ENUM_CONSTANT(FLAG_SRGB_VERTEX_COLOR); @@ -2300,15 +2457,17 @@ void SpatialMaterial::_bind_methods() { BIND_ENUM_CONSTANT(FLAG_BILLBOARD_KEEP_SCALE); BIND_ENUM_CONSTANT(FLAG_UV1_USE_TRIPLANAR); BIND_ENUM_CONSTANT(FLAG_UV2_USE_TRIPLANAR); + BIND_ENUM_CONSTANT(FLAG_UV1_USE_WORLD_TRIPLANAR); + BIND_ENUM_CONSTANT(FLAG_UV2_USE_WORLD_TRIPLANAR); BIND_ENUM_CONSTANT(FLAG_AO_ON_UV2); BIND_ENUM_CONSTANT(FLAG_EMISSION_ON_UV2); - BIND_ENUM_CONSTANT(FLAG_USE_ALPHA_SCISSOR); - BIND_ENUM_CONSTANT(FLAG_TRIPLANAR_USE_WORLD); BIND_ENUM_CONSTANT(FLAG_ALBEDO_TEXTURE_FORCE_SRGB); BIND_ENUM_CONSTANT(FLAG_DONT_RECEIVE_SHADOWS); BIND_ENUM_CONSTANT(FLAG_DISABLE_AMBIENT_LIGHT); - BIND_ENUM_CONSTANT(FLAG_ENSURE_CORRECT_NORMALS); BIND_ENUM_CONSTANT(FLAG_USE_SHADOW_TO_OPACITY); + BIND_ENUM_CONSTANT(FLAG_USE_TEXTURE_REPEAT); + BIND_ENUM_CONSTANT(FLAG_INVERT_HEIGHTMAP); + BIND_ENUM_CONSTANT(FLAG_SUBSURFACE_MODE_SKIN); BIND_ENUM_CONSTANT(FLAG_MAX); BIND_ENUM_CONSTANT(DIFFUSE_BURLEY); @@ -2343,10 +2502,12 @@ void SpatialMaterial::_bind_methods() { BIND_ENUM_CONSTANT(DISTANCE_FADE_OBJECT_DITHER); } -SpatialMaterial::SpatialMaterial() : +BaseMaterial3D::BaseMaterial3D(bool p_orm) : element(this) { - + orm = p_orm; // Initialize to the same values as the shader + transparency = TRANSPARENCY_DISABLED; + shading_mode = SHADING_MODE_PER_PIXEL; set_albedo(Color(1.0, 1.0, 1.0, 1.0)); set_specular(0.5); set_roughness(1.0); @@ -2359,11 +2520,14 @@ SpatialMaterial::SpatialMaterial() : set_clearcoat(1); set_clearcoat_gloss(0.5); set_anisotropy(0); - set_depth_scale(0.05); + set_heightmap_scale(0.05); set_subsurface_scattering_strength(0); - set_transmission(Color(0, 0, 0)); + set_backlight(Color(0, 0, 0)); + set_transmittance_color(Color(1, 1, 1, 1)); + set_transmittance_depth(0.1); + set_transmittance_curve(1.0); + set_transmittance_boost(0.0); set_refraction(0.05); - set_line_width(1); set_point_size(1); set_uv1_offset(Vector3(0, 0, 0)); set_uv1_scale(Vector3(1, 1, 1)); @@ -2395,11 +2559,11 @@ SpatialMaterial::SpatialMaterial() : set_grow(0.0); deep_parallax = false; - depth_parallax_flip_tangent = false; - depth_parallax_flip_binormal = false; - set_depth_deep_parallax_min_layers(8); - set_depth_deep_parallax_max_layers(32); - set_depth_deep_parallax_flip_tangent(false); //also sets binormal + heightmap_parallax_flip_tangent = false; + heightmap_parallax_flip_binormal = false; + set_heightmap_deep_parallax_min_layers(8); + set_heightmap_deep_parallax_max_layers(32); + set_heightmap_deep_parallax_flip_tangent(false); //also sets binormal detail_uv = DETAIL_UV_1; blend_mode = BLEND_MODE_MIX; @@ -2407,8 +2571,10 @@ SpatialMaterial::SpatialMaterial() : depth_draw_mode = DEPTH_DRAW_OPAQUE_ONLY; cull_mode = CULL_BACK; for (int i = 0; i < FLAG_MAX; i++) { - flags[i] = 0; + flags[i] = false; } + flags[FLAG_USE_TEXTURE_REPEAT] = true; + diffuse_mode = DIFFUSE_BURLEY; specular_mode = SPECULAR_SCHLICK_GGX; @@ -2416,27 +2582,116 @@ SpatialMaterial::SpatialMaterial() : features[i] = false; } - current_key.key = 0; + current_key.key0 = 0; + current_key.key1 = 0; current_key.invalid_key = 1; + texture_filter = TEXTURE_FILTER_LINEAR_WITH_MIPMAPS; _queue_shader_change(); } -SpatialMaterial::~SpatialMaterial() { - - if (material_mutex) - material_mutex->lock(); +BaseMaterial3D::~BaseMaterial3D() { + MutexLock lock(material_mutex); if (shader_map.has(current_key)) { shader_map[current_key].users--; if (shader_map[current_key].users == 0) { //deallocate shader, as it's no longer in use - VS::get_singleton()->free(shader_map[current_key].shader); + RS::get_singleton()->free(shader_map[current_key].shader); shader_map.erase(current_key); } - VS::get_singleton()->material_set_shader(_get_material(), RID()); + RS::get_singleton()->material_set_shader(_get_material(), RID()); + } +} + +////////////////////// + +#ifndef DISABLE_DEPRECATED +// Kept for compatibility from 3.x to 4.0. +bool StandardMaterial3D::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "flags_transparent") { + bool transparent = p_value; + if (transparent) { + set_transparency(TRANSPARENCY_ALPHA); + } + return true; + } else if (p_name == "flags_unshaded") { + bool unshaded = p_value; + if (unshaded) { + set_shading_mode(SHADING_MODE_UNSHADED); + } + return true; + } else if (p_name == "flags_vertex_lighting") { + bool vertex_lit = p_value; + if (vertex_lit && get_shading_mode() != SHADING_MODE_UNSHADED) { + set_shading_mode(SHADING_MODE_PER_VERTEX); + } + return true; + } else if (p_name == "params_use_alpha_scissor") { + bool use_scissor = p_value; + if (use_scissor) { + set_transparency(TRANSPARENCY_ALPHA_SCISSOR); + } + return true; + } else if (p_name == "params_depth_draw_mode") { + int mode = p_value; + if (mode == 3) { + set_transparency(TRANSPARENCY_ALPHA_DEPTH_PRE_PASS); + } + return true; + } else if (p_name == "depth_enabled") { + bool enabled = p_value; + if (enabled) { + set_feature(FEATURE_HEIGHT_MAPPING, true); + set_flag(FLAG_INVERT_HEIGHTMAP, true); + } + return true; + } else { + static const Pair<const char *, const char *> remaps[] = { + { "flags_use_shadow_to_opacity", "shadow_to_opacity" }, + { "flags_use_shadow_to_opacity", "shadow_to_opacity" }, + { "flags_no_depth_test", "no_depth_test" }, + { "flags_use_point_size", "use_point_size" }, + { "flags_fixed_size", "fixed_Size" }, + { "flags_albedo_tex_force_srg", "albedo_tex_force_srgb" }, + { "flags_do_not_receive_shadows", "disable_receive_shadows" }, + { "flags_disable_ambient_light", "disable_ambient_light" }, + { "params_diffuse_mode", "diffuse_mode" }, + { "params_specular_mode", "specular_mode" }, + { "params_blend_mode", "blend_mode" }, + { "params_cull_mode", "cull_mode" }, + { "params_depth_draw_mode", "params_depth_draw_mode" }, + { "params_point_size", "point_size" }, + { "params_billboard_mode", "billboard_mode" }, + { "params_billboard_keep_scale", "billboard_keep_scale" }, + { "params_grow", "grow" }, + { "params_grow_amount", "grow_amount" }, + { "params_alpha_scissor_threshold", "alpha_scissor_threshold" }, + + { "depth_scale", "heightmap_scale" }, + { "depth_deep_parallax", "heightmap_deep_parallax" }, + { "depth_min_layers", "heightmap_min_layers" }, + { "depth_max_layers", "heightmap_max_layers" }, + { "depth_flip_tangent", "heightmap_flip_tangent" }, + { "depth_flip_binormal", "heightmap_flip_binormal" }, + { "depth_texture", "heightmap_texture" }, + + { nullptr, nullptr }, + }; + + int idx = 0; + while (remaps[idx].first) { + if (p_name == remaps[idx].first) { + set(remaps[idx].second, p_value); + return true; + } + idx++; + } + + print_line("remapped parameter not found: " + String(p_name)); + return true; } - if (material_mutex) - material_mutex->unlock(); + return false; } +#endif // DISABLE_DEPRECATED diff --git a/scene/resources/material.h b/scene/resources/material.h index 8e66011bec..b5bdd77eb5 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -35,11 +35,10 @@ #include "core/self_list.h" #include "scene/resources/shader.h" #include "scene/resources/texture.h" -#include "servers/visual/shader_language.h" -#include "servers/visual_server.h" +#include "servers/rendering/shader_language.h" +#include "servers/rendering_server.h" class Material : public Resource { - GDCLASS(Material, Resource); RES_BASE_EXTENSION("material") OBJ_SAVE_TYPE(Material); @@ -53,12 +52,12 @@ protected: static void _bind_methods(); virtual bool _can_do_next_pass() const { return false; } - void _validate_property(PropertyInfo &property) const; + void _validate_property(PropertyInfo &property) const override; public: enum { - RENDER_PRIORITY_MAX = VS::MATERIAL_RENDER_PRIORITY_MAX, - RENDER_PRIORITY_MIN = VS::MATERIAL_RENDER_PRIORITY_MIN, + RENDER_PRIORITY_MAX = RS::MATERIAL_RENDER_PRIORITY_MAX, + RENDER_PRIORITY_MIN = RS::MATERIAL_RENDER_PRIORITY_MIN, }; void set_next_pass(const Ref<Material> &p_pass); Ref<Material> get_next_pass() const; @@ -66,7 +65,7 @@ public: void set_render_priority(int p_priority); int get_render_priority() const; - virtual RID get_rid() const; + virtual RID get_rid() const override; virtual Shader::Mode get_shader_mode() const = 0; Material(); @@ -74,7 +73,6 @@ public: }; class ShaderMaterial : public Material { - GDCLASS(ShaderMaterial, Material); Ref<Shader> shader; @@ -87,9 +85,9 @@ protected: static void _bind_methods(); - void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const; + void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override; - virtual bool _can_do_next_pass() const; + virtual bool _can_do_next_pass() const override; void _shader_changed(); @@ -100,15 +98,16 @@ public: void set_shader_param(const StringName &p_param, const Variant &p_value); Variant get_shader_param(const StringName &p_param) const; - virtual Shader::Mode get_shader_mode() const; + virtual Shader::Mode get_shader_mode() const override; ShaderMaterial(); ~ShaderMaterial(); }; -class SpatialMaterial : public Material { +class StandardMaterial3D; - GDCLASS(SpatialMaterial, Material); +class BaseMaterial3D : public Material { + GDCLASS(BaseMaterial3D, Material); public: enum TextureParam { @@ -121,33 +120,60 @@ public: TEXTURE_CLEARCOAT, TEXTURE_FLOWMAP, TEXTURE_AMBIENT_OCCLUSION, - TEXTURE_DEPTH, + TEXTURE_HEIGHTMAP, TEXTURE_SUBSURFACE_SCATTERING, - TEXTURE_TRANSMISSION, + TEXTURE_SUBSURFACE_TRANSMITTANCE, + TEXTURE_BACKLIGHT, TEXTURE_REFRACTION, TEXTURE_DETAIL_MASK, TEXTURE_DETAIL_ALBEDO, TEXTURE_DETAIL_NORMAL, + TEXTURE_ORM, TEXTURE_MAX }; + enum TextureFilter { + TEXTURE_FILTER_NEAREST, + TEXTURE_FILTER_LINEAR, + TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, + TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, + TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, + TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, + TEXTURE_FILTER_MAX + }; + enum DetailUV { DETAIL_UV_1, DETAIL_UV_2 }; + enum Transparency { + TRANSPARENCY_DISABLED, + TRANSPARENCY_ALPHA, + TRANSPARENCY_ALPHA_SCISSOR, + TRANSPARENCY_ALPHA_DEPTH_PRE_PASS, + TRANSPARENCY_MAX, + }; + + enum ShadingMode { + SHADING_MODE_UNSHADED, + SHADING_MODE_PER_PIXEL, + SHADING_MODE_PER_VERTEX, + SHADING_MODE_MAX + }; + enum Feature { - FEATURE_TRANSPARENT, FEATURE_EMISSION, FEATURE_NORMAL_MAPPING, FEATURE_RIM, FEATURE_CLEARCOAT, FEATURE_ANISOTROPY, FEATURE_AMBIENT_OCCLUSION, - FEATURE_DEPTH_MAPPING, - FEATURE_SUBSURACE_SCATTERING, - FEATURE_TRANSMISSION, + FEATURE_HEIGHT_MAPPING, + FEATURE_SUBSURFACE_SCATTERING, + FEATURE_SUBSURFACE_TRANSMITTANCE, + FEATURE_BACKLIGHT, FEATURE_REFRACTION, FEATURE_DETAIL, FEATURE_MAX @@ -164,8 +190,6 @@ public: DEPTH_DRAW_OPAQUE_ONLY, DEPTH_DRAW_ALWAYS, DEPTH_DRAW_DISABLED, - DEPTH_DRAW_ALPHA_OPAQUE_PREPASS - }; enum CullMode { @@ -175,8 +199,6 @@ public: }; enum Flags { - FLAG_UNSHADED, - FLAG_USE_VERTEX_LIGHTING, FLAG_DISABLE_DEPTH_TEST, FLAG_ALBEDO_FROM_VERTEX_COLOR, FLAG_SRGB_VERTEX_COLOR, @@ -185,15 +207,17 @@ public: FLAG_BILLBOARD_KEEP_SCALE, FLAG_UV1_USE_TRIPLANAR, FLAG_UV2_USE_TRIPLANAR, - FLAG_TRIPLANAR_USE_WORLD, + FLAG_UV1_USE_WORLD_TRIPLANAR, + FLAG_UV2_USE_WORLD_TRIPLANAR, FLAG_AO_ON_UV2, FLAG_EMISSION_ON_UV2, - FLAG_USE_ALPHA_SCISSOR, FLAG_ALBEDO_TEXTURE_FORCE_SRGB, FLAG_DONT_RECEIVE_SHADOWS, - FLAG_ENSURE_CORRECT_NORMALS, FLAG_DISABLE_AMBIENT_LIGHT, FLAG_USE_SHADOW_TO_OPACITY, + FLAG_USE_TEXTURE_REPEAT, + FLAG_INVERT_HEIGHTMAP, + FLAG_SUBSURFACE_MODE_SKIN, FLAG_MAX }; @@ -242,14 +266,13 @@ public: private: union MaterialKey { - struct { - uint64_t feature_mask : 12; + uint64_t feature_mask : FEATURE_MAX; uint64_t detail_uv : 1; uint64_t blend_mode : 2; uint64_t depth_draw_mode : 2; uint64_t cull_mode : 2; - uint64_t flags : 19; + uint64_t flags : FLAG_MAX; uint64_t detail_blend_mode : 2; uint64_t diffuse_mode : 3; uint64_t specular_mode : 3; @@ -260,14 +283,22 @@ private: uint64_t proximity_fade : 1; uint64_t distance_fade : 2; uint64_t emission_op : 1; - uint64_t texture_metallic : 1; - uint64_t texture_roughness : 1; + uint64_t texture_filter : 3; + uint64_t transparency : 2; + uint64_t shading_mode : 2; + uint64_t roughness_channel : 3; }; - uint64_t key; + struct { + uint64_t key0; + uint64_t key1; + }; + bool operator==(const MaterialKey &p_key) const { + return (key0 == p_key.key0) && (key1 == p_key.key1); + } bool operator<(const MaterialKey &p_key) const { - return key < p_key.key; + return (key0 == p_key.key0) ? (key1 < p_key.key1) : (key0 < p_key.key0); } }; @@ -281,9 +312,9 @@ private: MaterialKey current_key; _FORCE_INLINE_ MaterialKey _compute_key() const { - MaterialKey mk; - mk.key = 0; + mk.key0 = 0; + mk.key1 = 0; for (int i = 0; i < FEATURE_MAX; i++) { if (features[i]) { mk.feature_mask |= ((uint64_t)1 << i); @@ -293,6 +324,10 @@ private: mk.blend_mode = blend_mode; mk.depth_draw_mode = depth_draw_mode; mk.cull_mode = cull_mode; + mk.texture_filter = texture_filter; + mk.transparency = transparency; + mk.shading_mode = shading_mode; + mk.roughness_channel = roughness_texture_channel; for (int i = 0; i < FLAG_MAX; i++) { if (flags[i]) { mk.flags |= ((uint64_t)1 << i); @@ -307,8 +342,6 @@ private: mk.proximity_fade = proximity_fade_enabled; mk.distance_fade = distance_fade; mk.emission_op = emission_op; - mk.texture_metallic = textures[TEXTURE_METALLIC].is_valid() ? 1 : 0; - mk.texture_roughness = textures[TEXTURE_ROUGHNESS].is_valid() ? 1 : 0; return mk; } @@ -326,9 +359,13 @@ private: StringName clearcoat; StringName clearcoat_gloss; StringName anisotropy; - StringName depth_scale; + StringName heightmap_scale; StringName subsurface_scattering_strength; - StringName transmission; + StringName transmittance_color; + StringName transmittance_curve; + StringName transmittance_depth; + StringName transmittance_boost; + StringName backlight; StringName refraction; StringName point_size; StringName uv1_scale; @@ -338,9 +375,9 @@ private: StringName particles_anim_h_frames; StringName particles_anim_v_frames; StringName particles_anim_loop; - StringName depth_min_layers; - StringName depth_max_layers; - StringName depth_flip; + StringName heightmap_min_layers; + StringName heightmap_max_layers; + StringName heightmap_flip; StringName uv1_blend_sharpness; StringName uv2_blend_sharpness; StringName grow; @@ -350,27 +387,28 @@ private: StringName ao_light_affect; StringName metallic_texture_channel; - StringName roughness_texture_channel; StringName ao_texture_channel; StringName clearcoat_texture_channel; StringName rim_texture_channel; - StringName depth_texture_channel; + StringName heightmap_texture_channel; StringName refraction_texture_channel; StringName alpha_scissor_threshold; StringName texture_names[TEXTURE_MAX]; }; - static Mutex *material_mutex; - static SelfList<SpatialMaterial>::List *dirty_materials; + static Mutex material_mutex; + static SelfList<BaseMaterial3D>::List *dirty_materials; static ShaderNames *shader_names; - SelfList<SpatialMaterial> element; + SelfList<BaseMaterial3D> element; void _update_shader(); _FORCE_INLINE_ void _queue_shader_change(); _FORCE_INLINE_ bool _is_shader_dirty() const; + bool orm; + Color albedo; float specular; float metallic; @@ -383,11 +421,16 @@ private: float clearcoat; float clearcoat_gloss; float anisotropy; - float depth_scale; + float heightmap_scale; float subsurface_scattering_strength; - Color transmission; + float transmittance_amount; + Color transmittance_color; + float transmittance_depth; + float transmittance_curve; + float transmittance_boost; + + Color backlight; float refraction; - float line_width; float point_size; float alpha_scissor_threshold; bool grow_enabled; @@ -396,6 +439,10 @@ private: int particles_anim_h_frames; int particles_anim_v_frames; bool particles_anim_loop; + Transparency transparency; + ShadingMode shading_mode; + + TextureFilter texture_filter; Vector3 uv1_scale; Vector3 uv1_offset; @@ -410,8 +457,8 @@ private: bool deep_parallax; int deep_parallax_min_layers; int deep_parallax_max_layers; - bool depth_parallax_flip_tangent; - bool depth_parallax_flip_binormal; + bool heightmap_parallax_flip_tangent; + bool heightmap_parallax_flip_binormal; bool proximity_fade_enabled; float proximity_fade_distance; @@ -437,20 +484,20 @@ private: bool features[FEATURE_MAX]; - Ref<Texture> textures[TEXTURE_MAX]; + Ref<Texture2D> textures[TEXTURE_MAX]; _FORCE_INLINE_ void _validate_feature(const String &text, Feature feature, PropertyInfo &property) const; static const int MAX_MATERIALS_FOR_2D = 128; - static Ref<SpatialMaterial> materials_for_2d[MAX_MATERIALS_FOR_2D]; //used by Sprite3D and other stuff + static Ref<StandardMaterial3D> materials_for_2d[MAX_MATERIALS_FOR_2D]; //used by Sprite3D and other stuff void _validate_high_end(const String &text, PropertyInfo &property) const; protected: static void _bind_methods(); - void _validate_property(PropertyInfo &property) const; - virtual bool _can_do_next_pass() const { return true; } + void _validate_property(PropertyInfo &property) const override; + virtual bool _can_do_next_pass() const override { return true; } public: void set_albedo(const Color &p_albedo); @@ -492,39 +539,54 @@ public: void set_anisotropy(float p_anisotropy); float get_anisotropy() const; - void set_depth_scale(float p_depth_scale); - float get_depth_scale() const; + void set_heightmap_scale(float p_heightmap_scale); + float get_heightmap_scale() const; - void set_depth_deep_parallax(bool p_enable); - bool is_depth_deep_parallax_enabled() const; + void set_heightmap_deep_parallax(bool p_enable); + bool is_heightmap_deep_parallax_enabled() const; - void set_depth_deep_parallax_min_layers(int p_layer); - int get_depth_deep_parallax_min_layers() const; + void set_heightmap_deep_parallax_min_layers(int p_layer); + int get_heightmap_deep_parallax_min_layers() const; - void set_depth_deep_parallax_max_layers(int p_layer); - int get_depth_deep_parallax_max_layers() const; + void set_heightmap_deep_parallax_max_layers(int p_layer); + int get_heightmap_deep_parallax_max_layers() const; - void set_depth_deep_parallax_flip_tangent(bool p_flip); - bool get_depth_deep_parallax_flip_tangent() const; + void set_heightmap_deep_parallax_flip_tangent(bool p_flip); + bool get_heightmap_deep_parallax_flip_tangent() const; - void set_depth_deep_parallax_flip_binormal(bool p_flip); - bool get_depth_deep_parallax_flip_binormal() const; + void set_heightmap_deep_parallax_flip_binormal(bool p_flip); + bool get_heightmap_deep_parallax_flip_binormal() const; void set_subsurface_scattering_strength(float p_subsurface_scattering_strength); float get_subsurface_scattering_strength() const; - void set_transmission(const Color &p_transmission); - Color get_transmission() const; + void set_transmittance_color(const Color &p_color); + Color get_transmittance_color() const; + + void set_transmittance_depth(float p_depth); + float get_transmittance_depth() const; + + void set_transmittance_curve(float p_curve); + float get_transmittance_curve() const; + + void set_transmittance_boost(float p_boost); + float get_transmittance_boost() const; + + void set_backlight(const Color &p_backlight); + Color get_backlight() const; void set_refraction(float p_refraction); float get_refraction() const; - void set_line_width(float p_line_width); - float get_line_width() const; - void set_point_size(float p_point_size); float get_point_size() const; + void set_transparency(Transparency p_transparency); + Transparency get_transparency() const; + + void set_shading_mode(ShadingMode p_shading_mode); + ShadingMode get_shading_mode() const; + void set_detail_uv(DetailUV p_detail_uv); DetailUV get_detail_uv() const; @@ -549,10 +611,13 @@ public: void set_flag(Flags p_flag, bool p_enabled); bool get_flag(Flags p_flag) const; - void set_texture(TextureParam p_param, const Ref<Texture> &p_texture); - Ref<Texture> get_texture(TextureParam p_param) const; + void set_texture(TextureParam p_param, const Ref<Texture2D> &p_texture); + Ref<Texture2D> get_texture(TextureParam p_param) const; // Used only for shader material conversion - Ref<Texture> get_texture_by_name(StringName p_name) const; + Ref<Texture2D> get_texture_by_name(StringName p_name) const; + + void set_texture_filter(TextureFilter p_filter); + TextureFilter get_texture_filter() const; void set_feature(Feature p_feature, bool p_enabled); bool get_feature(Feature p_feature) const; @@ -632,25 +697,48 @@ public: RID get_shader_rid() const; - virtual Shader::Mode get_shader_mode() const; + virtual Shader::Mode get_shader_mode() const override; - SpatialMaterial(); - virtual ~SpatialMaterial(); + BaseMaterial3D(bool p_orm); + virtual ~BaseMaterial3D(); }; -VARIANT_ENUM_CAST(SpatialMaterial::TextureParam) -VARIANT_ENUM_CAST(SpatialMaterial::DetailUV) -VARIANT_ENUM_CAST(SpatialMaterial::Feature) -VARIANT_ENUM_CAST(SpatialMaterial::BlendMode) -VARIANT_ENUM_CAST(SpatialMaterial::DepthDrawMode) -VARIANT_ENUM_CAST(SpatialMaterial::CullMode) -VARIANT_ENUM_CAST(SpatialMaterial::Flags) -VARIANT_ENUM_CAST(SpatialMaterial::DiffuseMode) -VARIANT_ENUM_CAST(SpatialMaterial::SpecularMode) -VARIANT_ENUM_CAST(SpatialMaterial::BillboardMode) -VARIANT_ENUM_CAST(SpatialMaterial::TextureChannel) -VARIANT_ENUM_CAST(SpatialMaterial::EmissionOperator) -VARIANT_ENUM_CAST(SpatialMaterial::DistanceFadeMode) +VARIANT_ENUM_CAST(BaseMaterial3D::TextureParam) +VARIANT_ENUM_CAST(BaseMaterial3D::TextureFilter) +VARIANT_ENUM_CAST(BaseMaterial3D::ShadingMode) +VARIANT_ENUM_CAST(BaseMaterial3D::Transparency) +VARIANT_ENUM_CAST(BaseMaterial3D::DetailUV) +VARIANT_ENUM_CAST(BaseMaterial3D::Feature) +VARIANT_ENUM_CAST(BaseMaterial3D::BlendMode) +VARIANT_ENUM_CAST(BaseMaterial3D::DepthDrawMode) +VARIANT_ENUM_CAST(BaseMaterial3D::CullMode) +VARIANT_ENUM_CAST(BaseMaterial3D::Flags) +VARIANT_ENUM_CAST(BaseMaterial3D::DiffuseMode) +VARIANT_ENUM_CAST(BaseMaterial3D::SpecularMode) +VARIANT_ENUM_CAST(BaseMaterial3D::BillboardMode) +VARIANT_ENUM_CAST(BaseMaterial3D::TextureChannel) +VARIANT_ENUM_CAST(BaseMaterial3D::EmissionOperator) +VARIANT_ENUM_CAST(BaseMaterial3D::DistanceFadeMode) + +class StandardMaterial3D : public BaseMaterial3D { + GDCLASS(StandardMaterial3D, BaseMaterial3D) +protected: +#ifndef DISABLE_DEPRECATED + // Kept for compatibility from 3.x to 4.0. + bool _set(const StringName &p_name, const Variant &p_value); +#endif + +public: + StandardMaterial3D() : + BaseMaterial3D(false) {} +}; + +class ORMMaterial3D : public BaseMaterial3D { + GDCLASS(ORMMaterial3D, BaseMaterial3D) +public: + ORMMaterial3D() : + BaseMaterial3D(true) {} +}; ////////////////////// diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 0599920303..10f0a040d0 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -31,61 +31,59 @@ #include "mesh.h" #include "core/pair.h" -#include "scene/resources/concave_polygon_shape.h" -#include "scene/resources/convex_polygon_shape.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_composition_function = NULL; +Mesh::ConvexDecompositionFunc Mesh::convex_composition_function = nullptr; Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { - - if (triangle_mesh.is_valid()) + if (triangle_mesh.is_valid()) { return triangle_mesh; + } int facecount = 0; for (int i = 0; i < get_surface_count(); i++) { - - if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) + if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) { continue; + } if (surface_get_format(i) & ARRAY_FORMAT_INDEX) { - facecount += surface_get_array_index_len(i); } else { - facecount += surface_get_array_len(i); } } - if (facecount == 0 || (facecount % 3) != 0) + if (facecount == 0 || (facecount % 3) != 0) { return triangle_mesh; + } - PoolVector<Vector3> faces; + Vector<Vector3> faces; faces.resize(facecount); - PoolVector<Vector3>::Write facesw = faces.write(); + Vector3 *facesw = faces.ptrw(); int widx = 0; for (int i = 0; i < get_surface_count(); i++) { - - if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) + if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) { continue; + } Array a = surface_get_arrays(i); ERR_FAIL_COND_V(a.empty(), Ref<TriangleMesh>()); int vc = surface_get_array_len(i); - PoolVector<Vector3> vertices = a[ARRAY_VERTEX]; - PoolVector<Vector3>::Read vr = vertices.read(); + Vector<Vector3> vertices = a[ARRAY_VERTEX]; + const Vector3 *vr = vertices.ptr(); if (surface_get_format(i) & ARRAY_FORMAT_INDEX) { - int ic = surface_get_array_index_len(i); - PoolVector<int> indices = a[ARRAY_INDEX]; - PoolVector<int>::Read ir = indices.read(); + Vector<int> indices = a[ARRAY_INDEX]; + const int *ir = indices.ptr(); for (int j = 0; j < ic; j++) { int index = ir[j]; @@ -93,14 +91,12 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { } } else { - - for (int j = 0; j < vc; j++) + for (int j = 0; j < vc; j++) { facesw[widx++] = vr[j]; + } } } - facesw.release(); - triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh)); triangle_mesh->create(faces); @@ -108,25 +104,25 @@ Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { } void Mesh::generate_debug_mesh_lines(Vector<Vector3> &r_lines) { - if (debug_lines.size() > 0) { r_lines = debug_lines; return; } Ref<TriangleMesh> tm = generate_triangle_mesh(); - if (tm.is_null()) + if (tm.is_null()) { return; + } - PoolVector<int> triangle_indices; + Vector<int> triangle_indices; tm->get_indices(&triangle_indices); const int triangles_num = tm->get_triangles().size(); - PoolVector<Vector3> vertices = tm->get_vertices(); + Vector<Vector3> vertices = tm->get_vertices(); debug_lines.resize(tm->get_triangles().size() * 6); // 3 lines x 2 points each line - PoolVector<int>::Read ind_r = triangle_indices.read(); - PoolVector<Vector3>::Read ver_r = vertices.read(); + const int *ind_r = triangle_indices.ptr(); + const Vector3 *ver_r = vertices.ptr(); for (int j = 0, x = 0, i = 0; i < triangles_num; j += 6, x += 3, ++i) { // Triangle line 1 debug_lines.write[j + 0] = ver_r[ind_r[x + 0]]; @@ -143,12 +139,14 @@ void Mesh::generate_debug_mesh_lines(Vector<Vector3> &r_lines) { r_lines = debug_lines; } + void Mesh::generate_debug_mesh_indices(Vector<Vector3> &r_points) { Ref<TriangleMesh> tm = generate_triangle_mesh(); - if (tm.is_null()) + if (tm.is_null()) { return; + } - PoolVector<Vector3> vertices = tm->get_vertices(); + Vector<Vector3> vertices = tm->get_vertices(); int vertices_size = vertices.size(); r_points.resize(vertices_size); @@ -159,32 +157,32 @@ void Mesh::generate_debug_mesh_indices(Vector<Vector3> &r_points) { bool Mesh::surface_is_softbody_friendly(int p_idx) const { const uint32_t surface_format = surface_get_format(p_idx); - return (surface_format & Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE && (!(surface_format & Mesh::ARRAY_COMPRESS_VERTEX)) && (!(surface_format & Mesh::ARRAY_COMPRESS_NORMAL))); + return (surface_format & Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE && (!(surface_format & Mesh::ARRAY_COMPRESS_NORMAL))); } -PoolVector<Face3> Mesh::get_faces() const { - +Vector<Face3> Mesh::get_faces() const { Ref<TriangleMesh> tm = generate_triangle_mesh(); - if (tm.is_valid()) + if (tm.is_valid()) { return tm->get_faces(); - return PoolVector<Face3>(); + } + return Vector<Face3>(); /* for (int i=0;i<surfaces.size();i++) { - if (VisualServer::get_singleton()->mesh_surface_get_primitive_type( mesh, i ) != VisualServer::PRIMITIVE_TRIANGLES ) + if (RenderingServer::get_singleton()->mesh_surface_get_primitive_type( mesh, i ) != RenderingServer::PRIMITIVE_TRIANGLES ) continue; - PoolVector<int> indices; - PoolVector<Vector3> vertices; + Vector<int> indices; + Vector<Vector3> vertices; - vertices=VisualServer::get_singleton()->mesh_surface_get_array(mesh, i,VisualServer::ARRAY_VERTEX); + vertices=RenderingServer::get_singleton()->mesh_surface_get_array(mesh, i,RenderingServer::ARRAY_VERTEX); - int len=VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, i); + int len=RenderingServer::get_singleton()->mesh_surface_get_array_index_len(mesh, i); bool has_indices; if (len>0) { - indices=VisualServer::get_singleton()->mesh_surface_get_array(mesh, i,VisualServer::ARRAY_INDEX); + indices=RenderingServer::get_singleton()->mesh_surface_get_array(mesh, i,RenderingServer::ARRAY_INDEX); has_indices=true; } else { @@ -196,10 +194,10 @@ PoolVector<Face3> Mesh::get_faces() const { if (len<=0) continue; - PoolVector<int>::Read indicesr = indices.read(); + const int* indicesr = indices.ptr(); const int *indicesptr = indicesr.ptr(); - PoolVector<Vector3>::Read verticesr = vertices.read(); + const Vector3* verticesr = vertices.ptr(); const Vector3 *verticesptr = verticesr.ptr(); int old_faces=faces.size(); @@ -207,7 +205,7 @@ PoolVector<Face3> Mesh::get_faces() const { faces.resize(new_faces); - PoolVector<Face3>::Write facesw = faces.write(); + Face3* facesw = faces.ptrw(); Face3 *facesptr=facesw.ptr(); @@ -228,64 +226,60 @@ PoolVector<Face3> Mesh::get_faces() const { */ } -Ref<Shape> Mesh::create_convex_shape() const { - - PoolVector<Vector3> vertices; +Ref<Shape3D> Mesh::create_convex_shape() const { + Vector<Vector3> vertices; for (int i = 0; i < get_surface_count(); i++) { - Array a = surface_get_arrays(i); - ERR_FAIL_COND_V(a.empty(), Ref<ConvexPolygonShape>()); - PoolVector<Vector3> v = a[ARRAY_VERTEX]; + ERR_FAIL_COND_V(a.empty(), Ref<ConvexPolygonShape3D>()); + Vector<Vector3> v = a[ARRAY_VERTEX]; vertices.append_array(v); } - Ref<ConvexPolygonShape> shape = memnew(ConvexPolygonShape); + Ref<ConvexPolygonShape3D> shape = memnew(ConvexPolygonShape3D); shape->set_points(vertices); return shape; } -Ref<Shape> Mesh::create_trimesh_shape() const { - - PoolVector<Face3> faces = get_faces(); - if (faces.size() == 0) - return Ref<Shape>(); +Ref<Shape3D> Mesh::create_trimesh_shape() const { + Vector<Face3> faces = get_faces(); + if (faces.size() == 0) { + return Ref<Shape3D>(); + } - PoolVector<Vector3> face_points; + Vector<Vector3> face_points; face_points.resize(faces.size() * 3); - for (int i = 0; i < face_points.size(); i++) { - + for (int i = 0; i < face_points.size(); i += 3) { Face3 f = faces.get(i / 3); - face_points.set(i, f.vertex[i % 3]); + face_points.set(i, f.vertex[0]); + face_points.set(i + 1, f.vertex[1]); + face_points.set(i + 2, f.vertex[2]); } - Ref<ConcavePolygonShape> shape = memnew(ConcavePolygonShape); + Ref<ConcavePolygonShape3D> shape = memnew(ConcavePolygonShape3D); shape->set_faces(face_points); return shape; } Ref<Mesh> Mesh::create_outline(float p_margin) const { - Array arrays; int index_accum = 0; for (int i = 0; i < get_surface_count(); i++) { - - if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) + if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) { continue; + } Array a = surface_get_arrays(i); ERR_FAIL_COND_V(a.empty(), Ref<ArrayMesh>()); if (i == 0) { arrays = a; - PoolVector<Vector3> v = a[ARRAY_VERTEX]; + Vector<Vector3> v = a[ARRAY_VERTEX]; index_accum += v.size(); } else { - int vcount = 0; for (int j = 0; j < arrays.size(); j++) { - if (arrays[j].get_type() == Variant::NIL || a[j].get_type() == Variant::NIL) { //mismatch, do not use arrays[j] = Variant(); @@ -293,14 +287,13 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { } switch (j) { - case ARRAY_VERTEX: case ARRAY_NORMAL: { - - PoolVector<Vector3> dst = arrays[j]; - PoolVector<Vector3> src = a[j]; - if (j == ARRAY_VERTEX) + Vector<Vector3> dst = arrays[j]; + Vector<Vector3> src = a[j]; + if (j == ARRAY_VERTEX) { vcount = src.size(); + } if (dst.size() == 0 || src.size() == 0) { arrays[j] = Variant(); continue; @@ -311,9 +304,8 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { case ARRAY_TANGENT: case ARRAY_BONES: case ARRAY_WEIGHTS: { - - PoolVector<real_t> dst = arrays[j]; - PoolVector<real_t> src = a[j]; + Vector<real_t> dst = arrays[j]; + Vector<real_t> src = a[j]; if (dst.size() == 0 || src.size() == 0) { arrays[j] = Variant(); continue; @@ -323,8 +315,8 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { } break; case ARRAY_COLOR: { - PoolVector<Color> dst = arrays[j]; - PoolVector<Color> src = a[j]; + Vector<Color> dst = arrays[j]; + Vector<Color> src = a[j]; if (dst.size() == 0 || src.size() == 0) { arrays[j] = Variant(); continue; @@ -335,8 +327,8 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { } break; case ARRAY_TEX_UV: case ARRAY_TEX_UV2: { - PoolVector<Vector2> dst = arrays[j]; - PoolVector<Vector2> src = a[j]; + Vector<Vector2> dst = arrays[j]; + Vector<Vector2> src = a[j]; if (dst.size() == 0 || src.size() == 0) { arrays[j] = Variant(); continue; @@ -346,15 +338,15 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { } break; case ARRAY_INDEX: { - PoolVector<int> dst = arrays[j]; - PoolVector<int> src = a[j]; + Vector<int> dst = arrays[j]; + Vector<int> src = a[j]; if (dst.size() == 0 || src.size() == 0) { arrays[j] = Variant(); continue; } { int ss = src.size(); - PoolVector<int>::Write w = src.write(); + int *w = src.ptrw(); for (int k = 0; k < ss; k++) { w[k] += index_accum; } @@ -372,18 +364,18 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { ERR_FAIL_COND_V(arrays.size() != ARRAY_MAX, Ref<ArrayMesh>()); { - PoolVector<int>::Write ir; - PoolVector<int> indices = arrays[ARRAY_INDEX]; + int *ir = nullptr; + Vector<int> indices = arrays[ARRAY_INDEX]; bool has_indices = false; - PoolVector<Vector3> vertices = arrays[ARRAY_VERTEX]; + Vector<Vector3> vertices = arrays[ARRAY_VERTEX]; int vc = vertices.size(); ERR_FAIL_COND_V(!vc, Ref<ArrayMesh>()); - PoolVector<Vector3>::Write r = vertices.write(); + Vector3 *r = vertices.ptrw(); if (indices.size()) { ERR_FAIL_COND_V(indices.size() % 3 != 0, Ref<ArrayMesh>()); vc = indices.size(); - ir = indices.write(); + ir = indices.ptrw(); has_indices = true; } @@ -391,7 +383,6 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { //fill normals with triangle normals for (int i = 0; i < vc; i += 3) { - Vector3 t[3]; if (has_indices) { @@ -407,14 +398,14 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { Vector3 n = Plane(t[0], t[1], t[2]).normal; for (int j = 0; j < 3; j++) { - Map<Vector3, Vector3>::Element *E = normal_accum.find(t[j]); if (!E) { normal_accum[t[j]] = n; } else { float d = n.dot(E->get()); - if (d < 1.0) + if (d < 1.0) { E->get() += n * (1.0 - d); + } //E->get()+=n; } } @@ -430,7 +421,6 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { int vc2 = vertices.size(); for (int i = 0; i < vc2; i++) { - Vector3 t = r[i]; Map<Vector3, Vector3>::Element *E = normal_accum.find(t); @@ -440,32 +430,25 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { r[i] = t; } - r.release(); arrays[ARRAY_VERTEX] = vertices; if (!has_indices) { - - PoolVector<int> new_indices; + Vector<int> new_indices; new_indices.resize(vertices.size()); - PoolVector<int>::Write iw = new_indices.write(); + int *iw = new_indices.ptrw(); for (int j = 0; j < vc2; j += 3) { - iw[j] = j; iw[j + 1] = j + 2; iw[j + 2] = j + 1; } - iw.release(); arrays[ARRAY_INDEX] = new_indices; } else { - for (int j = 0; j < vc; j += 3) { - SWAP(ir[j + 1], ir[j + 2]); } - ir.release(); arrays[ARRAY_INDEX] = indices; } } @@ -475,21 +458,20 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const { return newmesh; } -void Mesh::set_lightmap_size_hint(const Vector2 &p_size) { +void Mesh::set_lightmap_size_hint(const Size2i &p_size) { lightmap_size_hint = p_size; } -Size2 Mesh::get_lightmap_size_hint() const { +Size2i Mesh::get_lightmap_size_hint() const { return lightmap_size_hint; } void Mesh::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_lightmap_size_hint", "size"), &Mesh::set_lightmap_size_hint); ClassDB::bind_method(D_METHOD("get_lightmap_size_hint"), &Mesh::get_lightmap_size_hint); ClassDB::bind_method(D_METHOD("get_aabb"), &Mesh::get_aabb); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "lightmap_size_hint"), "set_lightmap_size_hint", "get_lightmap_size_hint"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "lightmap_size_hint"), "set_lightmap_size_hint", "get_lightmap_size_hint"); ClassDB::bind_method(D_METHOD("get_surface_count"), &Mesh::get_surface_count); ClassDB::bind_method(D_METHOD("surface_get_arrays", "surf_idx"), &Mesh::surface_get_arrays); @@ -500,10 +482,8 @@ void Mesh::_bind_methods() { BIND_ENUM_CONSTANT(PRIMITIVE_POINTS); BIND_ENUM_CONSTANT(PRIMITIVE_LINES); BIND_ENUM_CONSTANT(PRIMITIVE_LINE_STRIP); - BIND_ENUM_CONSTANT(PRIMITIVE_LINE_LOOP); BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLES); BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_STRIP); - BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_FAN); BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED); BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE); @@ -518,19 +498,14 @@ void Mesh::_bind_methods() { BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS); BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX); - BIND_ENUM_CONSTANT(ARRAY_COMPRESS_BASE); - BIND_ENUM_CONSTANT(ARRAY_COMPRESS_VERTEX); BIND_ENUM_CONSTANT(ARRAY_COMPRESS_NORMAL); BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TANGENT); BIND_ENUM_CONSTANT(ARRAY_COMPRESS_COLOR); BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV); BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV2); - BIND_ENUM_CONSTANT(ARRAY_COMPRESS_BONES); - BIND_ENUM_CONSTANT(ARRAY_COMPRESS_WEIGHTS); BIND_ENUM_CONSTANT(ARRAY_COMPRESS_INDEX); BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES); - BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_16_BIT_BONES); BIND_ENUM_CONSTANT(ARRAY_COMPRESS_DEFAULT); @@ -551,21 +526,14 @@ void Mesh::clear_cache() const { debug_lines.clear(); } -Vector<Ref<Shape> > Mesh::convex_decompose() const { +Vector<Ref<Shape3D>> Mesh::convex_decompose() const { + ERR_FAIL_COND_V(!convex_composition_function, Vector<Ref<Shape3D>>()); - ERR_FAIL_COND_V(!convex_composition_function, Vector<Ref<Shape> >()); - - PoolVector<Face3> faces = get_faces(); - Vector<Face3> f3; - f3.resize(faces.size()); - PoolVector<Face3>::Read f = faces.read(); - for (int i = 0; i < f3.size(); i++) { - f3.write[i] = f[i]; - } + const Vector<Face3> faces = get_faces(); - Vector<Vector<Face3> > decomposed = convex_composition_function(f3); + Vector<Vector<Face3>> decomposed = convex_composition_function(faces); - Vector<Ref<Shape> > ret; + Vector<Ref<Shape3D>> ret; for (int i = 0; i < decomposed.size(); i++) { Set<Vector3> points; @@ -575,17 +543,17 @@ Vector<Ref<Shape> > Mesh::convex_decompose() const { points.insert(decomposed[i][j].vertex[2]); } - PoolVector<Vector3> convex_points; + Vector<Vector3> convex_points; convex_points.resize(points.size()); { - PoolVector<Vector3>::Write w = convex_points.write(); + Vector3 *w = convex_points.ptrw(); int idx = 0; for (Set<Vector3>::Element *E = points.front(); E; E = E->next()) { w[idx++] = E->get(); } } - Ref<ConvexPolygonShape> shape; + Ref<ConvexPolygonShape3D> shape; shape.instance(); shape->set_points(convex_points); ret.push_back(shape); @@ -597,86 +565,225 @@ Vector<Ref<Shape> > Mesh::convex_decompose() const { Mesh::Mesh() { } -bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { +static Vector<uint8_t> _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_format, uint32_t p_elements) { + bool vertex_16bit = p_format & ((1 << (Mesh::ARRAY_VERTEX + Mesh::ARRAY_COMPRESS_BASE))); + bool has_bones = (p_format & Mesh::ARRAY_FORMAT_BONES); + bool bone_8 = has_bones && !(p_format & (Mesh::ARRAY_COMPRESS_INDEX << 2)); + bool weight_32 = has_bones && !(p_format & (Mesh::ARRAY_COMPRESS_TEX_UV2 << 2)); + + print_line("convert vertex16: " + itos(vertex_16bit) + " convert bone 8 " + itos(bone_8) + " convert weight 32 " + itos(weight_32)); + + if (!vertex_16bit && !bone_8 && !weight_32) { + return p_src; + } + + bool vertex_2d = (p_format & (Mesh::ARRAY_COMPRESS_INDEX << 1)); + + uint32_t src_stride = p_src.size() / p_elements; + uint32_t dst_stride = src_stride + (vertex_16bit ? 4 : 0) + (bone_8 ? 4 : 0) - (weight_32 ? 8 : 0); + + Vector<uint8_t> ret = p_src; + + ret.resize(dst_stride * p_elements); + { + uint8_t *w = ret.ptrw(); + const uint8_t *r = p_src.ptr(); + + for (uint32_t i = 0; i < p_elements; i++) { + uint32_t remaining = src_stride; + const uint8_t *src = (const uint8_t *)(r + src_stride * i); + uint8_t *dst = (uint8_t *)(w + dst_stride * i); + + if (!vertex_2d) { //3D + if (vertex_16bit) { + float *dstw = (float *)dst; + const uint16_t *srcr = (const uint16_t *)src; + dstw[0] = Math::half_to_float(srcr[0]); + dstw[1] = Math::half_to_float(srcr[1]); + dstw[2] = Math::half_to_float(srcr[2]); + remaining -= 8; + src += 8; + } else { + src += 12; + remaining -= 12; + } + dst += 12; + } else { + if (vertex_16bit) { + float *dstw = (float *)dst; + const uint16_t *srcr = (const uint16_t *)src; + dstw[0] = Math::half_to_float(srcr[0]); + dstw[1] = Math::half_to_float(srcr[1]); + remaining -= 4; + src += 4; + } else { + src += 8; + remaining -= 8; + } + dst += 8; + } + + if (has_bones) { + remaining -= bone_8 ? 4 : 8; + remaining -= weight_32 ? 16 : 8; + } + + for (uint32_t j = 0; j < remaining; j++) { + dst[j] = src[j]; + } + + if (has_bones) { + dst += remaining; + src += remaining; + + if (bone_8) { + const uint8_t *src_bones = (const uint8_t *)src; + uint16_t *dst_bones = (uint16_t *)dst; + + dst_bones[0] = src_bones[0]; + dst_bones[1] = src_bones[1]; + dst_bones[2] = src_bones[2]; + dst_bones[3] = src_bones[3]; + + src += 4; + } else { + for (uint32_t j = 0; j < 8; j++) { + dst[j] = src[j]; + } + src += 8; + } + + dst += 8; + + if (weight_32) { + const float *src_weights = (const float *)src; + uint16_t *dst_weights = (uint16_t *)dst; + + dst_weights[0] = CLAMP(src_weights[0] * 65535, 0, 65535); //16bits unorm + dst_weights[1] = CLAMP(src_weights[1] * 65535, 0, 65535); + dst_weights[2] = CLAMP(src_weights[2] * 65535, 0, 65535); + dst_weights[3] = CLAMP(src_weights[3] * 65535, 0, 65535); + + } else { + for (uint32_t j = 0; j < 8; j++) { + dst[j] = src[j]; + } + } + } + } + } + + return ret; +} + +bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { String sname = p_name; if (p_name == "blend_shape/names") { - - PoolVector<String> sk = p_value; + Vector<String> sk = p_value; int sz = sk.size(); - PoolVector<String>::Read r = sk.read(); - for (int i = 0; i < sz; i++) + const String *r = sk.ptr(); + for (int i = 0; i < sz; i++) { add_blend_shape(r[i]); + } return true; } if (p_name == "blend_shape/mode") { - set_blend_shape_mode(BlendShapeMode(int(p_value))); return true; } if (sname.begins_with("surface_")) { - int sl = sname.find("/"); - if (sl == -1) + if (sl == -1) { return false; + } int idx = sname.substr(8, sl - 8).to_int() - 1; String what = sname.get_slicec('/', 1); - if (what == "material") + if (what == "material") { surface_set_material(idx, p_value); - else if (what == "name") + } else if (what == "name") { surface_set_name(idx, p_value); + } return true; } - if (!sname.begins_with("surfaces")) +#ifndef DISABLE_DEPRECATED + // Kept for compatibility from 3.x to 4.0. + if (!sname.begins_with("surfaces")) { return false; + } + + WARN_DEPRECATED_MSG("Mesh uses old surface format, which is deprecated (and loads slower). Consider re-importing or re-saving the scene."); int idx = sname.get_slicec('/', 1).to_int(); String what = sname.get_slicec('/', 2); if (idx == surfaces.size()) { - //create Dictionary d = p_value; ERR_FAIL_COND_V(!d.has("primitive"), false); if (d.has("arrays")) { - //old format + //oldest format (2.x) ERR_FAIL_COND_V(!d.has("morph_arrays"), false); add_surface_from_arrays(PrimitiveType(int(d["primitive"])), d["arrays"], d["morph_arrays"]); } else if (d.has("array_data")) { - - PoolVector<uint8_t> array_data = d["array_data"]; - PoolVector<uint8_t> array_index_data; - if (d.has("array_index_data")) + //print_line("array data (old style"); + //older format (3.x) + Vector<uint8_t> array_data = d["array_data"]; + Vector<uint8_t> array_index_data; + if (d.has("array_index_data")) { array_index_data = d["array_index_data"]; + } ERR_FAIL_COND_V(!d.has("format"), false); uint32_t format = d["format"]; uint32_t primitive = d["primitive"]; + uint32_t primitive_remap[7] = { + PRIMITIVE_POINTS, + PRIMITIVE_LINES, + PRIMITIVE_LINE_STRIP, + PRIMITIVE_LINES, + PRIMITIVE_TRIANGLES, + PRIMITIVE_TRIANGLE_STRIP, + PRIMITIVE_TRIANGLE_STRIP + }; + + primitive = primitive_remap[primitive]; //compatibility + ERR_FAIL_COND_V(!d.has("vertex_count"), false); int vertex_count = d["vertex_count"]; + array_data = _fix_array_compatibility(array_data, format, vertex_count); + int index_count = 0; - if (d.has("index_count")) + if (d.has("index_count")) { index_count = d["index_count"]; + } - Vector<PoolVector<uint8_t> > blend_shapes; + Vector<Vector<uint8_t>> blend_shapes; if (d.has("blend_shape_data")) { Array blend_shape_data = d["blend_shape_data"]; for (int i = 0; i < blend_shape_data.size(); i++) { - PoolVector<uint8_t> shape = blend_shape_data[i]; + Vector<uint8_t> shape = blend_shape_data[i]; + shape = _fix_array_compatibility(shape, format, vertex_count); + blend_shapes.push_back(shape); } } + //clear unused flags + print_line("format pre: " + itos(format)); + format &= ~uint32_t((1 << (ARRAY_VERTEX + ARRAY_COMPRESS_BASE)) | (ARRAY_COMPRESS_INDEX << 2) | (ARRAY_COMPRESS_TEX_UV2 << 2)); + print_line("format post: " + itos(format)); + ERR_FAIL_COND_V(!d.has("aabb"), false); AABB aabb = d["aabb"]; @@ -696,7 +803,6 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { } if (d.has("material")) { - surface_set_material(idx, d["material"]); } if (d.has("name")) { @@ -705,276 +811,412 @@ bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { return true; } +#endif // DISABLE_DEPRECATED return false; } -bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const { +Array ArrayMesh::_get_surfaces() const { + if (mesh.is_null()) { + return Array(); + } + + Array ret; + for (int i = 0; i < surfaces.size(); i++) { + RenderingServer::SurfaceData surface = RS::get_singleton()->mesh_get_surface(mesh, i); + Dictionary data; + data["format"] = surface.format; + data["primitive"] = surface.primitive; + data["vertex_data"] = surface.vertex_data; + data["vertex_count"] = surface.vertex_count; + data["aabb"] = surface.aabb; + if (surface.index_count) { + data["index_data"] = surface.index_data; + data["index_count"] = surface.index_count; + }; + + Array lods; + for (int j = 0; j < surface.lods.size(); j++) { + lods.push_back(surface.lods[j].edge_length); + lods.push_back(surface.lods[j].index_data); + } + + if (lods.size()) { + data["lods"] = lods; + } + + Array bone_aabbs; + for (int j = 0; j < surface.bone_aabbs.size(); j++) { + bone_aabbs.push_back(surface.bone_aabbs[j]); + } + if (bone_aabbs.size()) { + data["bone_aabbs"] = bone_aabbs; + } + + Array blend_shapes; + for (int j = 0; j < surface.blend_shapes.size(); j++) { + blend_shapes.push_back(surface.blend_shapes[j]); + } + + if (surfaces[i].material.is_valid()) { + data["material"] = surfaces[i].material; + } + + if (surfaces[i].name != String()) { + data["name"] = surfaces[i].name; + } + + if (surfaces[i].is_2d) { + data["2d"] = true; + } + + ret.push_back(data); + } + print_line("Saving surfaces: " + itos(ret.size())); + + return ret; +} + +void ArrayMesh::_create_if_empty() const { + if (!mesh.is_valid()) { + mesh = RS::get_singleton()->mesh_create(); + RS::get_singleton()->mesh_set_blend_shape_mode(mesh, (RS::BlendShapeMode)blend_shape_mode); + } +} + +void ArrayMesh::_set_surfaces(const Array &p_surfaces) { + Vector<RS::SurfaceData> surface_data; + Vector<Ref<Material>> surface_materials; + Vector<String> surface_names; + Vector<bool> surface_2d; + + for (int i = 0; i < p_surfaces.size(); i++) { + RS::SurfaceData surface; + Dictionary d = p_surfaces[i]; + ERR_FAIL_COND(!d.has("format")); + ERR_FAIL_COND(!d.has("primitive")); + ERR_FAIL_COND(!d.has("vertex_data")); + ERR_FAIL_COND(!d.has("vertex_count")); + ERR_FAIL_COND(!d.has("aabb")); + surface.format = d["format"]; + surface.primitive = RS::PrimitiveType(int(d["primitive"])); + surface.vertex_data = d["vertex_data"]; + surface.vertex_count = d["vertex_count"]; + surface.aabb = d["aabb"]; + + if (d.has("index_data")) { + ERR_FAIL_COND(!d.has("index_count")); + surface.index_data = d["index_data"]; + surface.index_count = d["index_count"]; + } + + if (d.has("lods")) { + Array lods = d["lods"]; + ERR_FAIL_COND(lods.size() & 1); //must be even + for (int j = 0; j < lods.size(); j += 2) { + RS::SurfaceData::LOD lod; + lod.edge_length = lods[j + 0]; + lod.index_data = lods[j + 1]; + surface.lods.push_back(lod); + } + } + + if (d.has("bone_aabbs")) { + Array bone_aabbs = d["bone_aabbs"]; + for (int j = 0; j < bone_aabbs.size(); j++) { + surface.bone_aabbs.push_back(bone_aabbs[j]); + } + } + + if (d.has("blend_shapes")) { + Array blend_shapes; + for (int j = 0; j < blend_shapes.size(); j++) { + surface.blend_shapes.push_back(blend_shapes[j]); + } + } + + Ref<Material> material; + if (d.has("material")) { + material = d["material"]; + if (material.is_valid()) { + surface.material = material->get_rid(); + } + } + + String name; + if (d.has("name")) { + name = d["name"]; + } + + bool _2d = false; + if (d.has("2d")) { + _2d = d["2d"]; + } + /* + print_line("format: " + itos(surface.format)); + print_line("aabb: " + surface.aabb); + print_line("array size: " + itos(surface.vertex_data.size())); + print_line("vertex count: " + itos(surface.vertex_count)); + print_line("index size: " + itos(surface.index_data.size())); + print_line("index count: " + itos(surface.index_count)); + print_line("primitive: " + itos(surface.primitive)); +*/ + surface_data.push_back(surface); + surface_materials.push_back(material); + surface_names.push_back(name); + surface_2d.push_back(_2d); + } + + if (mesh.is_valid()) { + //if mesh exists, it needs to be updated + RS::get_singleton()->mesh_clear(mesh); + for (int i = 0; i < surface_data.size(); i++) { + RS::get_singleton()->mesh_add_surface(mesh, surface_data[i]); + } + } else { + // if mesh does not exist (first time this is loaded, most likely), + // we can create it with a single call, which is a lot more efficient and thread friendly + mesh = RS::get_singleton()->mesh_create_from_surfaces(surface_data); + RS::get_singleton()->mesh_set_blend_shape_mode(mesh, (RS::BlendShapeMode)blend_shape_mode); + } + + surfaces.clear(); + + aabb = AABB(); + for (int i = 0; i < surface_data.size(); i++) { + Surface s; + s.aabb = surface_data[i].aabb; + if (i == 0) { + aabb = s.aabb; + blend_shapes.resize(surface_data[i].blend_shapes.size()); + } else { + aabb.merge_with(s.aabb); + } + + s.material = surface_materials[i]; + s.is_2d = surface_2d[i]; + s.name = surface_names[i]; + + s.format = surface_data[i].format; + s.primitive = PrimitiveType(surface_data[i].primitive); + s.array_length = surface_data[i].vertex_count; + s.index_array_length = surface_data[i].index_count; - if (_is_generated()) + surfaces.push_back(s); + } +} + +bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const { + if (_is_generated()) { return false; + } String sname = p_name; if (p_name == "blend_shape/names") { - - PoolVector<String> sk; - for (int i = 0; i < blend_shapes.size(); i++) + Vector<String> sk; + for (int i = 0; i < blend_shapes.size(); i++) { sk.push_back(blend_shapes[i]); + } r_ret = sk; return true; } else if (p_name == "blend_shape/mode") { - r_ret = get_blend_shape_mode(); return true; } else if (sname.begins_with("surface_")) { - int sl = sname.find("/"); - if (sl == -1) + if (sl == -1) { return false; + } int idx = sname.substr(8, sl - 8).to_int() - 1; String what = sname.get_slicec('/', 1); - if (what == "material") + if (what == "material") { r_ret = surface_get_material(idx); - else if (what == "name") + } else if (what == "name") { r_ret = surface_get_name(idx); + } return true; - } else if (!sname.begins_with("surfaces")) - return false; - - int idx = sname.get_slicec('/', 1).to_int(); - ERR_FAIL_INDEX_V(idx, surfaces.size(), false); - - Dictionary d; - - d["array_data"] = VS::get_singleton()->mesh_surface_get_array(mesh, idx); - d["vertex_count"] = VS::get_singleton()->mesh_surface_get_array_len(mesh, idx); - d["array_index_data"] = VS::get_singleton()->mesh_surface_get_index_array(mesh, idx); - d["index_count"] = VS::get_singleton()->mesh_surface_get_array_index_len(mesh, idx); - d["primitive"] = VS::get_singleton()->mesh_surface_get_primitive_type(mesh, idx); - d["format"] = VS::get_singleton()->mesh_surface_get_format(mesh, idx); - d["aabb"] = VS::get_singleton()->mesh_surface_get_aabb(mesh, idx); - - Vector<AABB> skel_aabb = VS::get_singleton()->mesh_surface_get_skeleton_aabb(mesh, idx); - Array arr; - arr.resize(skel_aabb.size()); - for (int i = 0; i < skel_aabb.size(); i++) { - arr[i] = skel_aabb[i]; } - d["skeleton_aabb"] = arr; - - Vector<PoolVector<uint8_t> > blend_shape_data = VS::get_singleton()->mesh_surface_get_blend_shapes(mesh, idx); - - Array md; - for (int i = 0; i < blend_shape_data.size(); i++) { - md.push_back(blend_shape_data[i]); - } - - d["blend_shape_data"] = md; - - Ref<Material> m = surface_get_material(idx); - if (m.is_valid()) - d["material"] = m; - String n = surface_get_name(idx); - if (n != "") - d["name"] = n; - - r_ret = d; return true; } void ArrayMesh::_get_property_list(List<PropertyInfo> *p_list) const { - - if (_is_generated()) + if (_is_generated()) { return; + } if (blend_shapes.size()) { - p_list->push_back(PropertyInfo(Variant::POOL_STRING_ARRAY, "blend_shape/names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); + p_list->push_back(PropertyInfo(Variant::PACKED_STRING_ARRAY, "blend_shape/names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::INT, "blend_shape/mode", PROPERTY_HINT_ENUM, "Normalized,Relative")); } for (int i = 0; i < surfaces.size(); i++) { - - p_list->push_back(PropertyInfo(Variant::DICTIONARY, "surfaces/" + itos(i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::STRING, "surface_" + itos(i + 1) + "/name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); if (surfaces[i].is_2d) { p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,CanvasItemMaterial", PROPERTY_USAGE_EDITOR)); } else { - p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,SpatialMaterial", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i + 1) + "/material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D", PROPERTY_USAGE_EDITOR)); } } } void ArrayMesh::_recompute_aabb() { - // regenerate AABB aabb = AABB(); for (int i = 0; i < surfaces.size(); i++) { - - if (i == 0) + if (i == 0) { aabb = surfaces[i].aabb; - else + } else { aabb.merge_with(surfaces[i].aabb); + } } } - -void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<AABB> &p_bone_aabbs) { +#ifndef _MSC_VER +#warning need to add binding to add_surface using future MeshSurfaceData object +#endif +void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const Vector<uint8_t> &p_array, int p_vertex_count, const Vector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<Vector<uint8_t>> &p_blend_shapes, const Vector<AABB> &p_bone_aabb, const Vector<RS::SurfaceData::LOD> &p_lods) { + _create_if_empty(); Surface s; s.aabb = p_aabb; s.is_2d = p_format & ARRAY_FLAG_USE_2D_VERTICES; + s.primitive = p_primitive; + s.array_length = p_vertex_count; + s.index_array_length = p_index_count; + s.format = p_format; + surfaces.push_back(s); _recompute_aabb(); - VisualServer::get_singleton()->mesh_add_surface(mesh, p_format, (VS::PrimitiveType)p_primitive, p_array, p_vertex_count, p_index_array, p_index_count, p_aabb, p_blend_shapes, p_bone_aabbs); -} - -void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, uint32_t p_flags) { - - ERR_FAIL_COND(p_arrays.size() != ARRAY_MAX); - - Surface s; - - VisualServer::get_singleton()->mesh_add_surface_from_arrays(mesh, (VisualServer::PrimitiveType)p_primitive, p_arrays, p_blend_shapes, p_flags); + RS::SurfaceData sd; + sd.format = p_format; + sd.primitive = RS::PrimitiveType(p_primitive); + sd.aabb = p_aabb; + sd.vertex_count = p_vertex_count; + sd.vertex_data = p_array; + sd.index_count = p_index_count; + sd.index_data = p_index_array; + sd.blend_shapes = p_blend_shapes; + sd.bone_aabbs = p_bone_aabb; + sd.lods = p_lods; - /* make aABB? */ { + RenderingServer::get_singleton()->mesh_add_surface(mesh, sd); - Variant arr = p_arrays[ARRAY_VERTEX]; - PoolVector<Vector3> vertices = arr; - int len = vertices.size(); - ERR_FAIL_COND(len == 0); - PoolVector<Vector3>::Read r = vertices.read(); - const Vector3 *vtx = r.ptr(); - - // check AABB - AABB aabb; - for (int i = 0; i < len; i++) { + clear_cache(); + _change_notify(); + emit_changed(); +} - if (i == 0) - aabb.position = vtx[i]; - else - aabb.expand_to(vtx[i]); - } +void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, uint32_t p_flags) { + ERR_FAIL_COND(p_arrays.size() != ARRAY_MAX); - s.aabb = aabb; - s.is_2d = arr.get_type() == Variant::POOL_VECTOR2_ARRAY; - surfaces.push_back(s); + RS::SurfaceData surface; - _recompute_aabb(); - } + Error err = RS::get_singleton()->mesh_create_surface_data_from_arrays(&surface, (RenderingServer::PrimitiveType)p_primitive, p_arrays, p_blend_shapes, p_lods, p_flags); + ERR_FAIL_COND(err != OK); - clear_cache(); - _change_notify(); - emit_changed(); + /* print_line("format: " + itos(surface.format)); + print_line("aabb: " + surface.aabb); + print_line("array size: " + itos(surface.vertex_data.size())); + print_line("vertex count: " + itos(surface.vertex_count)); + print_line("index size: " + itos(surface.index_data.size())); + print_line("index count: " + itos(surface.index_count)); + print_line("primitive: " + itos(surface.primitive)); +*/ + add_surface(surface.format, PrimitiveType(surface.primitive), surface.vertex_data, surface.vertex_count, surface.index_data, surface.index_count, surface.aabb, surface.blend_shapes, surface.bone_aabbs, surface.lods); } Array ArrayMesh::surface_get_arrays(int p_surface) const { - ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); - return VisualServer::get_singleton()->mesh_surface_get_arrays(mesh, p_surface); + return RenderingServer::get_singleton()->mesh_surface_get_arrays(mesh, p_surface); } -Array ArrayMesh::surface_get_blend_shape_arrays(int p_surface) const { +Array ArrayMesh::surface_get_blend_shape_arrays(int p_surface) const { ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); - return VisualServer::get_singleton()->mesh_surface_get_blend_shape_arrays(mesh, p_surface); + return RenderingServer::get_singleton()->mesh_surface_get_blend_shape_arrays(mesh, p_surface); } -int ArrayMesh::get_surface_count() const { +Dictionary ArrayMesh::surface_get_lods(int p_surface) const { + ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Dictionary()); + return RenderingServer::get_singleton()->mesh_surface_get_lods(mesh, p_surface); +} +int ArrayMesh::get_surface_count() const { return surfaces.size(); } void ArrayMesh::add_blend_shape(const StringName &p_name) { - ERR_FAIL_COND_MSG(surfaces.size(), "Can't add a shape key count if surfaces are already created."); StringName name = p_name; if (blend_shapes.find(name) != -1) { - int count = 2; do { - name = String(p_name) + " " + itos(count); count++; } while (blend_shapes.find(name) != -1); } blend_shapes.push_back(name); - VS::get_singleton()->mesh_set_blend_shape_count(mesh, blend_shapes.size()); + //RS::get_singleton()->mesh_set_blend_shape_count(mesh, blend_shapes.size()); } int ArrayMesh::get_blend_shape_count() const { - return blend_shapes.size(); } + StringName ArrayMesh::get_blend_shape_name(int p_index) const { ERR_FAIL_INDEX_V(p_index, blend_shapes.size(), StringName()); return blend_shapes[p_index]; } -void ArrayMesh::clear_blend_shapes() { +void ArrayMesh::clear_blend_shapes() { ERR_FAIL_COND_MSG(surfaces.size(), "Can't set shape key count if surfaces are already created."); blend_shapes.clear(); } void ArrayMesh::set_blend_shape_mode(BlendShapeMode p_mode) { - blend_shape_mode = p_mode; - VS::get_singleton()->mesh_set_blend_shape_mode(mesh, (VS::BlendShapeMode)p_mode); + if (mesh.is_valid()) { + RS::get_singleton()->mesh_set_blend_shape_mode(mesh, (RS::BlendShapeMode)p_mode); + } } ArrayMesh::BlendShapeMode ArrayMesh::get_blend_shape_mode() const { - return blend_shape_mode; } -void ArrayMesh::surface_remove(int p_idx) { - - ERR_FAIL_INDEX(p_idx, surfaces.size()); - VisualServer::get_singleton()->mesh_remove_surface(mesh, p_idx); - surfaces.remove(p_idx); - - clear_cache(); - _recompute_aabb(); - _change_notify(); - emit_changed(); -} - int ArrayMesh::surface_get_array_len(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), -1); - return VisualServer::get_singleton()->mesh_surface_get_array_len(mesh, p_idx); + return surfaces[p_idx].array_length; } int ArrayMesh::surface_get_array_index_len(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), -1); - return VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, p_idx); + return surfaces[p_idx].index_array_length; } uint32_t ArrayMesh::surface_get_format(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), 0); - return VisualServer::get_singleton()->mesh_surface_get_format(mesh, p_idx); + return surfaces[p_idx].format; } ArrayMesh::PrimitiveType ArrayMesh::surface_get_primitive_type(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), PRIMITIVE_LINES); - return (PrimitiveType)VisualServer::get_singleton()->mesh_surface_get_primitive_type(mesh, p_idx); + return surfaces[p_idx].primitive; } void ArrayMesh::surface_set_material(int p_idx, const Ref<Material> &p_material) { - ERR_FAIL_INDEX(p_idx, surfaces.size()); - if (surfaces[p_idx].material == p_material) + if (surfaces[p_idx].material == p_material) { return; + } surfaces.write[p_idx].material = p_material; - VisualServer::get_singleton()->mesh_surface_set_material(mesh, p_idx, p_material.is_null() ? RID() : p_material->get_rid()); + RenderingServer::get_singleton()->mesh_surface_set_material(mesh, p_idx, p_material.is_null() ? RID() : p_material->get_rid()); _change_notify("material"); emit_changed(); @@ -986,12 +1228,10 @@ int ArrayMesh::surface_find_by_name(const String &p_name) const { return i; } } - return -1; } void ArrayMesh::surface_set_name(int p_idx, const String &p_name) { - ERR_FAIL_INDEX(p_idx, surfaces.size()); surfaces.write[p_idx].name = p_name; @@ -999,20 +1239,17 @@ void ArrayMesh::surface_set_name(int p_idx, const String &p_name) { } String ArrayMesh::surface_get_name(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), String()); return surfaces[p_idx].name; } -void ArrayMesh::surface_update_region(int p_surface, int p_offset, const PoolVector<uint8_t> &p_data) { - +void ArrayMesh::surface_update_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) { ERR_FAIL_INDEX(p_surface, surfaces.size()); - VS::get_singleton()->mesh_surface_update_region(mesh, p_surface, p_offset, p_data); + RS::get_singleton()->mesh_surface_update_region(mesh, p_surface, p_offset, p_data); emit_changed(); } void ArrayMesh::surface_set_custom_aabb(int p_idx, const AABB &p_aabb) { - ERR_FAIL_INDEX(p_idx, surfaces.size()); surfaces.write[p_idx].aabb = p_aabb; // set custom aabb too? @@ -1020,85 +1257,62 @@ void ArrayMesh::surface_set_custom_aabb(int p_idx, const AABB &p_aabb) { } Ref<Material> ArrayMesh::surface_get_material(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, surfaces.size(), Ref<Material>()); return surfaces[p_idx].material; } -void ArrayMesh::add_surface_from_mesh_data(const Geometry::MeshData &p_mesh_data) { - - VisualServer::get_singleton()->mesh_add_surface_from_mesh_data(mesh, p_mesh_data); - AABB aabb; - for (int i = 0; i < p_mesh_data.vertices.size(); i++) { - - if (i == 0) - aabb.position = p_mesh_data.vertices[i]; - else - aabb.expand_to(p_mesh_data.vertices[i]); - } - - Surface s; - s.aabb = aabb; - if (surfaces.size() == 0) - aabb = s.aabb; - else - aabb.merge_with(s.aabb); - - clear_cache(); - - surfaces.push_back(s); - _change_notify(); - - emit_changed(); -} - RID ArrayMesh::get_rid() const { - + _create_if_empty(); return mesh; } -AABB ArrayMesh::get_aabb() const { +AABB ArrayMesh::get_aabb() const { return aabb; } -void ArrayMesh::set_custom_aabb(const AABB &p_custom) { +void ArrayMesh::clear_surfaces() { + if (!mesh.is_valid()) { + return; + } + RS::get_singleton()->mesh_clear(mesh); + surfaces.clear(); + aabb = AABB(); +} +void ArrayMesh::set_custom_aabb(const AABB &p_custom) { + _create_if_empty(); custom_aabb = p_custom; - VS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); + RS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); emit_changed(); } AABB ArrayMesh::get_custom_aabb() const { - return custom_aabb; } void ArrayMesh::regen_normalmaps() { - - Vector<Ref<SurfaceTool> > surfs; + if (surfaces.size() == 0) { + return; + } + Vector<Ref<SurfaceTool>> surfs; for (int i = 0; i < get_surface_count(); i++) { - Ref<SurfaceTool> st = memnew(SurfaceTool); st->create_from(Ref<ArrayMesh>(this), i); surfs.push_back(st); } - while (get_surface_count()) { - surface_remove(0); - } + clear_surfaces(); for (int i = 0; i < surfs.size(); i++) { - surfs.write[i]->generate_tangents(); surfs.write[i]->commit(Ref<ArrayMesh>(this)); } } //dirty hack -bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y) = NULL; +bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y, int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache); struct ArrayMeshLightmapSurface { - Ref<Material> material; Vector<SurfaceTool::Vertex> vertices; Mesh::PrimitiveType primitive; @@ -1106,18 +1320,31 @@ struct ArrayMeshLightmapSurface { }; Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texel_size) { + int *cache_data = nullptr; + unsigned int cache_size = 0; + bool use_cache = false; // Don't use cache + return lightmap_unwrap_cached(cache_data, cache_size, use_cache, p_base_transform, p_texel_size); +} +Error ArrayMesh::lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache, const Transform &p_base_transform, float p_texel_size) { ERR_FAIL_COND_V(!array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED); ERR_FAIL_COND_V_MSG(blend_shapes.size() != 0, ERR_UNAVAILABLE, "Can't unwrap mesh with blend shapes."); Vector<float> vertices; Vector<float> normals; Vector<int> indices; - Vector<int> face_materials; Vector<float> uv; - Vector<Pair<int, int> > uv_index; + Vector<Pair<int, int>> uv_indices; + + Vector<ArrayMeshLightmapSurface> lightmap_surfaces; + + // Keep only the scale + Transform transform = p_base_transform; + transform.origin = Vector3(); + transform.looking_at(Vector3(1, 0, 0), Vector3(0, 1, 0)); + + Basis normal_basis = transform.basis.inverse().transposed(); - Vector<ArrayMeshLightmapSurface> surfaces; for (int i = 0; i < get_surface_count(); i++) { ArrayMeshLightmapSurface s; s.primitive = surface_get_primitive_type(i); @@ -1130,23 +1357,22 @@ Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texe s.material = surface_get_material(i); s.vertices = SurfaceTool::create_vertex_array_from_triangle_arrays(arrays); - PoolVector<Vector3> rvertices = arrays[Mesh::ARRAY_VERTEX]; + Vector<Vector3> rvertices = arrays[Mesh::ARRAY_VERTEX]; int vc = rvertices.size(); - PoolVector<Vector3>::Read r = rvertices.read(); + const Vector3 *r = rvertices.ptr(); - PoolVector<Vector3> rnormals = arrays[Mesh::ARRAY_NORMAL]; - PoolVector<Vector3>::Read rn = rnormals.read(); + Vector<Vector3> rnormals = arrays[Mesh::ARRAY_NORMAL]; + const Vector3 *rn = rnormals.ptr(); int vertex_ofs = vertices.size() / 3; vertices.resize((vertex_ofs + vc) * 3); normals.resize((vertex_ofs + vc) * 3); - uv_index.resize(vertex_ofs + vc); + uv_indices.resize(vertex_ofs + vc); for (int j = 0; j < vc; j++) { - - Vector3 v = p_base_transform.xform(r[j]); - Vector3 n = p_base_transform.basis.xform(rn[j]).normalized(); + Vector3 v = transform.xform(r[j]); + Vector3 n = normal_basis.xform(rn[j]).normalized(); vertices.write[(j + vertex_ofs) * 3 + 0] = v.x; vertices.write[(j + vertex_ofs) * 3 + 1] = v.y; @@ -1154,38 +1380,37 @@ Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texe normals.write[(j + vertex_ofs) * 3 + 0] = n.x; normals.write[(j + vertex_ofs) * 3 + 1] = n.y; normals.write[(j + vertex_ofs) * 3 + 2] = n.z; - uv_index.write[j + vertex_ofs] = Pair<int, int>(i, j); + uv_indices.write[j + vertex_ofs] = Pair<int, int>(i, j); } - PoolVector<int> rindices = arrays[Mesh::ARRAY_INDEX]; + Vector<int> rindices = arrays[Mesh::ARRAY_INDEX]; int ic = rindices.size(); if (ic == 0) { - for (int j = 0; j < vc / 3; j++) { - if (Face3(r[j * 3 + 0], r[j * 3 + 1], r[j * 3 + 2]).is_degenerate()) + if (Face3(r[j * 3 + 0], r[j * 3 + 1], r[j * 3 + 2]).is_degenerate()) { continue; + } indices.push_back(vertex_ofs + j * 3 + 0); indices.push_back(vertex_ofs + j * 3 + 1); indices.push_back(vertex_ofs + j * 3 + 2); - face_materials.push_back(i); } } else { - PoolVector<int>::Read ri = rindices.read(); + const int *ri = rindices.ptr(); for (int j = 0; j < ic / 3; j++) { - if (Face3(r[ri[j * 3 + 0]], r[ri[j * 3 + 1]], r[ri[j * 3 + 2]]).is_degenerate()) + if (Face3(r[ri[j * 3 + 0]], r[ri[j * 3 + 1]], r[ri[j * 3 + 2]]).is_degenerate()) { continue; + } indices.push_back(vertex_ofs + ri[j * 3 + 0]); indices.push_back(vertex_ofs + ri[j * 3 + 1]); indices.push_back(vertex_ofs + ri[j * 3 + 2]); - face_materials.push_back(i); } } - surfaces.push_back(s); + lightmap_surfaces.push_back(s); } //unwrap @@ -1198,63 +1423,59 @@ Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texe int size_x; int size_y; - bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), face_materials.ptr(), indices.size(), &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y); + bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), indices.size(), &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y, r_cache_data, r_cache_size, r_used_cache); if (!ok) { return ERR_CANT_CREATE; } //remove surfaces - while (get_surface_count()) { - surface_remove(0); - } + clear_surfaces(); //create surfacetools for each surface.. - Vector<Ref<SurfaceTool> > surfaces_tools; + Vector<Ref<SurfaceTool>> surfaces_tools; - for (int i = 0; i < surfaces.size(); i++) { + for (int i = 0; i < lightmap_surfaces.size(); i++) { Ref<SurfaceTool> st; st.instance(); st->begin(Mesh::PRIMITIVE_TRIANGLES); - st->set_material(surfaces[i].material); + st->set_material(lightmap_surfaces[i].material); surfaces_tools.push_back(st); //stay there } print_verbose("Mesh: Gen indices: " + itos(gen_index_count)); //go through all indices for (int i = 0; i < gen_index_count; i += 3) { + ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], uv_indices.size(), ERR_BUG); + ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], uv_indices.size(), ERR_BUG); + ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], uv_indices.size(), ERR_BUG); - ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], uv_index.size(), ERR_BUG); - ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], uv_index.size(), ERR_BUG); - ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], uv_index.size(), ERR_BUG); - - ERR_FAIL_COND_V(uv_index[gen_vertices[gen_indices[i + 0]]].first != uv_index[gen_vertices[gen_indices[i + 1]]].first || uv_index[gen_vertices[gen_indices[i + 0]]].first != uv_index[gen_vertices[gen_indices[i + 2]]].first, ERR_BUG); + ERR_FAIL_COND_V(uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 1]]].first || uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 2]]].first, ERR_BUG); - int surface = uv_index[gen_vertices[gen_indices[i + 0]]].first; + int surface = uv_indices[gen_vertices[gen_indices[i + 0]]].first; for (int j = 0; j < 3; j++) { + SurfaceTool::Vertex v = lightmap_surfaces[surface].vertices[uv_indices[gen_vertices[gen_indices[i + j]]].second]; - SurfaceTool::Vertex v = surfaces[surface].vertices[uv_index[gen_vertices[gen_indices[i + j]]].second]; - - if (surfaces[surface].format & ARRAY_FORMAT_COLOR) { + if (lightmap_surfaces[surface].format & ARRAY_FORMAT_COLOR) { surfaces_tools.write[surface]->add_color(v.color); } - if (surfaces[surface].format & ARRAY_FORMAT_TEX_UV) { + if (lightmap_surfaces[surface].format & ARRAY_FORMAT_TEX_UV) { surfaces_tools.write[surface]->add_uv(v.uv); } - if (surfaces[surface].format & ARRAY_FORMAT_NORMAL) { + if (lightmap_surfaces[surface].format & ARRAY_FORMAT_NORMAL) { surfaces_tools.write[surface]->add_normal(v.normal); } - if (surfaces[surface].format & ARRAY_FORMAT_TANGENT) { + if (lightmap_surfaces[surface].format & ARRAY_FORMAT_TANGENT) { Plane t; t.normal = v.tangent; t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1; surfaces_tools.write[surface]->add_tangent(t); } - if (surfaces[surface].format & ARRAY_FORMAT_BONES) { + if (lightmap_surfaces[surface].format & ARRAY_FORMAT_BONES) { surfaces_tools.write[surface]->add_bones(v.bones); } - if (surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) { + if (lightmap_surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) { surfaces_tools.write[surface]->add_weights(v.weights); } @@ -1265,25 +1486,26 @@ Error ArrayMesh::lightmap_unwrap(const Transform &p_base_transform, float p_texe } } - //free stuff - ::free(gen_vertices); - ::free(gen_indices); - ::free(gen_uvs); - //generate surfaces for (int i = 0; i < surfaces_tools.size(); i++) { surfaces_tools.write[i]->index(); - surfaces_tools.write[i]->commit(Ref<ArrayMesh>((ArrayMesh *)this), surfaces[i].format); + surfaces_tools.write[i]->commit(Ref<ArrayMesh>((ArrayMesh *)this), lightmap_surfaces[i].format); } set_lightmap_size_hint(Size2(size_x, size_y)); + if (!r_used_cache) { + //free stuff + ::free(gen_vertices); + ::free(gen_indices); + ::free(gen_uvs); + } + return OK; } void ArrayMesh::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_blend_shape", "name"), &ArrayMesh::add_blend_shape); ClassDB::bind_method(D_METHOD("get_blend_shape_count"), &ArrayMesh::get_blend_shape_count); ClassDB::bind_method(D_METHOD("get_blend_shape_name", "index"), &ArrayMesh::get_blend_shape_name); @@ -1291,8 +1513,8 @@ void ArrayMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_blend_shape_mode", "mode"), &ArrayMesh::set_blend_shape_mode); ClassDB::bind_method(D_METHOD("get_blend_shape_mode"), &ArrayMesh::get_blend_shape_mode); - ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "compress_flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(ARRAY_COMPRESS_DEFAULT)); - ClassDB::bind_method(D_METHOD("surface_remove", "surf_idx"), &ArrayMesh::surface_remove); + ClassDB::bind_method(D_METHOD("add_surface_from_arrays", "primitive", "arrays", "blend_shapes", "lods", "compress_flags"), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(ARRAY_COMPRESS_DEFAULT)); + ClassDB::bind_method(D_METHOD("clear_surfaces"), &ArrayMesh::clear_surfaces); ClassDB::bind_method(D_METHOD("surface_update_region", "surf_idx", "offset", "data"), &ArrayMesh::surface_update_region); ClassDB::bind_method(D_METHOD("surface_get_array_len", "surf_idx"), &ArrayMesh::surface_get_array_len); ClassDB::bind_method(D_METHOD("surface_get_array_index_len", "surf_idx"), &ArrayMesh::surface_get_array_index_len); @@ -1314,7 +1536,11 @@ void ArrayMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &ArrayMesh::set_custom_aabb); ClassDB::bind_method(D_METHOD("get_custom_aabb"), &ArrayMesh::get_custom_aabb); - ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_shape_mode", PROPERTY_HINT_ENUM, "Normalized,Relative", PROPERTY_USAGE_NOEDITOR), "set_blend_shape_mode", "get_blend_shape_mode"); + ClassDB::bind_method(D_METHOD("_set_surfaces", "surfaces"), &ArrayMesh::_set_surfaces); + ClassDB::bind_method(D_METHOD("_get_surfaces"), &ArrayMesh::_get_surfaces); + + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_surfaces", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_surfaces", "_get_surfaces"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_shape_mode", PROPERTY_HINT_ENUM, "Normalized,Relative"), "set_blend_shape_mode", "get_blend_shape_mode"); ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, ""), "set_custom_aabb", "get_custom_aabb"); BIND_CONSTANT(NO_INDEX_ARRAY); @@ -1343,7 +1569,7 @@ void ArrayMesh::_bind_methods() { } void ArrayMesh::reload_from_file() { - VisualServer::get_singleton()->mesh_clear(mesh); + RenderingServer::get_singleton()->mesh_clear(mesh); surfaces.clear(); clear_blend_shapes(); clear_cache(); @@ -1354,12 +1580,13 @@ void ArrayMesh::reload_from_file() { } ArrayMesh::ArrayMesh() { - - mesh = VisualServer::get_singleton()->mesh_create(); + //mesh is now created on demand + //mesh = RenderingServer::get_singleton()->mesh_create(); blend_shape_mode = BLEND_SHAPE_MODE_RELATIVE; } ArrayMesh::~ArrayMesh() { - - VisualServer::get_singleton()->free(mesh); + if (mesh.is_valid()) { + RenderingServer::get_singleton()->free(mesh); + } } diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 30ce94f16b..b0a30a5627 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -35,15 +35,15 @@ #include "core/math/triangle_mesh.h" #include "core/resource.h" #include "scene/resources/material.h" -#include "scene/resources/shape.h" -#include "servers/visual_server.h" +#include "scene/resources/shape_3d.h" +#include "servers/rendering_server.h" class Mesh : public Resource { GDCLASS(Mesh, Resource); mutable Ref<TriangleMesh> triangle_mesh; //cached mutable Vector<Vector3> debug_lines; - Size2 lightmap_size_hint; + Size2i lightmap_size_hint; protected: static void _bind_methods(); @@ -51,22 +51,22 @@ protected: public: enum { - NO_INDEX_ARRAY = VisualServer::NO_INDEX_ARRAY, - ARRAY_WEIGHTS_SIZE = VisualServer::ARRAY_WEIGHTS_SIZE + NO_INDEX_ARRAY = RenderingServer::NO_INDEX_ARRAY, + ARRAY_WEIGHTS_SIZE = RenderingServer::ARRAY_WEIGHTS_SIZE }; enum ArrayType { - ARRAY_VERTEX = VisualServer::ARRAY_VERTEX, - ARRAY_NORMAL = VisualServer::ARRAY_NORMAL, - ARRAY_TANGENT = VisualServer::ARRAY_TANGENT, - ARRAY_COLOR = VisualServer::ARRAY_COLOR, - ARRAY_TEX_UV = VisualServer::ARRAY_TEX_UV, - ARRAY_TEX_UV2 = VisualServer::ARRAY_TEX_UV2, - ARRAY_BONES = VisualServer::ARRAY_BONES, - ARRAY_WEIGHTS = VisualServer::ARRAY_WEIGHTS, - ARRAY_INDEX = VisualServer::ARRAY_INDEX, - ARRAY_MAX = VisualServer::ARRAY_MAX + ARRAY_VERTEX = RenderingServer::ARRAY_VERTEX, + ARRAY_NORMAL = RenderingServer::ARRAY_NORMAL, + ARRAY_TANGENT = RenderingServer::ARRAY_TANGENT, + ARRAY_COLOR = RenderingServer::ARRAY_COLOR, + ARRAY_TEX_UV = RenderingServer::ARRAY_TEX_UV, + ARRAY_TEX_UV2 = RenderingServer::ARRAY_TEX_UV2, + ARRAY_BONES = RenderingServer::ARRAY_BONES, + ARRAY_WEIGHTS = RenderingServer::ARRAY_WEIGHTS, + ARRAY_INDEX = RenderingServer::ARRAY_INDEX, + ARRAY_MAX = RenderingServer::ARRAY_MAX }; @@ -83,38 +83,33 @@ public: ARRAY_FORMAT_INDEX = 1 << ARRAY_INDEX, ARRAY_COMPRESS_BASE = (ARRAY_INDEX + 1), - ARRAY_COMPRESS_VERTEX = 1 << (ARRAY_VERTEX + ARRAY_COMPRESS_BASE), // mandatory ARRAY_COMPRESS_NORMAL = 1 << (ARRAY_NORMAL + ARRAY_COMPRESS_BASE), ARRAY_COMPRESS_TANGENT = 1 << (ARRAY_TANGENT + ARRAY_COMPRESS_BASE), ARRAY_COMPRESS_COLOR = 1 << (ARRAY_COLOR + ARRAY_COMPRESS_BASE), ARRAY_COMPRESS_TEX_UV = 1 << (ARRAY_TEX_UV + ARRAY_COMPRESS_BASE), ARRAY_COMPRESS_TEX_UV2 = 1 << (ARRAY_TEX_UV2 + ARRAY_COMPRESS_BASE), - ARRAY_COMPRESS_BONES = 1 << (ARRAY_BONES + ARRAY_COMPRESS_BASE), - ARRAY_COMPRESS_WEIGHTS = 1 << (ARRAY_WEIGHTS + ARRAY_COMPRESS_BASE), ARRAY_COMPRESS_INDEX = 1 << (ARRAY_INDEX + ARRAY_COMPRESS_BASE), ARRAY_FLAG_USE_2D_VERTICES = ARRAY_COMPRESS_INDEX << 1, - ARRAY_FLAG_USE_16_BIT_BONES = ARRAY_COMPRESS_INDEX << 2, ARRAY_FLAG_USE_DYNAMIC_UPDATE = ARRAY_COMPRESS_INDEX << 3, - ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2 | ARRAY_COMPRESS_WEIGHTS + ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2 }; enum PrimitiveType { - PRIMITIVE_POINTS = VisualServer::PRIMITIVE_POINTS, - PRIMITIVE_LINES = VisualServer::PRIMITIVE_LINES, - PRIMITIVE_LINE_STRIP = VisualServer::PRIMITIVE_LINE_STRIP, - PRIMITIVE_LINE_LOOP = VisualServer::PRIMITIVE_LINE_LOOP, - PRIMITIVE_TRIANGLES = VisualServer::PRIMITIVE_TRIANGLES, - PRIMITIVE_TRIANGLE_STRIP = VisualServer::PRIMITIVE_TRIANGLE_STRIP, - PRIMITIVE_TRIANGLE_FAN = VisualServer::PRIMITIVE_TRIANGLE_FAN, + PRIMITIVE_POINTS = RenderingServer::PRIMITIVE_POINTS, + PRIMITIVE_LINES = RenderingServer::PRIMITIVE_LINES, + PRIMITIVE_LINE_STRIP = RenderingServer::PRIMITIVE_LINE_STRIP, + PRIMITIVE_TRIANGLES = RenderingServer::PRIMITIVE_TRIANGLES, + PRIMITIVE_TRIANGLE_STRIP = RenderingServer::PRIMITIVE_TRIANGLE_STRIP, + PRIMITIVE_MAX = RenderingServer::PRIMITIVE_MAX, }; enum BlendShapeMode { - BLEND_SHAPE_MODE_NORMALIZED = VS::BLEND_SHAPE_MODE_NORMALIZED, - BLEND_SHAPE_MODE_RELATIVE = VS::BLEND_SHAPE_MODE_RELATIVE, + BLEND_SHAPE_MODE_NORMALIZED = RS::BLEND_SHAPE_MODE_NORMALIZED, + BLEND_SHAPE_MODE_RELATIVE = RS::BLEND_SHAPE_MODE_RELATIVE, }; virtual int get_surface_count() const = 0; @@ -123,6 +118,7 @@ public: virtual bool surface_is_softbody_friendly(int p_idx) const; virtual Array surface_get_arrays(int p_surface) const = 0; virtual Array surface_get_blend_shape_arrays(int p_surface) const = 0; + virtual Dictionary surface_get_lods(int p_surface) const = 0; virtual uint32_t surface_get_format(int p_idx) const = 0; virtual PrimitiveType surface_get_primitive_type(int p_idx) const = 0; virtual void surface_set_material(int p_idx, const Ref<Material> &p_material) = 0; @@ -130,50 +126,58 @@ public: virtual int get_blend_shape_count() const = 0; virtual StringName get_blend_shape_name(int p_index) const = 0; - PoolVector<Face3> get_faces() const; + Vector<Face3> get_faces() const; Ref<TriangleMesh> generate_triangle_mesh() const; void generate_debug_mesh_lines(Vector<Vector3> &r_lines); void generate_debug_mesh_indices(Vector<Vector3> &r_points); - Ref<Shape> create_trimesh_shape() const; - Ref<Shape> create_convex_shape() const; + Ref<Shape3D> create_trimesh_shape() const; + Ref<Shape3D> create_convex_shape() const; Ref<Mesh> create_outline(float p_margin) const; virtual AABB get_aabb() const = 0; - void set_lightmap_size_hint(const Vector2 &p_size); - Size2 get_lightmap_size_hint() const; + void set_lightmap_size_hint(const Size2i &p_size); + Size2i get_lightmap_size_hint() const; void clear_cache() const; - typedef Vector<Vector<Face3> > (*ConvexDecompositionFunc)(const Vector<Face3> &); + typedef Vector<Vector<Face3>> (*ConvexDecompositionFunc)(const Vector<Face3> &); static ConvexDecompositionFunc convex_composition_function; - Vector<Ref<Shape> > convex_decompose() const; + Vector<Ref<Shape3D>> convex_decompose() const; Mesh(); }; class ArrayMesh : public Mesh { - GDCLASS(ArrayMesh, Mesh); RES_BASE_EXTENSION("mesh"); + Array _get_surfaces() const; + void _set_surfaces(const Array &p_data); + private: struct Surface { + uint32_t format; + int array_length; + int index_array_length; + PrimitiveType primitive; + String name; AABB aabb; Ref<Material> material; bool is_2d; }; Vector<Surface> surfaces; - RID mesh; + mutable RID mesh; AABB aabb; BlendShapeMode blend_shape_mode; Vector<StringName> blend_shapes; AABB custom_aabb; + _FORCE_INLINE_ void _create_if_empty() const; void _recompute_aabb(); protected: @@ -186,53 +190,55 @@ protected: static void _bind_methods(); public: - void add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), uint32_t p_flags = ARRAY_COMPRESS_DEFAULT); - void add_surface(uint32_t p_format, PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes = Vector<PoolVector<uint8_t> >(), const Vector<AABB> &p_bone_aabbs = Vector<AABB>()); + void add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_flags = ARRAY_COMPRESS_DEFAULT); - Array surface_get_arrays(int p_surface) const; - Array surface_get_blend_shape_arrays(int p_surface) const; + void add_surface(uint32_t p_format, PrimitiveType p_primitive, const Vector<uint8_t> &p_array, int p_vertex_count, const Vector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<Vector<uint8_t>> &p_blend_shapes = Vector<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; + Dictionary surface_get_lods(int p_surface) const override; void add_blend_shape(const StringName &p_name); - int get_blend_shape_count() const; - StringName get_blend_shape_name(int p_index) const; + int get_blend_shape_count() const override; + StringName get_blend_shape_name(int p_index) const override; void clear_blend_shapes(); void set_blend_shape_mode(BlendShapeMode p_mode); BlendShapeMode get_blend_shape_mode() const; - void surface_update_region(int p_surface, int p_offset, const PoolVector<uint8_t> &p_data); + void surface_update_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data); + + int get_surface_count() const override; - int get_surface_count() const; - void surface_remove(int p_idx); + void clear_surfaces(); void surface_set_custom_aabb(int p_idx, const AABB &p_aabb); //only recognized by driver - int surface_get_array_len(int p_idx) const; - int surface_get_array_index_len(int p_idx) const; - uint32_t surface_get_format(int p_idx) const; - PrimitiveType surface_get_primitive_type(int p_idx) const; + int surface_get_array_len(int p_idx) const override; + int surface_get_array_index_len(int p_idx) const override; + uint32_t surface_get_format(int p_idx) const override; + PrimitiveType surface_get_primitive_type(int p_idx) const override; bool surface_is_alpha_sorting_enabled(int p_idx) const; - virtual void surface_set_material(int p_idx, const Ref<Material> &p_material); - virtual Ref<Material> surface_get_material(int p_idx) const; + virtual void surface_set_material(int p_idx, const Ref<Material> &p_material) override; + virtual Ref<Material> surface_get_material(int p_idx) const override; int surface_find_by_name(const String &p_name) const; void surface_set_name(int p_idx, const String &p_name); String surface_get_name(int p_idx) const; - void add_surface_from_mesh_data(const Geometry::MeshData &p_mesh_data); - void set_custom_aabb(const AABB &p_custom); AABB get_custom_aabb() const; - AABB get_aabb() const; - virtual RID get_rid() const; + AABB get_aabb() const override; + virtual RID get_rid() const override; void regen_normalmaps(); Error lightmap_unwrap(const Transform &p_base_transform = Transform(), float p_texel_size = 0.05); + Error lightmap_unwrap_cached(int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache, const Transform &p_base_transform = Transform(), float p_texel_size = 0.05); - virtual void reload_from_file(); + virtual void reload_from_file() override; ArrayMesh(); diff --git a/scene/resources/mesh_data_tool.cpp b/scene/resources/mesh_data_tool.cpp index 7a303443e3..a5c360f123 100644 --- a/scene/resources/mesh_data_tool.cpp +++ b/scene/resources/mesh_data_tool.cpp @@ -31,7 +31,6 @@ #include "mesh_data_tool.h" void MeshDataTool::clear() { - vertices.clear(); edges.clear(); faces.clear(); @@ -40,14 +39,13 @@ void MeshDataTool::clear() { } Error MeshDataTool::create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surface) { - ERR_FAIL_COND_V(p_mesh.is_null(), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_mesh->surface_get_primitive_type(p_surface) != Mesh::PRIMITIVE_TRIANGLES, ERR_INVALID_PARAMETER); Array arrays = p_mesh->surface_get_arrays(p_surface); ERR_FAIL_COND_V(arrays.empty(), ERR_INVALID_PARAMETER); - PoolVector<Vector3> varray = arrays[Mesh::ARRAY_VERTEX]; + Vector<Vector3> varray = arrays[Mesh::ARRAY_VERTEX]; int vcount = varray.size(); ERR_FAIL_COND_V(vcount == 0, ERR_INVALID_PARAMETER); @@ -56,62 +54,71 @@ Error MeshDataTool::create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surf format = p_mesh->surface_get_format(p_surface); material = p_mesh->surface_get_material(p_surface); - PoolVector<Vector3>::Read vr = varray.read(); + const Vector3 *vr = varray.ptr(); - PoolVector<Vector3>::Read nr; - if (arrays[Mesh::ARRAY_NORMAL].get_type() != Variant::NIL) - nr = arrays[Mesh::ARRAY_NORMAL].operator PoolVector<Vector3>().read(); + const Vector3 *nr = nullptr; + if (arrays[Mesh::ARRAY_NORMAL].get_type() != Variant::NIL) { + nr = arrays[Mesh::ARRAY_NORMAL].operator Vector<Vector3>().ptr(); + } - PoolVector<real_t>::Read ta; - if (arrays[Mesh::ARRAY_TANGENT].get_type() != Variant::NIL) - ta = arrays[Mesh::ARRAY_TANGENT].operator PoolVector<real_t>().read(); + const real_t *ta = nullptr; + if (arrays[Mesh::ARRAY_TANGENT].get_type() != Variant::NIL) { + ta = arrays[Mesh::ARRAY_TANGENT].operator Vector<real_t>().ptr(); + } - PoolVector<Vector2>::Read uv; - if (arrays[Mesh::ARRAY_TEX_UV].get_type() != Variant::NIL) - uv = arrays[Mesh::ARRAY_TEX_UV].operator PoolVector<Vector2>().read(); - PoolVector<Vector2>::Read uv2; - if (arrays[Mesh::ARRAY_TEX_UV2].get_type() != Variant::NIL) - uv2 = arrays[Mesh::ARRAY_TEX_UV2].operator PoolVector<Vector2>().read(); + const Vector2 *uv = nullptr; + if (arrays[Mesh::ARRAY_TEX_UV].get_type() != Variant::NIL) { + uv = arrays[Mesh::ARRAY_TEX_UV].operator Vector<Vector2>().ptr(); + } + const Vector2 *uv2 = nullptr; + if (arrays[Mesh::ARRAY_TEX_UV2].get_type() != Variant::NIL) { + uv2 = arrays[Mesh::ARRAY_TEX_UV2].operator Vector<Vector2>().ptr(); + } - PoolVector<Color>::Read col; - if (arrays[Mesh::ARRAY_COLOR].get_type() != Variant::NIL) - col = arrays[Mesh::ARRAY_COLOR].operator PoolVector<Color>().read(); + const Color *col = nullptr; + if (arrays[Mesh::ARRAY_COLOR].get_type() != Variant::NIL) { + col = arrays[Mesh::ARRAY_COLOR].operator Vector<Color>().ptr(); + } - PoolVector<int>::Read bo; - if (arrays[Mesh::ARRAY_BONES].get_type() != Variant::NIL) - bo = arrays[Mesh::ARRAY_BONES].operator PoolVector<int>().read(); + const int *bo = nullptr; + if (arrays[Mesh::ARRAY_BONES].get_type() != Variant::NIL) { + bo = arrays[Mesh::ARRAY_BONES].operator Vector<int>().ptr(); + } - PoolVector<real_t>::Read we; - if (arrays[Mesh::ARRAY_WEIGHTS].get_type() != Variant::NIL) - we = arrays[Mesh::ARRAY_WEIGHTS].operator PoolVector<real_t>().read(); + const real_t *we = nullptr; + if (arrays[Mesh::ARRAY_WEIGHTS].get_type() != Variant::NIL) { + we = arrays[Mesh::ARRAY_WEIGHTS].operator Vector<real_t>().ptr(); + } vertices.resize(vcount); for (int i = 0; i < vcount; i++) { - Vertex v; v.vertex = vr[i]; - if (nr.ptr()) + if (nr) { v.normal = nr[i]; - if (ta.ptr()) + } + if (ta) { v.tangent = Plane(ta[i * 4 + 0], ta[i * 4 + 1], ta[i * 4 + 2], ta[i * 4 + 3]); - if (uv.ptr()) + } + if (uv) { v.uv = uv[i]; - if (uv2.ptr()) + } + if (uv2) { v.uv2 = uv2[i]; - if (col.ptr()) + } + if (col) { v.color = col[i]; + } - if (we.ptr()) { - + if (we) { v.weights.push_back(we[i * 4 + 0]); v.weights.push_back(we[i * 4 + 1]); v.weights.push_back(we[i * 4 + 2]); v.weights.push_back(we[i * 4 + 3]); } - if (bo.ptr()) { - + if (bo) { v.bones.push_back(bo[i * 4 + 0]); v.bones.push_back(bo[i * 4 + 1]); v.bones.push_back(bo[i * 4 + 2]); @@ -121,33 +128,31 @@ Error MeshDataTool::create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surf vertices.write[i] = v; } - PoolVector<int> indices; + Vector<int> indices; if (arrays[Mesh::ARRAY_INDEX].get_type() != Variant::NIL) { - indices = arrays[Mesh::ARRAY_INDEX]; } else { //make code simpler indices.resize(vcount); - PoolVector<int>::Write iw = indices.write(); - for (int i = 0; i < vcount; i++) + int *iw = indices.ptrw(); + for (int i = 0; i < vcount; i++) { iw[i] = i; + } } int icount = indices.size(); - PoolVector<int>::Read r = indices.read(); + const int *r = indices.ptr(); Map<Point2i, int> edge_indices; for (int i = 0; i < icount; i += 3) { - Vertex *v[3] = { &vertices.write[r[i + 0]], &vertices.write[r[i + 1]], &vertices.write[r[i + 2]] }; int fidx = faces.size(); Face face; for (int j = 0; j < 3; j++) { - face.v[j] = r[i + j]; Point2i edge(r[i + j], r[i + (j + 1) % 3]); @@ -180,100 +185,99 @@ Error MeshDataTool::create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surf } Error MeshDataTool::commit_to_surface(const Ref<ArrayMesh> &p_mesh) { - ERR_FAIL_COND_V(p_mesh.is_null(), ERR_INVALID_PARAMETER); Array arr; arr.resize(Mesh::ARRAY_MAX); int vcount = vertices.size(); - PoolVector<Vector3> v; - PoolVector<Vector3> n; - PoolVector<real_t> t; - PoolVector<Vector2> u; - PoolVector<Vector2> u2; - PoolVector<Color> c; - PoolVector<int> b; - PoolVector<real_t> w; - PoolVector<int> in; + Vector<Vector3> v; + Vector<Vector3> n; + Vector<real_t> t; + Vector<Vector2> u; + Vector<Vector2> u2; + Vector<Color> c; + Vector<int> b; + Vector<real_t> w; + Vector<int> in; { - v.resize(vcount); - PoolVector<Vector3>::Write vr = v.write(); + Vector3 *vr = v.ptrw(); - PoolVector<Vector3>::Write nr; + Vector3 *nr = nullptr; if (format & Mesh::ARRAY_FORMAT_NORMAL) { n.resize(vcount); - nr = n.write(); + nr = n.ptrw(); } - PoolVector<real_t>::Write ta; + real_t *ta = nullptr; if (format & Mesh::ARRAY_FORMAT_TANGENT) { t.resize(vcount * 4); - ta = t.write(); + ta = t.ptrw(); } - PoolVector<Vector2>::Write uv; + Vector2 *uv = nullptr; if (format & Mesh::ARRAY_FORMAT_TEX_UV) { u.resize(vcount); - uv = u.write(); + uv = u.ptrw(); } - PoolVector<Vector2>::Write uv2; + Vector2 *uv2 = nullptr; if (format & Mesh::ARRAY_FORMAT_TEX_UV2) { u2.resize(vcount); - uv2 = u2.write(); + uv2 = u2.ptrw(); } - PoolVector<Color>::Write col; + Color *col = nullptr; if (format & Mesh::ARRAY_FORMAT_COLOR) { c.resize(vcount); - col = c.write(); + col = c.ptrw(); } - PoolVector<int>::Write bo; + int *bo = nullptr; if (format & Mesh::ARRAY_FORMAT_BONES) { b.resize(vcount * 4); - bo = b.write(); + bo = b.ptrw(); } - PoolVector<real_t>::Write we; + real_t *we = nullptr; if (format & Mesh::ARRAY_FORMAT_WEIGHTS) { w.resize(vcount * 4); - we = w.write(); + we = w.ptrw(); } for (int i = 0; i < vcount; i++) { - const Vertex &vtx = vertices[i]; vr[i] = vtx.vertex; - if (nr.ptr()) + if (nr) { nr[i] = vtx.normal; - if (ta.ptr()) { + } + if (ta) { ta[i * 4 + 0] = vtx.tangent.normal.x; ta[i * 4 + 1] = vtx.tangent.normal.y; ta[i * 4 + 2] = vtx.tangent.normal.z; ta[i * 4 + 3] = vtx.tangent.d; } - if (uv.ptr()) + if (uv) { uv[i] = vtx.uv; - if (uv2.ptr()) + } + if (uv2) { uv2[i] = vtx.uv2; - if (col.ptr()) + } + if (col) { col[i] = vtx.color; + } - if (we.ptr()) { - + if (we) { we[i * 4 + 0] = vtx.weights[0]; we[i * 4 + 1] = vtx.weights[1]; we[i * 4 + 2] = vtx.weights[2]; we[i * 4 + 3] = vtx.weights[3]; } - if (bo.ptr()) { - + if (bo) { bo[i * 4 + 0] = vtx.bones[0]; bo[i * 4 + 1] = vtx.bones[1]; bo[i * 4 + 2] = vtx.bones[2]; @@ -283,9 +287,8 @@ Error MeshDataTool::commit_to_surface(const Ref<ArrayMesh> &p_mesh) { int fc = faces.size(); in.resize(fc * 3); - PoolVector<int>::Write iw = in.write(); + int *iw = in.ptrw(); for (int i = 0; i < fc; i++) { - iw[i * 3 + 0] = faces[i].v[0]; iw[i * 3 + 1] = faces[i].v[1]; iw[i * 3 + 2] = faces[i].v[2]; @@ -294,20 +297,27 @@ Error MeshDataTool::commit_to_surface(const Ref<ArrayMesh> &p_mesh) { arr[Mesh::ARRAY_VERTEX] = v; arr[Mesh::ARRAY_INDEX] = in; - if (n.size()) + if (n.size()) { arr[Mesh::ARRAY_NORMAL] = n; - if (c.size()) + } + if (c.size()) { arr[Mesh::ARRAY_COLOR] = c; - if (u.size()) + } + if (u.size()) { arr[Mesh::ARRAY_TEX_UV] = u; - if (u2.size()) + } + if (u2.size()) { arr[Mesh::ARRAY_TEX_UV2] = u2; - if (t.size()) + } + if (t.size()) { arr[Mesh::ARRAY_TANGENT] = t; - if (b.size()) + } + if (b.size()) { arr[Mesh::ARRAY_BONES] = b; - if (w.size()) + } + if (w.size()) { arr[Mesh::ARRAY_WEIGHTS] = w; + } Ref<ArrayMesh> ncmesh = p_mesh; int sc = ncmesh->get_surface_count(); @@ -318,111 +328,102 @@ Error MeshDataTool::commit_to_surface(const Ref<ArrayMesh> &p_mesh) { } int MeshDataTool::get_format() const { - return format; } int MeshDataTool::get_vertex_count() const { - return vertices.size(); } -int MeshDataTool::get_edge_count() const { +int MeshDataTool::get_edge_count() const { return edges.size(); } -int MeshDataTool::get_face_count() const { +int MeshDataTool::get_face_count() const { return faces.size(); } Vector3 MeshDataTool::get_vertex(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, vertices.size(), Vector3()); return vertices[p_idx].vertex; } -void MeshDataTool::set_vertex(int p_idx, const Vector3 &p_vertex) { +void MeshDataTool::set_vertex(int p_idx, const Vector3 &p_vertex) { ERR_FAIL_INDEX(p_idx, vertices.size()); vertices.write[p_idx].vertex = p_vertex; } Vector3 MeshDataTool::get_vertex_normal(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, vertices.size(), Vector3()); return vertices[p_idx].normal; } -void MeshDataTool::set_vertex_normal(int p_idx, const Vector3 &p_normal) { +void MeshDataTool::set_vertex_normal(int p_idx, const Vector3 &p_normal) { ERR_FAIL_INDEX(p_idx, vertices.size()); vertices.write[p_idx].normal = p_normal; format |= Mesh::ARRAY_FORMAT_NORMAL; } Plane MeshDataTool::get_vertex_tangent(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, vertices.size(), Plane()); return vertices[p_idx].tangent; } -void MeshDataTool::set_vertex_tangent(int p_idx, const Plane &p_tangent) { +void MeshDataTool::set_vertex_tangent(int p_idx, const Plane &p_tangent) { ERR_FAIL_INDEX(p_idx, vertices.size()); vertices.write[p_idx].tangent = p_tangent; format |= Mesh::ARRAY_FORMAT_TANGENT; } Vector2 MeshDataTool::get_vertex_uv(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, vertices.size(), Vector2()); return vertices[p_idx].uv; } -void MeshDataTool::set_vertex_uv(int p_idx, const Vector2 &p_uv) { +void MeshDataTool::set_vertex_uv(int p_idx, const Vector2 &p_uv) { ERR_FAIL_INDEX(p_idx, vertices.size()); vertices.write[p_idx].uv = p_uv; format |= Mesh::ARRAY_FORMAT_TEX_UV; } Vector2 MeshDataTool::get_vertex_uv2(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, vertices.size(), Vector2()); return vertices[p_idx].uv2; } -void MeshDataTool::set_vertex_uv2(int p_idx, const Vector2 &p_uv2) { +void MeshDataTool::set_vertex_uv2(int p_idx, const Vector2 &p_uv2) { ERR_FAIL_INDEX(p_idx, vertices.size()); vertices.write[p_idx].uv2 = p_uv2; format |= Mesh::ARRAY_FORMAT_TEX_UV2; } Color MeshDataTool::get_vertex_color(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, vertices.size(), Color()); return vertices[p_idx].color; } -void MeshDataTool::set_vertex_color(int p_idx, const Color &p_color) { +void MeshDataTool::set_vertex_color(int p_idx, const Color &p_color) { ERR_FAIL_INDEX(p_idx, vertices.size()); vertices.write[p_idx].color = p_color; format |= Mesh::ARRAY_FORMAT_COLOR; } Vector<int> MeshDataTool::get_vertex_bones(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, vertices.size(), Vector<int>()); return vertices[p_idx].bones; } -void MeshDataTool::set_vertex_bones(int p_idx, const Vector<int> &p_bones) { +void MeshDataTool::set_vertex_bones(int p_idx, const Vector<int> &p_bones) { ERR_FAIL_INDEX(p_idx, vertices.size()); vertices.write[p_idx].bones = p_bones; format |= Mesh::ARRAY_FORMAT_BONES; } Vector<float> MeshDataTool::get_vertex_weights(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, vertices.size(), Vector<float>()); return vertices[p_idx].weights; } + void MeshDataTool::set_vertex_weights(int p_idx, const Vector<float> &p_weights) { ERR_FAIL_INDEX(p_idx, vertices.size()); vertices.write[p_idx].weights = p_weights; @@ -430,75 +431,69 @@ void MeshDataTool::set_vertex_weights(int p_idx, const Vector<float> &p_weights) } Variant MeshDataTool::get_vertex_meta(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, vertices.size(), Variant()); return vertices[p_idx].meta; } void MeshDataTool::set_vertex_meta(int p_idx, const Variant &p_meta) { - ERR_FAIL_INDEX(p_idx, vertices.size()); vertices.write[p_idx].meta = p_meta; } Vector<int> MeshDataTool::get_vertex_edges(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, vertices.size(), Vector<int>()); return vertices[p_idx].edges; } -Vector<int> MeshDataTool::get_vertex_faces(int p_idx) const { +Vector<int> MeshDataTool::get_vertex_faces(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, vertices.size(), Vector<int>()); return vertices[p_idx].faces; } int MeshDataTool::get_edge_vertex(int p_edge, int p_vertex) const { - ERR_FAIL_INDEX_V(p_edge, edges.size(), -1); ERR_FAIL_INDEX_V(p_vertex, 2, -1); return edges[p_edge].vertex[p_vertex]; } -Vector<int> MeshDataTool::get_edge_faces(int p_edge) const { +Vector<int> MeshDataTool::get_edge_faces(int p_edge) const { ERR_FAIL_INDEX_V(p_edge, edges.size(), Vector<int>()); return edges[p_edge].faces; } -Variant MeshDataTool::get_edge_meta(int p_idx) const { +Variant MeshDataTool::get_edge_meta(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, edges.size(), Variant()); return edges[p_idx].meta; } -void MeshDataTool::set_edge_meta(int p_idx, const Variant &p_meta) { +void MeshDataTool::set_edge_meta(int p_idx, const Variant &p_meta) { ERR_FAIL_INDEX(p_idx, edges.size()); edges.write[p_idx].meta = p_meta; } int MeshDataTool::get_face_vertex(int p_face, int p_vertex) const { - ERR_FAIL_INDEX_V(p_face, faces.size(), -1); ERR_FAIL_INDEX_V(p_vertex, 3, -1); return faces[p_face].v[p_vertex]; } -int MeshDataTool::get_face_edge(int p_face, int p_vertex) const { +int MeshDataTool::get_face_edge(int p_face, int p_vertex) const { ERR_FAIL_INDEX_V(p_face, faces.size(), -1); ERR_FAIL_INDEX_V(p_vertex, 3, -1); return faces[p_face].edges[p_vertex]; } -Variant MeshDataTool::get_face_meta(int p_face) const { +Variant MeshDataTool::get_face_meta(int p_face) const { ERR_FAIL_INDEX_V(p_face, faces.size(), Variant()); return faces[p_face].meta; } -void MeshDataTool::set_face_meta(int p_face, const Variant &p_meta) { +void MeshDataTool::set_face_meta(int p_face, const Variant &p_meta) { ERR_FAIL_INDEX(p_face, faces.size()); faces.write[p_face].meta = p_meta; } Vector3 MeshDataTool::get_face_normal(int p_face) const { - ERR_FAIL_INDEX_V(p_face, faces.size(), Vector3()); Vector3 v0 = vertices[faces[p_face].v[0]].vertex; Vector3 v1 = vertices[faces[p_face].v[1]].vertex; @@ -508,17 +503,14 @@ Vector3 MeshDataTool::get_face_normal(int p_face) const { } Ref<Material> MeshDataTool::get_material() const { - return material; } void MeshDataTool::set_material(const Ref<Material> &p_material) { - material = p_material; } void MeshDataTool::_bind_methods() { - ClassDB::bind_method(D_METHOD("clear"), &MeshDataTool::clear); ClassDB::bind_method(D_METHOD("create_from_surface", "mesh", "surface"), &MeshDataTool::create_from_surface); ClassDB::bind_method(D_METHOD("commit_to_surface", "mesh"), &MeshDataTool::commit_to_surface); @@ -578,6 +570,5 @@ void MeshDataTool::_bind_methods() { } MeshDataTool::MeshDataTool() { - clear(); } diff --git a/scene/resources/mesh_data_tool.h b/scene/resources/mesh_data_tool.h index 5ac2c7e702..bf9f0dd25f 100644 --- a/scene/resources/mesh_data_tool.h +++ b/scene/resources/mesh_data_tool.h @@ -34,7 +34,6 @@ #include "scene/resources/mesh.h" class MeshDataTool : public Reference { - GDCLASS(MeshDataTool, Reference); int format; @@ -55,7 +54,6 @@ class MeshDataTool : public Reference { Vector<Vertex> vertices; struct Edge { - int vertex[2]; Vector<int> faces; Variant meta; @@ -64,7 +62,6 @@ class MeshDataTool : public Reference { Vector<Edge> edges; struct Face { - int v[3]; int edges[3]; Variant meta; diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp index 754cad4def..09b0d4b038 100644 --- a/scene/resources/mesh_library.cpp +++ b/scene/resources/mesh_library.cpp @@ -29,23 +29,21 @@ /*************************************************************************/ #include "mesh_library.h" -#include "core/engine.h" bool MeshLibrary::_set(const StringName &p_name, const Variant &p_value) { - String name = p_name; if (name.begins_with("item/")) { - int idx = name.get_slicec('/', 1).to_int(); String what = name.get_slicec('/', 2); - if (!item_map.has(idx)) + if (!item_map.has(idx)) { create_item(idx); + } - if (what == "name") + if (what == "name") { set_item_name(idx, p_value); - else if (what == "mesh") + } else if (what == "mesh") { set_item_mesh(idx, p_value); - else if (what == "shape") { + } else if (what == "shape") { Vector<ShapeData> shapes; ShapeData sd; sd.shape = p_value; @@ -53,14 +51,15 @@ bool MeshLibrary::_set(const StringName &p_name, const Variant &p_value) { set_item_shapes(idx, shapes); } else if (what == "shapes") { _set_item_shapes(idx, p_value); - } else if (what == "preview") + } else if (what == "preview") { set_item_preview(idx, p_value); - else if (what == "navmesh") + } else if (what == "navmesh") { set_item_navmesh(idx, p_value); - else if (what == "navmesh_transform") + } else if (what == "navmesh_transform") { set_item_navmesh_transform(idx, p_value); - else + } else { return false; + } return true; } @@ -69,34 +68,32 @@ bool MeshLibrary::_set(const StringName &p_name, const Variant &p_value) { } bool MeshLibrary::_get(const StringName &p_name, Variant &r_ret) const { - String name = p_name; int idx = name.get_slicec('/', 1).to_int(); ERR_FAIL_COND_V(!item_map.has(idx), false); String what = name.get_slicec('/', 2); - if (what == "name") + if (what == "name") { r_ret = get_item_name(idx); - else if (what == "mesh") + } else if (what == "mesh") { r_ret = get_item_mesh(idx); - else if (what == "shapes") + } else if (what == "shapes") { r_ret = _get_item_shapes(idx); - else if (what == "navmesh") + } else if (what == "navmesh") { r_ret = get_item_navmesh(idx); - else if (what == "navmesh_transform") + } else if (what == "navmesh_transform") { r_ret = get_item_navmesh_transform(idx); - else if (what == "preview") + } else if (what == "preview") { r_ret = get_item_preview(idx); - else + } else { return false; + } return true; } void MeshLibrary::_get_property_list(List<PropertyInfo> *p_list) const { - for (Map<int, Item>::Element *E = item_map.front(); E; E = E->next()) { - String name = "item/" + itos(E->key()) + "/"; p_list->push_back(PropertyInfo(Variant::STRING, name + "name")); p_list->push_back(PropertyInfo(Variant::OBJECT, name + "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh")); @@ -104,12 +101,11 @@ void MeshLibrary::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::ARRAY, name + "shapes")); p_list->push_back(PropertyInfo(Variant::OBJECT, name + "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh")); p_list->push_back(PropertyInfo(Variant::TRANSFORM, name + "navmesh_transform")); - p_list->push_back(PropertyInfo(Variant::OBJECT, name + "preview", PROPERTY_HINT_RESOURCE_TYPE, "Texture", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_HELPER)); + p_list->push_back(PropertyInfo(Variant::OBJECT, name + "preview", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_HELPER)); } } void MeshLibrary::create_item(int p_item) { - ERR_FAIL_COND(p_item < 0); ERR_FAIL_COND(item_map.has(p_item)); item_map[p_item] = Item(); @@ -117,7 +113,6 @@ void MeshLibrary::create_item(int p_item) { } void MeshLibrary::set_item_name(int p_item, const String &p_name) { - ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); item_map[p_item].name = p_name; emit_changed(); @@ -125,7 +120,6 @@ void MeshLibrary::set_item_name(int p_item, const String &p_name) { } void MeshLibrary::set_item_mesh(int p_item, const Ref<Mesh> &p_mesh) { - ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); item_map[p_item].mesh = p_mesh; notify_change_to_owners(); @@ -134,7 +128,6 @@ void MeshLibrary::set_item_mesh(int p_item, const Ref<Mesh> &p_mesh) { } void MeshLibrary::set_item_shapes(int p_item, const Vector<ShapeData> &p_shapes) { - ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); item_map[p_item].shapes = p_shapes; _change_notify(); @@ -144,7 +137,6 @@ void MeshLibrary::set_item_shapes(int p_item, const Vector<ShapeData> &p_shapes) } void MeshLibrary::set_item_navmesh(int p_item, const Ref<NavigationMesh> &p_navmesh) { - ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); item_map[p_item].navmesh = p_navmesh; _change_notify(); @@ -154,7 +146,6 @@ void MeshLibrary::set_item_navmesh(int p_item, const Ref<NavigationMesh> &p_navm } void MeshLibrary::set_item_navmesh_transform(int p_item, const Transform &p_transform) { - ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); item_map[p_item].navmesh_transform = p_transform; notify_change_to_owners(); @@ -162,8 +153,7 @@ void MeshLibrary::set_item_navmesh_transform(int p_item, const Transform &p_tran _change_notify(); } -void MeshLibrary::set_item_preview(int p_item, const Ref<Texture> &p_preview) { - +void MeshLibrary::set_item_preview(int p_item, const Ref<Texture2D> &p_preview) { ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); item_map[p_item].preview = p_preview; emit_changed(); @@ -171,52 +161,40 @@ void MeshLibrary::set_item_preview(int p_item, const Ref<Texture> &p_preview) { } String MeshLibrary::get_item_name(int p_item) const { - ERR_FAIL_COND_V_MSG(!item_map.has(p_item), "", "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); return item_map[p_item].name; } Ref<Mesh> MeshLibrary::get_item_mesh(int p_item) const { - ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Ref<Mesh>(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); return item_map[p_item].mesh; } Vector<MeshLibrary::ShapeData> MeshLibrary::get_item_shapes(int p_item) const { - ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Vector<ShapeData>(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); return item_map[p_item].shapes; } Ref<NavigationMesh> MeshLibrary::get_item_navmesh(int p_item) const { - ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Ref<NavigationMesh>(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); return item_map[p_item].navmesh; } Transform MeshLibrary::get_item_navmesh_transform(int p_item) const { - ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Transform(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); return item_map[p_item].navmesh_transform; } -Ref<Texture> MeshLibrary::get_item_preview(int p_item) const { - - if (!Engine::get_singleton()->is_editor_hint()) { - ERR_PRINT("MeshLibrary item previews are only generated in an editor context, which means they aren't available in a running project."); - return Ref<Texture>(); - } - - ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Ref<Texture>(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); +Ref<Texture2D> MeshLibrary::get_item_preview(int p_item) const { + ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Ref<Texture2D>(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); return item_map[p_item].preview; } bool MeshLibrary::has_item(int p_item) const { - return item_map.has(p_item); } -void MeshLibrary::remove_item(int p_item) { +void MeshLibrary::remove_item(int p_item) { ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); item_map.erase(p_item); notify_change_to_owners(); @@ -225,7 +203,6 @@ void MeshLibrary::remove_item(int p_item) { } void MeshLibrary::clear() { - item_map.clear(); notify_change_to_owners(); _change_notify(); @@ -233,12 +210,10 @@ void MeshLibrary::clear() { } Vector<int> MeshLibrary::get_item_list() const { - Vector<int> ret; ret.resize(item_map.size()); int idx = 0; for (Map<int, Item>::Element *E = item_map.front(); E; E = E->next()) { - ret.write[idx++] = E->key(); } @@ -246,25 +221,23 @@ Vector<int> MeshLibrary::get_item_list() const { } int MeshLibrary::find_item_by_name(const String &p_name) const { - for (Map<int, Item>::Element *E = item_map.front(); E; E = E->next()) { - - if (E->get().name == p_name) + if (E->get().name == p_name) { return E->key(); + } } return -1; } int MeshLibrary::get_last_unused_item_id() const { - - if (!item_map.size()) + if (!item_map.size()) { return 0; - else + } else { return item_map.back()->key() + 1; + } } void MeshLibrary::_set_item_shapes(int p_item, const Array &p_shapes) { - ERR_FAIL_COND(p_shapes.size() & 1); Vector<ShapeData> shapes; for (int i = 0; i < p_shapes.size(); i += 2) { @@ -281,7 +254,6 @@ void MeshLibrary::_set_item_shapes(int p_item, const Array &p_shapes) { } Array MeshLibrary::_get_item_shapes(int p_item) const { - Vector<ShapeData> shapes = get_item_shapes(p_item); Array ret; for (int i = 0; i < shapes.size(); i++) { @@ -293,7 +265,6 @@ Array MeshLibrary::_get_item_shapes(int p_item) const { } void MeshLibrary::_bind_methods() { - ClassDB::bind_method(D_METHOD("create_item", "id"), &MeshLibrary::create_item); ClassDB::bind_method(D_METHOD("set_item_name", "id", "name"), &MeshLibrary::set_item_name); ClassDB::bind_method(D_METHOD("set_item_mesh", "id", "mesh"), &MeshLibrary::set_item_mesh); @@ -317,5 +288,6 @@ void MeshLibrary::_bind_methods() { MeshLibrary::MeshLibrary() { } + MeshLibrary::~MeshLibrary() { } diff --git a/scene/resources/mesh_library.h b/scene/resources/mesh_library.h index 471db74175..450e2c16e3 100644 --- a/scene/resources/mesh_library.h +++ b/scene/resources/mesh_library.h @@ -28,30 +28,29 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GRID_THEME_H -#define GRID_THEME_H +#ifndef MESH_LIBRARY_H +#define MESH_LIBRARY_H #include "core/map.h" #include "core/resource.h" #include "mesh.h" -#include "scene/3d/navigation_mesh.h" -#include "shape.h" +#include "scene/3d/navigation_region_3d.h" +#include "shape_3d.h" class MeshLibrary : public Resource { - GDCLASS(MeshLibrary, Resource); RES_BASE_EXTENSION("meshlib"); public: struct ShapeData { - Ref<Shape> shape; + Ref<Shape3D> shape; Transform local_transform; }; struct Item { String name; Ref<Mesh> mesh; Vector<ShapeData> shapes; - Ref<Texture> preview; + Ref<Texture2D> preview; Transform navmesh_transform; Ref<NavigationMesh> navmesh; }; @@ -75,13 +74,13 @@ public: void set_item_navmesh(int p_item, const Ref<NavigationMesh> &p_navmesh); void set_item_navmesh_transform(int p_item, const Transform &p_transform); void set_item_shapes(int p_item, const Vector<ShapeData> &p_shapes); - void set_item_preview(int p_item, const Ref<Texture> &p_preview); + void set_item_preview(int p_item, const Ref<Texture2D> &p_preview); String get_item_name(int p_item) const; Ref<Mesh> get_item_mesh(int p_item) const; Ref<NavigationMesh> get_item_navmesh(int p_item) const; Transform get_item_navmesh_transform(int p_item) const; Vector<ShapeData> get_item_shapes(int p_item) const; - Ref<Texture> get_item_preview(int p_item) const; + Ref<Texture2D> get_item_preview(int p_item) const; void remove_item(int p_item); bool has_item(int p_item) const; @@ -97,4 +96,4 @@ public: ~MeshLibrary(); }; -#endif // CUBE_GRID_THEME_H +#endif // MESH_LIBRARY_H diff --git a/scene/resources/multimesh.cpp b/scene/resources/multimesh.cpp index ee831f36f5..f71cf383e5 100644 --- a/scene/resources/multimesh.cpp +++ b/scene/resources/multimesh.cpp @@ -29,22 +29,27 @@ /*************************************************************************/ #include "multimesh.h" -#include "servers/visual_server.h" -void MultiMesh::_set_transform_array(const PoolVector<Vector3> &p_array) { - if (transform_format != TRANSFORM_3D) +#include "servers/rendering_server.h" + +#ifndef DISABLE_DEPRECATED +// Kept for compatibility from 3.x to 4.0. + +void MultiMesh::_set_transform_array(const Vector<Vector3> &p_array) { + if (transform_format != TRANSFORM_3D) { return; + } - const PoolVector<Vector3> &xforms = p_array; + const Vector<Vector3> &xforms = p_array; int len = xforms.size(); ERR_FAIL_COND((len / 4) != instance_count); - if (len == 0) + if (len == 0) { return; + } - PoolVector<Vector3>::Read r = xforms.read(); + const Vector3 *r = xforms.ptr(); for (int i = 0; i < len / 4; i++) { - Transform t; t.basis[0] = r[i * 4 + 0]; t.basis[1] = r[i * 4 + 1]; @@ -55,21 +60,21 @@ void MultiMesh::_set_transform_array(const PoolVector<Vector3> &p_array) { } } -PoolVector<Vector3> MultiMesh::_get_transform_array() const { - - if (transform_format != TRANSFORM_3D) - return PoolVector<Vector3>(); +Vector<Vector3> MultiMesh::_get_transform_array() const { + if (transform_format != TRANSFORM_3D) { + return Vector<Vector3>(); + } - if (instance_count == 0) - return PoolVector<Vector3>(); + if (instance_count == 0) { + return Vector<Vector3>(); + } - PoolVector<Vector3> xforms; + Vector<Vector3> xforms; xforms.resize(instance_count * 4); - PoolVector<Vector3>::Write w = xforms.write(); + Vector3 *w = xforms.ptrw(); for (int i = 0; i < instance_count; i++) { - Transform t = get_instance_transform(i); w[i * 4 + 0] = t.basis[0]; w[i * 4 + 1] = t.basis[1]; @@ -80,21 +85,21 @@ PoolVector<Vector3> MultiMesh::_get_transform_array() const { return xforms; } -void MultiMesh::_set_transform_2d_array(const PoolVector<Vector2> &p_array) { - - if (transform_format != TRANSFORM_2D) +void MultiMesh::_set_transform_2d_array(const Vector<Vector2> &p_array) { + if (transform_format != TRANSFORM_2D) { return; + } - const PoolVector<Vector2> &xforms = p_array; + const Vector<Vector2> &xforms = p_array; int len = xforms.size(); ERR_FAIL_COND((len / 3) != instance_count); - if (len == 0) + if (len == 0) { return; + } - PoolVector<Vector2>::Read r = xforms.read(); + const Vector2 *r = xforms.ptr(); for (int i = 0; i < len / 3; i++) { - Transform2D t; t.elements[0] = r[i * 3 + 0]; t.elements[1] = r[i * 3 + 1]; @@ -104,21 +109,21 @@ void MultiMesh::_set_transform_2d_array(const PoolVector<Vector2> &p_array) { } } -PoolVector<Vector2> MultiMesh::_get_transform_2d_array() const { - - if (transform_format != TRANSFORM_2D) - return PoolVector<Vector2>(); +Vector<Vector2> MultiMesh::_get_transform_2d_array() const { + if (transform_format != TRANSFORM_2D) { + return Vector<Vector2>(); + } - if (instance_count == 0) - return PoolVector<Vector2>(); + if (instance_count == 0) { + return Vector<Vector2>(); + } - PoolVector<Vector2> xforms; + Vector<Vector2> xforms; xforms.resize(instance_count * 3); - PoolVector<Vector2>::Write w = xforms.write(); + Vector2 *w = xforms.ptrw(); for (int i = 0; i < instance_count; i++) { - Transform2D t = get_instance_transform_2d(i); w[i * 3 + 0] = t.elements[0]; w[i * 3 + 1] = t.elements[1]; @@ -128,196 +133,183 @@ PoolVector<Vector2> MultiMesh::_get_transform_2d_array() const { return xforms; } -void MultiMesh::_set_color_array(const PoolVector<Color> &p_array) { - - const PoolVector<Color> &colors = p_array; +void MultiMesh::_set_color_array(const Vector<Color> &p_array) { + const Vector<Color> &colors = p_array; int len = colors.size(); - if (len == 0) + if (len == 0) { return; + } ERR_FAIL_COND(len != instance_count); - PoolVector<Color>::Read r = colors.read(); + const Color *r = colors.ptr(); for (int i = 0; i < len; i++) { - set_instance_color(i, r[i]); } } -PoolVector<Color> MultiMesh::_get_color_array() const { - - if (instance_count == 0 || color_format == COLOR_NONE) - return PoolVector<Color>(); +Vector<Color> MultiMesh::_get_color_array() const { + if (instance_count == 0 || !use_colors) { + return Vector<Color>(); + } - PoolVector<Color> colors; + Vector<Color> colors; colors.resize(instance_count); for (int i = 0; i < instance_count; i++) { - colors.set(i, get_instance_color(i)); } return colors; } -void MultiMesh::_set_custom_data_array(const PoolVector<Color> &p_array) { - - const PoolVector<Color> &custom_datas = p_array; +void MultiMesh::_set_custom_data_array(const Vector<Color> &p_array) { + const Vector<Color> &custom_datas = p_array; int len = custom_datas.size(); - if (len == 0) + if (len == 0) { return; + } ERR_FAIL_COND(len != instance_count); - PoolVector<Color>::Read r = custom_datas.read(); + const Color *r = custom_datas.ptr(); for (int i = 0; i < len; i++) { - set_instance_custom_data(i, r[i]); } } -PoolVector<Color> MultiMesh::_get_custom_data_array() const { - - if (instance_count == 0 || custom_data_format == CUSTOM_DATA_NONE) - return PoolVector<Color>(); +Vector<Color> MultiMesh::_get_custom_data_array() const { + if (instance_count == 0 || !use_custom_data) { + return Vector<Color>(); + } - PoolVector<Color> custom_datas; + Vector<Color> custom_datas; custom_datas.resize(instance_count); for (int i = 0; i < instance_count; i++) { - custom_datas.set(i, get_instance_custom_data(i)); } return custom_datas; } -void MultiMesh::set_mesh(const Ref<Mesh> &p_mesh) { +#endif // DISABLE_DEPRECATED +void MultiMesh::set_buffer(const Vector<float> &p_buffer) { + RS::get_singleton()->multimesh_set_buffer(multimesh, p_buffer); +} + +Vector<float> MultiMesh::get_buffer() const { + return RS::get_singleton()->multimesh_get_buffer(multimesh); +} + +void MultiMesh::set_mesh(const Ref<Mesh> &p_mesh) { mesh = p_mesh; - if (!mesh.is_null()) - VisualServer::get_singleton()->multimesh_set_mesh(multimesh, mesh->get_rid()); - else - VisualServer::get_singleton()->multimesh_set_mesh(multimesh, RID()); + if (!mesh.is_null()) { + RenderingServer::get_singleton()->multimesh_set_mesh(multimesh, mesh->get_rid()); + } else { + RenderingServer::get_singleton()->multimesh_set_mesh(multimesh, RID()); + } } Ref<Mesh> MultiMesh::get_mesh() const { - return mesh; } void MultiMesh::set_instance_count(int p_count) { ERR_FAIL_COND(p_count < 0); - VisualServer::get_singleton()->multimesh_allocate(multimesh, p_count, VS::MultimeshTransformFormat(transform_format), VS::MultimeshColorFormat(color_format), VS::MultimeshCustomDataFormat(custom_data_format)); + RenderingServer::get_singleton()->multimesh_allocate(multimesh, p_count, RS::MultimeshTransformFormat(transform_format), use_colors, use_custom_data); instance_count = p_count; } -int MultiMesh::get_instance_count() const { +int MultiMesh::get_instance_count() const { return instance_count; } void MultiMesh::set_visible_instance_count(int p_count) { ERR_FAIL_COND(p_count < -1); - VisualServer::get_singleton()->multimesh_set_visible_instances(multimesh, p_count); + ERR_FAIL_COND(p_count > instance_count); + RenderingServer::get_singleton()->multimesh_set_visible_instances(multimesh, p_count); visible_instance_count = p_count; } -int MultiMesh::get_visible_instance_count() const { +int MultiMesh::get_visible_instance_count() const { return visible_instance_count; } void MultiMesh::set_instance_transform(int p_instance, const Transform &p_transform) { - - VisualServer::get_singleton()->multimesh_instance_set_transform(multimesh, p_instance, p_transform); + RenderingServer::get_singleton()->multimesh_instance_set_transform(multimesh, p_instance, p_transform); } void MultiMesh::set_instance_transform_2d(int p_instance, const Transform2D &p_transform) { - - VisualServer::get_singleton()->multimesh_instance_set_transform_2d(multimesh, p_instance, p_transform); + RenderingServer::get_singleton()->multimesh_instance_set_transform_2d(multimesh, p_instance, p_transform); } Transform MultiMesh::get_instance_transform(int p_instance) const { - - return VisualServer::get_singleton()->multimesh_instance_get_transform(multimesh, p_instance); + return RenderingServer::get_singleton()->multimesh_instance_get_transform(multimesh, p_instance); } Transform2D MultiMesh::get_instance_transform_2d(int p_instance) const { - - return VisualServer::get_singleton()->multimesh_instance_get_transform_2d(multimesh, p_instance); + return RenderingServer::get_singleton()->multimesh_instance_get_transform_2d(multimesh, p_instance); } void MultiMesh::set_instance_color(int p_instance, const Color &p_color) { - - VisualServer::get_singleton()->multimesh_instance_set_color(multimesh, p_instance, p_color); + RenderingServer::get_singleton()->multimesh_instance_set_color(multimesh, p_instance, p_color); } -Color MultiMesh::get_instance_color(int p_instance) const { - return VisualServer::get_singleton()->multimesh_instance_get_color(multimesh, p_instance); +Color MultiMesh::get_instance_color(int p_instance) const { + return RenderingServer::get_singleton()->multimesh_instance_get_color(multimesh, p_instance); } void MultiMesh::set_instance_custom_data(int p_instance, const Color &p_custom_data) { - - VisualServer::get_singleton()->multimesh_instance_set_custom_data(multimesh, p_instance, p_custom_data); -} -Color MultiMesh::get_instance_custom_data(int p_instance) const { - - return VisualServer::get_singleton()->multimesh_instance_get_custom_data(multimesh, p_instance); + RenderingServer::get_singleton()->multimesh_instance_set_custom_data(multimesh, p_instance, p_custom_data); } -void MultiMesh::set_as_bulk_array(const PoolVector<float> &p_array) { - - VisualServer::get_singleton()->multimesh_set_as_bulk_array(multimesh, p_array); +Color MultiMesh::get_instance_custom_data(int p_instance) const { + return RenderingServer::get_singleton()->multimesh_instance_get_custom_data(multimesh, p_instance); } AABB MultiMesh::get_aabb() const { - - return VisualServer::get_singleton()->multimesh_get_aabb(multimesh); + return RenderingServer::get_singleton()->multimesh_get_aabb(multimesh); } RID MultiMesh::get_rid() const { - return multimesh; } -void MultiMesh::set_color_format(ColorFormat p_color_format) { - +void MultiMesh::set_use_colors(bool p_enable) { ERR_FAIL_COND(instance_count > 0); - color_format = p_color_format; + use_colors = p_enable; } -MultiMesh::ColorFormat MultiMesh::get_color_format() const { - - return color_format; +bool MultiMesh::is_using_colors() const { + return use_colors; } -void MultiMesh::set_custom_data_format(CustomDataFormat p_custom_data_format) { - +void MultiMesh::set_use_custom_data(bool p_enable) { ERR_FAIL_COND(instance_count > 0); - custom_data_format = p_custom_data_format; + use_custom_data = p_enable; } -MultiMesh::CustomDataFormat MultiMesh::get_custom_data_format() const { - - return custom_data_format; +bool MultiMesh::is_using_custom_data() const { + return use_custom_data; } void MultiMesh::set_transform_format(TransformFormat p_transform_format) { - ERR_FAIL_COND(instance_count > 0); transform_format = p_transform_format; } -MultiMesh::TransformFormat MultiMesh::get_transform_format() const { +MultiMesh::TransformFormat MultiMesh::get_transform_format() const { return transform_format; } void MultiMesh::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &MultiMesh::set_mesh); ClassDB::bind_method(D_METHOD("get_mesh"), &MultiMesh::get_mesh); - ClassDB::bind_method(D_METHOD("set_color_format", "format"), &MultiMesh::set_color_format); - ClassDB::bind_method(D_METHOD("get_color_format"), &MultiMesh::get_color_format); - ClassDB::bind_method(D_METHOD("set_custom_data_format", "format"), &MultiMesh::set_custom_data_format); - ClassDB::bind_method(D_METHOD("get_custom_data_format"), &MultiMesh::get_custom_data_format); + ClassDB::bind_method(D_METHOD("set_use_colors", "enable"), &MultiMesh::set_use_colors); + ClassDB::bind_method(D_METHOD("is_using_colors"), &MultiMesh::is_using_colors); + ClassDB::bind_method(D_METHOD("set_use_custom_data", "enable"), &MultiMesh::set_use_custom_data); + ClassDB::bind_method(D_METHOD("is_using_custom_data"), &MultiMesh::is_using_custom_data); ClassDB::bind_method(D_METHOD("set_transform_format", "format"), &MultiMesh::set_transform_format); ClassDB::bind_method(D_METHOD("get_transform_format"), &MultiMesh::get_transform_format); @@ -333,9 +325,21 @@ void MultiMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("get_instance_color", "instance"), &MultiMesh::get_instance_color); ClassDB::bind_method(D_METHOD("set_instance_custom_data", "instance", "custom_data"), &MultiMesh::set_instance_custom_data); ClassDB::bind_method(D_METHOD("get_instance_custom_data", "instance"), &MultiMesh::get_instance_custom_data); - ClassDB::bind_method(D_METHOD("set_as_bulk_array", "array"), &MultiMesh::set_as_bulk_array); ClassDB::bind_method(D_METHOD("get_aabb"), &MultiMesh::get_aabb); + ClassDB::bind_method(D_METHOD("get_buffer"), &MultiMesh::get_buffer); + ClassDB::bind_method(D_METHOD("set_buffer", "buffer"), &MultiMesh::set_buffer); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "transform_format", PROPERTY_HINT_ENUM, "2D,3D"), "set_transform_format", "get_transform_format"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_colors"), "set_use_colors", "is_using_colors"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_custom_data"), "set_use_custom_data", "is_using_custom_data"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "instance_count", PROPERTY_HINT_RANGE, "0,16384,1,or_greater"), "set_instance_count", "get_instance_count"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_instance_count", PROPERTY_HINT_RANGE, "-1,16384,1,or_greater"), "set_visible_instance_count", "get_visible_instance_count"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_FLOAT32_ARRAY, "buffer", PROPERTY_HINT_NONE), "set_buffer", "get_buffer"); + +#ifndef DISABLE_DEPRECATED + // Kept for compatibility from 3.x to 4.0. ClassDB::bind_method(D_METHOD("_set_transform_array"), &MultiMesh::_set_transform_array); ClassDB::bind_method(D_METHOD("_get_transform_array"), &MultiMesh::_get_transform_array); ClassDB::bind_method(D_METHOD("_set_transform_2d_array"), &MultiMesh::_set_transform_2d_array); @@ -345,40 +349,25 @@ void MultiMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_custom_data_array"), &MultiMesh::_set_custom_data_array); ClassDB::bind_method(D_METHOD("_get_custom_data_array"), &MultiMesh::_get_custom_data_array); - ADD_PROPERTY(PropertyInfo(Variant::INT, "color_format", PROPERTY_HINT_ENUM, "None,Byte,Float"), "set_color_format", "get_color_format"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "transform_format", PROPERTY_HINT_ENUM, "2D,3D"), "set_transform_format", "get_transform_format"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "custom_data_format", PROPERTY_HINT_ENUM, "None,Byte,Float"), "set_custom_data_format", "get_custom_data_format"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "instance_count", PROPERTY_HINT_RANGE, "0,16384,1,or_greater"), "set_instance_count", "get_instance_count"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_instance_count", PROPERTY_HINT_RANGE, "-1,16384,1,or_greater"), "set_visible_instance_count", "get_visible_instance_count"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); - ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "transform_array", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_transform_array", "_get_transform_array"); - ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "transform_2d_array", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_transform_2d_array", "_get_transform_2d_array"); - ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "color_array", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_color_array", "_get_color_array"); - ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "custom_data_array", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_custom_data_array", "_get_custom_data_array"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "transform_array", PROPERTY_HINT_NONE, "", 0), "_set_transform_array", "_get_transform_array"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "transform_2d_array", PROPERTY_HINT_NONE, "", 0), "_set_transform_2d_array", "_get_transform_2d_array"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "color_array", PROPERTY_HINT_NONE, "", 0), "_set_color_array", "_get_color_array"); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "custom_data_array", PROPERTY_HINT_NONE, "", 0), "_set_custom_data_array", "_get_custom_data_array"); +#endif BIND_ENUM_CONSTANT(TRANSFORM_2D); BIND_ENUM_CONSTANT(TRANSFORM_3D); - - BIND_ENUM_CONSTANT(COLOR_NONE); - BIND_ENUM_CONSTANT(COLOR_8BIT); - BIND_ENUM_CONSTANT(COLOR_FLOAT); - - BIND_ENUM_CONSTANT(CUSTOM_DATA_NONE); - BIND_ENUM_CONSTANT(CUSTOM_DATA_8BIT); - BIND_ENUM_CONSTANT(CUSTOM_DATA_FLOAT); } MultiMesh::MultiMesh() { - - multimesh = VisualServer::get_singleton()->multimesh_create(); - color_format = COLOR_NONE; - custom_data_format = CUSTOM_DATA_NONE; + multimesh = RenderingServer::get_singleton()->multimesh_create(); + use_colors = false; + use_custom_data = false; transform_format = TRANSFORM_2D; visible_instance_count = -1; instance_count = 0; } MultiMesh::~MultiMesh() { - - VisualServer::get_singleton()->free(multimesh); + RenderingServer::get_singleton()->free(multimesh); } diff --git a/scene/resources/multimesh.h b/scene/resources/multimesh.h index 9394737799..16f5998a04 100644 --- a/scene/resources/multimesh.h +++ b/scene/resources/multimesh.h @@ -32,64 +32,56 @@ #define MULTIMESH_H #include "scene/resources/mesh.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" class MultiMesh : public Resource { - GDCLASS(MultiMesh, Resource); RES_BASE_EXTENSION("multimesh"); public: enum TransformFormat { - TRANSFORM_2D = VS::MULTIMESH_TRANSFORM_2D, - TRANSFORM_3D = VS::MULTIMESH_TRANSFORM_3D - }; - - enum ColorFormat { - COLOR_NONE = VS::MULTIMESH_COLOR_NONE, - COLOR_8BIT = VS::MULTIMESH_COLOR_8BIT, - COLOR_FLOAT = VS::MULTIMESH_COLOR_FLOAT, - }; - - enum CustomDataFormat { - CUSTOM_DATA_NONE, - CUSTOM_DATA_8BIT, - CUSTOM_DATA_FLOAT, + TRANSFORM_2D = RS::MULTIMESH_TRANSFORM_2D, + TRANSFORM_3D = RS::MULTIMESH_TRANSFORM_3D }; private: Ref<Mesh> mesh; RID multimesh; TransformFormat transform_format; - ColorFormat color_format; - CustomDataFormat custom_data_format; + bool use_colors; + bool use_custom_data; int instance_count; int visible_instance_count; protected: static void _bind_methods(); - void _set_transform_array(const PoolVector<Vector3> &p_array); - PoolVector<Vector3> _get_transform_array() const; +#ifndef DISABLE_DEPRECATED + // Kept for compatibility from 3.x to 4.0. + void _set_transform_array(const Vector<Vector3> &p_array); + Vector<Vector3> _get_transform_array() const; - void _set_transform_2d_array(const PoolVector<Vector2> &p_array); - PoolVector<Vector2> _get_transform_2d_array() const; + void _set_transform_2d_array(const Vector<Vector2> &p_array); + Vector<Vector2> _get_transform_2d_array() const; - void _set_color_array(const PoolVector<Color> &p_array); - PoolVector<Color> _get_color_array() const; + void _set_color_array(const Vector<Color> &p_array); + Vector<Color> _get_color_array() const; - void _set_custom_data_array(const PoolVector<Color> &p_array); - PoolVector<Color> _get_custom_data_array() const; + void _set_custom_data_array(const Vector<Color> &p_array); + Vector<Color> _get_custom_data_array() const; +#endif + void set_buffer(const Vector<float> &p_buffer); + Vector<float> get_buffer() const; public: void set_mesh(const Ref<Mesh> &p_mesh); Ref<Mesh> get_mesh() const; - void set_color_format(ColorFormat p_color_format); - ColorFormat get_color_format() const; + void set_use_colors(bool p_enable); + bool is_using_colors() const; - void set_custom_data_format(CustomDataFormat p_custom_data_format); - CustomDataFormat get_custom_data_format() const; + void set_use_custom_data(bool p_enable); + bool is_using_custom_data() const; void set_transform_format(TransformFormat p_transform_format); TransformFormat get_transform_format() const; @@ -111,18 +103,14 @@ public: void set_instance_custom_data(int p_instance, const Color &p_custom_data); Color get_instance_custom_data(int p_instance) const; - void set_as_bulk_array(const PoolVector<float> &p_array); - virtual AABB get_aabb() const; - virtual RID get_rid() const; + virtual RID get_rid() const override; MultiMesh(); ~MultiMesh(); }; VARIANT_ENUM_CAST(MultiMesh::TransformFormat); -VARIANT_ENUM_CAST(MultiMesh::ColorFormat); -VARIANT_ENUM_CAST(MultiMesh::CustomDataFormat); #endif // MULTI_MESH_H diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp new file mode 100644 index 0000000000..e815da5d45 --- /dev/null +++ b/scene/resources/navigation_mesh.cpp @@ -0,0 +1,536 @@ +/*************************************************************************/ +/* navigation_mesh.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "navigation_mesh.h" + +void NavigationMesh::create_from_mesh(const Ref<Mesh> &p_mesh) { + vertices = Vector<Vector3>(); + clear_polygons(); + + for (int i = 0; i < p_mesh->get_surface_count(); i++) { + if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { + continue; + } + Array arr = p_mesh->surface_get_arrays(i); + Vector<Vector3> varr = arr[Mesh::ARRAY_VERTEX]; + Vector<int> iarr = arr[Mesh::ARRAY_INDEX]; + if (varr.size() == 0 || iarr.size() == 0) { + continue; + } + + int from = vertices.size(); + vertices.append_array(varr); + int rlen = iarr.size(); + const int *r = iarr.ptr(); + + for (int j = 0; j < rlen; j += 3) { + Vector<int> vi; + vi.resize(3); + vi.write[0] = r[j + 0] + from; + vi.write[1] = r[j + 1] + from; + vi.write[2] = r[j + 2] + from; + + add_polygon(vi); + } + } +} + +void NavigationMesh::set_sample_partition_type(int p_value) { + ERR_FAIL_COND(p_value >= SAMPLE_PARTITION_MAX); + partition_type = static_cast<SamplePartitionType>(p_value); +} + +int NavigationMesh::get_sample_partition_type() const { + return static_cast<int>(partition_type); +} + +void NavigationMesh::set_parsed_geometry_type(int p_value) { + ERR_FAIL_COND(p_value >= PARSED_GEOMETRY_MAX); + parsed_geometry_type = static_cast<ParsedGeometryType>(p_value); + _change_notify(); +} + +int NavigationMesh::get_parsed_geometry_type() const { + return parsed_geometry_type; +} + +void NavigationMesh::set_collision_mask(uint32_t p_mask) { + collision_mask = p_mask; +} + +uint32_t NavigationMesh::get_collision_mask() const { + return collision_mask; +} + +void NavigationMesh::set_collision_mask_bit(int p_bit, bool p_value) { + uint32_t mask = get_collision_mask(); + if (p_value) { + mask |= 1 << p_bit; + } else { + mask &= ~(1 << p_bit); + } + set_collision_mask(mask); +} + +bool NavigationMesh::get_collision_mask_bit(int p_bit) const { + return get_collision_mask() & (1 << p_bit); +} + +void NavigationMesh::set_source_geometry_mode(int p_geometry_mode) { + ERR_FAIL_INDEX(p_geometry_mode, SOURCE_GEOMETRY_MAX); + source_geometry_mode = static_cast<SourceGeometryMode>(p_geometry_mode); + _change_notify(); +} + +int NavigationMesh::get_source_geometry_mode() const { + return source_geometry_mode; +} + +void NavigationMesh::set_source_group_name(StringName p_group_name) { + source_group_name = p_group_name; +} + +StringName NavigationMesh::get_source_group_name() const { + return source_group_name; +} + +void NavigationMesh::set_cell_size(float p_value) { + cell_size = p_value; +} + +float NavigationMesh::get_cell_size() const { + return cell_size; +} + +void NavigationMesh::set_cell_height(float p_value) { + cell_height = p_value; +} + +float NavigationMesh::get_cell_height() const { + return cell_height; +} + +void NavigationMesh::set_agent_height(float p_value) { + agent_height = p_value; +} + +float NavigationMesh::get_agent_height() const { + return agent_height; +} + +void NavigationMesh::set_agent_radius(float p_value) { + agent_radius = p_value; +} + +float NavigationMesh::get_agent_radius() { + return agent_radius; +} + +void NavigationMesh::set_agent_max_climb(float p_value) { + agent_max_climb = p_value; +} + +float NavigationMesh::get_agent_max_climb() const { + return agent_max_climb; +} + +void NavigationMesh::set_agent_max_slope(float p_value) { + agent_max_slope = p_value; +} + +float NavigationMesh::get_agent_max_slope() const { + return agent_max_slope; +} + +void NavigationMesh::set_region_min_size(float p_value) { + region_min_size = p_value; +} + +float NavigationMesh::get_region_min_size() const { + return region_min_size; +} + +void NavigationMesh::set_region_merge_size(float p_value) { + region_merge_size = p_value; +} + +float NavigationMesh::get_region_merge_size() const { + return region_merge_size; +} + +void NavigationMesh::set_edge_max_length(float p_value) { + edge_max_length = p_value; +} + +float NavigationMesh::get_edge_max_length() const { + return edge_max_length; +} + +void NavigationMesh::set_edge_max_error(float p_value) { + edge_max_error = p_value; +} + +float NavigationMesh::get_edge_max_error() const { + return edge_max_error; +} + +void NavigationMesh::set_verts_per_poly(float p_value) { + verts_per_poly = p_value; +} + +float NavigationMesh::get_verts_per_poly() const { + return verts_per_poly; +} + +void NavigationMesh::set_detail_sample_distance(float p_value) { + detail_sample_distance = p_value; +} + +float NavigationMesh::get_detail_sample_distance() const { + return detail_sample_distance; +} + +void NavigationMesh::set_detail_sample_max_error(float p_value) { + detail_sample_max_error = p_value; +} + +float NavigationMesh::get_detail_sample_max_error() const { + return detail_sample_max_error; +} + +void NavigationMesh::set_filter_low_hanging_obstacles(bool p_value) { + filter_low_hanging_obstacles = p_value; +} + +bool NavigationMesh::get_filter_low_hanging_obstacles() const { + return filter_low_hanging_obstacles; +} + +void NavigationMesh::set_filter_ledge_spans(bool p_value) { + filter_ledge_spans = p_value; +} + +bool NavigationMesh::get_filter_ledge_spans() const { + return filter_ledge_spans; +} + +void NavigationMesh::set_filter_walkable_low_height_spans(bool p_value) { + filter_walkable_low_height_spans = p_value; +} + +bool NavigationMesh::get_filter_walkable_low_height_spans() const { + return filter_walkable_low_height_spans; +} + +void NavigationMesh::set_vertices(const Vector<Vector3> &p_vertices) { + vertices = p_vertices; + _change_notify(); +} + +Vector<Vector3> NavigationMesh::get_vertices() const { + return vertices; +} + +void NavigationMesh::_set_polygons(const Array &p_array) { + polygons.resize(p_array.size()); + for (int i = 0; i < p_array.size(); i++) { + polygons.write[i].indices = p_array[i]; + } + _change_notify(); +} + +Array NavigationMesh::_get_polygons() const { + Array ret; + ret.resize(polygons.size()); + for (int i = 0; i < ret.size(); i++) { + ret[i] = polygons[i].indices; + } + + return ret; +} + +void NavigationMesh::add_polygon(const Vector<int> &p_polygon) { + Polygon polygon; + polygon.indices = p_polygon; + polygons.push_back(polygon); + _change_notify(); +} + +int NavigationMesh::get_polygon_count() const { + return polygons.size(); +} + +Vector<int> NavigationMesh::get_polygon(int p_idx) { + ERR_FAIL_INDEX_V(p_idx, polygons.size(), Vector<int>()); + return polygons[p_idx].indices; +} + +void NavigationMesh::clear_polygons() { + polygons.clear(); +} + +Ref<Mesh> NavigationMesh::get_debug_mesh() { + if (debug_mesh.is_valid()) { + return debug_mesh; + } + + Vector<Vector3> vertices = get_vertices(); + const Vector3 *vr = vertices.ptr(); + List<Face3> faces; + for (int i = 0; i < get_polygon_count(); i++) { + Vector<int> p = get_polygon(i); + + for (int j = 2; j < p.size(); j++) { + Face3 f; + f.vertex[0] = vr[p[0]]; + f.vertex[1] = vr[p[j - 1]]; + f.vertex[2] = vr[p[j]]; + + faces.push_back(f); + } + } + + Map<_EdgeKey, bool> edge_map; + Vector<Vector3> tmeshfaces; + tmeshfaces.resize(faces.size() * 3); + + { + Vector3 *tw = tmeshfaces.ptrw(); + int tidx = 0; + + for (List<Face3>::Element *E = faces.front(); E; E = E->next()) { + const Face3 &f = E->get(); + + for (int j = 0; j < 3; j++) { + tw[tidx++] = f.vertex[j]; + _EdgeKey ek; + ek.from = f.vertex[j].snapped(Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON)); + ek.to = f.vertex[(j + 1) % 3].snapped(Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON)); + if (ek.from < ek.to) { + SWAP(ek.from, ek.to); + } + + Map<_EdgeKey, bool>::Element *F = edge_map.find(ek); + + if (F) { + F->get() = false; + + } else { + edge_map[ek] = true; + } + } + } + } + List<Vector3> lines; + + for (Map<_EdgeKey, bool>::Element *E = edge_map.front(); E; E = E->next()) { + if (E->get()) { + lines.push_back(E->key().from); + lines.push_back(E->key().to); + } + } + + Vector<Vector3> varr; + varr.resize(lines.size()); + { + Vector3 *w = varr.ptrw(); + int idx = 0; + for (List<Vector3>::Element *E = lines.front(); E; E = E->next()) { + w[idx++] = E->get(); + } + } + + debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh)); + + Array arr; + arr.resize(Mesh::ARRAY_MAX); + arr[Mesh::ARRAY_VERTEX] = varr; + + debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, arr); + + return debug_mesh; +} + +void NavigationMesh::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_sample_partition_type", "sample_partition_type"), &NavigationMesh::set_sample_partition_type); + ClassDB::bind_method(D_METHOD("get_sample_partition_type"), &NavigationMesh::get_sample_partition_type); + + ClassDB::bind_method(D_METHOD("set_parsed_geometry_type", "geometry_type"), &NavigationMesh::set_parsed_geometry_type); + ClassDB::bind_method(D_METHOD("get_parsed_geometry_type"), &NavigationMesh::get_parsed_geometry_type); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &NavigationMesh::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &NavigationMesh::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &NavigationMesh::set_collision_mask_bit); + ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &NavigationMesh::get_collision_mask_bit); + + ClassDB::bind_method(D_METHOD("set_source_geometry_mode", "mask"), &NavigationMesh::set_source_geometry_mode); + ClassDB::bind_method(D_METHOD("get_source_geometry_mode"), &NavigationMesh::get_source_geometry_mode); + + ClassDB::bind_method(D_METHOD("set_source_group_name", "mask"), &NavigationMesh::set_source_group_name); + ClassDB::bind_method(D_METHOD("get_source_group_name"), &NavigationMesh::get_source_group_name); + + ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &NavigationMesh::set_cell_size); + ClassDB::bind_method(D_METHOD("get_cell_size"), &NavigationMesh::get_cell_size); + + ClassDB::bind_method(D_METHOD("set_cell_height", "cell_height"), &NavigationMesh::set_cell_height); + ClassDB::bind_method(D_METHOD("get_cell_height"), &NavigationMesh::get_cell_height); + + ClassDB::bind_method(D_METHOD("set_agent_height", "agent_height"), &NavigationMesh::set_agent_height); + ClassDB::bind_method(D_METHOD("get_agent_height"), &NavigationMesh::get_agent_height); + + ClassDB::bind_method(D_METHOD("set_agent_radius", "agent_radius"), &NavigationMesh::set_agent_radius); + ClassDB::bind_method(D_METHOD("get_agent_radius"), &NavigationMesh::get_agent_radius); + + ClassDB::bind_method(D_METHOD("set_agent_max_climb", "agent_max_climb"), &NavigationMesh::set_agent_max_climb); + ClassDB::bind_method(D_METHOD("get_agent_max_climb"), &NavigationMesh::get_agent_max_climb); + + ClassDB::bind_method(D_METHOD("set_agent_max_slope", "agent_max_slope"), &NavigationMesh::set_agent_max_slope); + ClassDB::bind_method(D_METHOD("get_agent_max_slope"), &NavigationMesh::get_agent_max_slope); + + ClassDB::bind_method(D_METHOD("set_region_min_size", "region_min_size"), &NavigationMesh::set_region_min_size); + ClassDB::bind_method(D_METHOD("get_region_min_size"), &NavigationMesh::get_region_min_size); + + ClassDB::bind_method(D_METHOD("set_region_merge_size", "region_merge_size"), &NavigationMesh::set_region_merge_size); + ClassDB::bind_method(D_METHOD("get_region_merge_size"), &NavigationMesh::get_region_merge_size); + + ClassDB::bind_method(D_METHOD("set_edge_max_length", "edge_max_length"), &NavigationMesh::set_edge_max_length); + ClassDB::bind_method(D_METHOD("get_edge_max_length"), &NavigationMesh::get_edge_max_length); + + ClassDB::bind_method(D_METHOD("set_edge_max_error", "edge_max_error"), &NavigationMesh::set_edge_max_error); + ClassDB::bind_method(D_METHOD("get_edge_max_error"), &NavigationMesh::get_edge_max_error); + + ClassDB::bind_method(D_METHOD("set_verts_per_poly", "verts_per_poly"), &NavigationMesh::set_verts_per_poly); + ClassDB::bind_method(D_METHOD("get_verts_per_poly"), &NavigationMesh::get_verts_per_poly); + + ClassDB::bind_method(D_METHOD("set_detail_sample_distance", "detail_sample_dist"), &NavigationMesh::set_detail_sample_distance); + ClassDB::bind_method(D_METHOD("get_detail_sample_distance"), &NavigationMesh::get_detail_sample_distance); + + ClassDB::bind_method(D_METHOD("set_detail_sample_max_error", "detail_sample_max_error"), &NavigationMesh::set_detail_sample_max_error); + ClassDB::bind_method(D_METHOD("get_detail_sample_max_error"), &NavigationMesh::get_detail_sample_max_error); + + ClassDB::bind_method(D_METHOD("set_filter_low_hanging_obstacles", "filter_low_hanging_obstacles"), &NavigationMesh::set_filter_low_hanging_obstacles); + ClassDB::bind_method(D_METHOD("get_filter_low_hanging_obstacles"), &NavigationMesh::get_filter_low_hanging_obstacles); + + ClassDB::bind_method(D_METHOD("set_filter_ledge_spans", "filter_ledge_spans"), &NavigationMesh::set_filter_ledge_spans); + ClassDB::bind_method(D_METHOD("get_filter_ledge_spans"), &NavigationMesh::get_filter_ledge_spans); + + ClassDB::bind_method(D_METHOD("set_filter_walkable_low_height_spans", "filter_walkable_low_height_spans"), &NavigationMesh::set_filter_walkable_low_height_spans); + ClassDB::bind_method(D_METHOD("get_filter_walkable_low_height_spans"), &NavigationMesh::get_filter_walkable_low_height_spans); + + ClassDB::bind_method(D_METHOD("set_vertices", "vertices"), &NavigationMesh::set_vertices); + ClassDB::bind_method(D_METHOD("get_vertices"), &NavigationMesh::get_vertices); + + ClassDB::bind_method(D_METHOD("add_polygon", "polygon"), &NavigationMesh::add_polygon); + ClassDB::bind_method(D_METHOD("get_polygon_count"), &NavigationMesh::get_polygon_count); + ClassDB::bind_method(D_METHOD("get_polygon", "idx"), &NavigationMesh::get_polygon); + ClassDB::bind_method(D_METHOD("clear_polygons"), &NavigationMesh::clear_polygons); + + ClassDB::bind_method(D_METHOD("create_from_mesh", "mesh"), &NavigationMesh::create_from_mesh); + + ClassDB::bind_method(D_METHOD("_set_polygons", "polygons"), &NavigationMesh::_set_polygons); + ClassDB::bind_method(D_METHOD("_get_polygons"), &NavigationMesh::_get_polygons); + + BIND_CONSTANT(SAMPLE_PARTITION_WATERSHED); + BIND_CONSTANT(SAMPLE_PARTITION_MONOTONE); + BIND_CONSTANT(SAMPLE_PARTITION_LAYERS); + + BIND_CONSTANT(PARSED_GEOMETRY_MESH_INSTANCES); + BIND_CONSTANT(PARSED_GEOMETRY_STATIC_COLLIDERS); + BIND_CONSTANT(PARSED_GEOMETRY_BOTH); + + ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons"); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "sample_partition_type/sample_partition_type", PROPERTY_HINT_ENUM, "Watershed,Monotone,Layers"), "set_sample_partition_type", "get_sample_partition_type"); + 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(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(PropertyInfo(Variant::FLOAT, "cell/size", PROPERTY_HINT_RANGE, "0.1,1.0,0.01,or_greater"), "set_cell_size", "get_cell_size"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell/height", PROPERTY_HINT_RANGE, "0.1,1.0,0.01,or_greater"), "set_cell_height", "get_cell_height"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent/height", PROPERTY_HINT_RANGE, "0.1,5.0,0.01,or_greater"), "set_agent_height", "get_agent_height"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent/radius", PROPERTY_HINT_RANGE, "0.1,5.0,0.01,or_greater"), "set_agent_radius", "get_agent_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent/max_climb", PROPERTY_HINT_RANGE, "0.1,5.0,0.01,or_greater"), "set_agent_max_climb", "get_agent_max_climb"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent/max_slope", PROPERTY_HINT_RANGE, "0.0,90.0,0.1"), "set_agent_max_slope", "get_agent_max_slope"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "region/min_size", PROPERTY_HINT_RANGE, "0.0,150.0,0.01,or_greater"), "set_region_min_size", "get_region_min_size"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "region/merge_size", PROPERTY_HINT_RANGE, "0.0,150.0,0.01,or_greater"), "set_region_merge_size", "get_region_merge_size"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge/max_length", PROPERTY_HINT_RANGE, "0.0,50.0,0.01,or_greater"), "set_edge_max_length", "get_edge_max_length"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge/max_error", PROPERTY_HINT_RANGE, "0.1,3.0,0.01,or_greater"), "set_edge_max_error", "get_edge_max_error"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "polygon/verts_per_poly", PROPERTY_HINT_RANGE, "3.0,12.0,1.0,or_greater"), "set_verts_per_poly", "get_verts_per_poly"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail/sample_distance", PROPERTY_HINT_RANGE, "0.0,16.0,0.01,or_greater"), "set_detail_sample_distance", "get_detail_sample_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail/sample_max_error", PROPERTY_HINT_RANGE, "0.0,16.0,0.01,or_greater"), "set_detail_sample_max_error", "get_detail_sample_max_error"); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter/low_hanging_obstacles"), "set_filter_low_hanging_obstacles", "get_filter_low_hanging_obstacles"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter/ledge_spans"), "set_filter_ledge_spans", "get_filter_ledge_spans"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter/filter_walkable_low_height_spans"), "set_filter_walkable_low_height_spans", "get_filter_walkable_low_height_spans"); +} + +void NavigationMesh::_validate_property(PropertyInfo &property) const { + if (property.name == "geometry/collision_mask") { + if (parsed_geometry_type == PARSED_GEOMETRY_MESH_INSTANCES) { + property.usage = 0; + return; + } + } + + if (property.name == "geometry/source_group_name") { + if (source_geometry_mode == SOURCE_GEOMETRY_NAVMESH_CHILDREN) { + property.usage = 0; + return; + } + } +} + +NavigationMesh::NavigationMesh() { + cell_size = 0.3f; + cell_height = 0.2f; + agent_height = 2.0f; + agent_radius = 0.6f; + agent_max_climb = 0.9f; + agent_max_slope = 45.0f; + region_min_size = 8.0f; + region_merge_size = 20.0f; + edge_max_length = 12.0f; + edge_max_error = 1.3f; + verts_per_poly = 6.0f; + detail_sample_distance = 6.0f; + detail_sample_max_error = 1.0f; + + partition_type = SAMPLE_PARTITION_WATERSHED; + parsed_geometry_type = PARSED_GEOMETRY_MESH_INSTANCES; + collision_mask = 0xFFFFFFFF; + source_geometry_mode = SOURCE_GEOMETRY_NAVMESH_CHILDREN; + source_group_name = "navmesh"; + filter_low_hanging_obstacles = false; + filter_ledge_spans = false; + filter_walkable_low_height_spans = false; +} diff --git a/scene/resources/navigation_mesh.h b/scene/resources/navigation_mesh.h new file mode 100644 index 0000000000..b94f4408e1 --- /dev/null +++ b/scene/resources/navigation_mesh.h @@ -0,0 +1,193 @@ +/*************************************************************************/ +/* navigation_mesh.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef NAVIGATION_MESH_H +#define NAVIGATION_MESH_H + +#include "scene/resources/mesh.h" + +class Mesh; + +class NavigationMesh : public Resource { + GDCLASS(NavigationMesh, Resource); + + Vector<Vector3> vertices; + struct Polygon { + Vector<int> indices; + }; + Vector<Polygon> polygons; + Ref<ArrayMesh> debug_mesh; + + struct _EdgeKey { + Vector3 from; + Vector3 to; + + bool operator<(const _EdgeKey &p_with) const { return from == p_with.from ? to < p_with.to : from < p_with.from; } + }; + +protected: + static void _bind_methods(); + virtual void _validate_property(PropertyInfo &property) const override; + + void _set_polygons(const Array &p_array); + Array _get_polygons() const; + +public: + enum SamplePartitionType { + SAMPLE_PARTITION_WATERSHED = 0, + SAMPLE_PARTITION_MONOTONE, + SAMPLE_PARTITION_LAYERS, + SAMPLE_PARTITION_MAX + }; + + enum ParsedGeometryType { + PARSED_GEOMETRY_MESH_INSTANCES = 0, + PARSED_GEOMETRY_STATIC_COLLIDERS, + PARSED_GEOMETRY_BOTH, + PARSED_GEOMETRY_MAX + }; + + enum SourceGeometryMode { + SOURCE_GEOMETRY_NAVMESH_CHILDREN = 0, + SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN, + SOURCE_GEOMETRY_GROUPS_EXPLICIT, + SOURCE_GEOMETRY_MAX + }; + +protected: + float cell_size; + float cell_height; + float agent_height; + float agent_radius; + float agent_max_climb; + float agent_max_slope; + float region_min_size; + float region_merge_size; + float edge_max_length; + float edge_max_error; + float verts_per_poly; + float detail_sample_distance; + float detail_sample_max_error; + + SamplePartitionType partition_type; + ParsedGeometryType parsed_geometry_type; + uint32_t collision_mask; + + SourceGeometryMode source_geometry_mode; + StringName source_group_name; + + bool filter_low_hanging_obstacles; + bool filter_ledge_spans; + bool filter_walkable_low_height_spans; + +public: + // Recast settings + void set_sample_partition_type(int p_value); + int get_sample_partition_type() const; + + void set_parsed_geometry_type(int p_value); + int get_parsed_geometry_type() const; + + void set_collision_mask(uint32_t p_mask); + uint32_t get_collision_mask() const; + + void set_collision_mask_bit(int p_bit, bool p_value); + bool get_collision_mask_bit(int p_bit) const; + + void set_source_geometry_mode(int p_geometry_mode); + int get_source_geometry_mode() const; + + void set_source_group_name(StringName p_group_name); + StringName get_source_group_name() const; + + void set_cell_size(float p_value); + float get_cell_size() const; + + void set_cell_height(float p_value); + float get_cell_height() const; + + void set_agent_height(float p_value); + float get_agent_height() const; + + void set_agent_radius(float p_value); + float get_agent_radius(); + + void set_agent_max_climb(float p_value); + float get_agent_max_climb() const; + + void set_agent_max_slope(float p_value); + float get_agent_max_slope() const; + + void set_region_min_size(float p_value); + float get_region_min_size() const; + + void set_region_merge_size(float p_value); + float get_region_merge_size() const; + + void set_edge_max_length(float p_value); + float get_edge_max_length() const; + + void set_edge_max_error(float p_value); + float get_edge_max_error() const; + + void set_verts_per_poly(float p_value); + float get_verts_per_poly() const; + + void set_detail_sample_distance(float p_value); + float get_detail_sample_distance() const; + + void set_detail_sample_max_error(float p_value); + float get_detail_sample_max_error() const; + + void set_filter_low_hanging_obstacles(bool p_value); + bool get_filter_low_hanging_obstacles() const; + + void set_filter_ledge_spans(bool p_value); + bool get_filter_ledge_spans() const; + + void set_filter_walkable_low_height_spans(bool p_value); + bool get_filter_walkable_low_height_spans() const; + + void create_from_mesh(const Ref<Mesh> &p_mesh); + + void set_vertices(const Vector<Vector3> &p_vertices); + Vector<Vector3> get_vertices() const; + + void add_polygon(const Vector<int> &p_polygon); + int get_polygon_count() const; + Vector<int> get_polygon(int p_idx); + void clear_polygons(); + + Ref<Mesh> get_debug_mesh(); + + NavigationMesh(); +}; + +#endif // NAVIGATION_MESH_H diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 3e7d350eec..5e8bfd9387 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -35,44 +35,44 @@ #include "core/io/resource_loader.h" #include "core/project_settings.h" #include "scene/2d/node_2d.h" -#include "scene/3d/spatial.h" +#include "scene/3d/node_3d.h" #include "scene/gui/control.h" #include "scene/main/instance_placeholder.h" #define PACKED_SCENE_VERSION 2 bool SceneState::can_instance() const { - return nodes.size() > 0; } Node *SceneState::instance(GenEditState p_edit_state) const { - // nodes where instancing failed (because something is missing) List<Node *> stray_instances; -#define NODE_FROM_ID(p_name, p_id) \ - Node *p_name; \ - if (p_id & FLAG_ID_IS_PATH) { \ - NodePath np = node_paths[p_id & FLAG_MASK]; \ - p_name = ret_nodes[0]->get_node_or_null(np); \ - } else { \ - ERR_FAIL_INDEX_V(p_id &FLAG_MASK, nc, NULL); \ - p_name = ret_nodes[p_id & FLAG_MASK]; \ +#define NODE_FROM_ID(p_name, p_id) \ + Node *p_name; \ + if (p_id & FLAG_ID_IS_PATH) { \ + NodePath np = node_paths[p_id & FLAG_MASK]; \ + p_name = ret_nodes[0]->get_node_or_null(np); \ + } else { \ + ERR_FAIL_INDEX_V(p_id &FLAG_MASK, nc, nullptr); \ + p_name = ret_nodes[p_id & FLAG_MASK]; \ } int nc = nodes.size(); - ERR_FAIL_COND_V(nc == 0, NULL); + ERR_FAIL_COND_V(nc == 0, nullptr); - const StringName *snames = NULL; + const StringName *snames = nullptr; int sname_count = names.size(); - if (sname_count) + if (sname_count) { snames = &names[0]; + } - const Variant *props = NULL; + const Variant *props = nullptr; int prop_count = variants.size(); - if (prop_count) + if (prop_count) { props = &variants[0]; + } //Vector<Variant> properties; @@ -82,35 +82,35 @@ Node *SceneState::instance(GenEditState p_edit_state) const { bool gen_node_path_cache = p_edit_state != GEN_EDIT_STATE_DISABLED && node_path_cache.empty(); - Map<Ref<Resource>, Ref<Resource> > resources_local_to_scene; + Map<Ref<Resource>, Ref<Resource>> resources_local_to_scene; for (int i = 0; i < nc; i++) { - const NodeData &n = nd[i]; - Node *parent = NULL; + Node *parent = nullptr; if (i > 0) { - - ERR_FAIL_COND_V_MSG(n.parent == -1, NULL, vformat("Invalid scene: node %s does not specify its parent node.", snames[n.name])); + ERR_FAIL_COND_V_MSG(n.parent == -1, nullptr, vformat("Invalid scene: node %s does not specify its parent node.", snames[n.name])); NODE_FROM_ID(nparent, n.parent); #ifdef DEBUG_ENABLED if (!nparent && (n.parent & FLAG_ID_IS_PATH)) { - WARN_PRINT(String("Parent path '" + String(node_paths[n.parent & FLAG_MASK]) + "' for node '" + String(snames[n.name]) + "' has vanished when instancing: '" + get_path() + "'.").ascii().get_data()); } #endif parent = nparent; + } else { + // i == 0 is root node. Confirm that it doesn't have a parent defined. + ERR_FAIL_COND_V_MSG(n.parent != -1, nullptr, vformat("Invalid scene: root node %s cannot specify a parent node.", snames[n.name])); } - Node *node = NULL; + Node *node = nullptr; if (i == 0 && base_scene_idx >= 0) { //scene inheritance on root node Ref<PackedScene> sdata = props[base_scene_idx]; - ERR_FAIL_COND_V(!sdata.is_valid(), NULL); + ERR_FAIL_COND_V(!sdata.is_valid(), nullptr); node = sdata->instance(p_edit_state == GEN_EDIT_STATE_DISABLED ? PackedScene::GEN_EDIT_STATE_DISABLED : PackedScene::GEN_EDIT_STATE_INSTANCE); //only main gets main edit state - ERR_FAIL_COND_V(!node, NULL); + ERR_FAIL_COND_V(!node, nullptr); if (p_edit_state != GEN_EDIT_STATE_DISABLED) { node->set_scene_inherited_state(sdata->get_state()); } @@ -118,14 +118,12 @@ Node *SceneState::instance(GenEditState p_edit_state) const { } else if (n.instance >= 0) { //instance a scene into this node if (n.instance & FLAG_INSTANCE_IS_PLACEHOLDER) { - String path = props[n.instance & FLAG_MASK]; if (disable_placeholders) { - Ref<PackedScene> sdata = ResourceLoader::load(path, "PackedScene"); - ERR_FAIL_COND_V(!sdata.is_valid(), NULL); + ERR_FAIL_COND_V(!sdata.is_valid(), nullptr); node = sdata->instance(p_edit_state == GEN_EDIT_STATE_DISABLED ? PackedScene::GEN_EDIT_STATE_DISABLED : PackedScene::GEN_EDIT_STATE_INSTANCE); - ERR_FAIL_COND_V(!node, NULL); + ERR_FAIL_COND_V(!node, nullptr); } else { InstancePlaceholder *ip = memnew(InstancePlaceholder); ip->set_instance_path(path); @@ -134,9 +132,9 @@ Node *SceneState::instance(GenEditState p_edit_state) const { node->set_scene_instance_load_placeholder(true); } else { Ref<PackedScene> sdata = props[n.instance & FLAG_MASK]; - ERR_FAIL_COND_V(!sdata.is_valid(), NULL); + ERR_FAIL_COND_V(!sdata.is_valid(), nullptr); node = sdata->instance(p_edit_state == GEN_EDIT_STATE_DISABLED ? PackedScene::GEN_EDIT_STATE_DISABLED : PackedScene::GEN_EDIT_STATE_INSTANCE); - ERR_FAIL_COND_V(!node, NULL); + ERR_FAIL_COND_V(!node, nullptr); } } else if (n.type == TYPE_INSTANCED) { @@ -155,12 +153,12 @@ Node *SceneState::instance(GenEditState p_edit_state) const { if (!Object::cast_to<Node>(obj)) { if (obj) { memdelete(obj); - obj = NULL; + obj = nullptr; } WARN_PRINT(String("Warning node of type " + snames[n.type].operator String() + " does not exist.").ascii().get_data()); if (n.parent >= 0 && n.parent < nc && ret_nodes[n.parent]) { - if (Object::cast_to<Spatial>(ret_nodes[n.parent])) { - obj = memnew(Spatial); + if (Object::cast_to<Node3D>(ret_nodes[n.parent])) { + obj = memnew(Node3D); } else if (Object::cast_to<Control>(ret_nodes[n.parent])) { obj = memnew(Control); } else if (Object::cast_to<Node2D>(ret_nodes[n.parent])) { @@ -187,21 +185,19 @@ Node *SceneState::instance(GenEditState p_edit_state) const { //properties int nprop_count = n.properties.size(); if (nprop_count) { - const NodeData::Property *nprops = &n.properties[0]; for (int j = 0; j < nprop_count; j++) { - bool valid; - ERR_FAIL_INDEX_V(nprops[j].name, sname_count, NULL); - ERR_FAIL_INDEX_V(nprops[j].value, prop_count, NULL); + ERR_FAIL_INDEX_V(nprops[j].name, sname_count, nullptr); + ERR_FAIL_INDEX_V(nprops[j].value, prop_count, nullptr); if (snames[nprops[j].name] == CoreStringNames::get_singleton()->_script) { //work around to avoid old script variables from disappearing, should be the proper fix to: //https://github.com/godotengine/godot/issues/2958 //store old state - List<Pair<StringName, Variant> > old_state; + List<Pair<StringName, Variant>> old_state; if (node->get_script_instance()) { node->get_script_instance()->get_property_state(old_state); } @@ -209,11 +205,10 @@ Node *SceneState::instance(GenEditState p_edit_state) const { node->set(snames[nprops[j].name], props[nprops[j].value], &valid); //restore old state for new script, if exists - for (List<Pair<StringName, Variant> >::Element *E = old_state.front(); E; E = E->next()) { + for (List<Pair<StringName, Variant>>::Element *E = old_state.front(); E; E = E->next()) { node->set(E->get().first, E->get().second); } } else { - Variant value = props[nprops[j].value]; if (value.get_type() == Variant::OBJECT) { @@ -221,13 +216,11 @@ Node *SceneState::instance(GenEditState p_edit_state) const { Ref<Resource> res = value; if (res.is_valid()) { if (res->is_local_to_scene()) { - - Map<Ref<Resource>, Ref<Resource> >::Element *E = resources_local_to_scene.find(res); + Map<Ref<Resource>, Ref<Resource>>::Element *E = resources_local_to_scene.find(res); if (E) { value = E->get(); } else { - Node *base = i == 0 ? node : ret_nodes[0]; if (p_edit_state == GEN_EDIT_STATE_MAIN) { @@ -259,8 +252,7 @@ Node *SceneState::instance(GenEditState p_edit_state) const { //groups for (int j = 0; j < n.groups.size(); j++) { - - ERR_FAIL_INDEX_V(n.groups[j], sname_count, NULL); + ERR_FAIL_INDEX_V(n.groups[j], sname_count, nullptr); node->add_to_group(snames[n.groups[j]], true); } @@ -269,8 +261,9 @@ Node *SceneState::instance(GenEditState p_edit_state) const { if (i > 0) { if (parent) { parent->_add_child_nocheck(node, snames[n.name]); - if (n.index >= 0 && n.index < parent->get_child_count() - 1) + if (n.index >= 0 && n.index < parent->get_child_count() - 1) { parent->move_child(node, n.index); + } } else { //it may be possible that an instanced scene has changed //and the node has nowhere to go anymore @@ -287,10 +280,10 @@ Node *SceneState::instance(GenEditState p_edit_state) const { } if (n.owner >= 0) { - NODE_FROM_ID(owner, n.owner); - if (owner) + if (owner) { node->_set_owner_nocheck(owner); + } } } @@ -302,8 +295,7 @@ Node *SceneState::instance(GenEditState p_edit_state) const { } } - for (Map<Ref<Resource>, Ref<Resource> >::Element *E = resources_local_to_scene.front(); E; E = E->next()) { - + for (Map<Ref<Resource>, Ref<Resource>>::Element *E = resources_local_to_scene.front(); E; E = E->next()) { E->get()->setup_local_to_scene(); } @@ -313,25 +305,26 @@ Node *SceneState::instance(GenEditState p_edit_state) const { const ConnectionData *cdata = connections.ptr(); for (int i = 0; i < cc; i++) { - const ConnectionData &c = cdata[i]; - //ERR_FAIL_INDEX_V( c.from, nc, NULL ); - //ERR_FAIL_INDEX_V( c.to, nc, NULL ); + //ERR_FAIL_INDEX_V( c.from, nc, nullptr ); + //ERR_FAIL_INDEX_V( c.to, nc, nullptr ); NODE_FROM_ID(cfrom, c.from); NODE_FROM_ID(cto, c.to); - if (!cfrom || !cto) + if (!cfrom || !cto) { continue; + } Vector<Variant> binds; if (c.binds.size()) { binds.resize(c.binds.size()); - for (int j = 0; j < c.binds.size(); j++) + for (int j = 0; j < c.binds.size(); j++) { binds.write[j] = props[c.binds[j]]; + } } - cfrom->connect(snames[c.signal], cto, snames[c.method], binds, CONNECT_PERSIST | c.flags); + cfrom->connect(snames[c.signal], Callable(cto, snames[c.method]), binds, CONNECT_PERSIST | c.flags); } //Node *s = ret_nodes[0]; @@ -353,9 +346,9 @@ Node *SceneState::instance(GenEditState p_edit_state) const { } static int _nm_get_string(const String &p_string, Map<StringName, int> &name_map) { - - if (name_map.has(p_string)) + if (name_map.has(p_string)) { return name_map[p_string]; + } int idx = name_map.size(); name_map[p_string] = idx; @@ -363,9 +356,9 @@ static int _nm_get_string(const String &p_string, Map<StringName, int> &name_map } static int _vm_get_variant(const Variant &p_variant, HashMap<Variant, int, VariantHasher, VariantComparator> &variant_map) { - - if (variant_map.has(p_variant)) + if (variant_map.has(p_variant)) { return variant_map[p_variant]; + } int idx = variant_map.size(); variant_map[p_variant] = idx; @@ -373,20 +366,21 @@ static int _vm_get_variant(const Variant &p_variant, HashMap<Variant, int, Varia } Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map<StringName, int> &name_map, HashMap<Variant, int, VariantHasher, VariantComparator> &variant_map, Map<Node *, int> &node_map, Map<Node *, int> &nodepath_map) { - // this function handles all the work related to properly packing scenes, be it // instanced or inherited. // given the complexity of this process, an attempt will be made to properly // document it. if you fail to understand something, please ask! //discard nodes that do not belong to be processed - if (p_node != p_owner && p_node->get_owner() != p_owner && !p_owner->is_editable_instance(p_node->get_owner())) + if (p_node != p_owner && p_node->get_owner() != p_owner && !p_owner->is_editable_instance(p_node->get_owner())) { return OK; + } // save the child instanced scenes that are chosen as editable, so they can be restored // upon load back - if (p_node != p_owner && p_node->get_filename() != String() && p_owner->is_editable_instance(p_node)) + if (p_node != p_owner && p_node->get_filename() != String() && p_owner->is_editable_instance(p_node)) { editable_instances.push_back(p_owner->get_path_to(p_node)); + } NodeData nd; @@ -418,9 +412,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map Node *n = p_node; while (n) { - if (n == p_owner) { - Ref<SceneState> state = n->get_scene_inherited_state(); if (state.is_valid()) { int node = state->find_node_by_path(n->get_path_to(p_node)); @@ -435,7 +427,6 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map } if (p_node->get_filename() != String() && p_node->get_owner() == p_owner && instanced_by_owner) { - if (p_node->get_scene_instance_load_placeholder()) { //it's a placeholder, use the placeholder path nd.instance = _vm_get_variant(p_node->get_filename(), variant_map); @@ -450,7 +441,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map nd.instance = _vm_get_variant(instance, variant_map); } } - n = NULL; + n = nullptr; } else { if (n->get_filename() != String()) { //is an instance @@ -479,7 +470,6 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map StringName type = p_node->get_class(); for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) { continue; } @@ -530,17 +520,16 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map } if (exists) { - //check if already exists and did not change - if (value.get_type() == Variant::REAL && original.get_type() == Variant::REAL) { + if (value.get_type() == Variant::FLOAT && original.get_type() == Variant::FLOAT) { //this must be done because, as some scenes save as text, there might be a tiny difference in floats due to numerical error float a = value; float b = original; - if (Math::is_equal_approx(a, b)) + if (Math::is_equal_approx(a, b)) { continue; + } } else if (bool(Variant::evaluate(Variant::OP_EQUAL, value, original))) { - continue; } } @@ -552,7 +541,6 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map } } else { - if (isdefault) { //it's the default value, no point in saving it continue; @@ -573,8 +561,9 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map for (List<Node::GroupInfo>::Element *E = groups.front(); E; E = E->next()) { Node::GroupInfo &gi = E->get(); - if (!gi.persistent) + if (!gi.persistent) { continue; + } /* if (instance_state_node>=0 && instance_state->is_node_in_group(instance_state_node,gi.name)) continue; //group was instanced, don't add here @@ -590,8 +579,9 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map } } - if (skip) + if (skip) { continue; + } nd.groups.push_back(_nm_get_string(gi.name, name_map)); } @@ -608,7 +598,6 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map //part of saved scene nd.owner = 0; } else { - nd.owner = -1; } @@ -637,14 +626,12 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map int parent_node = NO_PARENT_SAVED; if (save_node) { - //don't save the node if nothing and subscene node_map[p_node] = idx; //ok validate parent node if (p_parent_idx == NO_PARENT_SAVED) { - int sidx; if (nodepath_map.has(p_node->get_parent())) { sidx = nodepath_map[p_node->get_parent()]; @@ -663,20 +650,20 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map } for (int i = 0; i < p_node->get_child_count(); i++) { - Node *c = p_node->get_child(i); Error err = _parse_node(p_owner, c, parent_node, name_map, variant_map, node_map, nodepath_map); - if (err) + if (err) { return err; + } } return OK; } Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName, int> &name_map, HashMap<Variant, int, VariantHasher, VariantComparator> &variant_map, Map<Node *, int> &node_map, Map<Node *, int> &nodepath_map) { - - if (p_node != p_owner && p_node->get_owner() && p_node->get_owner() != p_owner && !p_owner->is_editable_instance(p_node->get_owner())) + if (p_node != p_owner && p_node->get_owner() && p_node->get_owner() != p_owner && !p_owner->is_editable_instance(p_node->get_owner())) { return OK; + } List<MethodInfo> _signals; p_node->get_signal_list(&_signals); @@ -686,23 +673,22 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName //NodeData &nd = nodes[node_map[p_node]]; for (List<MethodInfo>::Element *E = _signals.front(); E; E = E->next()) { - List<Node::Connection> conns; p_node->get_signal_connection_list(E->get().name, &conns); conns.sort(); for (List<Node::Connection>::Element *F = conns.front(); F; F = F->next()) { - const Node::Connection &c = F->get(); - if (!(c.flags & CONNECT_PERSIST)) //only persistent connections get saved + if (!(c.flags & CONNECT_PERSIST)) { //only persistent connections get saved continue; + } // only connections that originate or end into main saved scene are saved // everything else is discarded - Node *target = Object::cast_to<Node>(c.target); + Node *target = Object::cast_to<Node>(c.callable.get_object()); if (!target) { continue; @@ -721,29 +707,29 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName //go through ownership chain to see if this exists while (common_parent) { - Ref<SceneState> ps; - if (common_parent == p_owner) + if (common_parent == p_owner) { ps = common_parent->get_scene_inherited_state(); - else + } else { ps = common_parent->get_scene_instance_state(); + } if (ps.is_valid()) { - NodePath signal_from = common_parent->get_path_to(p_node); NodePath signal_to = common_parent->get_path_to(target); - if (ps->has_connection(signal_from, c.signal, signal_to, c.method)) { + if (ps->has_connection(signal_from, c.signal.get_name(), signal_to, c.callable.get_method())) { exists = true; break; } } - if (common_parent == p_owner) + if (common_parent == p_owner) { break; - else + } else { common_parent = common_parent->get_owner(); + } } if (exists) { //already exists (comes from instance or inheritance), so don't save @@ -756,9 +742,7 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName bool exists2 = false; while (nl) { - if (nl == p_owner) { - Ref<SceneState> state = nl->get_scene_inherited_state(); if (state.is_valid()) { int from_node = state->find_node_by_path(nl->get_path_to(p_node)); @@ -766,14 +750,14 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName if (from_node >= 0 && to_node >= 0) { //this one has state for this node, save - if (state->is_connection(from_node, c.signal, to_node, c.method)) { + if (state->is_connection(from_node, c.signal.get_name(), to_node, c.callable.get_method())) { exists2 = true; break; } } } - nl = NULL; + nl = nullptr; } else { if (nl->get_filename() != String()) { //is an instance @@ -784,7 +768,7 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName if (from_node >= 0 && to_node >= 0) { //this one has state for this node, save - if (state->is_connection(from_node, c.signal, to_node, c.method)) { + if (state->is_connection(from_node, c.signal.get_name(), to_node, c.callable.get_method())) { exists2 = true; break; } @@ -831,11 +815,10 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName ConnectionData cd; cd.from = src_id; cd.to = target_id; - cd.method = _nm_get_string(c.method, name_map); - cd.signal = _nm_get_string(c.signal, name_map); + cd.method = _nm_get_string(c.callable.get_method(), name_map); + cd.signal = _nm_get_string(c.signal.get_name(), name_map); cd.flags = c.flags; for (int i = 0; i < c.binds.size(); i++) { - cd.binds.push_back(_vm_get_variant(c.binds[i], variant_map)); } connections.push_back(cd); @@ -843,11 +826,11 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName } for (int i = 0; i < p_node->get_child_count(); i++) { - Node *c = p_node->get_child(i); Error err = _parse_connections(p_owner, c, name_map, variant_map, node_map, nodepath_map); - if (err) + if (err) { return err; + } } return OK; @@ -865,17 +848,16 @@ Error SceneState::pack(Node *p_scene) { Map<Node *, int> node_map; Map<Node *, int> nodepath_map; - //if using scene inheritance, pack the scene it inherits from + // If using scene inheritance, pack the scene it inherits from. if (scene->get_scene_inherited_state().is_valid()) { String path = scene->get_scene_inherited_state()->get_path(); Ref<PackedScene> instance = ResourceLoader::load(path); if (instance.is_valid()) { - base_scene_idx = _vm_get_variant(instance, variant_map); } } - //instanced, only direct sub-scnes are supported of course + // Instanced, only direct sub-scenes are supported of course. Error err = _parse_node(scene, scene, -1, name_map, variant_map, node_map, nodepath_map); if (err) { clear(); @@ -891,21 +873,18 @@ Error SceneState::pack(Node *p_scene) { names.resize(name_map.size()); for (Map<StringName, int>::Element *E = name_map.front(); E; E = E->next()) { - names.write[E->get()] = E->key(); } variants.resize(variant_map.size()); - const Variant *K = NULL; + const Variant *K = nullptr; while ((K = variant_map.next(K))) { - int idx = variant_map[*K]; variants.write[idx] = *K; } node_paths.resize(nodepath_map.size()); for (Map<Node *, int>::Element *E = nodepath_map.front(); E; E = E->next()) { - node_paths.write[E->get()] = scene->get_path_to(E->key()); } @@ -913,17 +892,14 @@ Error SceneState::pack(Node *p_scene) { } void SceneState::set_path(const String &p_path) { - path = p_path; } String SceneState::get_path() const { - return path; } void SceneState::clear() { - names.clear(); variants.clear(); nodes.clear(); @@ -935,9 +911,7 @@ void SceneState::clear() { } Ref<SceneState> SceneState::_get_base_scene_state() const { - if (base_scene_idx >= 0) { - Ref<PackedScene> ps = variants[base_scene_idx]; if (ps.is_valid()) { return ps->get_state(); @@ -948,7 +922,6 @@ Ref<SceneState> SceneState::_get_base_scene_state() const { } int SceneState::find_node_by_path(const NodePath &p_node) const { - if (!node_path_cache.has(p_node)) { if (_get_base_scene_state().is_valid()) { int idx = _get_base_scene_state()->find_node_by_path(p_node); @@ -980,7 +953,6 @@ int SceneState::find_node_by_path(const NodePath &p_node) const { } int SceneState::_find_base_scene_node_remap_key(int p_idx) const { - for (Map<int, int>::Element *E = base_scene_node_remap.front(); E; E = E->next()) { if (E->value() == p_idx) { return E->key(); @@ -990,7 +962,6 @@ int SceneState::_find_base_scene_node_remap_key(int p_idx) const { } Variant SceneState::get_property_value(int p_node, const StringName &p_property, bool &found) const { - found = false; ERR_FAIL_COND_V(p_node < 0, Variant()); @@ -1019,14 +990,14 @@ Variant SceneState::get_property_value(int p_node, const StringName &p_property, } bool SceneState::is_node_in_group(int p_node, const StringName &p_group) const { - ERR_FAIL_COND_V(p_node < 0, false); if (p_node < nodes.size()) { const StringName *namep = names.ptr(); for (int i = 0; i < nodes[p_node].groups.size(); i++) { - if (namep[nodes[p_node].groups[i]] == p_group) + if (namep[nodes[p_node].groups[i]] == p_group) { return true; + } } } @@ -1040,17 +1011,14 @@ bool SceneState::is_node_in_group(int p_node, const StringName &p_group) const { bool SceneState::disable_placeholders = false; void SceneState::set_disable_placeholders(bool p_disable) { - disable_placeholders = p_disable; } bool SceneState::is_connection(int p_node, const StringName &p_signal, int p_to_node, const StringName &p_to_method) const { - ERR_FAIL_COND_V(p_node < 0, false); ERR_FAIL_COND_V(p_to_node < 0, false); if (p_node < nodes.size() && p_to_node < nodes.size()) { - int signal_idx = -1; int method_idx = -1; for (int i = 0; i < names.size(); i++) { @@ -1065,9 +1033,7 @@ bool SceneState::is_connection(int p_node, const StringName &p_signal, int p_to_ //signal and method strings are stored.. for (int i = 0; i < connections.size(); i++) { - if (connections[i].from == p_node && connections[i].to == p_to_node && connections[i].signal == signal_idx && connections[i].method == method_idx) { - return true; } } @@ -1082,7 +1048,6 @@ bool SceneState::is_connection(int p_node, const StringName &p_signal, int p_to_ } void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { - ERR_FAIL_COND(!p_dictionary.has("names")); ERR_FAIL_COND(!p_dictionary.has("variants")); ERR_FAIL_COND(!p_dictionary.has("node_count")); @@ -1092,27 +1057,28 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { //ERR_FAIL_COND( !p_dictionary.has("path")); int version = 1; - if (p_dictionary.has("version")) + if (p_dictionary.has("version")) { version = p_dictionary["version"]; + } ERR_FAIL_COND_MSG(version > PACKED_SCENE_VERSION, "Save format version too new."); const int node_count = p_dictionary["node_count"]; - const PoolVector<int> snodes = p_dictionary["nodes"]; + const Vector<int> snodes = p_dictionary["nodes"]; ERR_FAIL_COND(snodes.size() < node_count); const int conn_count = p_dictionary["conn_count"]; - const PoolVector<int> sconns = p_dictionary["conns"]; + const Vector<int> sconns = p_dictionary["conns"]; ERR_FAIL_COND(sconns.size() < conn_count); - PoolVector<String> snames = p_dictionary["names"]; + Vector<String> snames = p_dictionary["names"]; if (snames.size()) { - int namecount = snames.size(); names.resize(namecount); - PoolVector<String>::Read r = snames.read(); - for (int i = 0; i < names.size(); i++) + const String *r = snames.ptr(); + for (int i = 0; i < names.size(); i++) { names.write[i] = r[i]; + } } Array svariants = p_dictionary["variants"]; @@ -1121,7 +1087,6 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { int varcount = svariants.size(); variants.resize(varcount); for (int i = 0; i < varcount; i++) { - variants.write[i] = svariants[i]; } @@ -1131,7 +1096,7 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { nodes.resize(node_count); if (node_count) { - PoolVector<int>::Read r = snodes.read(); + const int *r = snodes.ptr(); int idx = 0; for (int i = 0; i < node_count; i++) { NodeData &nd = nodes.write[i]; @@ -1145,13 +1110,11 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { nd.instance = r[idx++]; nd.properties.resize(r[idx++]); for (int j = 0; j < nd.properties.size(); j++) { - nd.properties.write[j].name = r[idx++]; nd.properties.write[j].value = r[idx++]; } nd.groups.resize(r[idx++]); for (int j = 0; j < nd.groups.size(); j++) { - nd.groups.write[j] = r[idx++]; } } @@ -1159,7 +1122,7 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { connections.resize(conn_count); if (conn_count) { - PoolVector<int>::Read r = sconns.read(); + const int *r = sconns.ptr(); int idx = 0; for (int i = 0; i < conn_count; i++) { ConnectionData &cd = connections.write[i]; @@ -1171,7 +1134,6 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { cd.binds.resize(r[idx++]); for (int j = 0; j < cd.binds.size(); j++) { - cd.binds.write[j] = r[idx++]; } } @@ -1204,16 +1166,15 @@ void SceneState::set_bundled_scene(const Dictionary &p_dictionary) { } Dictionary SceneState::get_bundled_scene() const { - - PoolVector<String> rnames; + Vector<String> rnames; rnames.resize(names.size()); if (names.size()) { + String *r = rnames.ptrw(); - PoolVector<String>::Write r = rnames.write(); - - for (int i = 0; i < names.size(); i++) + for (int i = 0; i < names.size(); i++) { r[i] = names[i]; + } } Dictionary d; @@ -1224,7 +1185,6 @@ Dictionary SceneState::get_bundled_scene() const { d["node_count"] = nodes.size(); for (int i = 0; i < nodes.size(); i++) { - const NodeData &nd = nodes[i]; rnodes.push_back(nd.parent); rnodes.push_back(nd.owner); @@ -1237,13 +1197,11 @@ Dictionary SceneState::get_bundled_scene() const { rnodes.push_back(nd.instance); rnodes.push_back(nd.properties.size()); for (int j = 0; j < nd.properties.size(); j++) { - rnodes.push_back(nd.properties[j].name); rnodes.push_back(nd.properties[j].value); } rnodes.push_back(nd.groups.size()); for (int j = 0; j < nd.groups.size(); j++) { - rnodes.push_back(nd.groups[j]); } } @@ -1254,7 +1212,6 @@ Dictionary SceneState::get_bundled_scene() const { d["conn_count"] = connections.size(); for (int i = 0; i < connections.size(); i++) { - const ConnectionData &cd = connections[i]; rconns.push_back(cd.from); rconns.push_back(cd.to); @@ -1262,8 +1219,9 @@ Dictionary SceneState::get_bundled_scene() const { rconns.push_back(cd.method); rconns.push_back(cd.flags); rconns.push_back(cd.binds.size()); - for (int j = 0; j < cd.binds.size(); j++) + for (int j = 0; j < cd.binds.size(); j++) { rconns.push_back(cd.binds[j]); + } } d["conns"] = rconns; @@ -1291,20 +1249,18 @@ Dictionary SceneState::get_bundled_scene() const { } int SceneState::get_node_count() const { - return nodes.size(); } StringName SceneState::get_node_type(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, nodes.size(), StringName()); - if (nodes[p_idx].type == TYPE_INSTANCED) + if (nodes[p_idx].type == TYPE_INSTANCED) { return StringName(); + } return names[nodes[p_idx].type]; } StringName SceneState::get_node_name(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, nodes.size(), StringName()); return names[nodes[p_idx].name]; } @@ -1315,7 +1271,6 @@ int SceneState::get_node_index(int p_idx) const { } bool SceneState::is_node_instance_placeholder(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, nodes.size(), false); return nodes[p_idx].instance >= 0 && (nodes[p_idx].instance & FLAG_INSTANCE_IS_PLACEHOLDER); @@ -1325,12 +1280,12 @@ Ref<PackedScene> SceneState::get_node_instance(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, nodes.size(), Ref<PackedScene>()); if (nodes[p_idx].instance >= 0) { - if (nodes[p_idx].instance & FLAG_INSTANCE_IS_PLACEHOLDER) + if (nodes[p_idx].instance & FLAG_INSTANCE_IS_PLACEHOLDER) { return Ref<PackedScene>(); - else + } else { return variants[nodes[p_idx].instance & FLAG_MASK]; + } } else if (nodes[p_idx].parent < 0 || nodes[p_idx].parent == NO_PARENT_SAVED) { - if (base_scene_idx >= 0) { return variants[base_scene_idx]; } @@ -1340,7 +1295,6 @@ Ref<PackedScene> SceneState::get_node_instance(int p_idx) const { } String SceneState::get_node_instance_placeholder(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, nodes.size(), String()); if (nodes[p_idx].instance >= 0 && (nodes[p_idx].instance & FLAG_INSTANCE_IS_PLACEHOLDER)) { @@ -1360,7 +1314,6 @@ Vector<StringName> SceneState::get_node_groups(int p_idx) const { } NodePath SceneState::get_node_path(int p_idx, bool p_for_parent) const { - ERR_FAIL_INDEX_V(p_idx, nodes.size(), NodePath()); if (nodes[p_idx].parent < 0 || nodes[p_idx].parent == NO_PARENT_SAVED) { @@ -1376,7 +1329,6 @@ NodePath SceneState::get_node_path(int p_idx, bool p_for_parent) const { int nidx = p_idx; while (true) { if (nodes[nidx].parent == NO_PARENT_SAVED || nodes[nidx].parent < 0) { - sub_path.insert(0, "."); break; } @@ -1405,15 +1357,16 @@ NodePath SceneState::get_node_path(int p_idx, bool p_for_parent) const { } int SceneState::get_node_property_count(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, nodes.size(), -1); return nodes[p_idx].properties.size(); } + StringName SceneState::get_node_property_name(int p_idx, int p_prop) const { ERR_FAIL_INDEX_V(p_idx, nodes.size(), StringName()); ERR_FAIL_INDEX_V(p_prop, nodes[p_idx].properties.size(), StringName()); return names[nodes[p_idx].properties[p_prop].name]; } + Variant SceneState::get_node_property_value(int p_idx, int p_prop) const { ERR_FAIL_INDEX_V(p_idx, nodes.size(), Variant()); ERR_FAIL_INDEX_V(p_prop, nodes[p_idx].properties.size(), Variant()); @@ -1422,10 +1375,10 @@ Variant SceneState::get_node_property_value(int p_idx, int p_prop) const { } NodePath SceneState::get_node_owner_path(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, nodes.size(), NodePath()); - if (nodes[p_idx].owner < 0 || nodes[p_idx].owner == NO_PARENT_SAVED) + if (nodes[p_idx].owner < 0 || nodes[p_idx].owner == NO_PARENT_SAVED) { return NodePath(); //root likely + } if (nodes[p_idx].owner & FLAG_ID_IS_PATH) { return node_paths[nodes[p_idx].owner & FLAG_MASK]; } else { @@ -1434,11 +1387,10 @@ NodePath SceneState::get_node_owner_path(int p_idx) const { } int SceneState::get_connection_count() const { - return connections.size(); } -NodePath SceneState::get_connection_source(int p_idx) const { +NodePath SceneState::get_connection_source(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, connections.size(), NodePath()); if (connections[p_idx].from & FLAG_ID_IS_PATH) { return node_paths[connections[p_idx].from & FLAG_MASK]; @@ -1448,12 +1400,11 @@ NodePath SceneState::get_connection_source(int p_idx) const { } StringName SceneState::get_connection_signal(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, connections.size(), StringName()); return names[connections[p_idx].signal]; } -NodePath SceneState::get_connection_target(int p_idx) const { +NodePath SceneState::get_connection_target(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, connections.size(), NodePath()); if (connections[p_idx].to & FLAG_ID_IS_PATH) { return node_paths[connections[p_idx].to & FLAG_MASK]; @@ -1461,20 +1412,18 @@ NodePath SceneState::get_connection_target(int p_idx) const { return get_node_path(connections[p_idx].to & FLAG_MASK); } } -StringName SceneState::get_connection_method(int p_idx) const { +StringName SceneState::get_connection_method(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, connections.size(), StringName()); return names[connections[p_idx].method]; } int SceneState::get_connection_flags(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, connections.size(), -1); return connections[p_idx].flags; } Array SceneState::get_connection_binds(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, connections.size(), Array()); Array binds; for (int i = 0; i < connections[p_idx].binds.size(); i++) { @@ -1484,7 +1433,6 @@ Array SceneState::get_connection_binds(int p_idx) const { } bool SceneState::has_connection(const NodePath &p_node_from, const StringName &p_signal, const NodePath &p_node_to, const StringName &p_method) { - // this method cannot be const because of this Ref<SceneState> ss = this; @@ -1525,37 +1473,35 @@ bool SceneState::has_connection(const NodePath &p_node_from, const StringName &p Vector<NodePath> SceneState::get_editable_instances() const { return editable_instances; } + //add int SceneState::add_name(const StringName &p_name) { - names.push_back(p_name); return names.size() - 1; } int SceneState::find_name(const StringName &p_name) const { - for (int i = 0; i < names.size(); i++) { - if (names[i] == p_name) + if (names[i] == p_name) { return i; + } } return -1; } int SceneState::add_value(const Variant &p_value) { - variants.push_back(p_value); return variants.size() - 1; } int SceneState::add_node_path(const NodePath &p_path) { - node_paths.push_back(p_path); return (node_paths.size() - 1) | FLAG_ID_IS_PATH; } -int SceneState::add_node(int p_parent, int p_owner, int p_type, int p_name, int p_instance, int p_index) { +int SceneState::add_node(int p_parent, int p_owner, int p_type, int p_name, int p_instance, int p_index) { NodeData nd; nd.parent = p_parent; nd.owner = p_owner; @@ -1568,8 +1514,8 @@ int SceneState::add_node(int p_parent, int p_owner, int p_type, int p_name, int return nodes.size() - 1; } -void SceneState::add_node_property(int p_node, int p_name, int p_value) { +void SceneState::add_node_property(int p_node, int p_name, int p_value) { ERR_FAIL_INDEX(p_node, nodes.size()); ERR_FAIL_INDEX(p_name, names.size()); ERR_FAIL_INDEX(p_value, variants.size()); @@ -1579,19 +1525,19 @@ void SceneState::add_node_property(int p_node, int p_name, int p_value) { prop.value = p_value; nodes.write[p_node].properties.push_back(prop); } -void SceneState::add_node_group(int p_node, int p_group) { +void SceneState::add_node_group(int p_node, int p_group) { ERR_FAIL_INDEX(p_node, nodes.size()); ERR_FAIL_INDEX(p_group, names.size()); nodes.write[p_node].groups.push_back(p_group); } -void SceneState::set_base_scene(int p_idx) { +void SceneState::set_base_scene(int p_idx) { ERR_FAIL_INDEX(p_idx, variants.size()); base_scene_idx = p_idx; } -void SceneState::add_connection(int p_from, int p_to, int p_signal, int p_method, int p_flags, const Vector<int> &p_binds) { +void SceneState::add_connection(int p_from, int p_to, int p_signal, int p_method, int p_flags, const Vector<int> &p_binds) { ERR_FAIL_INDEX(p_signal, names.size()); ERR_FAIL_INDEX(p_method, names.size()); @@ -1607,24 +1553,23 @@ void SceneState::add_connection(int p_from, int p_to, int p_signal, int p_method c.binds = p_binds; connections.push_back(c); } -void SceneState::add_editable_instance(const NodePath &p_path) { +void SceneState::add_editable_instance(const NodePath &p_path) { editable_instances.push_back(p_path); } -PoolVector<String> SceneState::_get_node_groups(int p_idx) const { - +Vector<String> SceneState::_get_node_groups(int p_idx) const { Vector<StringName> groups = get_node_groups(p_idx); - PoolVector<String> ret; + Vector<String> ret; - for (int i = 0; i < groups.size(); i++) + for (int i = 0; i < groups.size(); i++) { ret.push_back(groups[i]); + } return ret; } void SceneState::_bind_methods() { - //unbuild API ClassDB::bind_method(D_METHOD("get_node_count"), &SceneState::get_node_count); @@ -1654,7 +1599,6 @@ void SceneState::_bind_methods() { } SceneState::SceneState() { - base_scene_idx = -1; last_modified_time = 0; } @@ -1662,46 +1606,42 @@ SceneState::SceneState() { //////////////// void PackedScene::_set_bundled_scene(const Dictionary &p_scene) { - state->set_bundled_scene(p_scene); } Dictionary PackedScene::_get_bundled_scene() const { - return state->get_bundled_scene(); } Error PackedScene::pack(Node *p_scene) { - return state->pack(p_scene); } void PackedScene::clear() { - state->clear(); } bool PackedScene::can_instance() const { - return state->can_instance(); } Node *PackedScene::instance(GenEditState p_edit_state) const { - #ifndef TOOLS_ENABLED - ERR_FAIL_COND_V_MSG(p_edit_state != GEN_EDIT_STATE_DISABLED, NULL, "Edit state is only for editors, does not work without tools compiled."); + ERR_FAIL_COND_V_MSG(p_edit_state != GEN_EDIT_STATE_DISABLED, nullptr, "Edit state is only for editors, does not work without tools compiled."); #endif Node *s = state->instance((SceneState::GenEditState)p_edit_state); - if (!s) - return NULL; + if (!s) { + return nullptr; + } if (p_edit_state != GEN_EDIT_STATE_DISABLED) { s->set_scene_instance_state(state); } - if (get_path() != "" && get_path().find("::") == -1) + if (get_path() != "" && get_path().find("::") == -1) { s->set_filename(get_path()); + } s->notification(Node::NOTIFICATION_INSTANCED); @@ -1709,7 +1649,6 @@ Node *PackedScene::instance(GenEditState p_edit_state) const { } void PackedScene::replace_state(Ref<SceneState> p_by) { - state = p_by; state->set_path(get_path()); #ifdef TOOLS_ENABLED @@ -1718,7 +1657,6 @@ void PackedScene::replace_state(Ref<SceneState> p_by) { } void PackedScene::recreate_state() { - state = Ref<SceneState>(memnew(SceneState)); state->set_path(get_path()); #ifdef TOOLS_ENABLED @@ -1727,18 +1665,15 @@ void PackedScene::recreate_state() { } Ref<SceneState> PackedScene::get_state() { - return state; } void PackedScene::set_path(const String &p_path, bool p_take_over) { - state->set_path(p_path); Resource::set_path(p_path, p_take_over); } void PackedScene::_bind_methods() { - ClassDB::bind_method(D_METHOD("pack", "path"), &PackedScene::pack); ClassDB::bind_method(D_METHOD("instance", "edit_state"), &PackedScene::instance, DEFVAL(GEN_EDIT_STATE_DISABLED)); ClassDB::bind_method(D_METHOD("can_instance"), &PackedScene::can_instance); @@ -1754,6 +1689,5 @@ void PackedScene::_bind_methods() { } PackedScene::PackedScene() { - state = Ref<SceneState>(memnew(SceneState)); } diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h index b4966e2528..004758afa5 100644 --- a/scene/resources/packed_scene.h +++ b/scene/resources/packed_scene.h @@ -35,7 +35,6 @@ #include "scene/main/node.h" class SceneState : public Reference { - GDCLASS(SceneState, Reference); Vector<StringName> names; @@ -54,7 +53,6 @@ class SceneState : public Reference { }; struct NodeData { - int parent; int owner; int type; @@ -63,7 +61,6 @@ class SceneState : public Reference { int index; struct Property { - int name; int value; }; @@ -81,7 +78,6 @@ class SceneState : public Reference { Vector<NodeData> nodes; struct ConnectionData { - int from; int to; int signal; @@ -103,7 +99,7 @@ class SceneState : public Reference { static bool disable_placeholders; - PoolVector<String> _get_node_groups(int p_idx) const; + Vector<String> _get_node_groups(int p_idx) const; int _find_base_scene_node_remap_key(int p_idx) const; @@ -195,7 +191,6 @@ public: VARIANT_ENUM_CAST(SceneState::GenEditState) class PackedScene : public Resource { - GDCLASS(PackedScene, Resource); RES_BASE_EXTENSION("scn"); @@ -205,7 +200,7 @@ class PackedScene : public Resource { Dictionary _get_bundled_scene() const; protected: - virtual bool editor_can_reload_from_file() { return false; } // this is handled by editor better + virtual bool editor_can_reload_from_file() override { return false; } // this is handled by editor better static void _bind_methods(); public: @@ -225,9 +220,9 @@ public: void recreate_state(); void replace_state(Ref<SceneState> p_by); - virtual void set_path(const String &p_path, bool p_take_over = false); + virtual void set_path(const String &p_path, bool p_take_over = false) override; #ifdef TOOLS_ENABLED - virtual void set_last_modified_time(uint64_t p_time) { state->set_last_modified_time(p_time); } + virtual void set_last_modified_time(uint64_t p_time) override { state->set_last_modified_time(p_time); } #endif Ref<SceneState> get_state(); diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index 412b5c259c..4bbfa8965a 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -30,17 +30,12 @@ #include "particles_material.h" -Mutex *ParticlesMaterial::material_mutex = NULL; -SelfList<ParticlesMaterial>::List *ParticlesMaterial::dirty_materials = NULL; +Mutex ParticlesMaterial::material_mutex; +SelfList<ParticlesMaterial>::List *ParticlesMaterial::dirty_materials = nullptr; Map<ParticlesMaterial::MaterialKey, ParticlesMaterial::ShaderData> ParticlesMaterial::shader_map; -ParticlesMaterial::ShaderNames *ParticlesMaterial::shader_names = NULL; +ParticlesMaterial::ShaderNames *ParticlesMaterial::shader_names = nullptr; void ParticlesMaterial::init_shaders() { - -#ifndef NO_THREADS - material_mutex = Mutex::create(); -#endif - dirty_materials = memnew(SelfList<ParticlesMaterial>::List); shader_names = memnew(ShaderNames); @@ -96,40 +91,35 @@ void ParticlesMaterial::init_shaders() { shader_names->emission_texture_normal = "emission_texture_normal"; shader_names->emission_texture_color = "emission_texture_color"; - shader_names->trail_divisor = "trail_divisor"; - shader_names->trail_size_modifier = "trail_size_modifier"; - shader_names->trail_color_modifier = "trail_color_modifier"; - shader_names->gravity = "gravity"; shader_names->lifetime_randomness = "lifetime_randomness"; + + shader_names->sub_emitter_frequency = "sub_emitter_frequency"; + shader_names->sub_emitter_amount_at_end = "sub_emitter_amount_at_end"; + shader_names->sub_emitter_keep_velocity = "sub_emitter_keep_velocity"; } void ParticlesMaterial::finish_shaders() { - -#ifndef NO_THREADS - memdelete(material_mutex); -#endif - memdelete(dirty_materials); - dirty_materials = NULL; + dirty_materials = nullptr; memdelete(shader_names); } void ParticlesMaterial::_update_shader() { - dirty_materials->remove(&element); MaterialKey mk = _compute_key(); - if (mk.key == current_key.key) + if (mk.key == current_key.key) { return; //no update required in the end + } if (shader_map.has(current_key)) { shader_map[current_key].users--; if (shader_map[current_key].users == 0) { //deallocate shader, as it's no longer in use - VS::get_singleton()->free(shader_map[current_key].shader); + RS::get_singleton()->free(shader_map[current_key].shader); shader_map.erase(current_key); } } @@ -137,8 +127,7 @@ void ParticlesMaterial::_update_shader() { current_key = mk; if (shader_map.has(mk)) { - - VS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); + RS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); shader_map[mk].users++; return; } @@ -189,7 +178,7 @@ void ParticlesMaterial::_update_shader() { } break; case EMISSION_SHAPE_DIRECTED_POINTS: { code += "uniform sampler2D emission_texture_normal : hint_black;\n"; - FALLTHROUGH; + [[fallthrough]]; } case EMISSION_SHAPE_POINTS: { code += "uniform sampler2D emission_texture_points : hint_black;\n"; @@ -203,46 +192,59 @@ void ParticlesMaterial::_update_shader() { } } - code += "uniform vec4 color_value : hint_color;\n"; + if (sub_emitter_mode != SUB_EMITTER_DISABLED) { + if (sub_emitter_mode == SUB_EMITTER_CONSTANT) { + code += "uniform float sub_emitter_frequency;\n"; + } + if (sub_emitter_mode == SUB_EMITTER_AT_END) { + code += "uniform int sub_emitter_amount_at_end;\n"; + } + code += "uniform bool sub_emitter_keep_velocity;\n"; + } - code += "uniform int trail_divisor;\n"; + code += "uniform vec4 color_value : hint_color;\n"; code += "uniform vec3 gravity;\n"; - if (color_ramp.is_valid()) + if (color_ramp.is_valid()) { code += "uniform sampler2D color_ramp;\n"; + } - if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { code += "uniform sampler2D linear_velocity_texture;\n"; - if (tex_parameters[PARAM_ORBIT_VELOCITY].is_valid()) + } + if (tex_parameters[PARAM_ORBIT_VELOCITY].is_valid()) { code += "uniform sampler2D orbit_velocity_texture;\n"; - if (tex_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) + } + if (tex_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) { code += "uniform sampler2D angular_velocity_texture;\n"; - if (tex_parameters[PARAM_LINEAR_ACCEL].is_valid()) + } + if (tex_parameters[PARAM_LINEAR_ACCEL].is_valid()) { code += "uniform sampler2D linear_accel_texture;\n"; - if (tex_parameters[PARAM_RADIAL_ACCEL].is_valid()) + } + if (tex_parameters[PARAM_RADIAL_ACCEL].is_valid()) { code += "uniform sampler2D radial_accel_texture;\n"; - if (tex_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) + } + if (tex_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) { code += "uniform sampler2D tangent_accel_texture;\n"; - if (tex_parameters[PARAM_DAMPING].is_valid()) + } + if (tex_parameters[PARAM_DAMPING].is_valid()) { code += "uniform sampler2D damping_texture;\n"; - if (tex_parameters[PARAM_ANGLE].is_valid()) + } + if (tex_parameters[PARAM_ANGLE].is_valid()) { code += "uniform sampler2D angle_texture;\n"; - if (tex_parameters[PARAM_SCALE].is_valid()) + } + if (tex_parameters[PARAM_SCALE].is_valid()) { code += "uniform sampler2D scale_texture;\n"; - if (tex_parameters[PARAM_HUE_VARIATION].is_valid()) + } + if (tex_parameters[PARAM_HUE_VARIATION].is_valid()) { code += "uniform sampler2D hue_variation_texture;\n"; - if (tex_parameters[PARAM_ANIM_SPEED].is_valid()) + } + if (tex_parameters[PARAM_ANIM_SPEED].is_valid()) { code += "uniform sampler2D anim_speed_texture;\n"; - if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) - code += "uniform sampler2D anim_offset_texture;\n"; - - if (trail_size_modifier.is_valid()) { - code += "uniform sampler2D trail_size_modifier;\n"; } - - if (trail_color_modifier.is_valid()) { - code += "uniform sampler2D trail_color_modifier;\n"; + if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) { + code += "uniform sampler2D anim_offset_texture;\n"; } //need a random function @@ -275,8 +277,8 @@ void ParticlesMaterial::_update_shader() { code += "}\n"; code += "\n"; - code += "void vertex() {\n"; - code += " uint base_number = NUMBER / uint(trail_divisor);\n"; + code += "void compute() {\n"; + code += " uint base_number = NUMBER;\n"; code += " uint alt_seed = hash(base_number + uint(1) + RANDOM_SEED);\n"; code += " float angle_rand = rand_from_seed(alt_seed);\n"; code += " float scale_rand = rand_from_seed(alt_seed);\n"; @@ -291,46 +293,50 @@ void ParticlesMaterial::_update_shader() { code += " ivec2 emission_tex_size = textureSize(emission_texture_points, 0);\n"; code += " ivec2 emission_tex_ofs = ivec2(point % emission_tex_size.x, point / emission_tex_size.x);\n"; } - code += " bool restart = false;\n"; - code += " if (CUSTOM.y > CUSTOM.w) {\n"; - code += " restart = true;\n"; - code += " }\n\n"; - code += " if (RESTART || restart) {\n"; - - if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) - code += " float tex_linear_velocity = textureLod(linear_velocity_texture, vec2(0.0, 0.0), 0.0).r;\n"; - else - code += " float tex_linear_velocity = 0.0;\n"; + code += " if (RESTART) {\n"; - if (tex_parameters[PARAM_ANGLE].is_valid()) + if (tex_parameters[PARAM_ANGLE].is_valid()) { code += " float tex_angle = textureLod(angle_texture, vec2(0.0, 0.0), 0.0).r;\n"; - else + } else { code += " float tex_angle = 0.0;\n"; + } - if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) + if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) { code += " float tex_anim_offset = textureLod(anim_offset_texture, vec2(0.0, 0.0), 0.0).r;\n"; - else + } else { code += " float tex_anim_offset = 0.0;\n"; + } code += " float spread_rad = spread * degree_to_rad;\n"; - if (flags[FLAG_DISABLE_Z]) { + code += " if (RESTART_VELOCITY) {\n"; + + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { + code += " float tex_linear_velocity = textureLod(linear_velocity_texture, vec2(0.0, 0.0), 0.0).r;\n"; + } else { + code += " float tex_linear_velocity = 0.0;\n"; + } - code += " float angle1_rad = atan(direction.y, direction.x) + rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; - code += " vec3 rot = vec3(cos(angle1_rad), sin(angle1_rad), 0.0);\n"; - code += " VELOCITY = rot * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; + if (flags[FLAG_DISABLE_Z]) { + code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; + code += " angle1_rad += direction.x != 0.0 ? atan(direction.y, direction.x) : sign(direction.y) * (pi / 2.0);\n"; + code += " vec3 rot = vec3(cos(angle1_rad), sin(angle1_rad), 0.0);\n"; + code += " VELOCITY = rot * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; } else { //initiate velocity spread in 3D - code += " float angle1_rad = atan(direction.x, direction.z) + rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; - code += " float angle2_rad = atan(direction.y, abs(direction.z)) + rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n"; - code += " vec3 direction_xz = vec3(sin(angle1_rad), 0.0, cos(angle1_rad));\n"; - code += " vec3 direction_yz = vec3(0.0, sin(angle2_rad), cos(angle2_rad));\n"; - code += " direction_yz.z = direction_yz.z / max(0.0001,sqrt(abs(direction_yz.z))); // better uniform distribution\n"; - code += " vec3 vec_direction = vec3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);\n"; - code += " vec_direction = normalize(vec_direction);\n"; - code += " VELOCITY = vec_direction * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; + code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; + code += " float angle2_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n"; + code += " angle1_rad += direction.z != 0.0 ? atan(direction.x, direction.z) : sign(direction.x) * (pi / 2.0);\n"; + code += " angle2_rad += direction.z != 0.0 ? atan(direction.y, abs(direction.z)) : (direction.x != 0.0 ? atan(direction.y, abs(direction.x)) : sign(direction.y) * (pi / 2.0));\n"; + code += " vec3 direction_xz = vec3(sin(angle1_rad), 0.0, cos(angle1_rad));\n"; + code += " vec3 direction_yz = vec3(0.0, sin(angle2_rad), cos(angle2_rad));\n"; + code += " direction_yz.z = direction_yz.z / max(0.0001,sqrt(abs(direction_yz.z))); // better uniform distribution\n"; + code += " vec3 vec_direction = vec3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);\n"; + code += " vec_direction = normalize(vec_direction);\n"; + code += " VELOCITY = vec_direction * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; } + code += " }\n"; code += " float base_angle = (initial_angle + tex_angle) * mix(1.0, angle_rand, initial_angle_random);\n"; code += " CUSTOM.x = base_angle * degree_to_rad;\n"; // angle @@ -338,36 +344,38 @@ void ParticlesMaterial::_update_shader() { code += " CUSTOM.w = (1.0 - lifetime_randomness * rand_from_seed(alt_seed));\n"; code += " CUSTOM.z = (anim_offset + tex_anim_offset) * mix(1.0, anim_offset_rand, anim_offset_random);\n"; // animation offset (0-1) + code += " if (RESTART_POSITION) {\n"; + switch (emission_shape) { case EMISSION_SHAPE_POINT: { - //do none + //do none, identity (will later be multiplied by emission transform) + code += " TRANSFORM = mat4(vec4(1,0,0,0),vec4(0,1,0,0),vec4(0,0,1,0),vec4(0,0,0,1));\n"; } break; case EMISSION_SHAPE_SPHERE: { - code += " float s = rand_from_seed(alt_seed) * 2.0 - 1.0;\n"; - code += " float t = rand_from_seed(alt_seed) * 2.0 * pi;\n"; - code += " float radius = emission_sphere_radius * sqrt(1.0 - s * s);\n"; - code += " TRANSFORM[3].xyz = vec3(radius * cos(t), radius * sin(t), emission_sphere_radius * s);\n"; + code += " float s = rand_from_seed(alt_seed) * 2.0 - 1.0;\n"; + code += " float t = rand_from_seed(alt_seed) * 2.0 * pi;\n"; + code += " float radius = emission_sphere_radius * sqrt(1.0 - s * s);\n"; + code += " TRANSFORM[3].xyz = vec3(radius * cos(t), radius * sin(t), emission_sphere_radius * s);\n"; } break; case EMISSION_SHAPE_BOX: { - code += " TRANSFORM[3].xyz = vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0) * emission_box_extents;\n"; + code += " TRANSFORM[3].xyz = vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0) * emission_box_extents;\n"; } break; case EMISSION_SHAPE_POINTS: case EMISSION_SHAPE_DIRECTED_POINTS: { - code += " TRANSFORM[3].xyz = texelFetch(emission_texture_points, emission_tex_ofs, 0).xyz;\n"; + code += " TRANSFORM[3].xyz = texelFetch(emission_texture_points, emission_tex_ofs, 0).xyz;\n"; if (emission_shape == EMISSION_SHAPE_DIRECTED_POINTS) { if (flags[FLAG_DISABLE_Z]) { - - code += " mat2 rotm;"; - code += " rotm[0] = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xy;\n"; - code += " rotm[1] = rotm[0].yx * vec2(1.0, -1.0);\n"; - code += " VELOCITY.xy = rotm * VELOCITY.xy;\n"; + code += " mat2 rotm;"; + code += " rotm[0] = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xy;\n"; + code += " rotm[1] = rotm[0].yx * vec2(1.0, -1.0);\n"; + code += " if (RESTART_VELOCITY) VELOCITY.xy = rotm * VELOCITY.xy;\n"; } else { - code += " vec3 normal = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xyz;\n"; - code += " vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);\n"; - code += " vec3 tangent = normalize(cross(v0, normal));\n"; - code += " vec3 bitangent = normalize(cross(tangent, normal));\n"; - code += " VELOCITY = mat3(tangent, bitangent, normal) * VELOCITY;\n"; + code += " vec3 normal = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xyz;\n"; + code += " vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);\n"; + code += " vec3 tangent = normalize(cross(v0, normal));\n"; + code += " vec3 bitangent = normalize(cross(tangent, normal));\n"; + code += " if (RESTART_VELOCITY) VELOCITY = mat3(tangent, bitangent, normal) * VELOCITY;\n"; } } } break; @@ -375,68 +383,79 @@ void ParticlesMaterial::_update_shader() { break; } } - code += " VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;\n"; - code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n"; + + code += " if (RESTART_VELOCITY) VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;\n"; + code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n"; if (flags[FLAG_DISABLE_Z]) { - code += " VELOCITY.z = 0.0;\n"; - code += " TRANSFORM[3].z = 0.0;\n"; + code += " VELOCITY.z = 0.0;\n"; + code += " TRANSFORM[3].z = 0.0;\n"; } + code += " }\n"; code += " } else {\n"; code += " CUSTOM.y += DELTA / LIFETIME;\n"; - if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { code += " float tex_linear_velocity = textureLod(linear_velocity_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; - else + } else { code += " float tex_linear_velocity = 0.0;\n"; + } if (flags[FLAG_DISABLE_Z]) { - - if (tex_parameters[PARAM_ORBIT_VELOCITY].is_valid()) + if (tex_parameters[PARAM_ORBIT_VELOCITY].is_valid()) { code += " float tex_orbit_velocity = textureLod(orbit_velocity_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; - else + } else { code += " float tex_orbit_velocity = 0.0;\n"; + } } - if (tex_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) + if (tex_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) { code += " float tex_angular_velocity = textureLod(angular_velocity_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; - else + } else { code += " float tex_angular_velocity = 0.0;\n"; + } - if (tex_parameters[PARAM_LINEAR_ACCEL].is_valid()) + if (tex_parameters[PARAM_LINEAR_ACCEL].is_valid()) { code += " float tex_linear_accel = textureLod(linear_accel_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; - else + } else { code += " float tex_linear_accel = 0.0;\n"; + } - if (tex_parameters[PARAM_RADIAL_ACCEL].is_valid()) + if (tex_parameters[PARAM_RADIAL_ACCEL].is_valid()) { code += " float tex_radial_accel = textureLod(radial_accel_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; - else + } else { code += " float tex_radial_accel = 0.0;\n"; + } - if (tex_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) + if (tex_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) { code += " float tex_tangent_accel = textureLod(tangent_accel_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; - else + } else { code += " float tex_tangent_accel = 0.0;\n"; + } - if (tex_parameters[PARAM_DAMPING].is_valid()) + if (tex_parameters[PARAM_DAMPING].is_valid()) { code += " float tex_damping = textureLod(damping_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; - else + } else { code += " float tex_damping = 0.0;\n"; + } - if (tex_parameters[PARAM_ANGLE].is_valid()) + if (tex_parameters[PARAM_ANGLE].is_valid()) { code += " float tex_angle = textureLod(angle_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; - else + } else { code += " float tex_angle = 0.0;\n"; + } - if (tex_parameters[PARAM_ANIM_SPEED].is_valid()) + if (tex_parameters[PARAM_ANIM_SPEED].is_valid()) { code += " float tex_anim_speed = textureLod(anim_speed_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; - else + } else { code += " float tex_anim_speed = 0.0;\n"; + } - if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) + if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) { code += " float tex_anim_offset = textureLod(anim_offset_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; - else + } else { code += " float tex_anim_offset = 0.0;\n"; + } code += " vec3 force = gravity;\n"; code += " vec3 pos = TRANSFORM[3].xyz;\n"; @@ -461,7 +480,6 @@ void ParticlesMaterial::_update_shader() { code += " VELOCITY += force * DELTA;\n"; code += " // orbit velocity\n"; if (flags[FLAG_DISABLE_Z]) { - code += " float orbit_amount = (orbit_velocity + tex_orbit_velocity) * mix(1.0, rand_from_seed(alt_seed), orbit_velocity_random);\n"; code += " if (orbit_amount != 0.0) {\n"; code += " float ang = orbit_amount * DELTA * pi * 2.0;\n"; @@ -491,15 +509,17 @@ void ParticlesMaterial::_update_shader() { code += " }\n"; // apply color // apply hue rotation - if (tex_parameters[PARAM_SCALE].is_valid()) + if (tex_parameters[PARAM_SCALE].is_valid()) { code += " float tex_scale = textureLod(scale_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; - else + } else { code += " float tex_scale = 1.0;\n"; + } - if (tex_parameters[PARAM_HUE_VARIATION].is_valid()) + if (tex_parameters[PARAM_HUE_VARIATION].is_valid()) { code += " float tex_hue_variation = textureLod(hue_variation_texture, vec2(CUSTOM.y, 0.0), 0.0).r;\n"; - else + } else { code += " float tex_hue_variation = 0.0;\n"; + } code += " float hue_rot_angle = (hue_variation + tex_hue_variation) * pi * 2.0 * mix(1.0, hue_rot_rand * 2.0 - 1.0, hue_variation_random);\n"; code += " float hue_rot_c = cos(hue_rot_angle);\n"; @@ -524,15 +544,9 @@ void ParticlesMaterial::_update_shader() { if (emission_color_texture.is_valid() && (emission_shape == EMISSION_SHAPE_POINTS || emission_shape == EMISSION_SHAPE_DIRECTED_POINTS)) { code += " COLOR *= texelFetch(emission_texture_color, emission_tex_ofs, 0);\n"; } - if (trail_color_modifier.is_valid()) { - code += " if (trail_divisor > 1) {\n"; - code += " COLOR *= textureLod(trail_color_modifier, vec2(float(int(NUMBER) % trail_divisor) / float(trail_divisor - 1), 0.0), 0.0);\n"; - code += " }\n"; - } code += "\n"; if (flags[FLAG_DISABLE_Z]) { - if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) { code += " if (length(VELOCITY) > 0.0) {\n"; code += " TRANSFORM[1].xyz = normalize(VELOCITY);\n"; @@ -577,11 +591,6 @@ void ParticlesMaterial::_update_shader() { code += " if (base_scale < 0.000001) {\n"; code += " base_scale = 0.000001;\n"; code += " }\n"; - if (trail_size_modifier.is_valid()) { - code += " if (trail_divisor > 1) {\n"; - code += " base_scale *= textureLod(trail_size_modifier, vec2(float(int(NUMBER) % trail_divisor) / float(trail_divisor - 1), 0.0), 0.0).r;\n"; - code += " }\n"; - } code += " TRANSFORM[0].xyz *= base_scale;\n"; code += " TRANSFORM[1].xyz *= base_scale;\n"; @@ -590,6 +599,33 @@ void ParticlesMaterial::_update_shader() { code += " VELOCITY.z = 0.0;\n"; code += " TRANSFORM[3].z = 0.0;\n"; } + if (sub_emitter_mode != SUB_EMITTER_DISABLED) { + code += " int emit_count = 0;\n"; + switch (sub_emitter_mode) { + case SUB_EMITTER_CONSTANT: { + code += " float interval_from = CUSTOM.y * LIFETIME - DELTA;\n"; + code += " float interval_rem = sub_emitter_frequency - mod(interval_from,sub_emitter_frequency);\n"; + code += " if (DELTA >= interval_rem) emit_count = 1;\n"; + } break; + case SUB_EMITTER_AT_COLLISION: { + //not implemented yet + } break; + case SUB_EMITTER_AT_END: { + //not implemented yet + code += " float unit_delta = DELTA/LIFETIME;\n"; + code += " float end_time = CUSTOM.w * 0.95;\n"; // if we do at the end we might miss it, as it can just get deactivated by emitter + code += " if (CUSTOM.y < end_time && (CUSTOM.y + unit_delta) >= end_time) emit_count = sub_emitter_amount_at_end;\n"; + } break; + default: { + } + } + code += " for(int i=0;i<emit_count;i++) {\n"; + code += " uint flags = FLAG_EMIT_POSITION|FLAG_EMIT_ROT_SCALE;\n"; + code += " if (sub_emitter_keep_velocity) flags|=FLAG_EMIT_VELOCITY;\n"; + code += " emit_particle(TRANSFORM,VELOCITY,vec4(0.0),vec4(0.0),flags);\n"; + code += " }"; + } + code += " if (CUSTOM.y > CUSTOM.w) {"; code += " ACTIVE = false;\n"; code += " }\n"; @@ -597,207 +633,181 @@ void ParticlesMaterial::_update_shader() { code += "\n"; ShaderData shader_data; - shader_data.shader = VS::get_singleton()->shader_create(); + shader_data.shader = RS::get_singleton()->shader_create(); shader_data.users = 1; - VS::get_singleton()->shader_set_code(shader_data.shader, code); + RS::get_singleton()->shader_set_code(shader_data.shader, code); shader_map[mk] = shader_data; - VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); + RS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); } void ParticlesMaterial::flush_changes() { - - if (material_mutex) - material_mutex->lock(); + MutexLock lock(material_mutex); while (dirty_materials->first()) { - dirty_materials->first()->self()->_update_shader(); } - - if (material_mutex) - material_mutex->unlock(); } void ParticlesMaterial::_queue_shader_change() { - - if (material_mutex) - material_mutex->lock(); + MutexLock lock(material_mutex); if (!element.in_list()) { dirty_materials->add(&element); } - - if (material_mutex) - material_mutex->unlock(); } bool ParticlesMaterial::_is_shader_dirty() const { + MutexLock lock(material_mutex); - bool dirty = false; - - if (material_mutex) - material_mutex->lock(); - - dirty = element.in_list(); - - if (material_mutex) - material_mutex->unlock(); - - return dirty; + return element.in_list(); } void ParticlesMaterial::set_direction(Vector3 p_direction) { - direction = p_direction; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->direction, direction); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->direction, direction); } Vector3 ParticlesMaterial::get_direction() const { - return direction; } void ParticlesMaterial::set_spread(float p_spread) { - spread = p_spread; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->spread, p_spread); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->spread, p_spread); } float ParticlesMaterial::get_spread() const { - return spread; } void ParticlesMaterial::set_flatness(float p_flatness) { - flatness = p_flatness; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->flatness, p_flatness); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->flatness, p_flatness); } -float ParticlesMaterial::get_flatness() const { +float ParticlesMaterial::get_flatness() const { return flatness; } void ParticlesMaterial::set_param(Parameter p_param, float p_value) { - ERR_FAIL_INDEX(p_param, PARAM_MAX); parameters[p_param] = p_value; switch (p_param) { case PARAM_INITIAL_LINEAR_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_linear_velocity, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_linear_velocity, p_value); } break; case PARAM_ANGULAR_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity, p_value); } break; case PARAM_ORBIT_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity, p_value); } break; case PARAM_LINEAR_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel, p_value); } break; case PARAM_RADIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel, p_value); } break; case PARAM_TANGENTIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel, p_value); } break; case PARAM_DAMPING: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->damping, p_value); } break; case PARAM_ANGLE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_angle, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_angle, p_value); } break; case PARAM_SCALE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->scale, p_value); } break; case PARAM_HUE_VARIATION: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation, p_value); } break; case PARAM_ANIM_SPEED: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed, p_value); } break; case PARAM_ANIM_OFFSET: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset, p_value); } break; - case PARAM_MAX: break; // Can't happen, but silences warning + case PARAM_MAX: + break; // Can't happen, but silences warning } } -float ParticlesMaterial::get_param(Parameter p_param) const { +float ParticlesMaterial::get_param(Parameter p_param) const { ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); return parameters[p_param]; } void ParticlesMaterial::set_param_randomness(Parameter p_param, float p_value) { - ERR_FAIL_INDEX(p_param, PARAM_MAX); randomness[p_param] = p_value; switch (p_param) { case PARAM_INITIAL_LINEAR_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_linear_velocity_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_linear_velocity_random, p_value); } break; case PARAM_ANGULAR_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_random, p_value); } break; case PARAM_ORBIT_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_random, p_value); } break; case PARAM_LINEAR_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_random, p_value); } break; case PARAM_RADIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_random, p_value); } break; case PARAM_TANGENTIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_random, p_value); } break; case PARAM_DAMPING: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_random, p_value); } break; case PARAM_ANGLE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_angle_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_angle_random, p_value); } break; case PARAM_SCALE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_random, p_value); } break; case PARAM_HUE_VARIATION: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_random, p_value); } break; case PARAM_ANIM_SPEED: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_random, p_value); } break; case PARAM_ANIM_OFFSET: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_random, p_value); } break; - case PARAM_MAX: break; // Can't happen, but silences warning + case PARAM_MAX: + break; // Can't happen, but silences warning } } -float ParticlesMaterial::get_param_randomness(Parameter p_param) const { +float ParticlesMaterial::get_param_randomness(Parameter p_param) const { ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); return randomness[p_param]; } -static void _adjust_curve_range(const Ref<Texture> &p_texture, float p_min, float p_max) { - +static void _adjust_curve_range(const Ref<Texture2D> &p_texture, float p_min, float p_max) { Ref<CurveTexture> curve_tex = p_texture; - if (!curve_tex.is_valid()) + if (!curve_tex.is_valid()) { return; + } curve_tex->ensure_default_setup(p_min, p_max); } -void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture> &p_texture) { - +void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture2D> &p_texture) { ERR_FAIL_INDEX(p_param, PARAM_MAX); tex_parameters[p_param] = p_texture; @@ -807,81 +817,78 @@ void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture> //do none for this one } break; case PARAM_ANGULAR_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_texture, p_texture); _adjust_curve_range(p_texture, -360, 360); } break; case PARAM_ORBIT_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_texture, p_texture); _adjust_curve_range(p_texture, -500, 500); } break; case PARAM_LINEAR_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_texture, p_texture); _adjust_curve_range(p_texture, -200, 200); } break; case PARAM_RADIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_texture, p_texture); _adjust_curve_range(p_texture, -200, 200); } break; case PARAM_TANGENTIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_texture, p_texture); _adjust_curve_range(p_texture, -200, 200); } break; case PARAM_DAMPING: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_texture, p_texture); _adjust_curve_range(p_texture, 0, 100); } break; case PARAM_ANGLE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angle_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->angle_texture, p_texture); _adjust_curve_range(p_texture, -360, 360); } break; case PARAM_SCALE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_texture, p_texture); _adjust_curve_range(p_texture, 0, 1); } break; case PARAM_HUE_VARIATION: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_texture, p_texture); _adjust_curve_range(p_texture, -1, 1); } break; case PARAM_ANIM_SPEED: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_texture, p_texture); _adjust_curve_range(p_texture, 0, 200); } break; case PARAM_ANIM_OFFSET: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_texture, p_texture); } break; - case PARAM_MAX: break; // Can't happen, but silences warning + case PARAM_MAX: + break; // Can't happen, but silences warning } _queue_shader_change(); } -Ref<Texture> ParticlesMaterial::get_param_texture(Parameter p_param) const { - ERR_FAIL_INDEX_V(p_param, PARAM_MAX, Ref<Texture>()); +Ref<Texture2D> ParticlesMaterial::get_param_texture(Parameter p_param) const { + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, Ref<Texture2D>()); return tex_parameters[p_param]; } void ParticlesMaterial::set_color(const Color &p_color) { - - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->color, p_color); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->color, p_color); color = p_color; } Color ParticlesMaterial::get_color() const { - return color; } -void ParticlesMaterial::set_color_ramp(const Ref<Texture> &p_texture) { - +void ParticlesMaterial::set_color_ramp(const Ref<Texture2D> &p_texture) { color_ramp = p_texture; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->color_ramp, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->color_ramp, p_texture); _queue_shader_change(); _change_notify(); } -Ref<Texture> ParticlesMaterial::get_color_ramp() const { - +Ref<Texture2D> ParticlesMaterial::get_color_ramp() const { return color_ramp; } @@ -907,149 +914,92 @@ void ParticlesMaterial::set_emission_shape(EmissionShape p_shape) { } void ParticlesMaterial::set_emission_sphere_radius(float p_radius) { - emission_sphere_radius = p_radius; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_sphere_radius, p_radius); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_sphere_radius, p_radius); } void ParticlesMaterial::set_emission_box_extents(Vector3 p_extents) { - emission_box_extents = p_extents; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_box_extents, p_extents); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_box_extents, p_extents); } -void ParticlesMaterial::set_emission_point_texture(const Ref<Texture> &p_points) { - +void ParticlesMaterial::set_emission_point_texture(const Ref<Texture2D> &p_points) { emission_point_texture = p_points; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_points, p_points); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_points, p_points); } -void ParticlesMaterial::set_emission_normal_texture(const Ref<Texture> &p_normals) { - +void ParticlesMaterial::set_emission_normal_texture(const Ref<Texture2D> &p_normals) { emission_normal_texture = p_normals; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_normal, p_normals); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_normal, p_normals); } -void ParticlesMaterial::set_emission_color_texture(const Ref<Texture> &p_colors) { - +void ParticlesMaterial::set_emission_color_texture(const Ref<Texture2D> &p_colors) { emission_color_texture = p_colors; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_color, p_colors); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_color, p_colors); _queue_shader_change(); } void ParticlesMaterial::set_emission_point_count(int p_count) { - emission_point_count = p_count; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_point_count, p_count); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_point_count, p_count); } ParticlesMaterial::EmissionShape ParticlesMaterial::get_emission_shape() const { - return emission_shape; } float ParticlesMaterial::get_emission_sphere_radius() const { - return emission_sphere_radius; } -Vector3 ParticlesMaterial::get_emission_box_extents() const { +Vector3 ParticlesMaterial::get_emission_box_extents() const { return emission_box_extents; } -Ref<Texture> ParticlesMaterial::get_emission_point_texture() const { +Ref<Texture2D> ParticlesMaterial::get_emission_point_texture() const { return emission_point_texture; } -Ref<Texture> ParticlesMaterial::get_emission_normal_texture() const { +Ref<Texture2D> ParticlesMaterial::get_emission_normal_texture() const { return emission_normal_texture; } -Ref<Texture> ParticlesMaterial::get_emission_color_texture() const { - +Ref<Texture2D> ParticlesMaterial::get_emission_color_texture() const { return emission_color_texture; } int ParticlesMaterial::get_emission_point_count() const { - return emission_point_count; } -void ParticlesMaterial::set_trail_divisor(int p_divisor) { - - trail_divisor = p_divisor; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_divisor, p_divisor); -} - -int ParticlesMaterial::get_trail_divisor() const { - - return trail_divisor; -} - -void ParticlesMaterial::set_trail_size_modifier(const Ref<CurveTexture> &p_trail_size_modifier) { - - trail_size_modifier = p_trail_size_modifier; - - Ref<CurveTexture> curve = trail_size_modifier; - if (curve.is_valid()) { - curve->ensure_default_setup(); - } - - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_size_modifier, curve); - _queue_shader_change(); -} - -Ref<CurveTexture> ParticlesMaterial::get_trail_size_modifier() const { - - return trail_size_modifier; -} - -void ParticlesMaterial::set_trail_color_modifier(const Ref<GradientTexture> &p_trail_color_modifier) { - - trail_color_modifier = p_trail_color_modifier; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_color_modifier, p_trail_color_modifier); - _queue_shader_change(); -} - -Ref<GradientTexture> ParticlesMaterial::get_trail_color_modifier() const { - - return trail_color_modifier; -} - void ParticlesMaterial::set_gravity(const Vector3 &p_gravity) { - gravity = p_gravity; Vector3 gset = gravity; if (gset == Vector3()) { gset = Vector3(0, -0.000001, 0); //as gravity is used as upvector in some calculations } - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->gravity, gset); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->gravity, gset); } Vector3 ParticlesMaterial::get_gravity() const { - return gravity; } void ParticlesMaterial::set_lifetime_randomness(float p_lifetime) { - lifetime_randomness = p_lifetime; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->lifetime_randomness, lifetime_randomness); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->lifetime_randomness, lifetime_randomness); } float ParticlesMaterial::get_lifetime_randomness() const { - return lifetime_randomness; } RID ParticlesMaterial::get_shader_rid() const { - ERR_FAIL_COND_V(!shader_map.has(current_key), RID()); return shader_map[current_key].shader; } void ParticlesMaterial::_validate_property(PropertyInfo &property) const { - if (property.name == "color" && color_ramp.is_valid()) { property.usage = 0; } @@ -1074,18 +1024,59 @@ void ParticlesMaterial::_validate_property(PropertyInfo &property) const { property.usage = 0; } + if (property.name == "sub_emitter_frequency" && sub_emitter_mode != SUB_EMITTER_CONSTANT) { + property.usage = 0; + } + + if (property.name == "sub_emitter_amount_at_end" && sub_emitter_mode != SUB_EMITTER_AT_END) { + property.usage = 0; + } + if (property.name.begins_with("orbit_") && !flags[FLAG_DISABLE_Z]) { property.usage = 0; } } -Shader::Mode ParticlesMaterial::get_shader_mode() const { +void ParticlesMaterial::set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode) { + sub_emitter_mode = p_sub_emitter_mode; + _queue_shader_change(); + _change_notify(); +} + +ParticlesMaterial::SubEmitterMode ParticlesMaterial::get_sub_emitter_mode() const { + return sub_emitter_mode; +} + +void ParticlesMaterial::set_sub_emitter_frequency(float p_frequency) { + sub_emitter_frequency = p_frequency; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_frequency, 1.0 / p_frequency); //pas delta instead of frequency, since its easier to compute +} +float ParticlesMaterial::get_sub_emitter_frequency() const { + return sub_emitter_frequency; +} +void ParticlesMaterial::set_sub_emitter_amount_at_end(int p_amount) { + sub_emitter_amount_at_end = p_amount; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_amount_at_end, p_amount); +} + +int ParticlesMaterial::get_sub_emitter_amount_at_end() const { + return sub_emitter_amount_at_end; +} + +void ParticlesMaterial::set_sub_emitter_keep_velocity(bool p_enable) { + sub_emitter_keep_velocity = p_enable; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_keep_velocity, p_enable); +} +bool ParticlesMaterial::get_sub_emitter_keep_velocity() const { + return sub_emitter_keep_velocity; +} + +Shader::Mode ParticlesMaterial::get_shader_mode() const { return Shader::MODE_PARTICLES; } void ParticlesMaterial::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_direction", "degrees"), &ParticlesMaterial::set_direction); ClassDB::bind_method(D_METHOD("get_direction"), &ParticlesMaterial::get_direction); @@ -1134,34 +1125,34 @@ void ParticlesMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_emission_point_count", "point_count"), &ParticlesMaterial::set_emission_point_count); ClassDB::bind_method(D_METHOD("get_emission_point_count"), &ParticlesMaterial::get_emission_point_count); - ClassDB::bind_method(D_METHOD("set_trail_divisor", "divisor"), &ParticlesMaterial::set_trail_divisor); - ClassDB::bind_method(D_METHOD("get_trail_divisor"), &ParticlesMaterial::get_trail_divisor); - - ClassDB::bind_method(D_METHOD("set_trail_size_modifier", "texture"), &ParticlesMaterial::set_trail_size_modifier); - ClassDB::bind_method(D_METHOD("get_trail_size_modifier"), &ParticlesMaterial::get_trail_size_modifier); - - ClassDB::bind_method(D_METHOD("set_trail_color_modifier", "texture"), &ParticlesMaterial::set_trail_color_modifier); - ClassDB::bind_method(D_METHOD("get_trail_color_modifier"), &ParticlesMaterial::get_trail_color_modifier); - ClassDB::bind_method(D_METHOD("get_gravity"), &ParticlesMaterial::get_gravity); ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &ParticlesMaterial::set_gravity); ClassDB::bind_method(D_METHOD("set_lifetime_randomness", "randomness"), &ParticlesMaterial::set_lifetime_randomness); ClassDB::bind_method(D_METHOD("get_lifetime_randomness"), &ParticlesMaterial::get_lifetime_randomness); + ClassDB::bind_method(D_METHOD("get_sub_emitter_mode"), &ParticlesMaterial::get_sub_emitter_mode); + ClassDB::bind_method(D_METHOD("set_sub_emitter_mode", "mode"), &ParticlesMaterial::set_sub_emitter_mode); + + ClassDB::bind_method(D_METHOD("get_sub_emitter_frequency"), &ParticlesMaterial::get_sub_emitter_frequency); + ClassDB::bind_method(D_METHOD("set_sub_emitter_frequency", "hz"), &ParticlesMaterial::set_sub_emitter_frequency); + + ClassDB::bind_method(D_METHOD("get_sub_emitter_amount_at_end"), &ParticlesMaterial::get_sub_emitter_amount_at_end); + ClassDB::bind_method(D_METHOD("set_sub_emitter_amount_at_end", "amount"), &ParticlesMaterial::set_sub_emitter_amount_at_end); + + ClassDB::bind_method(D_METHOD("get_sub_emitter_keep_velocity"), &ParticlesMaterial::get_sub_emitter_keep_velocity); + ClassDB::bind_method(D_METHOD("set_sub_emitter_keep_velocity", "enable"), &ParticlesMaterial::set_sub_emitter_keep_velocity); + ADD_GROUP("Time", ""); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime_randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_lifetime_randomness", "get_lifetime_randomness"); - ADD_GROUP("Trail", "trail_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_divisor", PROPERTY_HINT_RANGE, "1,1000000,1"), "set_trail_divisor", "get_trail_divisor"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_size_modifier", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_trail_size_modifier", "get_trail_size_modifier"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_color_modifier", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_trail_color_modifier", "get_trail_color_modifier"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime_randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_lifetime_randomness", "get_lifetime_randomness"); + ADD_GROUP("Emission Shape", "emission_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01,or_greater"), "set_emission_sphere_radius", "get_emission_sphere_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01,or_greater"), "set_emission_sphere_radius", "get_emission_sphere_radius"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_box_extents"), "set_emission_box_extents", "get_emission_box_extents"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_point_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_point_texture", "get_emission_point_texture"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_normal_texture", "get_emission_normal_texture"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_color_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_color_texture", "get_emission_color_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_point_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_emission_point_texture", "get_emission_point_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_emission_normal_texture", "get_emission_normal_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_color_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_emission_color_texture", "get_emission_color_texture"); ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_point_count", PROPERTY_HINT_RANGE, "0,1000000,1"), "set_emission_point_count", "get_emission_point_count"); ADD_GROUP("Flags", "flag_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_align_y"), "set_flag", "get_flag", FLAG_ALIGN_Y_TO_VELOCITY); @@ -1169,61 +1160,67 @@ void ParticlesMaterial::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_disable_z"), "set_flag", "get_flag", FLAG_DISABLE_Z); ADD_GROUP("Direction", ""); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "direction"), "set_direction", "get_direction"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "spread", PROPERTY_HINT_RANGE, "0,180,0.01"), "set_spread", "get_spread"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "flatness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_flatness", "get_flatness"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "spread", PROPERTY_HINT_RANGE, "0,180,0.01"), "set_spread", "get_spread"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "flatness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_flatness", "get_flatness"); ADD_GROUP("Gravity", ""); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity"), "set_gravity", "get_gravity"); ADD_GROUP("Initial Velocity", "initial_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "initial_velocity", PROPERTY_HINT_RANGE, "0,1000,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_INITIAL_LINEAR_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "initial_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_INITIAL_LINEAR_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "initial_velocity", PROPERTY_HINT_RANGE, "0,1000,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_INITIAL_LINEAR_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "initial_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_INITIAL_LINEAR_VELOCITY); ADD_GROUP("Angular Velocity", "angular_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_velocity", PROPERTY_HINT_RANGE, "-720,720,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGULAR_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGULAR_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_velocity", PROPERTY_HINT_RANGE, "-720,720,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGULAR_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angular_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGULAR_VELOCITY); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angular_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANGULAR_VELOCITY); ADD_GROUP("Orbit Velocity", "orbit_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "orbit_velocity", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ORBIT_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "orbit_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ORBIT_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "orbit_velocity", PROPERTY_HINT_RANGE, "-1000,1000,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_ORBIT_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "orbit_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ORBIT_VELOCITY); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "orbit_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ORBIT_VELOCITY); ADD_GROUP("Linear Accel", "linear_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_LINEAR_ACCEL); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_LINEAR_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_LINEAR_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "linear_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_LINEAR_ACCEL); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "linear_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_LINEAR_ACCEL); ADD_GROUP("Radial Accel", "radial_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "radial_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_RADIAL_ACCEL); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "radial_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_RADIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "radial_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_RADIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "radial_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_RADIAL_ACCEL); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "radial_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_RADIAL_ACCEL); ADD_GROUP("Tangential Accel", "tangential_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "tangential_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_TANGENTIAL_ACCEL); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "tangential_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_TANGENTIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "tangential_accel", PROPERTY_HINT_RANGE, "-100,100,0.01,or_lesser,or_greater"), "set_param", "get_param", PARAM_TANGENTIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "tangential_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_TANGENTIAL_ACCEL); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "tangential_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_TANGENTIAL_ACCEL); ADD_GROUP("Damping", ""); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping", PROPERTY_HINT_RANGE, "0,100,0.01,or_greater"), "set_param", "get_param", PARAM_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping", PROPERTY_HINT_RANGE, "0,100,0.01,or_greater"), "set_param", "get_param", PARAM_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_DAMPING); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_DAMPING); ADD_GROUP("Angle", ""); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGLE); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angle_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGLE); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1,or_lesser,or_greater"), "set_param", "get_param", PARAM_ANGLE); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGLE); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angle_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANGLE); ADD_GROUP("Scale", ""); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "scale", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param", "get_param", PARAM_SCALE); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "scale_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_SCALE); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "scale", PROPERTY_HINT_RANGE, "0,1000,0.01,or_greater"), "set_param", "get_param", PARAM_SCALE); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "scale_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_SCALE); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "scale_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_SCALE); ADD_GROUP("Color", ""); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_color_ramp", "get_color_ramp"); ADD_GROUP("Hue Variation", "hue_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param", "get_param", PARAM_HUE_VARIATION); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param", "get_param", PARAM_HUE_VARIATION); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_HUE_VARIATION); ADD_GROUP("Animation", "anim_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_speed", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater"), "set_param", "get_param", PARAM_ANIM_SPEED); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_speed_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_SPEED); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_speed", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater"), "set_param", "get_param", PARAM_ANIM_SPEED); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_speed_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_SPEED); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_speed_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANIM_SPEED); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_offset", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_ANIM_OFFSET); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_offset_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_OFFSET); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_offset", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_ANIM_OFFSET); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_offset_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_OFFSET); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_offset_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANIM_OFFSET); + ADD_GROUP("Sub Emitter", "sub_emitter_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_mode", PROPERTY_HINT_ENUM, "Disabled,Constant,AtEnd,AtCollision"), "set_sub_emitter_mode", "get_sub_emitter_mode"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sub_emitter_frequency", PROPERTY_HINT_RANGE, "0.01,100,0.01"), "set_sub_emitter_frequency", "get_sub_emitter_frequency"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_amount_at_end", PROPERTY_HINT_RANGE, "1,32,1"), "set_sub_emitter_amount_at_end", "get_sub_emitter_amount_at_end"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sub_emitter_keep_velocity"), "set_sub_emitter_keep_velocity", "get_sub_emitter_keep_velocity"); + BIND_ENUM_CONSTANT(PARAM_INITIAL_LINEAR_VELOCITY); BIND_ENUM_CONSTANT(PARAM_ANGULAR_VELOCITY); BIND_ENUM_CONSTANT(PARAM_ORBIT_VELOCITY); @@ -1249,11 +1246,16 @@ void ParticlesMaterial::_bind_methods() { BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS); BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS); BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX); + + BIND_ENUM_CONSTANT(SUB_EMITTER_DISABLED); + BIND_ENUM_CONSTANT(SUB_EMITTER_CONSTANT); + BIND_ENUM_CONSTANT(SUB_EMITTER_AT_END); + BIND_ENUM_CONSTANT(SUB_EMITTER_AT_COLLISION); + BIND_ENUM_CONSTANT(SUB_EMITTER_MAX); } ParticlesMaterial::ParticlesMaterial() : element(this) { - set_direction(Vector3(1, 0, 0)); set_spread(45); set_flatness(0); @@ -1272,11 +1274,15 @@ ParticlesMaterial::ParticlesMaterial() : set_emission_shape(EMISSION_SHAPE_POINT); set_emission_sphere_radius(1); set_emission_box_extents(Vector3(1, 1, 1)); - set_trail_divisor(1); set_gravity(Vector3(0, -9.8, 0)); set_lifetime_randomness(0); emission_point_count = 1; + set_sub_emitter_mode(SUB_EMITTER_DISABLED); + set_sub_emitter_frequency(4); + set_sub_emitter_amount_at_end(1); + set_sub_emitter_keep_velocity(false); + for (int i = 0; i < PARAM_MAX; i++) { set_param_randomness(Parameter(i), 0); } @@ -1294,21 +1300,16 @@ ParticlesMaterial::ParticlesMaterial() : } ParticlesMaterial::~ParticlesMaterial() { - - if (material_mutex) - material_mutex->lock(); + MutexLock lock(material_mutex); if (shader_map.has(current_key)) { shader_map[current_key].users--; if (shader_map[current_key].users == 0) { //deallocate shader, as it's no longer in use - VS::get_singleton()->free(shader_map[current_key].shader); + RS::get_singleton()->free(shader_map[current_key].shader); shader_map.erase(current_key); } - VS::get_singleton()->material_set_shader(_get_material(), RID()); + RS::get_singleton()->material_set_shader(_get_material(), RID()); } - - if (material_mutex) - material_mutex->unlock(); } diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h index cc860b3812..fa8858f67f 100644 --- a/scene/resources/particles_material.h +++ b/scene/resources/particles_material.h @@ -34,13 +34,22 @@ #ifndef PARTICLES_MATERIAL_H #define PARTICLES_MATERIAL_H -class ParticlesMaterial : public Material { +/* + TODO: +-Path following +*Manual emission +-Sub Emitters +-Attractors +-Emitter positions deformable by bones +-Collision +-Proper trails +*/ +class ParticlesMaterial : public Material { GDCLASS(ParticlesMaterial, Material); public: enum Parameter { - PARAM_INITIAL_LINEAR_VELOCITY, PARAM_ANGULAR_VELOCITY, PARAM_ORBIT_VELOCITY, @@ -72,18 +81,24 @@ public: EMISSION_SHAPE_MAX }; + enum SubEmitterMode { + SUB_EMITTER_DISABLED, + SUB_EMITTER_CONSTANT, + SUB_EMITTER_AT_END, + SUB_EMITTER_AT_COLLISION, + SUB_EMITTER_MAX + }; + private: union MaterialKey { - struct { uint32_t texture_mask : 16; uint32_t texture_color : 1; uint32_t flags : 4; uint32_t emission_shape : 2; - uint32_t trail_size_texture : 1; - uint32_t trail_color_texture : 1; uint32_t invalid_key : 1; uint32_t has_emission_color : 1; + uint32_t sub_emitter : 2; }; uint32_t key; @@ -103,7 +118,6 @@ private: MaterialKey current_key; _FORCE_INLINE_ MaterialKey _compute_key() const { - MaterialKey mk; mk.key = 0; for (int i = 0; i < PARAM_MAX; i++) { @@ -119,14 +133,13 @@ private: mk.texture_color = color_ramp.is_valid() ? 1 : 0; mk.emission_shape = emission_shape; - mk.trail_color_texture = trail_color_modifier.is_valid() ? 1 : 0; - mk.trail_size_texture = trail_size_modifier.is_valid() ? 1 : 0; mk.has_emission_color = emission_shape >= EMISSION_SHAPE_POINTS && emission_color_texture.is_valid(); + mk.sub_emitter = sub_emitter_mode; return mk; } - static Mutex *material_mutex; + static Mutex material_mutex; static SelfList<ParticlesMaterial>::List *dirty_materials; struct ShaderNames { @@ -181,13 +194,13 @@ private: StringName emission_texture_normal; StringName emission_texture_color; - StringName trail_divisor; - StringName trail_size_modifier; - StringName trail_color_modifier; - StringName gravity; StringName lifetime_randomness; + + StringName sub_emitter_frequency; + StringName sub_emitter_amount_at_end; + StringName sub_emitter_keep_velocity; }; static ShaderNames *shader_names; @@ -205,36 +218,35 @@ private: float parameters[PARAM_MAX]; float randomness[PARAM_MAX]; - Ref<Texture> tex_parameters[PARAM_MAX]; + Ref<Texture2D> tex_parameters[PARAM_MAX]; Color color; - Ref<Texture> color_ramp; + Ref<Texture2D> color_ramp; bool flags[FLAG_MAX]; EmissionShape emission_shape; float emission_sphere_radius; Vector3 emission_box_extents; - Ref<Texture> emission_point_texture; - Ref<Texture> emission_normal_texture; - Ref<Texture> emission_color_texture; + Ref<Texture2D> emission_point_texture; + Ref<Texture2D> emission_normal_texture; + Ref<Texture2D> emission_color_texture; int emission_point_count; bool anim_loop; - int trail_divisor; - - Ref<CurveTexture> trail_size_modifier; - Ref<GradientTexture> trail_color_modifier; - Vector3 gravity; float lifetime_randomness; + SubEmitterMode sub_emitter_mode; + float sub_emitter_frequency; + int sub_emitter_amount_at_end; + bool sub_emitter_keep_velocity; //do not save emission points here protected: static void _bind_methods(); - virtual void _validate_property(PropertyInfo &property) const; + virtual void _validate_property(PropertyInfo &property) const override; public: void set_direction(Vector3 p_direction); @@ -252,14 +264,14 @@ public: void set_param_randomness(Parameter p_param, float p_value); float get_param_randomness(Parameter p_param) const; - void set_param_texture(Parameter p_param, const Ref<Texture> &p_texture); - Ref<Texture> get_param_texture(Parameter p_param) const; + void set_param_texture(Parameter p_param, const Ref<Texture2D> &p_texture); + Ref<Texture2D> get_param_texture(Parameter p_param) const; void set_color(const Color &p_color); Color get_color() const; - void set_color_ramp(const Ref<Texture> &p_texture); - Ref<Texture> get_color_ramp() const; + void set_color_ramp(const Ref<Texture2D> &p_texture); + Ref<Texture2D> get_color_ramp() const; void set_flag(Flags p_flag, bool p_enable); bool get_flag(Flags p_flag) const; @@ -267,28 +279,19 @@ public: void set_emission_shape(EmissionShape p_shape); void set_emission_sphere_radius(float p_radius); void set_emission_box_extents(Vector3 p_extents); - void set_emission_point_texture(const Ref<Texture> &p_points); - void set_emission_normal_texture(const Ref<Texture> &p_normals); - void set_emission_color_texture(const Ref<Texture> &p_colors); + void set_emission_point_texture(const Ref<Texture2D> &p_points); + void set_emission_normal_texture(const Ref<Texture2D> &p_normals); + void set_emission_color_texture(const Ref<Texture2D> &p_colors); void set_emission_point_count(int p_count); EmissionShape get_emission_shape() const; float get_emission_sphere_radius() const; Vector3 get_emission_box_extents() const; - Ref<Texture> get_emission_point_texture() const; - Ref<Texture> get_emission_normal_texture() const; - Ref<Texture> get_emission_color_texture() const; + Ref<Texture2D> get_emission_point_texture() const; + Ref<Texture2D> get_emission_normal_texture() const; + Ref<Texture2D> get_emission_color_texture() const; int get_emission_point_count() const; - void set_trail_divisor(int p_divisor); - int get_trail_divisor() const; - - void set_trail_size_modifier(const Ref<CurveTexture> &p_trail_size_modifier); - Ref<CurveTexture> get_trail_size_modifier() const; - - void set_trail_color_modifier(const Ref<GradientTexture> &p_trail_color_modifier); - Ref<GradientTexture> get_trail_color_modifier() const; - void set_gravity(const Vector3 &p_gravity); Vector3 get_gravity() const; @@ -299,9 +302,21 @@ public: static void finish_shaders(); static void flush_changes(); + void set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode); + SubEmitterMode get_sub_emitter_mode() const; + + void set_sub_emitter_frequency(float p_frequency); + float get_sub_emitter_frequency() const; + + void set_sub_emitter_amount_at_end(int p_amount); + int get_sub_emitter_amount_at_end() const; + + void set_sub_emitter_keep_velocity(bool p_enable); + bool get_sub_emitter_keep_velocity() const; + RID get_shader_rid() const; - virtual Shader::Mode get_shader_mode() const; + virtual Shader::Mode get_shader_mode() const override; ParticlesMaterial(); ~ParticlesMaterial(); @@ -310,5 +325,6 @@ public: VARIANT_ENUM_CAST(ParticlesMaterial::Parameter) VARIANT_ENUM_CAST(ParticlesMaterial::Flags) VARIANT_ENUM_CAST(ParticlesMaterial::EmissionShape) +VARIANT_ENUM_CAST(ParticlesMaterial::SubEmitterMode) #endif // PARTICLES_MATERIAL_H diff --git a/scene/resources/physics_material.cpp b/scene/resources/physics_material.cpp index 0db115ecc0..59bf8c0e13 100644 --- a/scene/resources/physics_material.cpp +++ b/scene/resources/physics_material.cpp @@ -31,7 +31,6 @@ #include "physics_material.h" void PhysicsMaterial::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_friction", "friction"), &PhysicsMaterial::set_friction); ClassDB::bind_method(D_METHOD("get_friction"), &PhysicsMaterial::get_friction); @@ -44,9 +43,9 @@ void PhysicsMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_absorbent", "absorbent"), &PhysicsMaterial::set_absorbent); ClassDB::bind_method(D_METHOD("is_absorbent"), &PhysicsMaterial::is_absorbent); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "friction"), "set_friction", "get_friction"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rough"), "set_rough", "is_rough"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce"), "set_bounce", "get_bounce"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "absorbent"), "set_absorbent", "is_absorbent"); } @@ -69,9 +68,3 @@ void PhysicsMaterial::set_absorbent(bool p_val) { absorbent = p_val; emit_changed(); } - -PhysicsMaterial::PhysicsMaterial() : - friction(1), - rough(false), - bounce(0), - absorbent(false) {} diff --git a/scene/resources/physics_material.h b/scene/resources/physics_material.h index 2f7f4424b2..34aa7066df 100644 --- a/scene/resources/physics_material.h +++ b/scene/resources/physics_material.h @@ -28,22 +28,21 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef physics_material_override_H -#define physics_material_override_H +#ifndef PHYSICS_MATERIAL_H +#define PHYSICS_MATERIAL_H #include "core/resource.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" class PhysicsMaterial : public Resource { - GDCLASS(PhysicsMaterial, Resource); OBJ_SAVE_TYPE(PhysicsMaterial); RES_BASE_EXTENSION("phymat"); - real_t friction; - bool rough; - real_t bounce; - bool absorbent; + real_t friction = 1; + bool rough = false; + real_t bounce = 0; + bool absorbent = false; protected: static void _bind_methods(); @@ -69,7 +68,7 @@ public: return absorbent ? -bounce : bounce; } - PhysicsMaterial(); + PhysicsMaterial() {} }; -#endif // physics_material_override_H +#endif // PHYSICS_MATERIAL_H diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp index 9a1d478777..df98d4cfd4 100644 --- a/scene/resources/polygon_path_finder.cpp +++ b/scene/resources/polygon_path_finder.cpp @@ -29,20 +29,18 @@ /*************************************************************************/ #include "polygon_path_finder.h" -#include "core/math/geometry.h" +#include "core/math/geometry_2d.h" bool PolygonPathFinder::_is_point_inside(const Vector2 &p_point) const { - int crosses = 0; for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { - const Edge &e = E->get(); Vector2 a = points[e.points[0]].pos; Vector2 b = points[e.points[1]].pos; - if (Geometry::segment_intersects_segment_2d(a, b, p_point, outside_point, NULL)) { + if (Geometry2D::segment_intersects_segment(a, b, p_point, outside_point, nullptr)) { crosses++; } } @@ -51,7 +49,6 @@ bool PolygonPathFinder::_is_point_inside(const Vector2 &p_point) const { } void PolygonPathFinder::setup(const Vector<Vector2> &p_points, const Vector<int> &p_connections) { - ERR_FAIL_COND(p_connections.size() & 1); points.clear(); @@ -64,7 +61,6 @@ void PolygonPathFinder::setup(const Vector<Vector2> &p_points, const Vector<int> bounds = Rect2(); for (int i = 0; i < p_points.size(); i++) { - points.write[i].pos = p_points[i]; points.write[i].penalty = 0; @@ -84,7 +80,6 @@ void PolygonPathFinder::setup(const Vector<Vector2> &p_points, const Vector<int> //insert edges (which are also connetions) for (int i = 0; i < p_connections.size(); i += 2) { - Edge e(p_connections[i], p_connections[i + 1]); ERR_FAIL_INDEX(e.points[0], point_count); ERR_FAIL_INDEX(e.points[1], point_count); @@ -96,30 +91,30 @@ void PolygonPathFinder::setup(const Vector<Vector2> &p_points, const Vector<int> //fill the remaining connections based on visibility for (int i = 0; i < point_count; i++) { - for (int j = i + 1; j < point_count; j++) { - - if (edges.has(Edge(i, j))) + if (edges.has(Edge(i, j))) { continue; //if in edge ignore + } Vector2 from = points[i].pos; Vector2 to = points[j].pos; - if (!_is_point_inside(from * 0.5 + to * 0.5)) //connection between points in inside space + if (!_is_point_inside(from * 0.5 + to * 0.5)) { //connection between points in inside space continue; + } bool valid = true; for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { - const Edge &e = E->get(); - if (e.points[0] == i || e.points[1] == i || e.points[0] == j || e.points[1] == j) + if (e.points[0] == i || e.points[1] == i || e.points[0] == j || e.points[1] == j) { continue; + } Vector2 a = points[e.points[0]].pos; Vector2 b = points[e.points[1]].pos; - if (Geometry::segment_intersects_segment_2d(a, b, from, to, NULL)) { + if (Geometry2D::segment_intersects_segment(a, b, from, to, nullptr)) { valid = false; break; } @@ -134,7 +129,6 @@ void PolygonPathFinder::setup(const Vector<Vector2> &p_points, const Vector<int> } Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector2 &p_to) { - Vector<Vector2> path; Vector2 from = p_from; @@ -143,19 +137,17 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector Edge ignore_to_edge(-1, -1); if (!_is_point_inside(from)) { - float closest_dist = 1e20; Vector2 closest_point; for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { - const Edge &e = E->get(); Vector2 seg[2] = { points[e.points[0]].pos, points[e.points[1]].pos }; - Vector2 closest = Geometry::get_closest_point_to_segment_2d(from, seg); + Vector2 closest = Geometry2D::get_closest_point_to_segment(from, seg); float d = from.distance_squared_to(closest); if (d < closest_dist) { @@ -173,14 +165,13 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector Vector2 closest_point; for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { - const Edge &e = E->get(); Vector2 seg[2] = { points[e.points[0]].pos, points[e.points[1]].pos }; - Vector2 closest = Geometry::get_closest_point_to_segment_2d(to, seg); + Vector2 closest = Geometry2D::get_closest_point_to_segment(to, seg); float d = to.distance_squared_to(closest); if (d < closest_dist) { @@ -195,28 +186,27 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector //test direct connection { - bool can_see_eachother = true; for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { - const Edge &e = E->get(); - if (e.points[0] == ignore_from_edge.points[0] && e.points[1] == ignore_from_edge.points[1]) + if (e.points[0] == ignore_from_edge.points[0] && e.points[1] == ignore_from_edge.points[1]) { continue; - if (e.points[0] == ignore_to_edge.points[0] && e.points[1] == ignore_to_edge.points[1]) + } + if (e.points[0] == ignore_to_edge.points[0] && e.points[1] == ignore_to_edge.points[1]) { continue; + } Vector2 a = points[e.points[0]].pos; Vector2 b = points[e.points[1]].pos; - if (Geometry::segment_intersects_segment_2d(a, b, from, to, NULL)) { + if (Geometry2D::segment_intersects_segment(a, b, from, to, nullptr)) { can_see_eachother = false; break; } } if (can_see_eachother) { - path.push_back(from); path.push_back(to); return path; @@ -237,7 +227,6 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector points.write[bidx].penalty = 0; for (int i = 0; i < points.size() - 2; i++) { - bool valid_a = true; bool valid_b = true; points.write[i].prev = -1; @@ -252,43 +241,40 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector } for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { - const Edge &e = E->get(); - if (e.points[0] == i || e.points[1] == i) + if (e.points[0] == i || e.points[1] == i) { continue; + } Vector2 a = points[e.points[0]].pos; Vector2 b = points[e.points[1]].pos; if (valid_a) { - if (e.points[0] != ignore_from_edge.points[1] && e.points[1] != ignore_from_edge.points[1] && e.points[0] != ignore_from_edge.points[0] && e.points[1] != ignore_from_edge.points[0]) { - - if (Geometry::segment_intersects_segment_2d(a, b, from, points[i].pos, NULL)) { + if (Geometry2D::segment_intersects_segment(a, b, from, points[i].pos, nullptr)) { valid_a = false; } } } if (valid_b) { - if (e.points[0] != ignore_to_edge.points[1] && e.points[1] != ignore_to_edge.points[1] && e.points[0] != ignore_to_edge.points[0] && e.points[1] != ignore_to_edge.points[0]) { - - if (Geometry::segment_intersects_segment_2d(a, b, to, points[i].pos, NULL)) { + if (Geometry2D::segment_intersects_segment(a, b, to, points[i].pos, nullptr)) { valid_b = false; } } } - if (!valid_a && !valid_b) + if (!valid_a && !valid_b) { break; + } } if (valid_a) { @@ -308,7 +294,6 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector points.write[aidx].distance = 0; points.write[aidx].prev = aidx; for (Set<int>::Element *E = points[aidx].connections.front(); E; E = E->next()) { - open_list.insert(E->get()); points.write[E->get()].distance = from.distance_to(points[E->get()].pos); points.write[E->get()].prev = aidx; @@ -317,7 +302,6 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector bool found_route = false; while (true) { - if (open_list.size() == 0) { printf("open list empty\n"); break; @@ -329,14 +313,12 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector //this could be faster (cache previous results) for (Set<int>::Element *E = open_list.front(); E; E = E->next()) { - const Point &p = points[E->get()]; float cost = p.distance; cost += p.pos.distance_to(to); cost += p.penalty; if (cost < least_cost) { - least_cost_point = E->get(); least_cost = cost; } @@ -346,7 +328,6 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector //open the neighbours for search for (Set<int>::Element *E = np.connections.front(); E; E = E->next()) { - Point &p = points.write[E->get()]; float distance = np.pos.distance_to(p.pos) + np.distance; @@ -354,7 +335,6 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector //oh this was visited already, can we win the cost? if (p.distance > distance) { - p.prev = least_cost_point; //reasign previous p.distance = distance; } @@ -373,8 +353,9 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector } } - if (found_route) + if (found_route) { break; + } open_list.erase(least_cost_point); } @@ -391,7 +372,6 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector } for (int i = 0; i < points.size() - 2; i++) { - points.write[i].connections.erase(aidx); points.write[i].connections.erase(bidx); points.write[i].prev = -1; @@ -409,51 +389,48 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2 &p_from, const Vector } void PolygonPathFinder::_set_data(const Dictionary &p_data) { - ERR_FAIL_COND(!p_data.has("points")); ERR_FAIL_COND(!p_data.has("connections")); ERR_FAIL_COND(!p_data.has("segments")); ERR_FAIL_COND(!p_data.has("bounds")); - PoolVector<Vector2> p = p_data["points"]; + Vector<Vector2> p = p_data["points"]; Array c = p_data["connections"]; ERR_FAIL_COND(c.size() != p.size()); - if (c.size()) + if (c.size()) { return; + } int pc = p.size(); points.resize(pc + 2); - PoolVector<Vector2>::Read pr = p.read(); + const Vector2 *pr = p.ptr(); for (int i = 0; i < pc; i++) { points.write[i].pos = pr[i]; - PoolVector<int> con = c[i]; - PoolVector<int>::Read cr = con.read(); + Vector<int> con = c[i]; + const int *cr = con.ptr(); int cc = con.size(); for (int j = 0; j < cc; j++) { - points.write[i].connections.insert(cr[j]); } } if (p_data.has("penalties")) { - - PoolVector<float> penalties = p_data["penalties"]; + Vector<float> penalties = p_data["penalties"]; if (penalties.size() == pc) { - PoolVector<float>::Read pr2 = penalties.read(); + const float *pr2 = penalties.ptr(); for (int i = 0; i < pc; i++) { points.write[i].penalty = pr2[i]; } } } - PoolVector<int> segs = p_data["segments"]; + Vector<int> segs = p_data["segments"]; int sc = segs.size(); ERR_FAIL_COND(sc & 1); - PoolVector<int>::Read sr = segs.read(); + const int *sr = segs.ptr(); for (int i = 0; i < sc; i += 2) { - Edge e(sr[i], sr[i + 1]); edges.insert(e); } @@ -461,27 +438,26 @@ void PolygonPathFinder::_set_data(const Dictionary &p_data) { } Dictionary PolygonPathFinder::_get_data() const { - Dictionary d; - PoolVector<Vector2> p; - PoolVector<int> ind; + Vector<Vector2> p; + Vector<int> ind; Array connections; p.resize(MAX(0, points.size() - 2)); connections.resize(MAX(0, points.size() - 2)); ind.resize(edges.size() * 2); - PoolVector<float> penalties; + Vector<float> penalties; penalties.resize(MAX(0, points.size() - 2)); { - PoolVector<Vector2>::Write wp = p.write(); - PoolVector<float>::Write pw = penalties.write(); + Vector2 *wp = p.ptrw(); + float *pw = penalties.ptrw(); for (int i = 0; i < points.size() - 2; i++) { wp[i] = points[i].pos; pw[i] = points[i].penalty; - PoolVector<int> c; + Vector<int> c; c.resize(points[i].connections.size()); { - PoolVector<int>::Write cw = c.write(); + int *cw = c.ptrw(); int idx = 0; for (Set<int>::Element *E = points[i].connections.front(); E; E = E->next()) { cw[idx++] = E->get(); @@ -491,8 +467,7 @@ Dictionary PolygonPathFinder::_get_data() const { } } { - - PoolVector<int>::Write iw = ind.write(); + int *iw = ind.ptrw(); int idx = 0; for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { iw[idx++] = E->get().points[0]; @@ -510,24 +485,21 @@ Dictionary PolygonPathFinder::_get_data() const { } bool PolygonPathFinder::is_point_inside(const Vector2 &p_point) const { - return _is_point_inside(p_point); } Vector2 PolygonPathFinder::get_closest_point(const Vector2 &p_point) const { - float closest_dist = 1e20; Vector2 closest_point; for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { - const Edge &e = E->get(); Vector2 seg[2] = { points[e.points[0]].pos, points[e.points[1]].pos }; - Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point, seg); + Vector2 closest = Geometry2D::get_closest_point_to_segment(p_point, seg); float d = p_point.distance_squared_to(closest); if (d < closest_dist) { @@ -542,7 +514,6 @@ Vector2 PolygonPathFinder::get_closest_point(const Vector2 &p_point) const { } Vector<Vector2> PolygonPathFinder::get_intersections(const Vector2 &p_from, const Vector2 &p_to) const { - Vector<Vector2> inters; for (Set<Edge>::Element *E = edges.front(); E; E = E->next()) { @@ -550,7 +521,7 @@ Vector<Vector2> PolygonPathFinder::get_intersections(const Vector2 &p_from, cons Vector2 b = points[E->get().points[1]].pos; Vector2 res; - if (Geometry::segment_intersects_segment_2d(a, b, p_from, p_to, &res)) { + if (Geometry2D::segment_intersects_segment(a, b, p_from, p_to, &res)) { inters.push_back(res); } } @@ -559,24 +530,20 @@ Vector<Vector2> PolygonPathFinder::get_intersections(const Vector2 &p_from, cons } Rect2 PolygonPathFinder::get_bounds() const { - return bounds; } void PolygonPathFinder::set_point_penalty(int p_point, float p_penalty) { - ERR_FAIL_INDEX(p_point, points.size() - 2); points.write[p_point].penalty = p_penalty; } float PolygonPathFinder::get_point_penalty(int p_point) const { - ERR_FAIL_INDEX_V(p_point, points.size() - 2, 0); return points[p_point].penalty; } void PolygonPathFinder::_bind_methods() { - ClassDB::bind_method(D_METHOD("setup", "points", "connections"), &PolygonPathFinder::setup); ClassDB::bind_method(D_METHOD("find_path", "from", "to"), &PolygonPathFinder::find_path); ClassDB::bind_method(D_METHOD("get_intersections", "from", "to"), &PolygonPathFinder::get_intersections); diff --git a/scene/resources/polygon_path_finder.h b/scene/resources/polygon_path_finder.h index 2ef5c89e2a..baee4dc20d 100644 --- a/scene/resources/polygon_path_finder.h +++ b/scene/resources/polygon_path_finder.h @@ -34,7 +34,6 @@ #include "core/resource.h" class PolygonPathFinder : public Resource { - GDCLASS(PolygonPathFinder, Resource); struct Point { @@ -46,19 +45,17 @@ class PolygonPathFinder : public Resource { }; struct Edge { - int points[2]; _FORCE_INLINE_ bool operator<(const Edge &p_edge) const { - - if (points[0] == p_edge.points[0]) + if (points[0] == p_edge.points[0]) { return points[1] < p_edge.points[1]; - else + } else { return points[0] < p_edge.points[0]; + } } Edge(int a = 0, int b = 0) { - if (a > b) { SWAP(a, b); } diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index 74df72619a..8d9c5f07b2 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -29,42 +29,42 @@ /*************************************************************************/ #include "primitive_meshes.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" /** PrimitiveMesh */ void PrimitiveMesh::_update() const { - Array arr; - arr.resize(VS::ARRAY_MAX); + arr.resize(RS::ARRAY_MAX); _create_mesh_array(arr); - PoolVector<Vector3> points = arr[VS::ARRAY_VERTEX]; + Vector<Vector3> points = arr[RS::ARRAY_VERTEX]; aabb = AABB(); int pc = points.size(); ERR_FAIL_COND(pc == 0); { - - PoolVector<Vector3>::Read r = points.read(); + const Vector3 *r = points.ptr(); for (int i = 0; i < pc; i++) { - if (i == 0) + if (i == 0) { aabb.position = r[i]; - else + } else { aabb.expand_to(r[i]); + } } } + Vector<int> indices = arr[RS::ARRAY_INDEX]; + if (flip_faces) { - PoolVector<Vector3> normals = arr[VS::ARRAY_NORMAL]; - PoolVector<int> indices = arr[VS::ARRAY_INDEX]; - if (normals.size() && indices.size()) { + Vector<Vector3> normals = arr[RS::ARRAY_NORMAL]; + if (normals.size() && indices.size()) { { int nc = normals.size(); - PoolVector<Vector3>::Write w = normals.write(); + Vector3 *w = normals.ptrw(); for (int i = 0; i < nc; i++) { w[i] = -w[i]; } @@ -72,20 +72,22 @@ void PrimitiveMesh::_update() const { { int ic = indices.size(); - PoolVector<int>::Write w = indices.write(); + int *w = indices.ptrw(); for (int i = 0; i < ic; i += 3) { SWAP(w[i + 0], w[i + 1]); } } - arr[VS::ARRAY_NORMAL] = normals; - arr[VS::ARRAY_INDEX] = indices; + arr[RS::ARRAY_NORMAL] = normals; + arr[RS::ARRAY_INDEX] = indices; } } + array_len = pc; + index_array_len = indices.size(); // in with the new - VisualServer::get_singleton()->mesh_clear(mesh); - VisualServer::get_singleton()->mesh_add_surface_from_arrays(mesh, (VisualServer::PrimitiveType)primitive_type, arr); - VisualServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid()); + RenderingServer::get_singleton()->mesh_clear(mesh); + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(mesh, (RenderingServer::PrimitiveType)primitive_type, arr); + RenderingServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid()); pending_request = false; @@ -95,9 +97,9 @@ void PrimitiveMesh::_update() const { } void PrimitiveMesh::_request_update() { - - if (pending_request) + if (pending_request) { return; + } _update(); } @@ -114,7 +116,7 @@ int PrimitiveMesh::surface_get_array_len(int p_idx) const { _update(); } - return VisualServer::get_singleton()->mesh_surface_get_array_len(mesh, 0); + return array_len; } int PrimitiveMesh::surface_get_array_index_len(int p_idx) const { @@ -123,7 +125,7 @@ int PrimitiveMesh::surface_get_array_index_len(int p_idx) const { _update(); } - return VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, 0); + return index_array_len; } Array PrimitiveMesh::surface_get_arrays(int p_surface) const { @@ -132,25 +134,21 @@ Array PrimitiveMesh::surface_get_arrays(int p_surface) const { _update(); } - return VisualServer::get_singleton()->mesh_surface_get_arrays(mesh, 0); + return RenderingServer::get_singleton()->mesh_surface_get_arrays(mesh, 0); } -Array PrimitiveMesh::surface_get_blend_shape_arrays(int p_surface) const { - ERR_FAIL_INDEX_V(p_surface, 1, Array()); - if (pending_request) { - _update(); - } +Dictionary PrimitiveMesh::surface_get_lods(int p_surface) const { + return Dictionary(); //not really supported +} - return Array(); +Array PrimitiveMesh::surface_get_blend_shape_arrays(int p_surface) const { + return Array(); //not really supported } uint32_t PrimitiveMesh::surface_get_format(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, 1, 0); - if (pending_request) { - _update(); - } - return VisualServer::get_singleton()->mesh_surface_get_format(mesh, 0); + return RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV | RS::ARRAY_FORMAT_INDEX | RS::ARRAY_COMPRESS_DEFAULT; } Mesh::PrimitiveType PrimitiveMesh::surface_get_primitive_type(int p_idx) const { @@ -164,7 +162,7 @@ void PrimitiveMesh::surface_set_material(int p_idx, const Ref<Material> &p_mater } Ref<Material> PrimitiveMesh::surface_get_material(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, 1, NULL); + ERR_FAIL_INDEX_V(p_idx, 1, nullptr); return material; } @@ -206,7 +204,7 @@ void PrimitiveMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_flip_faces", "flip_faces"), &PrimitiveMesh::set_flip_faces); ClassDB::bind_method(D_METHOD("get_flip_faces"), &PrimitiveMesh::get_flip_faces); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "SpatialMaterial,ShaderMaterial"), "set_material", "get_material"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,StandardMaterial3D"), "set_material", "get_material"); ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, ""), "set_custom_aabb", "get_custom_aabb"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_faces"), "set_flip_faces", "get_flip_faces"); } @@ -215,7 +213,7 @@ void PrimitiveMesh::set_material(const Ref<Material> &p_material) { material = p_material; if (!pending_request) { // just apply it, else it'll happen when _update is called. - VisualServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid()); + RenderingServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid()); _change_notify(); emit_changed(); }; @@ -230,14 +228,12 @@ Array PrimitiveMesh::get_mesh_arrays() const { } void PrimitiveMesh::set_custom_aabb(const AABB &p_custom) { - custom_aabb = p_custom; - VS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); + RS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); emit_changed(); } AABB PrimitiveMesh::get_custom_aabb() const { - return custom_aabb; } @@ -251,20 +247,22 @@ bool PrimitiveMesh::get_flip_faces() const { } PrimitiveMesh::PrimitiveMesh() { - flip_faces = false; // defaults - mesh = VisualServer::get_singleton()->mesh_create(); + mesh = RenderingServer::get_singleton()->mesh_create(); // assume primitive triangles as the type, correct for all but one and it will change this :) primitive_type = Mesh::PRIMITIVE_TRIANGLES; // make sure we do an update after we've finished constructing our object pending_request = true; + + array_len = 0; + index_array_len = 0; } PrimitiveMesh::~PrimitiveMesh() { - VisualServer::get_singleton()->free(mesh); + RenderingServer::get_singleton()->free(mesh); } /** @@ -279,11 +277,11 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const { // note, this has been aligned with our collision shape but I've left the descriptions as top/middle/bottom - PoolVector<Vector3> points; - PoolVector<Vector3> normals; - PoolVector<float> tangents; - PoolVector<Vector2> uvs; - PoolVector<int> indices; + Vector<Vector3> points; + Vector<Vector3> normals; + Vector<float> tangents; + Vector<Vector2> uvs; + Vector<int> indices; point = 0; #define ADD_TANGENT(m_x, m_y, m_z, m_d) \ @@ -300,19 +298,19 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const { v /= (rings + 1); w = sin(0.5 * Math_PI * v); - z = radius * cos(0.5 * Math_PI * v); + y = radius * cos(0.5 * Math_PI * v); for (i = 0; i <= radial_segments; i++) { u = i; u /= radial_segments; - x = sin(u * (Math_PI * 2.0)); - y = -cos(u * (Math_PI * 2.0)); + x = -sin(u * (Math_PI * 2.0)); + z = cos(u * (Math_PI * 2.0)); - Vector3 p = Vector3(x * radius * w, y * radius * w, z); - points.push_back(p + Vector3(0.0, 0.0, 0.5 * mid_height)); + Vector3 p = Vector3(x * radius * w, y, -z * radius * w); + points.push_back(p + Vector3(0.0, 0.5 * mid_height, 0.0)); normals.push_back(p.normalized()); - ADD_TANGENT(-y, x, 0.0, 1.0) + ADD_TANGENT(z, 0.0, x, 1.0) uvs.push_back(Vector2(u, v * onethird)); point++; @@ -338,20 +336,20 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const { v = j; v /= (rings + 1); - z = mid_height * v; - z = (mid_height * 0.5) - z; + y = mid_height * v; + y = (mid_height * 0.5) - y; for (i = 0; i <= radial_segments; i++) { u = i; u /= radial_segments; - x = sin(u * (Math_PI * 2.0)); - y = -cos(u * (Math_PI * 2.0)); + x = -sin(u * (Math_PI * 2.0)); + z = cos(u * (Math_PI * 2.0)); - Vector3 p = Vector3(x * radius, y * radius, z); + Vector3 p = Vector3(x * radius, y, -z * radius); points.push_back(p); - normals.push_back(Vector3(x, y, 0.0)); - ADD_TANGENT(-y, x, 0.0, 1.0) + normals.push_back(Vector3(x, 0.0, -z)); + ADD_TANGENT(z, 0.0, x, 1.0) uvs.push_back(Vector2(u, onethird + (v * onethird))); point++; @@ -379,19 +377,19 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const { v /= (rings + 1); v += 1.0; w = sin(0.5 * Math_PI * v); - z = radius * cos(0.5 * Math_PI * v); + y = radius * cos(0.5 * Math_PI * v); for (i = 0; i <= radial_segments; i++) { float u2 = i; u2 /= radial_segments; - x = sin(u2 * (Math_PI * 2.0)); - y = -cos(u2 * (Math_PI * 2.0)); + x = -sin(u2 * (Math_PI * 2.0)); + z = cos(u2 * (Math_PI * 2.0)); - Vector3 p = Vector3(x * radius * w, y * radius * w, z); - points.push_back(p + Vector3(0.0, 0.0, -0.5 * mid_height)); + Vector3 p = Vector3(x * radius * w, y, -z * radius * w); + points.push_back(p + Vector3(0.0, -0.5 * mid_height, 0.0)); normals.push_back(p.normalized()); - ADD_TANGENT(-y, x, 0.0, 1.0) + ADD_TANGENT(z, 0.0, x, 1.0) uvs.push_back(Vector2(u2, twothirds + ((v - 1.0) * onethird))); point++; @@ -410,11 +408,11 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const { thisrow = point; }; - p_arr[VS::ARRAY_VERTEX] = points; - p_arr[VS::ARRAY_NORMAL] = normals; - p_arr[VS::ARRAY_TANGENT] = tangents; - p_arr[VS::ARRAY_TEX_UV] = uvs; - p_arr[VS::ARRAY_INDEX] = indices; + p_arr[RS::ARRAY_VERTEX] = points; + p_arr[RS::ARRAY_NORMAL] = normals; + p_arr[RS::ARRAY_TANGENT] = tangents; + p_arr[RS::ARRAY_TEX_UV] = uvs; + p_arr[RS::ARRAY_INDEX] = indices; } void CapsuleMesh::_bind_methods() { @@ -428,8 +426,8 @@ void CapsuleMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CapsuleMesh::set_rings); ClassDB::bind_method(D_METHOD("get_rings"), &CapsuleMesh::get_rings); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "mid_height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_mid_height", "get_mid_height"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mid_height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_mid_height", "get_mid_height"); ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments"); ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_rings", "get_rings"); } @@ -492,11 +490,11 @@ void CubeMesh::_create_mesh_array(Array &p_arr) const { // set our bounding box - PoolVector<Vector3> points; - PoolVector<Vector3> normals; - PoolVector<float> tangents; - PoolVector<Vector2> uvs; - PoolVector<int> indices; + Vector<Vector3> points; + Vector<Vector3> normals; + Vector<float> tangents; + Vector<Vector2> uvs; + Vector<int> indices; point = 0; #define ADD_TANGENT(m_x, m_y, m_z, m_d) \ @@ -667,11 +665,11 @@ void CubeMesh::_create_mesh_array(Array &p_arr) const { thisrow = point; }; - p_arr[VS::ARRAY_VERTEX] = points; - p_arr[VS::ARRAY_NORMAL] = normals; - p_arr[VS::ARRAY_TANGENT] = tangents; - p_arr[VS::ARRAY_TEX_UV] = uvs; - p_arr[VS::ARRAY_INDEX] = indices; + p_arr[RS::ARRAY_VERTEX] = points; + p_arr[RS::ARRAY_NORMAL] = normals; + p_arr[RS::ARRAY_TANGENT] = tangents; + p_arr[RS::ARRAY_TEX_UV] = uvs; + p_arr[RS::ARRAY_INDEX] = indices; } void CubeMesh::_bind_methods() { @@ -743,11 +741,11 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const { int i, j, prevrow, thisrow, point; float x, y, z, u, v, radius; - PoolVector<Vector3> points; - PoolVector<Vector3> normals; - PoolVector<float> tangents; - PoolVector<Vector2> uvs; - PoolVector<int> indices; + Vector<Vector3> points; + Vector<Vector3> normals; + Vector<float> tangents; + Vector<Vector2> uvs; + Vector<int> indices; point = 0; #define ADD_TANGENT(m_x, m_y, m_z, m_d) \ @@ -868,11 +866,11 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const { }; }; - p_arr[VS::ARRAY_VERTEX] = points; - p_arr[VS::ARRAY_NORMAL] = normals; - p_arr[VS::ARRAY_TANGENT] = tangents; - p_arr[VS::ARRAY_TEX_UV] = uvs; - p_arr[VS::ARRAY_INDEX] = indices; + p_arr[RS::ARRAY_VERTEX] = points; + p_arr[RS::ARRAY_NORMAL] = normals; + p_arr[RS::ARRAY_TANGENT] = tangents; + p_arr[RS::ARRAY_TEX_UV] = uvs; + p_arr[RS::ARRAY_INDEX] = indices; } void CylinderMesh::_bind_methods() { @@ -888,9 +886,9 @@ void CylinderMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_rings", "rings"), &CylinderMesh::set_rings); ClassDB::bind_method(D_METHOD("get_rings"), &CylinderMesh::get_rings); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "top_radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_top_radius", "get_top_radius"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "bottom_radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_bottom_radius", "get_bottom_radius"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_height", "get_height"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "top_radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_top_radius", "get_top_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bottom_radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_bottom_radius", "get_bottom_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_height", "get_height"); ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments"); ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_rings", "get_rings"); } @@ -959,11 +957,11 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const { Size2 start_pos = size * -0.5; - PoolVector<Vector3> points; - PoolVector<Vector3> normals; - PoolVector<float> tangents; - PoolVector<Vector2> uvs; - PoolVector<int> indices; + Vector<Vector3> points; + Vector<Vector3> normals; + Vector<float> tangents; + Vector<Vector2> uvs; + Vector<int> indices; point = 0; #define ADD_TANGENT(m_x, m_y, m_z, m_d) \ @@ -1007,11 +1005,11 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const { thisrow = point; }; - p_arr[VS::ARRAY_VERTEX] = points; - p_arr[VS::ARRAY_NORMAL] = normals; - p_arr[VS::ARRAY_TANGENT] = tangents; - p_arr[VS::ARRAY_TEX_UV] = uvs; - p_arr[VS::ARRAY_INDEX] = indices; + p_arr[RS::ARRAY_VERTEX] = points; + p_arr[RS::ARRAY_NORMAL] = normals; + p_arr[RS::ARRAY_TANGENT] = tangents; + p_arr[RS::ARRAY_TEX_UV] = uvs; + p_arr[RS::ARRAY_INDEX] = indices; } void PlaneMesh::_bind_methods() { @@ -1076,11 +1074,11 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const { // set our bounding box - PoolVector<Vector3> points; - PoolVector<Vector3> normals; - PoolVector<float> tangents; - PoolVector<Vector2> uvs; - PoolVector<int> indices; + Vector<Vector3> points; + Vector<Vector3> normals; + Vector<float> tangents; + Vector<Vector2> uvs; + Vector<int> indices; point = 0; #define ADD_TANGENT(m_x, m_y, m_z, m_d) \ @@ -1267,11 +1265,11 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const { thisrow = point; }; - p_arr[VS::ARRAY_VERTEX] = points; - p_arr[VS::ARRAY_NORMAL] = normals; - p_arr[VS::ARRAY_TANGENT] = tangents; - p_arr[VS::ARRAY_TEX_UV] = uvs; - p_arr[VS::ARRAY_INDEX] = indices; + p_arr[RS::ARRAY_VERTEX] = points; + p_arr[RS::ARRAY_NORMAL] = normals; + p_arr[RS::ARRAY_TANGENT] = tangents; + p_arr[RS::ARRAY_TEX_UV] = uvs; + p_arr[RS::ARRAY_INDEX] = indices; } void PrismMesh::_bind_methods() { @@ -1288,7 +1286,7 @@ void PrismMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_subdivide_depth", "segments"), &PrismMesh::set_subdivide_depth); ClassDB::bind_method(D_METHOD("get_subdivide_depth"), &PrismMesh::get_subdivide_depth); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "left_to_right", PROPERTY_HINT_RANGE, "-2.0,2.0,0.1"), "set_left_to_right", "get_left_to_right"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "left_to_right", PROPERTY_HINT_RANGE, "-2.0,2.0,0.1"), "set_left_to_right", "get_left_to_right"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "size"), "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_height", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_subdivide_height", "get_subdivide_height"); @@ -1354,10 +1352,10 @@ PrismMesh::PrismMesh() { */ void QuadMesh::_create_mesh_array(Array &p_arr) const { - PoolVector<Vector3> faces; - PoolVector<Vector3> normals; - PoolVector<float> tangents; - PoolVector<Vector2> uvs; + Vector<Vector3> faces; + Vector<Vector3> normals; + Vector<float> tangents; + Vector<Vector2> uvs; faces.resize(6); normals.resize(6); @@ -1379,7 +1377,6 @@ void QuadMesh::_create_mesh_array(Array &p_arr) const { }; for (int i = 0; i < 6; i++) { - int j = indices[i]; faces.set(i, quad_faces[j]); normals.set(i, Vector3(0, 0, 1)); @@ -1398,10 +1395,10 @@ void QuadMesh::_create_mesh_array(Array &p_arr) const { uvs.set(i, quad_uv[j]); } - p_arr[VS::ARRAY_VERTEX] = faces; - p_arr[VS::ARRAY_NORMAL] = normals; - p_arr[VS::ARRAY_TANGENT] = tangents; - p_arr[VS::ARRAY_TEX_UV] = uvs; + 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() { @@ -1434,11 +1431,11 @@ void SphereMesh::_create_mesh_array(Array &p_arr) const { // set our bounding box - PoolVector<Vector3> points; - PoolVector<Vector3> normals; - PoolVector<float> tangents; - PoolVector<Vector2> uvs; - PoolVector<int> indices; + Vector<Vector3> points; + Vector<Vector3> normals; + Vector<float> tangents; + Vector<Vector2> uvs; + Vector<int> indices; point = 0; #define ADD_TANGENT(m_x, m_y, m_z, m_d) \ @@ -1491,11 +1488,11 @@ void SphereMesh::_create_mesh_array(Array &p_arr) const { thisrow = point; }; - p_arr[VS::ARRAY_VERTEX] = points; - p_arr[VS::ARRAY_NORMAL] = normals; - p_arr[VS::ARRAY_TANGENT] = tangents; - p_arr[VS::ARRAY_TEX_UV] = uvs; - p_arr[VS::ARRAY_INDEX] = indices; + p_arr[RS::ARRAY_VERTEX] = points; + p_arr[RS::ARRAY_NORMAL] = normals; + p_arr[RS::ARRAY_TANGENT] = tangents; + p_arr[RS::ARRAY_TEX_UV] = uvs; + p_arr[RS::ARRAY_INDEX] = indices; } void SphereMesh::_bind_methods() { @@ -1512,8 +1509,8 @@ void SphereMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_is_hemisphere", "is_hemisphere"), &SphereMesh::set_is_hemisphere); ClassDB::bind_method(D_METHOD("get_is_hemisphere"), &SphereMesh::get_is_hemisphere); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_height", "get_height"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.001,100.0,0.001,or_greater"), "set_height", "get_height"); ADD_PROPERTY(PropertyInfo(Variant::INT, "radial_segments", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_radial_segments", "get_radial_segments"); ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "1,100,1,or_greater"), "set_rings", "get_rings"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "is_hemisphere"), "set_is_hemisphere", "get_is_hemisphere"); @@ -1578,11 +1575,11 @@ SphereMesh::SphereMesh() { */ void PointMesh::_create_mesh_array(Array &p_arr) const { - PoolVector<Vector3> faces; + Vector<Vector3> faces; faces.resize(1); faces.set(0, Vector3(0.0, 0.0, 0.0)); - p_arr[VS::ARRAY_VERTEX] = faces; + p_arr[RS::ARRAY_VERTEX] = faces; } PointMesh::PointMesh() { diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index 47126f1862..f0ae611b5e 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -42,7 +42,6 @@ This class is set apart that it assumes a single surface is always generated for our mesh. */ class PrimitiveMesh : public Mesh { - GDCLASS(PrimitiveMesh, Mesh); private: @@ -50,6 +49,9 @@ private: mutable AABB aabb; AABB custom_aabb; + mutable int array_len; + mutable int index_array_len; + Ref<Material> material; bool flip_faces; @@ -65,19 +67,20 @@ protected: void _request_update(); public: - 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 uint32_t surface_get_format(int p_idx) const; - virtual Mesh::PrimitiveType surface_get_primitive_type(int p_idx) const; - virtual void surface_set_material(int p_idx, const Ref<Material> &p_material); - virtual Ref<Material> surface_get_material(int p_idx) const; - virtual int get_blend_shape_count() const; - virtual StringName get_blend_shape_name(int p_index) const; - virtual AABB get_aabb() const; - virtual RID get_rid() const; + virtual int get_surface_count() const override; + 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 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; + virtual void surface_set_material(int p_idx, const Ref<Material> &p_material) override; + virtual Ref<Material> surface_get_material(int p_idx) const override; + virtual int get_blend_shape_count() const override; + virtual StringName get_blend_shape_name(int p_index) const override; + virtual AABB get_aabb() const override; + virtual RID get_rid() const override; void set_material(const Ref<Material> &p_material); Ref<Material> get_material() const; @@ -108,7 +111,7 @@ private: protected: static void _bind_methods(); - virtual void _create_mesh_array(Array &p_arr) const; + virtual void _create_mesh_array(Array &p_arr) const override; public: void set_radius(const float p_radius); @@ -130,7 +133,6 @@ public: Similar to test cube but with subdivision support and different texture coordinates */ class CubeMesh : public PrimitiveMesh { - GDCLASS(CubeMesh, PrimitiveMesh); private: @@ -141,7 +143,7 @@ private: protected: static void _bind_methods(); - virtual void _create_mesh_array(Array &p_arr) const; + virtual void _create_mesh_array(Array &p_arr) const override; public: void set_size(const Vector3 &p_size); @@ -164,7 +166,6 @@ public: */ class CylinderMesh : public PrimitiveMesh { - GDCLASS(CylinderMesh, PrimitiveMesh); private: @@ -176,7 +177,7 @@ private: protected: static void _bind_methods(); - virtual void _create_mesh_array(Array &p_arr) const; + virtual void _create_mesh_array(Array &p_arr) const override; public: void set_top_radius(const float p_radius); @@ -201,7 +202,6 @@ public: Similar to quadmesh but with tessellation support */ class PlaneMesh : public PrimitiveMesh { - GDCLASS(PlaneMesh, PrimitiveMesh); private: @@ -211,7 +211,7 @@ private: protected: static void _bind_methods(); - virtual void _create_mesh_array(Array &p_arr) const; + virtual void _create_mesh_array(Array &p_arr) const override; public: void set_size(const Size2 &p_size); @@ -230,7 +230,6 @@ public: A prism shapen, handy for ramps, triangles, etc. */ class PrismMesh : public PrimitiveMesh { - GDCLASS(PrismMesh, PrimitiveMesh); private: @@ -242,7 +241,7 @@ private: protected: static void _bind_methods(); - virtual void _create_mesh_array(Array &p_arr) const; + virtual void _create_mesh_array(Array &p_arr) const override; public: void set_left_to_right(const float p_left_to_right); @@ -268,7 +267,6 @@ public: */ class QuadMesh : public PrimitiveMesh { - GDCLASS(QuadMesh, PrimitiveMesh); private: @@ -276,7 +274,7 @@ private: protected: static void _bind_methods(); - virtual void _create_mesh_array(Array &p_arr) const; + virtual void _create_mesh_array(Array &p_arr) const override; public: QuadMesh(); @@ -289,7 +287,6 @@ public: A sphere.. */ class SphereMesh : public PrimitiveMesh { - GDCLASS(SphereMesh, PrimitiveMesh); private: @@ -301,7 +298,7 @@ private: protected: static void _bind_methods(); - virtual void _create_mesh_array(Array &p_arr) const; + virtual void _create_mesh_array(Array &p_arr) const override; public: void set_radius(const float p_radius); @@ -327,11 +324,10 @@ public: */ class PointMesh : public PrimitiveMesh { - GDCLASS(PointMesh, PrimitiveMesh) protected: - virtual void _create_mesh_array(Array &p_arr) const; + virtual void _create_mesh_array(Array &p_arr) const override; public: PointMesh(); diff --git a/scene/resources/ray_shape_2d.cpp b/scene/resources/ray_shape_2d.cpp new file mode 100644 index 0000000000..67c4f84749 --- /dev/null +++ b/scene/resources/ray_shape_2d.cpp @@ -0,0 +1,105 @@ +/*************************************************************************/ +/* ray_shape_2d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "ray_shape_2d.h" + +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" + +void RayShape2D::_update_shape() { + Dictionary d; + d["length"] = length; + d["slips_on_slope"] = slips_on_slope; + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), d); + emit_changed(); +} + +void RayShape2D::draw(const RID &p_to_rid, const Color &p_color) { + Vector2 tip = Vector2(0, get_length()); + RS::get_singleton()->canvas_item_add_line(p_to_rid, Vector2(), tip, p_color, 3); + Vector<Vector2> pts; + float tsize = 4; + pts.push_back(tip + Vector2(0, tsize)); + pts.push_back(tip + Vector2(Math_SQRT12 * tsize, 0)); + pts.push_back(tip + Vector2(-Math_SQRT12 * tsize, 0)); + Vector<Color> cols; + for (int i = 0; i < 3; i++) { + cols.push_back(p_color); + } + RS::get_singleton()->canvas_item_add_primitive(p_to_rid, pts, cols, Vector<Point2>(), RID()); +} + +Rect2 RayShape2D::get_rect() const { + Rect2 rect; + rect.position = Vector2(); + rect.expand_to(Vector2(0, length)); + rect = rect.grow(Math_SQRT12 * 4); + return rect; +} + +real_t RayShape2D::get_enclosing_radius() const { + return length; +} + +void RayShape2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape2D::set_length); + ClassDB::bind_method(D_METHOD("get_length"), &RayShape2D::get_length); + + ClassDB::bind_method(D_METHOD("set_slips_on_slope", "active"), &RayShape2D::set_slips_on_slope); + ClassDB::bind_method(D_METHOD("get_slips_on_slope"), &RayShape2D::get_slips_on_slope); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length"), "set_length", "get_length"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slips_on_slope"), "set_slips_on_slope", "get_slips_on_slope"); +} + +void RayShape2D::set_length(real_t p_length) { + length = p_length; + _update_shape(); +} + +real_t RayShape2D::get_length() const { + return length; +} + +void RayShape2D::set_slips_on_slope(bool p_active) { + slips_on_slope = p_active; + _update_shape(); +} + +bool RayShape2D::get_slips_on_slope() const { + return slips_on_slope; +} + +RayShape2D::RayShape2D() : + Shape2D(PhysicsServer2D::get_singleton()->ray_shape_create()) { + length = 20; + slips_on_slope = false; + _update_shape(); +} diff --git a/scene/resources/ray_shape_2d.h b/scene/resources/ray_shape_2d.h new file mode 100644 index 0000000000..c8202ca16c --- /dev/null +++ b/scene/resources/ray_shape_2d.h @@ -0,0 +1,61 @@ +/*************************************************************************/ +/* ray_shape_2d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RAY_SHAPE_2D_H +#define RAY_SHAPE_2D_H + +#include "scene/resources/shape_2d.h" + +class RayShape2D : public Shape2D { + GDCLASS(RayShape2D, Shape2D); + + real_t length; + bool slips_on_slope; + + void _update_shape(); + +protected: + static void _bind_methods(); + +public: + void set_length(real_t p_length); + real_t get_length() const; + + void set_slips_on_slope(bool p_active); + bool get_slips_on_slope() const; + + virtual void draw(const RID &p_to_rid, const Color &p_color) override; + virtual Rect2 get_rect() const override; + virtual real_t get_enclosing_radius() const override; + + RayShape2D(); +}; + +#endif // RAY_SHAPE_2D_H diff --git a/scene/resources/ray_shape.cpp b/scene/resources/ray_shape_3d.cpp index 3062e96293..39df4c22f9 100644 --- a/scene/resources/ray_shape.cpp +++ b/scene/resources/ray_shape_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* ray_shape.cpp */ +/* ray_shape_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,12 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "ray_shape.h" +#include "ray_shape_3d.h" -#include "servers/physics_server.h" - -Vector<Vector3> RayShape::get_debug_mesh_lines() { +#include "servers/physics_server_3d.h" +Vector<Vector3> RayShape3D::get_debug_mesh_lines() const { Vector<Vector3> points; points.push_back(Vector3()); points.push_back(Vector3(0, 0, get_length())); @@ -41,55 +40,53 @@ Vector<Vector3> RayShape::get_debug_mesh_lines() { return points; } -void RayShape::_update_shape() { +real_t RayShape3D::get_enclosing_radius() const { + return length; +} +void RayShape3D::_update_shape() { Dictionary d; d["length"] = length; d["slips_on_slope"] = slips_on_slope; - PhysicsServer::get_singleton()->shape_set_data(get_shape(), d); - Shape::_update_shape(); + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), d); + Shape3D::_update_shape(); } -void RayShape::set_length(float p_length) { - +void RayShape3D::set_length(float p_length) { length = p_length; _update_shape(); notify_change_to_owners(); _change_notify("length"); } -float RayShape::get_length() const { - +float RayShape3D::get_length() const { return length; } -void RayShape::set_slips_on_slope(bool p_active) { - +void RayShape3D::set_slips_on_slope(bool p_active) { slips_on_slope = p_active; _update_shape(); notify_change_to_owners(); _change_notify("slips_on_slope"); } -bool RayShape::get_slips_on_slope() const { +bool RayShape3D::get_slips_on_slope() const { return slips_on_slope; } -void RayShape::_bind_methods() { +void RayShape3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape3D::set_length); + ClassDB::bind_method(D_METHOD("get_length"), &RayShape3D::get_length); - ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape::set_length); - ClassDB::bind_method(D_METHOD("get_length"), &RayShape::get_length); + ClassDB::bind_method(D_METHOD("set_slips_on_slope", "active"), &RayShape3D::set_slips_on_slope); + ClassDB::bind_method(D_METHOD("get_slips_on_slope"), &RayShape3D::get_slips_on_slope); - ClassDB::bind_method(D_METHOD("set_slips_on_slope", "active"), &RayShape::set_slips_on_slope); - ClassDB::bind_method(D_METHOD("get_slips_on_slope"), &RayShape::get_slips_on_slope); - - ADD_PROPERTY(PropertyInfo(Variant::REAL, "length", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_length", "get_length"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_length", "get_length"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slips_on_slope"), "set_slips_on_slope", "get_slips_on_slope"); } -RayShape::RayShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_RAY)) { - +RayShape3D::RayShape3D() : + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_RAY)) { length = 1.0; slips_on_slope = false; diff --git a/scene/resources/ray_shape.h b/scene/resources/ray_shape_3d.h index ddf9f56ea3..a1a6702564 100644 --- a/scene/resources/ray_shape.h +++ b/scene/resources/ray_shape_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* ray_shape.h */ +/* ray_shape_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,17 +30,16 @@ #ifndef RAY_SHAPE_H #define RAY_SHAPE_H -#include "scene/resources/shape.h" +#include "scene/resources/shape_3d.h" -class RayShape : public Shape { - - GDCLASS(RayShape, Shape); +class RayShape3D : public Shape3D { + GDCLASS(RayShape3D, Shape3D); float length; bool slips_on_slope; protected: static void _bind_methods(); - virtual void _update_shape(); + virtual void _update_shape() override; public: void set_length(float p_length); @@ -49,8 +48,9 @@ public: void set_slips_on_slope(bool p_active); bool get_slips_on_slope() const; - virtual Vector<Vector3> get_debug_mesh_lines(); + virtual Vector<Vector3> get_debug_mesh_lines() const override; + virtual real_t get_enclosing_radius() const override; - RayShape(); + RayShape3D(); }; #endif // RAY_SHAPE_H diff --git a/scene/resources/rectangle_shape_2d.cpp b/scene/resources/rectangle_shape_2d.cpp index 0030e6dd4f..949fddf2e7 100644 --- a/scene/resources/rectangle_shape_2d.cpp +++ b/scene/resources/rectangle_shape_2d.cpp @@ -30,37 +30,35 @@ #include "rectangle_shape_2d.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" void RectangleShape2D::_update_shape() { - - Physics2DServer::get_singleton()->shape_set_data(get_rid(), extents); + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), extents); emit_changed(); } void RectangleShape2D::set_extents(const Vector2 &p_extents) { - extents = p_extents; _update_shape(); } Vector2 RectangleShape2D::get_extents() const { - return extents; } void RectangleShape2D::draw(const RID &p_to_rid, const Color &p_color) { - - VisualServer::get_singleton()->canvas_item_add_rect(p_to_rid, Rect2(-extents, extents * 2.0), p_color); + RenderingServer::get_singleton()->canvas_item_add_rect(p_to_rid, Rect2(-extents, extents * 2.0), p_color); } Rect2 RectangleShape2D::get_rect() const { - return Rect2(-extents, extents * 2.0); } -void RectangleShape2D::_bind_methods() { +real_t RectangleShape2D::get_enclosing_radius() const { + return extents.length(); +} +void RectangleShape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_extents", "extents"), &RectangleShape2D::set_extents); ClassDB::bind_method(D_METHOD("get_extents"), &RectangleShape2D::get_extents); @@ -68,8 +66,7 @@ void RectangleShape2D::_bind_methods() { } RectangleShape2D::RectangleShape2D() : - Shape2D(Physics2DServer::get_singleton()->rectangle_shape_create()) { - + Shape2D(PhysicsServer2D::get_singleton()->rectangle_shape_create()) { extents = Vector2(10, 10); _update_shape(); } diff --git a/scene/resources/rectangle_shape_2d.h b/scene/resources/rectangle_shape_2d.h index 686b421a2a..6efa7ab9c8 100644 --- a/scene/resources/rectangle_shape_2d.h +++ b/scene/resources/rectangle_shape_2d.h @@ -46,8 +46,9 @@ public: void set_extents(const Vector2 &p_extents); Vector2 get_extents() const; - virtual void draw(const RID &p_to_rid, const Color &p_color); - virtual Rect2 get_rect() const; + virtual void draw(const RID &p_to_rid, const Color &p_color) override; + virtual Rect2 get_rect() const override; + virtual real_t get_enclosing_radius() const override; RectangleShape2D(); }; diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index eb05defddd..d4d8018d43 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -35,7 +35,7 @@ #include "core/project_settings.h" #include "core/version.h" -//version 2: changed names for basis, aabb, poolvectors, etc. +//version 2: changed names for basis, aabb, Vectors, etc. #define FORMAT_VERSION 2 #include "core/os/dir_access.h" @@ -45,18 +45,15 @@ /// -void ResourceInteractiveLoaderText::set_local_path(const String &p_local_path) { - +void ResourceLoaderText::set_local_path(const String &p_local_path) { res_path = p_local_path; } -Ref<Resource> ResourceInteractiveLoaderText::get_resource() { - +Ref<Resource> ResourceLoaderText::get_resource() { return resource; } -Error ResourceInteractiveLoaderText::_parse_sub_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { - +Error ResourceLoaderText::_parse_sub_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { VariantParser::Token token; VariantParser::get_token(p_stream, token, line, r_err_str); if (token.type != VariantParser::TK_NUMBER) { @@ -85,8 +82,7 @@ Error ResourceInteractiveLoaderText::_parse_sub_resource_dummy(DummyReadData *p_ return OK; } -Error ResourceInteractiveLoaderText::_parse_ext_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { - +Error ResourceLoaderText::_parse_ext_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { VariantParser::Token token; VariantParser::get_token(p_stream, token, line, r_err_str); if (token.type != VariantParser::TK_NUMBER) { @@ -109,8 +105,7 @@ Error ResourceInteractiveLoaderText::_parse_ext_resource_dummy(DummyReadData *p_ return OK; } -Error ResourceInteractiveLoaderText::_parse_sub_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { - +Error ResourceLoaderText::_parse_sub_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { VariantParser::Token token; VariantParser::get_token(p_stream, token, line, r_err_str); if (token.type != VariantParser::TK_NUMBER) { @@ -120,18 +115,21 @@ Error ResourceInteractiveLoaderText::_parse_sub_resource(VariantParser::Stream * int index = token.value; - String path = local_path + "::" + itos(index); + if (use_nocache) { + r_res = int_resources[index]; + } else { + String path = local_path + "::" + itos(index); - if (!ignore_resource_parsing) { + if (!ignore_resource_parsing) { + if (!ResourceCache::has(path)) { + r_err_str = "Can't load cached sub-resource: " + path; + return ERR_PARSE_ERROR; + } - if (!ResourceCache::has(path)) { - r_err_str = "Can't load cached sub-resource: " + path; - return ERR_PARSE_ERROR; + r_res = RES(ResourceCache::get(path)); + } else { + r_res = RES(); } - - r_res = RES(ResourceCache::get(path)); - } else { - r_res = RES(); } VariantParser::get_token(p_stream, token, line, r_err_str); @@ -143,8 +141,7 @@ Error ResourceInteractiveLoaderText::_parse_sub_resource(VariantParser::Stream * return OK; } -Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { - +Error ResourceLoaderText::_parse_ext_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { VariantParser::Token token; VariantParser::get_token(p_stream, token, line, r_err_str); if (token.type != VariantParser::TK_NUMBER) { @@ -155,7 +152,6 @@ Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream * int id = token.value; if (!ignore_resource_parsing) { - if (!ext_resources.has(id)) { r_err_str = "Can't load cached ext-resource #" + itos(id); return ERR_PARSE_ERROR; @@ -164,15 +160,28 @@ Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream * String path = ext_resources[id].path; String type = ext_resources[id].type; - if (path.find("://") == -1 && path.is_rel_path()) { - // path is relative to file being loaded, so convert to a resource path - path = ProjectSettings::get_singleton()->localize_path(res_path.get_base_dir().plus_file(path)); - } - - r_res = ResourceLoader::load(path, type); - - if (r_res.is_null()) { - WARN_PRINT(String("Couldn't load external resource: " + path).utf8().get_data()); + if (ext_resources[id].cache.is_valid()) { + r_res = ext_resources[id].cache; + } else if (use_sub_threads) { + RES res = ResourceLoader::load_threaded_get(path); + if (res.is_null()) { + if (ResourceLoader::get_abort_on_missing_resources()) { + error = ERR_FILE_CORRUPT; + error_text = "[ext_resource] referenced nonexistent resource at: " + path; + _printerr(); + return error; + } else { + ResourceLoader::notify_dependency_error(local_path, path, type); + } + } else { + ext_resources[id].cache = res; + r_res = res; + } + } else { + error = ERR_FILE_CORRUPT; + error_text = "[ext_resource] referenced non-loaded resource at: " + path; + _printerr(); + return error; } } else { r_res = RES(); @@ -187,14 +196,12 @@ Error ResourceInteractiveLoaderText::_parse_ext_resource(VariantParser::Stream * return OK; } -Ref<PackedScene> ResourceInteractiveLoaderText::_parse_node_tag(VariantParser::ResourceParser &parser) { +Ref<PackedScene> ResourceLoaderText::_parse_node_tag(VariantParser::ResourceParser &parser) { Ref<PackedScene> packed_scene; packed_scene.instance(); while (true) { - if (next_tag.name == "node") { - int parent = -1; int owner = -1; int type = -1; @@ -220,7 +227,6 @@ Ref<PackedScene> ResourceInteractiveLoaderText::_parse_node_tag(VariantParser::R } if (next_tag.fields.has("instance")) { - instance = packed_scene->get_state()->add_value(next_tag.fields["instance"]); if (packed_scene->get_state()->get_node_count() == 0 && parent == -1) { @@ -230,7 +236,6 @@ Ref<PackedScene> ResourceInteractiveLoaderText::_parse_node_tag(VariantParser::R } if (next_tag.fields.has("instance_placeholder")) { - String path = next_tag.fields["instance_placeholder"]; int path_v = packed_scene->get_state()->add_value(path); @@ -248,8 +253,9 @@ Ref<PackedScene> ResourceInteractiveLoaderText::_parse_node_tag(VariantParser::R if (next_tag.fields.has("owner")) { owner = packed_scene->get_state()->add_node_path(next_tag.fields["owner"]); } else { - if (parent != -1 && !(type == SceneState::TYPE_INSTANCED && instance == -1)) + if (parent != -1 && !(type == SceneState::TYPE_INSTANCED && instance == -1)) { owner = 0; //if no owner, owner is root + } } if (next_tag.fields.has("index")) { @@ -259,7 +265,6 @@ Ref<PackedScene> ResourceInteractiveLoaderText::_parse_node_tag(VariantParser::R int node_id = packed_scene->get_state()->add_node(parent, owner, type, name, instance, index); if (next_tag.fields.has("groups")) { - Array groups = next_tag.fields["groups"]; for (int i = 0; i < groups.size(); i++) { packed_scene->get_state()->add_node_group(node_id, packed_scene->get_state()->add_name(groups[i])); @@ -267,7 +272,6 @@ Ref<PackedScene> ResourceInteractiveLoaderText::_parse_node_tag(VariantParser::R } while (true) { - String assign; Variant value; @@ -278,6 +282,7 @@ Ref<PackedScene> ResourceInteractiveLoaderText::_parse_node_tag(VariantParser::R _printerr(); return Ref<PackedScene>(); } else { + error = OK; return packed_scene; } } @@ -292,7 +297,6 @@ Ref<PackedScene> ResourceInteractiveLoaderText::_parse_node_tag(VariantParser::R } } } else if (next_tag.name == "connection") { - if (!next_tag.fields.has("from")) { error = ERR_FILE_CORRUPT; error_text = "missing 'from' field from connection tag"; @@ -321,7 +325,7 @@ Ref<PackedScene> ResourceInteractiveLoaderText::_parse_node_tag(VariantParser::R NodePath to = next_tag.fields["to"]; StringName method = next_tag.fields["method"]; StringName signal = next_tag.fields["signal"]; - int flags = CONNECT_PERSIST; + int flags = Object::CONNECT_PERSIST; Array binds; if (next_tag.fields.has("flags")) { @@ -352,11 +356,11 @@ Ref<PackedScene> ResourceInteractiveLoaderText::_parse_node_tag(VariantParser::R _printerr(); return Ref<PackedScene>(); } else { + error = OK; return packed_scene; } } } else if (next_tag.name == "editable") { - if (!next_tag.fields.has("path")) { error = ERR_FILE_CORRUPT; error_text = "missing 'path' field from connection tag"; @@ -375,26 +379,27 @@ Ref<PackedScene> ResourceInteractiveLoaderText::_parse_node_tag(VariantParser::R _printerr(); return Ref<PackedScene>(); } else { + error = OK; return packed_scene; } } } else { - error = ERR_FILE_CORRUPT; _printerr(); return Ref<PackedScene>(); } } - - return packed_scene; } -Error ResourceInteractiveLoaderText::poll() { - - if (error != OK) +Error ResourceLoaderText::load() { + if (error != OK) { return error; + } - if (next_tag.name == "ext_resource") { + while (true) { + if (next_tag.name != "ext_resource") { + break; + } if (!next_tag.fields.has("path")) { error = ERR_FILE_CORRUPT; @@ -430,30 +435,46 @@ Error ResourceInteractiveLoaderText::poll() { path = remaps[path]; } - RES res = ResourceLoader::load(path, type); + ExtResource er; + er.path = path; + er.type = type; - if (res.is_null()) { + if (use_sub_threads) { + Error err = ResourceLoader::load_threaded_request(path, type, use_sub_threads, local_path); - if (ResourceLoader::get_abort_on_missing_resources()) { - error = ERR_FILE_CORRUPT; - error_text = "[ext_resource] referenced nonexistent resource at: " + path; - _printerr(); - return error; - } else { - ResourceLoader::notify_dependency_error(local_path, path, type); + if (err != OK) { + if (ResourceLoader::get_abort_on_missing_resources()) { + error = ERR_FILE_CORRUPT; + error_text = "[ext_resource] referenced broken resource at: " + path; + _printerr(); + return error; + } else { + ResourceLoader::notify_dependency_error(local_path, path, type); + } } + } else { + RES res = ResourceLoader::load(path, type); - resource_cache.push_back(res); + if (res.is_null()) { + if (ResourceLoader::get_abort_on_missing_resources()) { + error = ERR_FILE_CORRUPT; + error_text = "[ext_resource] referenced nonexistent resource at: " + path; + _printerr(); + return error; + } else { + ResourceLoader::notify_dependency_error(local_path, path, type); + } + } else { #ifdef TOOLS_ENABLED - //remember ID for saving - res->set_id_for_path(local_path, index); + //remember ID for saving + res->set_id_for_path(local_path, index); #endif + } + + er.cache = res; } - ExtResource er; - er.path = path; - er.type = type; ext_resources[index] = er; error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp); @@ -463,9 +484,16 @@ Error ResourceInteractiveLoaderText::poll() { } resource_current++; - return error; + } - } else if (next_tag.name == "sub_resource") { + //these are the ones that count + resources_total -= resource_current; + resource_current = 0; + + while (true) { + if (next_tag.name != "sub_resource") { + break; + } if (!next_tag.fields.has("type")) { error = ERR_FILE_CORRUPT; @@ -490,11 +518,10 @@ Error ResourceInteractiveLoaderText::poll() { Ref<Resource> res; - if (!ResourceCache::has(path)) { //only if it doesn't exist + if (use_nocache || !ResourceCache::has(path)) { //only if it doesn't exist Object *obj = ClassDB::instance(type); if (!obj) { - error_text += "Can't create sub resource of type: " + type; _printerr(); error = ERR_FILE_CORRUPT; @@ -503,7 +530,6 @@ Error ResourceInteractiveLoaderText::poll() { Resource *r = Object::cast_to<Resource>(obj); if (!r) { - error_text += "Can't create sub resource of type, because not a resource: " + type; _printerr(); error = ERR_FILE_CORRUPT; @@ -511,14 +537,15 @@ Error ResourceInteractiveLoaderText::poll() { } res = Ref<Resource>(r); - resource_cache.push_back(res); - res->set_path(path); + int_resources[id] = res; + if (!use_nocache) { + res->set_path(path); + } } resource_current++; while (true) { - String assign; Variant value; @@ -535,7 +562,6 @@ Error ResourceInteractiveLoaderText::poll() { } //it's assignment } else if (next_tag.name != String()) { - error = OK; break; } else { @@ -546,12 +572,17 @@ Error ResourceInteractiveLoaderText::poll() { } } - return OK; + if (progress && resources_total > 0) { + *progress = resource_current / float(resources_total); + } + } - } else if (next_tag.name == "resource") { + while (true) { + if (next_tag.name != "resource") { + break; + } if (is_scene) { - error_text += "found the 'resource' tag on a scene file!"; _printerr(); error = ERR_FILE_CORRUPT; @@ -560,7 +591,6 @@ Error ResourceInteractiveLoaderText::poll() { Object *obj = ClassDB::instance(res_type); if (!obj) { - error_text += "Can't create sub resource of type: " + res_type; _printerr(); error = ERR_FILE_CORRUPT; @@ -569,7 +599,6 @@ Error ResourceInteractiveLoaderText::poll() { Resource *r = Object::cast_to<Resource>(obj); if (!r) { - error_text += "Can't create sub resource of type, because not a resource: " + res_type; _printerr(); error = ERR_FILE_CORRUPT; @@ -581,7 +610,6 @@ Error ResourceInteractiveLoaderText::poll() { resource_current++; while (true) { - String assign; Variant value; @@ -591,10 +619,13 @@ Error ResourceInteractiveLoaderText::poll() { if (error != ERR_FILE_EOF) { _printerr(); } else { - if (!ResourceCache::has(res_path)) { - resource->set_path(res_path); + error = OK; + if (!use_nocache) { + if (!ResourceCache::has(res_path)) { + resource->set_path(res_path); + } + resource->set_as_translation_remapped(translation_remapped); } - resource->set_as_translation_remapped(translation_remapped); } return error; } @@ -603,23 +634,25 @@ Error ResourceInteractiveLoaderText::poll() { resource->set(assign, value); //it's assignment } else if (next_tag.name != String()) { - error = ERR_FILE_CORRUPT; error_text = "Extra tag found when parsing main resource file"; _printerr(); return error; } else { - error = ERR_FILE_EOF; + error = OK; + if (progress && resources_total > 0) { + *progress = resource_current / float(resources_total); + } + return error; } } + } - return OK; - - } else if (next_tag.name == "node") { + //for scene files + if (next_tag.name == "node") { if (!is_scene) { - error_text += "found the 'node' tag on a resource file!"; _printerr(); error = ERR_FILE_CORRUPT; @@ -628,59 +661,68 @@ Error ResourceInteractiveLoaderText::poll() { Ref<PackedScene> packed_scene = _parse_node_tag(rp); - if (!packed_scene.is_valid()) + if (!packed_scene.is_valid()) { return error; + } - error = ERR_FILE_EOF; + error = OK; //get it here resource = packed_scene; - if (!ResourceCache::has(res_path)) { + if (!use_nocache && !ResourceCache::has(res_path)) { packed_scene->set_path(res_path); } - return error; + resource_current++; + if (progress && resources_total > 0) { + *progress = resource_current / float(resources_total); + } + + return error; } else { error_text += "Unknown tag in file: " + next_tag.name; _printerr(); error = ERR_FILE_CORRUPT; return error; } - - return OK; } -int ResourceInteractiveLoaderText::get_stage() const { - +int ResourceLoaderText::get_stage() const { return resource_current; } -int ResourceInteractiveLoaderText::get_stage_count() const { +int ResourceLoaderText::get_stage_count() const { return resources_total; //+ext_resources; } -void ResourceInteractiveLoaderText::set_translation_remapped(bool p_remapped) { - +void ResourceLoaderText::set_translation_remapped(bool p_remapped) { translation_remapped = p_remapped; } -ResourceInteractiveLoaderText::ResourceInteractiveLoaderText() { +ResourceLoaderText::ResourceLoaderText() { + use_nocache = false; + + resources_total = 0; + resource_current = 0; + use_sub_threads = false; + + progress = nullptr; + lines = false; translation_remapped = false; + use_sub_threads = false; + error = OK; } -ResourceInteractiveLoaderText::~ResourceInteractiveLoaderText() { - +ResourceLoaderText::~ResourceLoaderText() { memdelete(f); } -void ResourceInteractiveLoaderText::get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types) { - +void ResourceLoaderText::get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types) { open(p_f); ignore_resource_parsing = true; ERR_FAIL_COND(error != OK); while (next_tag.name == "ext_resource") { - if (!next_tag.fields.has("type")) { error = ERR_FILE_CORRUPT; error_text = "Missing 'type' in external resource tag"; @@ -720,21 +762,19 @@ void ResourceInteractiveLoaderText::get_dependencies(FileAccess *p_f, List<Strin } } -Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const String &p_path, const Map<String, String> &p_map) { - +Error ResourceLoaderText::rename_dependencies(FileAccess *p_f, const String &p_path, const Map<String, String> &p_map) { open(p_f, true); ERR_FAIL_COND_V(error != OK, error); ignore_resource_parsing = true; //FileAccess - FileAccess *fw = NULL; + FileAccess *fw = nullptr; String base_path = local_path.get_base_dir(); uint64_t tag_end = f->get_position(); while (true) { - Error err = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp); if (err != OK) { @@ -746,17 +786,15 @@ Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const } if (next_tag.name != "ext_resource") { - //nothing was done - if (!fw) + if (!fw) { return OK; + } break; } else { - if (!fw) { - fw = FileAccess::open(p_path + ".depren", FileAccess::WRITE); if (is_scene) { fw->store_line("[gd_scene load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + "]\n"); @@ -822,8 +860,7 @@ Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const return OK; } -void ResourceInteractiveLoaderText::open(FileAccess *p_f, bool p_skip_first_tag) { - +void ResourceLoaderText::open(FileAccess *p_f, bool p_skip_first_tag) { error = OK; lines = 1; @@ -838,7 +875,6 @@ void ResourceInteractiveLoaderText::open(FileAccess *p_f, bool p_skip_first_tag) Error err = VariantParser::parse_tag(&stream, lines, error_text, tag); if (err) { - error = err; _printerr(); return; @@ -881,7 +917,6 @@ void ResourceInteractiveLoaderText::open(FileAccess *p_f, bool p_skip_first_tag) } if (!p_skip_first_tag) { - err = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp); if (err) { @@ -893,12 +928,11 @@ void ResourceInteractiveLoaderText::open(FileAccess *p_f, bool p_skip_first_tag) rp.ext_func = _parse_ext_resources; rp.sub_func = _parse_sub_resources; - rp.func = NULL; + rp.func = nullptr; rp.userdata = this; } static void bs_save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len = false) { - CharString utf8 = p_string.utf8(); if (p_bit_on_len) { f->store_32((utf8.length() + 1) | 0x80000000); @@ -908,10 +942,10 @@ static void bs_save_unicode_string(FileAccess *f, const String &p_string, bool p f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1); } -Error ResourceInteractiveLoaderText::save_as_binary(FileAccess *p_f, const String &p_path) { - - if (error) +Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path) { + if (error) { return error; + } FileAccessRef wf = FileAccess::open(p_path, FileAccess::WRITE); if (!wf) { @@ -931,8 +965,9 @@ Error ResourceInteractiveLoaderText::save_as_binary(FileAccess *p_f, const Strin bs_save_unicode_string(wf.f, is_scene ? "PackedScene" : resource_type); wf->store_64(0); //offset to import metadata, this is no longer used - for (int i = 0; i < 14; i++) + for (int i = 0; i < 14; i++) { wf->store_32(0); // reserved + } wf->store_32(0); //string table size, will not be in use size_t ext_res_count_pos = wf->get_position(); @@ -948,7 +983,6 @@ Error ResourceInteractiveLoaderText::save_as_binary(FileAccess *p_f, const Strin rp.userdata = &dummy_read; while (next_tag.name == "ext_resource") { - if (!next_tag.fields.has("path")) { error = ERR_FILE_CORRUPT; error_text = "Missing 'path' in external resource tag"; @@ -1012,7 +1046,6 @@ Error ResourceInteractiveLoaderText::save_as_binary(FileAccess *p_f, const Strin Vector<size_t> local_pointers_pos; while (next_tag.name == "sub_resource" || next_tag.name == "resource") { - String type; int id = -1; bool main_res; @@ -1054,7 +1087,6 @@ Error ResourceInteractiveLoaderText::save_as_binary(FileAccess *p_f, const Strin int prop_count = 0; while (true) { - String assign; Variant value; @@ -1071,14 +1103,12 @@ Error ResourceInteractiveLoaderText::save_as_binary(FileAccess *p_f, const Strin } if (assign != String()) { - Map<StringName, int> empty_string_map; //unused bs_save_unicode_string(wf2, assign, true); ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_set, dummy_read.external_resources, empty_string_map); prop_count++; } else if (next_tag.name != String()) { - error = OK; break; } else { @@ -1098,7 +1128,6 @@ Error ResourceInteractiveLoaderText::save_as_binary(FileAccess *p_f, const Strin //this is a node, must save one more! if (!is_scene) { - error_text += "found the 'node' tag on a resource file!"; _printerr(); error = ERR_FILE_CORRUPT; @@ -1107,8 +1136,9 @@ Error ResourceInteractiveLoaderText::save_as_binary(FileAccess *p_f, const Strin Ref<PackedScene> packed_scene = _parse_node_tag(rp); - if (!packed_scene.is_valid()) + if (!packed_scene.is_valid()) { return error; + } error = OK; //get it here @@ -1127,9 +1157,9 @@ Error ResourceInteractiveLoaderText::save_as_binary(FileAccess *p_f, const Strin int prop_count = 0; for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { - - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) + if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) { continue; + } String name = E->get().name; Variant value = packed_scene->get(name); @@ -1172,8 +1202,7 @@ Error ResourceInteractiveLoaderText::save_as_binary(FileAccess *p_f, const Strin return OK; } -String ResourceInteractiveLoaderText::recognize(FileAccess *p_f) { - +String ResourceLoaderText::recognize(FileAccess *p_f) { error = OK; lines = 1; @@ -1200,11 +1229,13 @@ String ResourceInteractiveLoaderText::recognize(FileAccess *p_f) { } } - if (tag.name == "gd_scene") + if (tag.name == "gd_scene") { return "PackedScene"; + } - if (tag.name != "gd_resource") + if (tag.name != "gd_resource") { return ""; + } if (!tag.fields.has("type")) { error_text = "Missing 'type' field in 'gd_resource' tag"; @@ -1217,119 +1248,123 @@ String ResourceInteractiveLoaderText::recognize(FileAccess *p_f) { ///////////////////// -Ref<ResourceInteractiveLoader> ResourceFormatLoaderText::load_interactive(const String &p_path, const String &p_original_path, Error *r_error) { - - if (r_error) +RES ResourceFormatLoaderText::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { + if (r_error) { *r_error = ERR_CANT_OPEN; + } Error err; + FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); - ERR_FAIL_COND_V_MSG(err != OK, Ref<ResourceInteractiveLoader>(), "Cannot open file '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot open file '" + p_path + "'."); - Ref<ResourceInteractiveLoaderText> ria = memnew(ResourceInteractiveLoaderText); + ResourceLoaderText loader; String path = p_original_path != "" ? p_original_path : p_path; - ria->local_path = ProjectSettings::get_singleton()->localize_path(path); - ria->res_path = ria->local_path; - //ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) ); - ria->open(f); - - return ria; + loader.use_nocache = p_no_cache; + loader.use_sub_threads = p_use_sub_threads; + loader.local_path = ProjectSettings::get_singleton()->localize_path(path); + loader.progress = r_progress; + loader.res_path = loader.local_path; + //loader.set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) ); + loader.open(f); + err = loader.load(); + if (r_error) { + *r_error = err; + } + if (err == OK) { + return loader.get_resource(); + } else { + return RES(); + } } void ResourceFormatLoaderText::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const { - if (p_type == "") { get_recognized_extensions(p_extensions); return; } - if (p_type == "PackedScene") + if (p_type == "PackedScene") { p_extensions->push_back("tscn"); - else + } else { p_extensions->push_back("tres"); + } } void ResourceFormatLoaderText::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("tscn"); p_extensions->push_back("tres"); } bool ResourceFormatLoaderText::handles_type(const String &p_type) const { - return true; } -String ResourceFormatLoaderText::get_resource_type(const String &p_path) const { +String ResourceFormatLoaderText::get_resource_type(const String &p_path) const { String ext = p_path.get_extension().to_lower(); - if (ext == "tscn") + if (ext == "tscn") { return "PackedScene"; - else if (ext != "tres") + } else if (ext != "tres") { return String(); + } //for anyhting else must test.. FileAccess *f = FileAccess::open(p_path, FileAccess::READ); if (!f) { - return ""; //could not rwead } - Ref<ResourceInteractiveLoaderText> ria = memnew(ResourceInteractiveLoaderText); - ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path); - ria->res_path = ria->local_path; - //ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) ); - String r = ria->recognize(f); - return r; + ResourceLoaderText loader; + loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path); + loader.res_path = loader.local_path; + //loader.set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) ); + String r = loader.recognize(f); + return ClassDB::get_compatibility_remapped_class(r); } void ResourceFormatLoaderText::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { - FileAccess *f = FileAccess::open(p_path, FileAccess::READ); if (!f) { - ERR_FAIL(); } - Ref<ResourceInteractiveLoaderText> ria = memnew(ResourceInteractiveLoaderText); - ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path); - ria->res_path = ria->local_path; - //ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) ); - ria->get_dependencies(f, p_dependencies, p_add_types); + ResourceLoaderText loader; + loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path); + loader.res_path = loader.local_path; + //loader.set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) ); + loader.get_dependencies(f, p_dependencies, p_add_types); } Error ResourceFormatLoaderText::rename_dependencies(const String &p_path, const Map<String, String> &p_map) { - FileAccess *f = FileAccess::open(p_path, FileAccess::READ); if (!f) { - ERR_FAIL_V(ERR_CANT_OPEN); } - Ref<ResourceInteractiveLoaderText> ria = memnew(ResourceInteractiveLoaderText); - ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path); - ria->res_path = ria->local_path; - //ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) ); - return ria->rename_dependencies(f, p_path, p_map); + ResourceLoaderText loader; + loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path); + loader.res_path = loader.local_path; + //loader.set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) ); + return loader.rename_dependencies(f, p_path, p_map); } -ResourceFormatLoaderText *ResourceFormatLoaderText::singleton = NULL; +ResourceFormatLoaderText *ResourceFormatLoaderText::singleton = nullptr; Error ResourceFormatLoaderText::convert_file_to_binary(const String &p_src_path, const String &p_dst_path) { - Error err; FileAccess *f = FileAccess::open(p_src_path, FileAccess::READ, &err); ERR_FAIL_COND_V_MSG(err != OK, ERR_CANT_OPEN, "Cannot open file '" + p_src_path + "'."); - Ref<ResourceInteractiveLoaderText> ria = memnew(ResourceInteractiveLoaderText); + ResourceLoaderText loader; const String &path = p_src_path; - ria->local_path = ProjectSettings::get_singleton()->localize_path(path); - ria->res_path = ria->local_path; - //ria->set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) ); - ria->open(f); - return ria->save_as_binary(f, p_dst_path); + loader.local_path = ProjectSettings::get_singleton()->localize_path(path); + loader.res_path = loader.local_path; + //loader.set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) ); + loader.open(f); + return loader.save_as_binary(f, p_dst_path); } /*****************************************************************************************************/ @@ -1344,18 +1379,14 @@ Error ResourceFormatLoaderText::convert_file_to_binary(const String &p_src_path, /*****************************************************************************************************/ String ResourceFormatSaverTextInstance::_write_resources(void *ud, const RES &p_resource) { - ResourceFormatSaverTextInstance *rsi = (ResourceFormatSaverTextInstance *)ud; return rsi->_write_resource(p_resource); } String ResourceFormatSaverTextInstance::_write_resource(const RES &res) { - if (external_resources.has(res)) { - return "ExtResource( " + itos(external_resources[res]) + " )"; } else { - if (internal_resources.has(res)) { return "SubResource( " + itos(internal_resources[res]) + " )"; } else if (res->get_path().length() && res->get_path().find("::") == -1) { @@ -1373,18 +1404,17 @@ String ResourceFormatSaverTextInstance::_write_resource(const RES &res) { } void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant, bool p_main) { - switch (p_variant.get_type()) { case Variant::OBJECT: { + RES res = p_variant; - RES res = p_variant.operator RefPtr(); - - if (res.is_null() || external_resources.has(res)) + if (res.is_null() || external_resources.has(res)) { return; + } if (!p_main && (!bundle_resources) && res->get_path().length() && res->get_path().find("::") == -1) { if (res->get_path() == local_path) { - ERR_PRINTS("Circular reference to resource being saved found: '" + local_path + "' will be null next time it's loaded."); + ERR_PRINT("Circular reference to resource being saved found: '" + local_path + "' will be null next time it's loaded."); return; } int index = external_resources.size(); @@ -1392,8 +1422,9 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant, return; } - if (resource_set.has(res)) + if (resource_set.has(res)) { return; + } List<PropertyInfo> property_list; @@ -1403,11 +1434,9 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant, List<PropertyInfo>::Element *I = property_list.front(); while (I) { - PropertyInfo pi = I->get(); if (pi.usage & PROPERTY_USAGE_STORAGE) { - Variant v = res->get(I->get().name); if (pi.usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) { @@ -1433,23 +1462,19 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant, } break; case Variant::ARRAY: { - Array varray = p_variant; int len = varray.size(); for (int i = 0; i < len; i++) { - const Variant &v = varray.get(i); _find_resources(v); } } break; case Variant::DICTIONARY: { - Dictionary d = p_variant; List<Variant> keys; d.get_key_list(&keys); for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - Variant v = d[E->get()]; _find_resources(v); } @@ -1460,7 +1485,6 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant, } Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - if (p_path.ends_with(".tscn")) { packed_scene = p_resource; } @@ -1486,8 +1510,9 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r if (packed_scene.is_valid()) { //add instances to external resources if saving a packed scene for (int i = 0; i < packed_scene->get_state()->get_node_count(); i++) { - if (packed_scene->get_state()->is_node_instance_placeholder(i)) + if (packed_scene->get_state()->is_node_instance_placeholder(i)) { continue; + } Ref<PackedScene> instance = packed_scene->get_state()->get_node_instance(i); if (instance.is_valid() && !external_resources.has(instance)) { @@ -1499,8 +1524,9 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r { String title = packed_scene.is_valid() ? "[gd_scene " : "[gd_resource "; - if (packed_scene.is_null()) + if (packed_scene.is_null()) { title += "type=\"" + p_resource->get_class() + "\" "; + } int load_steps = saved_resources.size() + external_resources.size(); /* if (packed_scene.is_valid()) { @@ -1557,7 +1583,6 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r Vector<ResourceSort> sorted_er; for (Map<RES, int>::Element *E = external_resources.front(); E; E = E->next()) { - ResourceSort rs; rs.resource = E->key(); rs.index = E->get(); @@ -1572,16 +1597,15 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r f->store_string("[ext_resource path=\"" + p + "\" type=\"" + sorted_er[i].resource->get_save_class() + "\" id=" + itos(sorted_er[i].index) + "]\n"); //bundled } - if (external_resources.size()) + if (external_resources.size()) { f->store_line(String()); //separate + } Set<int> used_indices; for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) { - RES res = E->get(); if (E->next() && (res->get_path() == "" || res->get_path().find("::") != -1)) { - if (res->get_subindex() != 0) { if (used_indices.has(res->get_subindex())) { res->set_subindex(0); //repeated @@ -1593,13 +1617,13 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r } for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) { - RES res = E->get(); ERR_CONTINUE(!resource_set.has(res)); - bool main = (E->next() == NULL); + bool main = (E->next() == nullptr); - if (main && packed_scene.is_valid()) + if (main && packed_scene.is_valid()) { break; //save as a scene + } if (main) { f->store_line("[resource]"); @@ -1632,12 +1656,11 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r res->get_property_list(&property_list); //property_list.sort(); for (List<PropertyInfo>::Element *PE = property_list.front(); PE; PE = PE->next()) { - - if (skip_editor && PE->get().name.begins_with("__editor")) + if (skip_editor && PE->get().name.begins_with("__editor")) { continue; + } if (PE->get().usage & PROPERTY_USAGE_STORAGE) { - String name = PE->get().name; Variant value; if (PE->get().usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) { @@ -1656,8 +1679,9 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r continue; } - if (PE->get().type == Variant::OBJECT && value.is_zero() && !(PE->get().usage & PROPERTY_USAGE_STORE_IF_NULL)) + if (PE->get().type == Variant::OBJECT && value.is_zero() && !(PE->get().usage & PROPERTY_USAGE_STORE_IF_NULL)) { continue; + } String vars; VariantWriter::write_to_string(value, vars, _write_resources, this); @@ -1665,15 +1689,15 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r } } - if (E->next()) + if (E->next()) { f->store_line(String()); + } } if (packed_scene.is_valid()) { //if this is a scene, save nodes and connections! Ref<SceneState> state = packed_scene->get_state(); for (int i = 0; i < state->get_node_count(); i++) { - StringName type = state->get_node_type(i); StringName name = state->get_node_name(i); int index = state->get_node_index(i); @@ -1711,7 +1735,6 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r f->store_string(header); if (instance_placeholder != String()) { - String vars; f->store_string(" instance_placeholder="); VariantWriter::write_to_string(instance_placeholder, vars, _write_resources, this); @@ -1719,7 +1742,6 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r } if (instance.is_valid()) { - String vars; f->store_string(" instance="); VariantWriter::write_to_string(instance, vars, _write_resources, this); @@ -1729,19 +1751,18 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r f->store_line("]"); for (int j = 0; j < state->get_node_property_count(i); j++) { - String vars; VariantWriter::write_to_string(state->get_node_property_value(i, j), vars, _write_resources, this); f->store_string(String(state->get_node_property_name(i, j)).property_name_encode() + " = " + vars + "\n"); } - if (i < state->get_node_count() - 1) + if (i < state->get_node_count() - 1) { f->store_line(String()); + } } for (int i = 0; i < state->get_connection_count(); i++) { - String connstr = "[connection"; connstr += " signal=\"" + String(state->get_connection_signal(i)) + "\""; connstr += " from=\"" + String(state->get_connection_source(i).simplified()) + "\""; @@ -1781,7 +1802,6 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r } Error ResourceFormatSaverText::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - if (p_path.ends_with(".sct") && p_resource->get_class() != "PackedScene") { return ERR_FILE_UNRECOGNIZED; } @@ -1791,18 +1811,18 @@ Error ResourceFormatSaverText::save(const String &p_path, const RES &p_resource, } bool ResourceFormatSaverText::recognize(const RES &p_resource) const { - return true; // all recognized! } -void ResourceFormatSaverText::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { - if (p_resource->get_class() == "PackedScene") +void ResourceFormatSaverText::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { + if (p_resource->get_class() == "PackedScene") { p_extensions->push_back("tscn"); //text scene - else + } else { p_extensions->push_back("tres"); //text resource + } } -ResourceFormatSaverText *ResourceFormatSaverText::singleton = NULL; +ResourceFormatSaverText *ResourceFormatSaverText::singleton = nullptr; ResourceFormatSaverText::ResourceFormatSaverText() { singleton = this; } diff --git a/scene/resources/resource_format_text.h b/scene/resources/resource_format_text.h index 66c69725e8..cf522c9364 100644 --- a/scene/resources/resource_format_text.h +++ b/scene/resources/resource_format_text.h @@ -37,8 +37,7 @@ #include "core/variant_parser.h" #include "scene/resources/packed_scene.h" -class ResourceInteractiveLoaderText : public ResourceInteractiveLoader { - +class ResourceLoaderText { bool translation_remapped; String local_path; String res_path; @@ -49,6 +48,7 @@ class ResourceInteractiveLoaderText : public ResourceInteractiveLoader { VariantParser::StreamFile stream; struct ExtResource { + RES cache; String path; String type; }; @@ -61,6 +61,7 @@ class ResourceInteractiveLoaderText : public ResourceInteractiveLoader { //Map<String,String> remaps; Map<int, ExtResource> ext_resources; + Map<int, RES> int_resources; int resources_total; int resource_current; @@ -68,13 +69,18 @@ class ResourceInteractiveLoaderText : public ResourceInteractiveLoader { VariantParser::Tag next_tag; + bool use_nocache; + + bool use_sub_threads; + float *progress; + mutable int lines; Map<String, String> remaps; //void _printerr(); - static Error _parse_sub_resources(void *p_self, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { return reinterpret_cast<ResourceInteractiveLoaderText *>(p_self)->_parse_sub_resource(p_stream, r_res, line, r_err_str); } - static Error _parse_ext_resources(void *p_self, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { return reinterpret_cast<ResourceInteractiveLoaderText *>(p_self)->_parse_ext_resource(p_stream, r_res, line, r_err_str); } + static Error _parse_sub_resources(void *p_self, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { return reinterpret_cast<ResourceLoaderText *>(p_self)->_parse_sub_resource(p_stream, r_res, line, r_err_str); } + static Error _parse_ext_resources(void *p_self, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { return reinterpret_cast<ResourceLoaderText *>(p_self)->_parse_ext_resource(p_stream, r_res, line, r_err_str); } Error _parse_sub_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str); Error _parse_ext_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str); @@ -85,7 +91,6 @@ class ResourceInteractiveLoaderText : public ResourceInteractiveLoader { }; struct DummyReadData { - Map<RES, int> external_resources; Map<int, RES> rev_external_resources; Set<RES> resource_set; @@ -102,7 +107,6 @@ class ResourceInteractiveLoaderText : public ResourceInteractiveLoader { friend class ResourceFormatLoaderText; - List<RES> resource_cache; Error error; RES resource; @@ -110,12 +114,12 @@ class ResourceInteractiveLoaderText : public ResourceInteractiveLoader { Ref<PackedScene> _parse_node_tag(VariantParser::ResourceParser &parser); public: - virtual void set_local_path(const String &p_local_path); - virtual Ref<Resource> get_resource(); - virtual Error poll(); - virtual int get_stage() const; - virtual int get_stage_count() const; - virtual void set_translation_remapped(bool p_remapped); + void set_local_path(const String &p_local_path); + Ref<Resource> get_resource(); + Error load(); + int get_stage() const; + int get_stage_count() const; + void set_translation_remapped(bool p_remapped); void open(FileAccess *p_f, bool p_skip_first_tag = false); String recognize(FileAccess *p_f); @@ -123,14 +127,14 @@ public: Error rename_dependencies(FileAccess *p_f, const String &p_path, const Map<String, String> &p_map); Error save_as_binary(FileAccess *p_f, const String &p_path); - ResourceInteractiveLoaderText(); - ~ResourceInteractiveLoaderText(); + ResourceLoaderText(); + ~ResourceLoaderText(); }; class ResourceFormatLoaderText : public ResourceFormatLoader { public: static ResourceFormatLoaderText *singleton; - virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const; virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; @@ -144,7 +148,6 @@ public: }; class ResourceFormatSaverTextInstance { - String local_path; Ref<PackedScene> packed_scene; diff --git a/scene/resources/segment_shape_2d.cpp b/scene/resources/segment_shape_2d.cpp index 0070de72a2..b1001203a1 100644 --- a/scene/resources/segment_shape_2d.cpp +++ b/scene/resources/segment_shape_2d.cpp @@ -30,60 +30,58 @@ #include "segment_shape_2d.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "core/math/geometry_2d.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" bool SegmentShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { - Vector2 l[2] = { a, b }; - Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point, l); + Vector2 closest = Geometry2D::get_closest_point_to_segment(p_point, l); return p_point.distance_to(closest) < p_tolerance; } void SegmentShape2D::_update_shape() { - Rect2 r; r.position = a; r.size = b; - Physics2DServer::get_singleton()->shape_set_data(get_rid(), r); + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), r); emit_changed(); } void SegmentShape2D::set_a(const Vector2 &p_a) { - a = p_a; _update_shape(); } -Vector2 SegmentShape2D::get_a() const { +Vector2 SegmentShape2D::get_a() const { return a; } void SegmentShape2D::set_b(const Vector2 &p_b) { - b = p_b; _update_shape(); } -Vector2 SegmentShape2D::get_b() const { +Vector2 SegmentShape2D::get_b() const { return b; } void SegmentShape2D::draw(const RID &p_to_rid, const Color &p_color) { - - VisualServer::get_singleton()->canvas_item_add_line(p_to_rid, a, b, p_color, 3); + RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, a, b, p_color, 3); } Rect2 SegmentShape2D::get_rect() const { - Rect2 rect; rect.position = a; rect.expand_to(b); return rect; } -void SegmentShape2D::_bind_methods() { +real_t SegmentShape2D::get_enclosing_radius() const { + return (a + b).length(); +} +void SegmentShape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_a", "a"), &SegmentShape2D::set_a); ClassDB::bind_method(D_METHOD("get_a"), &SegmentShape2D::get_a); @@ -95,85 +93,8 @@ void SegmentShape2D::_bind_methods() { } SegmentShape2D::SegmentShape2D() : - Shape2D(Physics2DServer::get_singleton()->segment_shape_create()) { - + Shape2D(PhysicsServer2D::get_singleton()->segment_shape_create()) { a = Vector2(); b = Vector2(0, 10); _update_shape(); } - -//////////////////////////////////////////////////////////// - -void RayShape2D::_update_shape() { - - Dictionary d; - d["length"] = length; - d["slips_on_slope"] = slips_on_slope; - Physics2DServer::get_singleton()->shape_set_data(get_rid(), d); - emit_changed(); -} - -void RayShape2D::draw(const RID &p_to_rid, const Color &p_color) { - - Vector2 tip = Vector2(0, get_length()); - VS::get_singleton()->canvas_item_add_line(p_to_rid, Vector2(), tip, p_color, 3); - Vector<Vector2> pts; - float tsize = 4; - pts.push_back(tip + Vector2(0, tsize)); - pts.push_back(tip + Vector2(Math_SQRT12 * tsize, 0)); - pts.push_back(tip + Vector2(-Math_SQRT12 * tsize, 0)); - Vector<Color> cols; - for (int i = 0; i < 3; i++) - cols.push_back(p_color); - - VS::get_singleton()->canvas_item_add_primitive(p_to_rid, pts, cols, Vector<Point2>(), RID()); -} - -Rect2 RayShape2D::get_rect() const { - - Rect2 rect; - rect.position = Vector2(); - rect.expand_to(Vector2(0, length)); - rect = rect.grow(Math_SQRT12 * 4); - return rect; -} - -void RayShape2D::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_length", "length"), &RayShape2D::set_length); - ClassDB::bind_method(D_METHOD("get_length"), &RayShape2D::get_length); - - ClassDB::bind_method(D_METHOD("set_slips_on_slope", "active"), &RayShape2D::set_slips_on_slope); - ClassDB::bind_method(D_METHOD("get_slips_on_slope"), &RayShape2D::get_slips_on_slope); - - ADD_PROPERTY(PropertyInfo(Variant::REAL, "length"), "set_length", "get_length"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slips_on_slope"), "set_slips_on_slope", "get_slips_on_slope"); -} - -void RayShape2D::set_length(real_t p_length) { - - length = p_length; - _update_shape(); -} -real_t RayShape2D::get_length() const { - - return length; -} - -void RayShape2D::set_slips_on_slope(bool p_active) { - - slips_on_slope = p_active; - _update_shape(); -} - -bool RayShape2D::get_slips_on_slope() const { - return slips_on_slope; -} - -RayShape2D::RayShape2D() : - Shape2D(Physics2DServer::get_singleton()->ray_shape_create()) { - - length = 20; - slips_on_slope = false; - _update_shape(); -} diff --git a/scene/resources/segment_shape_2d.h b/scene/resources/segment_shape_2d.h index aaf838ebfb..31a61ea564 100644 --- a/scene/resources/segment_shape_2d.h +++ b/scene/resources/segment_shape_2d.h @@ -45,7 +45,7 @@ protected: static void _bind_methods(); public: - virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override; void set_a(const Vector2 &p_a); void set_b(const Vector2 &p_b); @@ -53,34 +53,11 @@ public: Vector2 get_a() const; Vector2 get_b() const; - virtual void draw(const RID &p_to_rid, const Color &p_color); - virtual Rect2 get_rect() const; + virtual void draw(const RID &p_to_rid, const Color &p_color) override; + virtual Rect2 get_rect() const override; + virtual real_t get_enclosing_radius() const override; SegmentShape2D(); }; -class RayShape2D : public Shape2D { - GDCLASS(RayShape2D, Shape2D); - - real_t length; - bool slips_on_slope; - - void _update_shape(); - -protected: - static void _bind_methods(); - -public: - void set_length(real_t p_length); - real_t get_length() const; - - void set_slips_on_slope(bool p_active); - bool get_slips_on_slope() const; - - virtual void draw(const RID &p_to_rid, const Color &p_color); - virtual Rect2 get_rect() const; - - RayShape2D(); -}; - #endif // SEGMENT_SHAPE_2D_H diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 44c2a46065..92f0353abf 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -31,50 +31,47 @@ #include "shader.h" #include "core/os/file_access.h" #include "scene/scene_string_names.h" -#include "servers/visual/shader_language.h" -#include "servers/visual_server.h" +#include "servers/rendering/shader_language.h" +#include "servers/rendering_server.h" #include "texture.h" Shader::Mode Shader::get_mode() const { - return mode; } void Shader::set_code(const String &p_code) { - String type = ShaderLanguage::get_shader_type(p_code); if (type == "canvas_item") { mode = MODE_CANVAS_ITEM; } else if (type == "particles") { mode = MODE_PARTICLES; + } else if (type == "sky") { + mode = MODE_SKY; } else { mode = MODE_SPATIAL; } - VisualServer::get_singleton()->shader_set_code(shader, p_code); + RenderingServer::get_singleton()->shader_set_code(shader, p_code); params_cache_dirty = true; emit_changed(); } String Shader::get_code() const { - _update_shader(); - return VisualServer::get_singleton()->shader_get_code(shader); + return RenderingServer::get_singleton()->shader_get_code(shader); } void Shader::get_param_list(List<PropertyInfo> *p_params) const { - _update_shader(); List<PropertyInfo> local; - VisualServer::get_singleton()->shader_get_param_list(shader, &local); + RenderingServer::get_singleton()->shader_get_param_list(shader, &local); params_cache.clear(); params_cache_dirty = false; for (List<PropertyInfo>::Element *E = local.front(); E; E = E->next()) { - PropertyInfo pi = E->get(); if (default_textures.has(pi.name)) { //do not show default textures continue; @@ -82,47 +79,43 @@ void Shader::get_param_list(List<PropertyInfo> *p_params) const { pi.name = "shader_param/" + pi.name; params_cache[pi.name] = E->get().name; if (p_params) { - //small little hack - if (pi.type == Variant::_RID) + if (pi.type == Variant::_RID) { pi.type = Variant::OBJECT; + } p_params->push_back(pi); } } } RID Shader::get_rid() const { - _update_shader(); return shader; } -void Shader::set_default_texture_param(const StringName &p_param, const Ref<Texture> &p_texture) { - +void Shader::set_default_texture_param(const StringName &p_param, const Ref<Texture2D> &p_texture) { if (p_texture.is_valid()) { default_textures[p_param] = p_texture; - VS::get_singleton()->shader_set_default_texture_param(shader, p_param, p_texture->get_rid()); + RS::get_singleton()->shader_set_default_texture_param(shader, p_param, p_texture->get_rid()); } else { default_textures.erase(p_param); - VS::get_singleton()->shader_set_default_texture_param(shader, p_param, RID()); + RS::get_singleton()->shader_set_default_texture_param(shader, p_param, RID()); } emit_changed(); } -Ref<Texture> Shader::get_default_texture_param(const StringName &p_param) const { - - if (default_textures.has(p_param)) +Ref<Texture2D> Shader::get_default_texture_param(const StringName &p_param) const { + if (default_textures.has(p_param)) { return default_textures[p_param]; - else - return Ref<Texture>(); + } else { + return Ref<Texture2D>(); + } } void Shader::get_default_texture_param_list(List<StringName> *r_textures) const { - - for (const Map<StringName, Ref<Texture> >::Element *E = default_textures.front(); E; E = E->next()) { - + for (const Map<StringName, Ref<Texture2D>>::Element *E = default_textures.front(); E; E = E->next()) { r_textures->push_back(E->key()); } } @@ -132,15 +125,13 @@ bool Shader::is_text_shader() const { } bool Shader::has_param(const StringName &p_param) const { - - return params_cache.has(p_param); + return params_cache.has("shader_param/" + p_param); } void Shader::_update_shader() const { } void Shader::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_mode"), &Shader::get_mode); ClassDB::bind_method(D_METHOD("set_code", "code"), &Shader::set_code); @@ -151,32 +142,30 @@ void Shader::_bind_methods() { ClassDB::bind_method(D_METHOD("has_param", "name"), &Shader::has_param); - //ClassDB::bind_method(D_METHOD("get_param_list"),&Shader::get_fragment_code); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_code", "get_code"); BIND_ENUM_CONSTANT(MODE_SPATIAL); BIND_ENUM_CONSTANT(MODE_CANVAS_ITEM); BIND_ENUM_CONSTANT(MODE_PARTICLES); + BIND_ENUM_CONSTANT(MODE_SKY); } Shader::Shader() { - mode = MODE_SPATIAL; - shader = VisualServer::get_singleton()->shader_create(); + shader = RenderingServer::get_singleton()->shader_create(); params_cache_dirty = true; } Shader::~Shader() { - - VisualServer::get_singleton()->free(shader); + RenderingServer::get_singleton()->free(shader); } -//////////// -RES ResourceFormatLoaderShader::load(const String &p_path, const String &p_original_path, Error *r_error) { +//////////// - if (r_error) +RES ResourceFormatLoaderShader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { + if (r_error) { *r_error = ERR_FILE_CANT_OPEN; + } Ref<Shader> shader; shader.instance(); @@ -188,32 +177,30 @@ RES ResourceFormatLoaderShader::load(const String &p_path, const String &p_origi shader->set_code(str); - if (r_error) + if (r_error) { *r_error = OK; + } return shader; } void ResourceFormatLoaderShader::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("shader"); } bool ResourceFormatLoaderShader::handles_type(const String &p_type) const { - return (p_type == "Shader"); } String ResourceFormatLoaderShader::get_resource_type(const String &p_path) const { - String el = p_path.get_extension().to_lower(); - if (el == "shader") + if (el == "shader") { return "Shader"; + } return ""; } Error ResourceFormatSaverShader::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - Ref<Shader> shader = p_resource; ERR_FAIL_COND_V(shader.is_null(), ERR_INVALID_PARAMETER); @@ -236,14 +223,13 @@ Error ResourceFormatSaverShader::save(const String &p_path, const RES &p_resourc } void ResourceFormatSaverShader::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { - if (const Shader *shader = Object::cast_to<Shader>(*p_resource)) { if (shader->is_text_shader()) { p_extensions->push_back("shader"); } } } -bool ResourceFormatSaverShader::recognize(const RES &p_resource) const { +bool ResourceFormatSaverShader::recognize(const RES &p_resource) const { return p_resource->get_class_name() == "Shader"; //only shader, not inherited } diff --git a/scene/resources/shader.h b/scene/resources/shader.h index 67ae436a4c..7dcec7811a 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -37,7 +37,6 @@ #include "scene/resources/texture.h" class Shader : public Resource { - GDCLASS(Shader, Resource); OBJ_SAVE_TYPE(Shader); @@ -47,6 +46,7 @@ public: MODE_SPATIAL, MODE_CANVAS_ITEM, MODE_PARTICLES, + MODE_SKY, MODE_MAX }; @@ -55,11 +55,11 @@ private: Mode mode; // hack the name of performance - // shaders keep a list of ShaderMaterial -> VisualServer name translations, to make + // shaders keep a list of ShaderMaterial -> RenderingServer name translations, to make // conversion fast and save memory. mutable bool params_cache_dirty; mutable Map<StringName, StringName> params_cache; //map a shader param to a material param.. - Map<StringName, Ref<Texture> > default_textures; + Map<StringName, Ref<Texture2D>> default_textures; virtual void _update_shader() const; //used for visual shader protected: @@ -75,23 +75,25 @@ public: void get_param_list(List<PropertyInfo> *p_params) const; bool has_param(const StringName &p_param) const; - void set_default_texture_param(const StringName &p_param, const Ref<Texture> &p_texture); - Ref<Texture> get_default_texture_param(const StringName &p_param) const; + void set_default_texture_param(const StringName &p_param, const Ref<Texture2D> &p_texture); + Ref<Texture2D> get_default_texture_param(const StringName &p_param) const; void get_default_texture_param_list(List<StringName> *r_textures) const; virtual bool is_text_shader() const; _FORCE_INLINE_ StringName remap_param(const StringName &p_param) const { - if (params_cache_dirty) - get_param_list(NULL); + if (params_cache_dirty) { + get_param_list(nullptr); + } const Map<StringName, StringName>::Element *E = params_cache.find(p_param); - if (E) + if (E) { return E->get(); + } return StringName(); } - virtual RID get_rid() const; + virtual RID get_rid() const override; Shader(); ~Shader(); @@ -101,7 +103,7 @@ VARIANT_ENUM_CAST(Shader::Mode); class ResourceFormatLoaderShader : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp index 9e97c65a3c..94cecc76eb 100644 --- a/scene/resources/shape_2d.cpp +++ b/scene/resources/shape_2d.cpp @@ -29,45 +29,41 @@ /*************************************************************************/ #include "shape_2d.h" -#include "servers/physics_2d_server.h" +#include "servers/physics_server_2d.h" RID Shape2D::get_rid() const { - return shape; } void Shape2D::set_custom_solver_bias(real_t p_bias) { - custom_bias = p_bias; - Physics2DServer::get_singleton()->shape_set_custom_solver_bias(shape, custom_bias); + PhysicsServer2D::get_singleton()->shape_set_custom_solver_bias(shape, custom_bias); } real_t Shape2D::get_custom_solver_bias() const { - return custom_bias; } bool Shape2D::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) { - ERR_FAIL_COND_V(p_shape.is_null(), false); int r; - return Physics2DServer::get_singleton()->shape_collide(get_rid(), p_local_xform, p_local_motion, p_shape->get_rid(), p_shape_xform, p_shape_motion, NULL, 0, r); + return PhysicsServer2D::get_singleton()->shape_collide(get_rid(), p_local_xform, p_local_motion, p_shape->get_rid(), p_shape_xform, p_shape_motion, nullptr, 0, r); } bool Shape2D::collide(const Transform2D &p_local_xform, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform) { ERR_FAIL_COND_V(p_shape.is_null(), false); int r; - return Physics2DServer::get_singleton()->shape_collide(get_rid(), p_local_xform, Vector2(), p_shape->get_rid(), p_shape_xform, Vector2(), NULL, 0, r); + 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()); const int max_contacts = 16; Vector2 result[max_contacts * 2]; int contacts = 0; - if (!Physics2DServer::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)) + 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(); + } Array results; results.resize(contacts * 2); @@ -77,15 +73,16 @@ Array Shape2D::collide_with_motion_and_get_contacts(const Transform2D &p_local_x return results; } -Array Shape2D::collide_and_get_contacts(const Transform2D &p_local_xform, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform) { +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()); const int max_contacts = 16; Vector2 result[max_contacts * 2]; int contacts = 0; - if (!Physics2DServer::get_singleton()->shape_collide(get_rid(), p_local_xform, Vector2(), p_shape->get_rid(), p_shape_xform, Vector2(), result, max_contacts, contacts)) + 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(); + } Array results; results.resize(contacts * 2); @@ -97,15 +94,15 @@ Array Shape2D::collide_and_get_contacts(const Transform2D &p_local_xform, const } void Shape2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_custom_solver_bias", "bias"), &Shape2D::set_custom_solver_bias); ClassDB::bind_method(D_METHOD("get_custom_solver_bias"), &Shape2D::get_custom_solver_bias); ClassDB::bind_method(D_METHOD("collide", "local_xform", "with_shape", "shape_xform"), &Shape2D::collide); ClassDB::bind_method(D_METHOD("collide_with_motion", "local_xform", "local_motion", "with_shape", "shape_xform", "shape_motion"), &Shape2D::collide_with_motion); ClassDB::bind_method(D_METHOD("collide_and_get_contacts", "local_xform", "with_shape", "shape_xform"), &Shape2D::collide_and_get_contacts); ClassDB::bind_method(D_METHOD("collide_with_motion_and_get_contacts", "local_xform", "local_motion", "with_shape", "shape_xform", "shape_motion"), &Shape2D::collide_with_motion_and_get_contacts); + ClassDB::bind_method(D_METHOD("draw", "canvas_item", "color"), &Shape2D::draw); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "custom_solver_bias", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_custom_solver_bias", "get_custom_solver_bias"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_solver_bias", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_custom_solver_bias", "get_custom_solver_bias"); } Shape2D::Shape2D(const RID &p_rid) { @@ -114,6 +111,5 @@ Shape2D::Shape2D(const RID &p_rid) { } Shape2D::~Shape2D() { - - Physics2DServer::get_singleton()->free(shape); + PhysicsServer2D::get_singleton()->free(shape); } diff --git a/scene/resources/shape_2d.h b/scene/resources/shape_2d.h index 13ad7492ae..bb4688a02d 100644 --- a/scene/resources/shape_2d.h +++ b/scene/resources/shape_2d.h @@ -58,7 +58,9 @@ public: virtual void draw(const RID &p_to_rid, const Color &p_color) {} virtual Rect2 get_rect() const { return Rect2(); } - virtual RID get_rid() const; + /// Returns the radius of a circle that fully enclose this shape + virtual real_t get_enclosing_radius() const = 0; + virtual RID get_rid() const override; Shape2D(); ~Shape2D(); }; diff --git a/scene/resources/shape.cpp b/scene/resources/shape_3d.cpp index b50c68727a..59766f4f1f 100644 --- a/scene/resources/shape.cpp +++ b/scene/resources/shape_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* shape.cpp */ +/* shape_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,41 +28,39 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "shape.h" +#include "shape_3d.h" #include "core/os/os.h" #include "scene/main/scene_tree.h" #include "scene/resources/mesh.h" -#include "servers/physics_server.h" - -void Shape::add_vertices_to_array(PoolVector<Vector3> &array, const Transform &p_xform) { +#include "servers/physics_server_3d.h" +void Shape3D::add_vertices_to_array(Vector<Vector3> &array, const Transform &p_xform) { Vector<Vector3> toadd = get_debug_mesh_lines(); if (toadd.size()) { - int base = array.size(); array.resize(base + toadd.size()); - PoolVector<Vector3>::Write w = array.write(); + Vector3 *w = array.ptrw(); for (int i = 0; i < toadd.size(); i++) { w[i + base] = p_xform.xform(toadd[i]); } } } -real_t Shape::get_margin() const { +real_t Shape3D::get_margin() const { return margin; } -void Shape::set_margin(real_t p_margin) { +void Shape3D::set_margin(real_t p_margin) { margin = p_margin; - PhysicsServer::get_singleton()->shape_set_margin(shape, margin); + PhysicsServer3D::get_singleton()->shape_set_margin(shape, margin); } -Ref<ArrayMesh> Shape::get_debug_mesh() { - - if (debug_mesh_cache.is_valid()) +Ref<ArrayMesh> Shape3D::get_debug_mesh() { + if (debug_mesh_cache.is_valid()) { return debug_mesh_cache; + } Vector<Vector3> lines = get_debug_mesh_lines(); @@ -70,11 +68,10 @@ Ref<ArrayMesh> Shape::get_debug_mesh() { if (!lines.empty()) { //make mesh - PoolVector<Vector3> array; + Vector<Vector3> array; array.resize(lines.size()); { - - PoolVector<Vector3>::Write w = array.write(); + Vector3 *w = array.ptrw(); for (int i = 0; i < lines.size(); i++) { w[i] = lines[i]; } @@ -96,32 +93,25 @@ Ref<ArrayMesh> Shape::get_debug_mesh() { return debug_mesh_cache; } -void Shape::_update_shape() { +void Shape3D::_update_shape() { emit_changed(); debug_mesh_cache.unref(); } -void Shape::_bind_methods() { +void Shape3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_margin", "margin"), &Shape3D::set_margin); + ClassDB::bind_method(D_METHOD("get_margin"), &Shape3D::get_margin); - ClassDB::bind_method(D_METHOD("set_margin", "margin"), &Shape::set_margin); - ClassDB::bind_method(D_METHOD("get_margin"), &Shape::get_margin); - - ADD_PROPERTY(PropertyInfo(Variant::REAL, "margin", PROPERTY_HINT_RANGE, "0.001,10,0.001"), "set_margin", "get_margin"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0.001,10,0.001"), "set_margin", "get_margin"); } -Shape::Shape() : - margin(0.04) { - - ERR_PRINT("Constructor must not be called!"); -} - -Shape::Shape(RID p_shape) : - margin(0.04) { - - shape = p_shape; +Shape3D::Shape3D() { + ERR_PRINT("Default constructor must not be called!"); } -Shape::~Shape() { +Shape3D::Shape3D(RID p_shape) : + shape(p_shape) {} - PhysicsServer::get_singleton()->free(shape); +Shape3D::~Shape3D() { + PhysicsServer3D::get_singleton()->free(shape); } diff --git a/scene/resources/shape.h b/scene/resources/shape_3d.h index 8fc265f3bc..eb9607e3a6 100644 --- a/scene/resources/shape.h +++ b/scene/resources/shape_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* shape.h */ +/* shape_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,19 +28,19 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SHAPE_H -#define SHAPE_H +#ifndef SHAPE_3D_H +#define SHAPE_3D_H #include "core/resource.h" -class ArrayMesh; -class Shape : public Resource { +class ArrayMesh; - GDCLASS(Shape, Resource); - OBJ_SAVE_TYPE(Shape); +class Shape3D : public Resource { + GDCLASS(Shape3D, Resource); + OBJ_SAVE_TYPE(Shape3D); RES_BASE_EXTENSION("shape"); RID shape; - real_t margin; + real_t margin = 0.04; Ref<ArrayMesh> debug_mesh_cache; @@ -48,23 +48,25 @@ protected: static void _bind_methods(); _FORCE_INLINE_ RID get_shape() const { return shape; } - Shape(RID p_shape); + Shape3D(RID p_shape); virtual void _update_shape(); public: - virtual RID get_rid() const { return shape; } + virtual RID get_rid() const override { return shape; } Ref<ArrayMesh> get_debug_mesh(); - virtual Vector<Vector3> get_debug_mesh_lines() = 0; // { return Vector<Vector3>(); } + virtual Vector<Vector3> get_debug_mesh_lines() const = 0; // { return Vector<Vector3>(); } + /// Returns the radius of a sphere that fully enclose this shape + virtual real_t get_enclosing_radius() const = 0; - void add_vertices_to_array(PoolVector<Vector3> &array, const Transform &p_xform); + void add_vertices_to_array(Vector<Vector3> &array, const Transform &p_xform); real_t get_margin() const; void set_margin(real_t p_margin); - Shape(); - ~Shape(); + Shape3D(); + ~Shape3D(); }; #endif // SHAPE_H diff --git a/scene/resources/skin.cpp b/scene/resources/skin.cpp index 9c8710a59c..e88841a531 100644 --- a/scene/resources/skin.cpp +++ b/scene/resources/skin.cpp @@ -45,6 +45,23 @@ void Skin::add_bind(int p_bone, const Transform &p_pose) { set_bind_pose(index, p_pose); } +void Skin::add_named_bind(const String &p_name, const Transform &p_pose) { + uint32_t index = bind_count; + set_bind_count(bind_count + 1); + set_bind_name(index, p_name); + set_bind_pose(index, p_pose); +} + +void Skin::set_bind_name(int p_index, const StringName &p_name) { + ERR_FAIL_INDEX(p_index, bind_count); + bool notify_change = (binds_ptr[p_index].name != StringName()) != (p_name != StringName()); + binds_ptr[p_index].name = p_name; + emit_changed(); + if (notify_change) { + _change_notify(); + } +} + void Skin::set_bind_bone(int p_index, int p_bone) { ERR_FAIL_INDEX(p_index, bind_count); binds_ptr[p_index].bone = p_bone; @@ -75,6 +92,9 @@ bool Skin::_set(const StringName &p_name, const Variant &p_value) { if (what == "bone") { set_bind_bone(index, p_value); return true; + } else if (what == "name") { + set_bind_name(index, p_value); + return true; } else if (what == "pose") { set_bind_pose(index, p_value); return true; @@ -84,7 +104,6 @@ bool Skin::_set(const StringName &p_name, const Variant &p_value) { } bool Skin::_get(const StringName &p_name, Variant &r_ret) const { - String name = p_name; if (name == "bind_count") { r_ret = get_bind_count(); @@ -95,6 +114,9 @@ bool Skin::_get(const StringName &p_name, Variant &r_ret) const { if (what == "bone") { r_ret = get_bind_bone(index); return true; + } else if (what == "name") { + r_ret = get_bind_name(index); + return true; } else if (what == "pose") { r_ret = get_bind_pose(index); return true; @@ -102,16 +124,17 @@ bool Skin::_get(const StringName &p_name, Variant &r_ret) const { } return false; } + void Skin::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::INT, "bind_count", PROPERTY_HINT_RANGE, "0,16384,1,or_greater")); for (int i = 0; i < get_bind_count(); i++) { - p_list->push_back(PropertyInfo(Variant::INT, "bind/" + itos(i) + "/bone", PROPERTY_HINT_RANGE, "0,16384,1,or_greater")); + p_list->push_back(PropertyInfo(Variant::STRING_NAME, "bind/" + itos(i) + "/name")); + p_list->push_back(PropertyInfo(Variant::INT, "bind/" + itos(i) + "/bone", PROPERTY_HINT_RANGE, "0,16384,1,or_greater", get_bind_name(i) != StringName() ? PROPERTY_USAGE_NOEDITOR : PROPERTY_USAGE_DEFAULT)); p_list->push_back(PropertyInfo(Variant::TRANSFORM, "bind/" + itos(i) + "/pose")); } } void Skin::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_bind_count", "bind_count"), &Skin::set_bind_count); ClassDB::bind_method(D_METHOD("get_bind_count"), &Skin::get_bind_count); @@ -120,6 +143,9 @@ void Skin::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bind_pose", "bind_index", "pose"), &Skin::set_bind_pose); ClassDB::bind_method(D_METHOD("get_bind_pose", "bind_index"), &Skin::get_bind_pose); + ClassDB::bind_method(D_METHOD("set_bind_name", "bind_index", "name"), &Skin::set_bind_name); + ClassDB::bind_method(D_METHOD("get_bind_name", "bind_index"), &Skin::get_bind_name); + ClassDB::bind_method(D_METHOD("set_bind_bone", "bind_index", "bone"), &Skin::set_bind_bone); ClassDB::bind_method(D_METHOD("get_bind_bone", "bind_index"), &Skin::get_bind_bone); diff --git a/scene/resources/skin.h b/scene/resources/skin.h index ddc7c655f5..57aaf1afd4 100644 --- a/scene/resources/skin.h +++ b/scene/resources/skin.h @@ -37,7 +37,8 @@ class Skin : public Resource { GDCLASS(Skin, Resource) struct Bind { - int bone; + int bone = -1; + StringName name; Transform pose; }; @@ -58,9 +59,11 @@ public: inline int get_bind_count() const { return bind_count; } void add_bind(int p_bone, const Transform &p_pose); + void add_named_bind(const String &p_name, const Transform &p_pose); void set_bind_bone(int p_index, int p_bone); void set_bind_pose(int p_index, const Transform &p_pose); + void set_bind_name(int p_index, const StringName &p_name); inline int get_bind_bone(int p_index) const { #ifdef DEBUG_ENABLED @@ -69,6 +72,13 @@ public: return binds_ptr[p_index].bone; } + inline StringName get_bind_name(int p_index) const { +#ifdef DEBUG_ENABLED + ERR_FAIL_INDEX_V(p_index, bind_count, StringName()); +#endif + return binds_ptr[p_index].name; + } + inline Transform get_bind_pose(int p_index) const { #ifdef DEBUG_ENABLED ERR_FAIL_INDEX_V(p_index, bind_count, Transform()); diff --git a/scene/resources/sky.cpp b/scene/resources/sky.cpp index c20fbb4129..7e32516f94 100644 --- a/scene/resources/sky.cpp +++ b/scene/resources/sky.cpp @@ -36,551 +36,77 @@ void Sky::set_radiance_size(RadianceSize p_size) { ERR_FAIL_INDEX(p_size, RADIANCE_SIZE_MAX); radiance_size = p_size; - _radiance_changed(); -} - -Sky::RadianceSize Sky::get_radiance_size() const { - - return radiance_size; -} - -void Sky::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_radiance_size", "size"), &Sky::set_radiance_size); - ClassDB::bind_method(D_METHOD("get_radiance_size"), &Sky::get_radiance_size); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "radiance_size", PROPERTY_HINT_ENUM, "32,64,128,256,512,1024,2048"), "set_radiance_size", "get_radiance_size"); - - BIND_ENUM_CONSTANT(RADIANCE_SIZE_32); - BIND_ENUM_CONSTANT(RADIANCE_SIZE_64); - BIND_ENUM_CONSTANT(RADIANCE_SIZE_128); - BIND_ENUM_CONSTANT(RADIANCE_SIZE_256); - BIND_ENUM_CONSTANT(RADIANCE_SIZE_512); - BIND_ENUM_CONSTANT(RADIANCE_SIZE_1024); - BIND_ENUM_CONSTANT(RADIANCE_SIZE_2048); - BIND_ENUM_CONSTANT(RADIANCE_SIZE_MAX); -} - -Sky::Sky() { - radiance_size = RADIANCE_SIZE_128; -} - -///////////////////////////////////////// - -void PanoramaSky::_radiance_changed() { - - if (panorama.is_valid()) { - static const int size[RADIANCE_SIZE_MAX] = { - 32, 64, 128, 256, 512, 1024, 2048 - }; - VS::get_singleton()->sky_set_texture(sky, panorama->get_rid(), size[get_radiance_size()]); - } -} - -void PanoramaSky::set_panorama(const Ref<Texture> &p_panorama) { - - panorama = p_panorama; - - if (panorama.is_valid()) { - - _radiance_changed(); - - } else { - VS::get_singleton()->sky_set_texture(sky, RID(), 0); - } -} - -Ref<Texture> PanoramaSky::get_panorama() const { - - return panorama; -} - -RID PanoramaSky::get_rid() const { - - return sky; -} - -void PanoramaSky::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_panorama", "texture"), &PanoramaSky::set_panorama); - ClassDB::bind_method(D_METHOD("get_panorama"), &PanoramaSky::get_panorama); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_panorama", "get_panorama"); -} - -PanoramaSky::PanoramaSky() { - - sky = VS::get_singleton()->sky_create(); -} - -PanoramaSky::~PanoramaSky() { - - VS::get_singleton()->free(sky); -} -////////////////////////////////// - -void ProceduralSky::_radiance_changed() { - - if (update_queued) - return; //do nothing yet - static const int size[RADIANCE_SIZE_MAX] = { 32, 64, 128, 256, 512, 1024, 2048 }; - VS::get_singleton()->sky_set_texture(sky, texture, size[get_radiance_size()]); -} - -Ref<Image> ProceduralSky::_generate_sky() { - - update_queued = false; - - PoolVector<uint8_t> imgdata; - - static const int size[TEXTURE_SIZE_MAX] = { - 256, 512, 1024, 2048, 4096 - }; - - int w = size[texture_size]; - int h = w / 2; - - imgdata.resize(w * h * 4); //RGBE - - { - PoolVector<uint8_t>::Write dataw = imgdata.write(); - - uint32_t *ptr = (uint32_t *)dataw.ptr(); - - Color sky_top_linear = sky_top_color.to_linear(); - Color sky_horizon_linear = sky_horizon_color.to_linear(); - - Color ground_bottom_linear = ground_bottom_color.to_linear(); - Color ground_horizon_linear = ground_horizon_color.to_linear(); - - Color sun_linear; - sun_linear.r = sun_color.r * sun_energy; - sun_linear.g = sun_color.g * sun_energy; - sun_linear.b = sun_color.b * sun_energy; - - Vector3 sun(0, 0, -1); - - sun = Basis(Vector3(1, 0, 0), Math::deg2rad(sun_latitude)).xform(sun); - sun = Basis(Vector3(0, 1, 0), Math::deg2rad(sun_longitude)).xform(sun); - - sun.normalize(); - - for (int i = 0; i < w; i++) { - - float u = float(i) / (w - 1); - float phi = u * 2.0 * Math_PI; - - for (int j = 0; j < h; j++) { - - float v = float(j) / (h - 1); - float theta = v * Math_PI; - - Vector3 normal( - Math::sin(phi) * Math::sin(theta) * -1.0, - Math::cos(theta), - Math::cos(phi) * Math::sin(theta) * -1.0); - - normal.normalize(); - - float v_angle = Math::acos(CLAMP(normal.y, -1.0, 1.0)); - - Color color; - - if (normal.y < 0) { - //ground - - float c = (v_angle - (Math_PI * 0.5)) / (Math_PI * 0.5); - color = ground_horizon_linear.linear_interpolate(ground_bottom_linear, Math::ease(c, ground_curve)); - color.r *= ground_energy; - color.g *= ground_energy; - color.b *= ground_energy; - } else { - float c = v_angle / (Math_PI * 0.5); - color = sky_horizon_linear.linear_interpolate(sky_top_linear, Math::ease(1.0 - c, sky_curve)); - color.r *= sky_energy; - color.g *= sky_energy; - color.b *= sky_energy; - - float sun_angle = Math::rad2deg(Math::acos(CLAMP(sun.dot(normal), -1.0, 1.0))); - - if (sun_angle < sun_angle_min) { - color = color.blend(sun_linear); - } else if (sun_angle < sun_angle_max) { - - float c2 = (sun_angle - sun_angle_min) / (sun_angle_max - sun_angle_min); - c2 = Math::ease(c2, sun_curve); - - color = color.blend(sun_linear).linear_interpolate(color, c2); - } - } - - ptr[j * w + i] = color.to_rgbe9995(); - } - } - } - - Ref<Image> image; - image.instance(); - image->create(w, h, false, Image::FORMAT_RGBE9995, imgdata); - - return image; -} - -void ProceduralSky::set_sky_top_color(const Color &p_sky_top) { - - sky_top_color = p_sky_top; - _queue_update(); -} - -Color ProceduralSky::get_sky_top_color() const { - - return sky_top_color; + RS::get_singleton()->sky_set_radiance_size(sky, size[radiance_size]); } -void ProceduralSky::set_sky_horizon_color(const Color &p_sky_horizon) { - - sky_horizon_color = p_sky_horizon; - _queue_update(); -} -Color ProceduralSky::get_sky_horizon_color() const { - - return sky_horizon_color; -} - -void ProceduralSky::set_sky_curve(float p_curve) { - - sky_curve = p_curve; - _queue_update(); -} -float ProceduralSky::get_sky_curve() const { - - return sky_curve; -} - -void ProceduralSky::set_sky_energy(float p_energy) { - - sky_energy = p_energy; - _queue_update(); -} -float ProceduralSky::get_sky_energy() const { - - return sky_energy; -} - -void ProceduralSky::set_ground_bottom_color(const Color &p_ground_bottom) { - - ground_bottom_color = p_ground_bottom; - _queue_update(); -} -Color ProceduralSky::get_ground_bottom_color() const { - - return ground_bottom_color; -} - -void ProceduralSky::set_ground_horizon_color(const Color &p_ground_horizon) { - - ground_horizon_color = p_ground_horizon; - _queue_update(); -} -Color ProceduralSky::get_ground_horizon_color() const { - - return ground_horizon_color; -} - -void ProceduralSky::set_ground_curve(float p_curve) { - - ground_curve = p_curve; - _queue_update(); -} -float ProceduralSky::get_ground_curve() const { - - return ground_curve; -} - -void ProceduralSky::set_ground_energy(float p_energy) { - - ground_energy = p_energy; - _queue_update(); -} -float ProceduralSky::get_ground_energy() const { - - return ground_energy; -} - -void ProceduralSky::set_sun_color(const Color &p_sun) { - - sun_color = p_sun; - _queue_update(); -} -Color ProceduralSky::get_sun_color() const { - - return sun_color; -} - -void ProceduralSky::set_sun_latitude(float p_angle) { - - sun_latitude = p_angle; - _queue_update(); -} -float ProceduralSky::get_sun_latitude() const { - - return sun_latitude; -} - -void ProceduralSky::set_sun_longitude(float p_angle) { - - sun_longitude = p_angle; - _queue_update(); -} -float ProceduralSky::get_sun_longitude() const { - - return sun_longitude; -} - -void ProceduralSky::set_sun_angle_min(float p_angle) { - - sun_angle_min = p_angle; - _queue_update(); -} -float ProceduralSky::get_sun_angle_min() const { - - return sun_angle_min; -} - -void ProceduralSky::set_sun_angle_max(float p_angle) { - - sun_angle_max = p_angle; - _queue_update(); -} -float ProceduralSky::get_sun_angle_max() const { - - return sun_angle_max; -} - -void ProceduralSky::set_sun_curve(float p_curve) { - - sun_curve = p_curve; - _queue_update(); -} -float ProceduralSky::get_sun_curve() const { - - return sun_curve; -} - -void ProceduralSky::set_sun_energy(float p_energy) { - - sun_energy = p_energy; - _queue_update(); +Sky::RadianceSize Sky::get_radiance_size() const { + return radiance_size; } -float ProceduralSky::get_sun_energy() const { - return sun_energy; +void Sky::set_process_mode(ProcessMode p_mode) { + mode = p_mode; + RS::get_singleton()->sky_set_mode(sky, RS::SkyMode(mode)); } -void ProceduralSky::set_texture_size(TextureSize p_size) { - ERR_FAIL_INDEX(p_size, TEXTURE_SIZE_MAX); - - texture_size = p_size; - _queue_update(); -} -ProceduralSky::TextureSize ProceduralSky::get_texture_size() const { - return texture_size; +Sky::ProcessMode Sky::get_process_mode() const { + return mode; } -RID ProceduralSky::get_rid() const { - return sky; -} - -void ProceduralSky::_update_sky() { - - bool use_thread = true; - if (first_time) { - use_thread = false; - first_time = false; - } -#ifdef NO_THREADS - use_thread = false; -#endif - if (use_thread) { - - if (!sky_thread) { - sky_thread = Thread::create(_thread_function, this); - regen_queued = false; - } else { - regen_queued = true; - } - - } else { - Ref<Image> image = _generate_sky(); - VS::get_singleton()->texture_allocate(texture, image->get_width(), image->get_height(), 0, Image::FORMAT_RGBE9995, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT); - VS::get_singleton()->texture_set_data(texture, image); - _radiance_changed(); +void Sky::set_material(const Ref<Material> &p_material) { + sky_material = p_material; + RID material_rid; + if (sky_material.is_valid()) { + material_rid = sky_material->get_rid(); } + RS::get_singleton()->sky_set_material(sky, material_rid); } -void ProceduralSky::_queue_update() { - - if (update_queued) - return; - - update_queued = true; - call_deferred("_update_sky"); +Ref<Material> Sky::get_material() const { + return sky_material; } -void ProceduralSky::_thread_done(const Ref<Image> &p_image) { - - VS::get_singleton()->texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, Image::FORMAT_RGBE9995, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT); - VS::get_singleton()->texture_set_data(texture, p_image); - _radiance_changed(); - Thread::wait_to_finish(sky_thread); - memdelete(sky_thread); - sky_thread = NULL; - if (regen_queued) { - sky_thread = Thread::create(_thread_function, this); - regen_queued = false; - } -} - -void ProceduralSky::_thread_function(void *p_ud) { - - ProceduralSky *psky = (ProceduralSky *)p_ud; - psky->call_deferred("_thread_done", psky->_generate_sky()); +RID Sky::get_rid() const { + return sky; } -void ProceduralSky::_bind_methods() { - - ClassDB::bind_method(D_METHOD("_update_sky"), &ProceduralSky::_update_sky); - - ClassDB::bind_method(D_METHOD("set_sky_top_color", "color"), &ProceduralSky::set_sky_top_color); - ClassDB::bind_method(D_METHOD("get_sky_top_color"), &ProceduralSky::get_sky_top_color); - - ClassDB::bind_method(D_METHOD("set_sky_horizon_color", "color"), &ProceduralSky::set_sky_horizon_color); - ClassDB::bind_method(D_METHOD("get_sky_horizon_color"), &ProceduralSky::get_sky_horizon_color); - - ClassDB::bind_method(D_METHOD("set_sky_curve", "curve"), &ProceduralSky::set_sky_curve); - ClassDB::bind_method(D_METHOD("get_sky_curve"), &ProceduralSky::get_sky_curve); - - ClassDB::bind_method(D_METHOD("set_sky_energy", "energy"), &ProceduralSky::set_sky_energy); - ClassDB::bind_method(D_METHOD("get_sky_energy"), &ProceduralSky::get_sky_energy); - - ClassDB::bind_method(D_METHOD("set_ground_bottom_color", "color"), &ProceduralSky::set_ground_bottom_color); - ClassDB::bind_method(D_METHOD("get_ground_bottom_color"), &ProceduralSky::get_ground_bottom_color); - - ClassDB::bind_method(D_METHOD("set_ground_horizon_color", "color"), &ProceduralSky::set_ground_horizon_color); - ClassDB::bind_method(D_METHOD("get_ground_horizon_color"), &ProceduralSky::get_ground_horizon_color); - - ClassDB::bind_method(D_METHOD("set_ground_curve", "curve"), &ProceduralSky::set_ground_curve); - ClassDB::bind_method(D_METHOD("get_ground_curve"), &ProceduralSky::get_ground_curve); - - ClassDB::bind_method(D_METHOD("set_ground_energy", "energy"), &ProceduralSky::set_ground_energy); - ClassDB::bind_method(D_METHOD("get_ground_energy"), &ProceduralSky::get_ground_energy); - - ClassDB::bind_method(D_METHOD("set_sun_color", "color"), &ProceduralSky::set_sun_color); - ClassDB::bind_method(D_METHOD("get_sun_color"), &ProceduralSky::get_sun_color); - - ClassDB::bind_method(D_METHOD("set_sun_latitude", "degrees"), &ProceduralSky::set_sun_latitude); - ClassDB::bind_method(D_METHOD("get_sun_latitude"), &ProceduralSky::get_sun_latitude); - - ClassDB::bind_method(D_METHOD("set_sun_longitude", "degrees"), &ProceduralSky::set_sun_longitude); - ClassDB::bind_method(D_METHOD("get_sun_longitude"), &ProceduralSky::get_sun_longitude); - - ClassDB::bind_method(D_METHOD("set_sun_angle_min", "degrees"), &ProceduralSky::set_sun_angle_min); - ClassDB::bind_method(D_METHOD("get_sun_angle_min"), &ProceduralSky::get_sun_angle_min); - - ClassDB::bind_method(D_METHOD("set_sun_angle_max", "degrees"), &ProceduralSky::set_sun_angle_max); - ClassDB::bind_method(D_METHOD("get_sun_angle_max"), &ProceduralSky::get_sun_angle_max); - - ClassDB::bind_method(D_METHOD("set_sun_curve", "curve"), &ProceduralSky::set_sun_curve); - ClassDB::bind_method(D_METHOD("get_sun_curve"), &ProceduralSky::get_sun_curve); - - ClassDB::bind_method(D_METHOD("set_sun_energy", "energy"), &ProceduralSky::set_sun_energy); - ClassDB::bind_method(D_METHOD("get_sun_energy"), &ProceduralSky::get_sun_energy); - - ClassDB::bind_method(D_METHOD("set_texture_size", "size"), &ProceduralSky::set_texture_size); - ClassDB::bind_method(D_METHOD("get_texture_size"), &ProceduralSky::get_texture_size); - - ClassDB::bind_method(D_METHOD("_thread_done", "image"), &ProceduralSky::_thread_done); +void Sky::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_radiance_size", "size"), &Sky::set_radiance_size); + ClassDB::bind_method(D_METHOD("get_radiance_size"), &Sky::get_radiance_size); - ADD_GROUP("Sky", "sky_"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_top_color"), "set_sky_top_color", "get_sky_top_color"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_horizon_color"), "set_sky_horizon_color", "get_sky_horizon_color"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "sky_curve", PROPERTY_HINT_EXP_EASING), "set_sky_curve", "get_sky_curve"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "sky_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sky_energy", "get_sky_energy"); + ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &Sky::set_process_mode); + ClassDB::bind_method(D_METHOD("get_process_mode"), &Sky::get_process_mode); - ADD_GROUP("Ground", "ground_"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_bottom_color"), "set_ground_bottom_color", "get_ground_bottom_color"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_horizon_color"), "set_ground_horizon_color", "get_ground_horizon_color"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ground_curve", PROPERTY_HINT_EXP_EASING), "set_ground_curve", "get_ground_curve"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "ground_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_ground_energy", "get_ground_energy"); + ClassDB::bind_method(D_METHOD("set_material", "material"), &Sky::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &Sky::get_material); - ADD_GROUP("Sun", "sun_"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sun_color"), "set_sun_color", "get_sun_color"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_latitude", PROPERTY_HINT_RANGE, "-180,180,0.01"), "set_sun_latitude", "get_sun_latitude"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_longitude", PROPERTY_HINT_RANGE, "-180,180,0.01"), "set_sun_longitude", "get_sun_longitude"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_angle_min", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_min", "get_sun_angle_min"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_angle_max", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_max", "get_sun_angle_max"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_curve", PROPERTY_HINT_EXP_EASING), "set_sun_curve", "get_sun_curve"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sun_energy", "get_sun_energy"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,PanoramaSkyMaterial,ProceduralSkyMaterial,PhysicalSkyMaterial"), "set_material", "get_material"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Automatic,HighQuality,HighQualityIncremental,RealTime"), "set_process_mode", "get_process_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "radiance_size", PROPERTY_HINT_ENUM, "32,64,128,256,512,1024,2048"), "set_radiance_size", "get_radiance_size"); - ADD_GROUP("Texture", "texture_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_size", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096"), "set_texture_size", "get_texture_size"); + BIND_ENUM_CONSTANT(RADIANCE_SIZE_32); + BIND_ENUM_CONSTANT(RADIANCE_SIZE_64); + BIND_ENUM_CONSTANT(RADIANCE_SIZE_128); + BIND_ENUM_CONSTANT(RADIANCE_SIZE_256); + BIND_ENUM_CONSTANT(RADIANCE_SIZE_512); + BIND_ENUM_CONSTANT(RADIANCE_SIZE_1024); + BIND_ENUM_CONSTANT(RADIANCE_SIZE_2048); + BIND_ENUM_CONSTANT(RADIANCE_SIZE_MAX); - BIND_ENUM_CONSTANT(TEXTURE_SIZE_256); - BIND_ENUM_CONSTANT(TEXTURE_SIZE_512); - BIND_ENUM_CONSTANT(TEXTURE_SIZE_1024); - BIND_ENUM_CONSTANT(TEXTURE_SIZE_2048); - BIND_ENUM_CONSTANT(TEXTURE_SIZE_4096); - BIND_ENUM_CONSTANT(TEXTURE_SIZE_MAX); + BIND_ENUM_CONSTANT(PROCESS_MODE_AUTOMATIC); + BIND_ENUM_CONSTANT(PROCESS_MODE_QUALITY); + BIND_ENUM_CONSTANT(PROCESS_MODE_INCREMENTAL); + BIND_ENUM_CONSTANT(PROCESS_MODE_REALTIME); } -ProceduralSky::ProceduralSky(bool p_desaturate) { - - sky = VS::get_singleton()->sky_create(); - texture = VS::get_singleton()->texture_create(); - - update_queued = false; - sky_top_color = Color::hex(0xa5d6f1ff); - sky_horizon_color = Color::hex(0xd6eafaff); - sky_curve = 0.09; - sky_energy = 1; - - ground_bottom_color = Color::hex(0x282f36ff); - ground_horizon_color = Color::hex(0x6c655fff); - ground_curve = 0.02; - ground_energy = 1; - - if (p_desaturate) { - sky_top_color.set_hsv(sky_top_color.get_h(), 0, sky_top_color.get_v()); - sky_horizon_color.set_hsv(sky_horizon_color.get_h(), 0, sky_horizon_color.get_v()); - ground_bottom_color.set_hsv(ground_bottom_color.get_h(), 0, ground_bottom_color.get_v()); - ground_horizon_color.set_hsv(ground_horizon_color.get_h(), 0, ground_horizon_color.get_v()); - } - sun_color = Color(1, 1, 1); - sun_latitude = 35; - sun_longitude = 0; - sun_angle_min = 1; - sun_angle_max = 100; - sun_curve = 0.05; - sun_energy = 1; - - texture_size = TEXTURE_SIZE_1024; - sky_thread = NULL; - regen_queued = false; - first_time = true; - - _queue_update(); +Sky::Sky() { + mode = PROCESS_MODE_AUTOMATIC; + radiance_size = RADIANCE_SIZE_256; + sky = RS::get_singleton()->sky_create(); } -ProceduralSky::~ProceduralSky() { - - if (sky_thread) { - Thread::wait_to_finish(sky_thread); - memdelete(sky_thread); - sky_thread = NULL; - } - VS::get_singleton()->free(sky); - VS::get_singleton()->free(texture); +Sky::~Sky() { + RS::get_singleton()->free(sky); } diff --git a/scene/resources/sky.h b/scene/resources/sky.h index 70ea9c4c18..526ca94317 100644 --- a/scene/resources/sky.h +++ b/scene/resources/sky.h @@ -32,6 +32,7 @@ #define SKY_H #include "core/os/thread.h" +#include "scene/resources/material.h" #include "scene/resources/texture.h" class Sky : public Resource { @@ -49,152 +50,39 @@ public: RADIANCE_SIZE_MAX }; -private: - RadianceSize radiance_size; - -protected: - static void _bind_methods(); - virtual void _radiance_changed() = 0; - -public: - void set_radiance_size(RadianceSize p_size); - RadianceSize get_radiance_size() const; - Sky(); -}; - -VARIANT_ENUM_CAST(Sky::RadianceSize) - -class PanoramaSky : public Sky { - GDCLASS(PanoramaSky, Sky); - -private: - RID sky; - Ref<Texture> panorama; - -protected: - static void _bind_methods(); - virtual void _radiance_changed(); - -public: - void set_panorama(const Ref<Texture> &p_panorama); - Ref<Texture> get_panorama() const; - - virtual RID get_rid() const; - - PanoramaSky(); - ~PanoramaSky(); -}; - -class ProceduralSky : public Sky { - GDCLASS(ProceduralSky, Sky); - -public: - enum TextureSize { - TEXTURE_SIZE_256, - TEXTURE_SIZE_512, - TEXTURE_SIZE_1024, - TEXTURE_SIZE_2048, - TEXTURE_SIZE_4096, - TEXTURE_SIZE_MAX + enum ProcessMode { + PROCESS_MODE_AUTOMATIC, + PROCESS_MODE_QUALITY, + PROCESS_MODE_INCREMENTAL, + PROCESS_MODE_REALTIME }; private: - Thread *sky_thread; - Color sky_top_color; - Color sky_horizon_color; - float sky_curve; - float sky_energy; - - Color ground_bottom_color; - Color ground_horizon_color; - float ground_curve; - float ground_energy; - - Color sun_color; - float sun_latitude; - float sun_longitude; - float sun_angle_min; - float sun_angle_max; - float sun_curve; - float sun_energy; - - TextureSize texture_size; - RID sky; - RID texture; - - bool update_queued; - bool regen_queued; - - bool first_time; - - void _thread_done(const Ref<Image> &p_image); - static void _thread_function(void *p_ud); + ProcessMode mode; + RadianceSize radiance_size; + Ref<Material> sky_material; protected: static void _bind_methods(); - virtual void _radiance_changed(); - - Ref<Image> _generate_sky(); - void _update_sky(); - - void _queue_update(); public: - void set_sky_top_color(const Color &p_sky_top); - Color get_sky_top_color() const; - - void set_sky_horizon_color(const Color &p_sky_horizon); - Color get_sky_horizon_color() const; - - void set_sky_curve(float p_curve); - float get_sky_curve() const; - - void set_sky_energy(float p_energy); - float get_sky_energy() const; - - void set_ground_bottom_color(const Color &p_ground_bottom); - Color get_ground_bottom_color() const; - - void set_ground_horizon_color(const Color &p_ground_horizon); - Color get_ground_horizon_color() const; - - void set_ground_curve(float p_curve); - float get_ground_curve() const; - - void set_ground_energy(float p_energy); - float get_ground_energy() const; - - void set_sun_color(const Color &p_sun); - Color get_sun_color() const; - - void set_sun_latitude(float p_angle); - float get_sun_latitude() const; - - void set_sun_longitude(float p_angle); - float get_sun_longitude() const; - - void set_sun_angle_min(float p_angle); - float get_sun_angle_min() const; - - void set_sun_angle_max(float p_angle); - float get_sun_angle_max() const; - - void set_sun_curve(float p_curve); - float get_sun_curve() const; + void set_radiance_size(RadianceSize p_size); + RadianceSize get_radiance_size() const; - void set_sun_energy(float p_energy); - float get_sun_energy() const; + void set_process_mode(ProcessMode p_mode); + ProcessMode get_process_mode() const; - void set_texture_size(TextureSize p_size); - TextureSize get_texture_size() const; + void set_material(const Ref<Material> &p_material); + Ref<Material> get_material() const; - virtual RID get_rid() const; + virtual RID get_rid() const override; - ProceduralSky(bool p_desaturate = false); - ~ProceduralSky(); + Sky(); + ~Sky(); }; -VARIANT_ENUM_CAST(ProceduralSky::TextureSize) +VARIANT_ENUM_CAST(Sky::RadianceSize) +VARIANT_ENUM_CAST(Sky::ProcessMode) #endif // SKY_H diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp new file mode 100644 index 0000000000..69e8e0b5bd --- /dev/null +++ b/scene/resources/sky_material.cpp @@ -0,0 +1,595 @@ +/*************************************************************************/ +/* sky_material.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "sky_material.h" + +void ProceduralSkyMaterial::set_sky_top_color(const Color &p_sky_top) { + sky_top_color = p_sky_top; + RS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color.to_linear()); +} + +Color ProceduralSkyMaterial::get_sky_top_color() const { + return sky_top_color; +} + +void ProceduralSkyMaterial::set_sky_horizon_color(const Color &p_sky_horizon) { + sky_horizon_color = p_sky_horizon; + RS::get_singleton()->material_set_param(_get_material(), "sky_horizon_color", sky_horizon_color.to_linear()); +} + +Color ProceduralSkyMaterial::get_sky_horizon_color() const { + return sky_horizon_color; +} + +void ProceduralSkyMaterial::set_sky_curve(float p_curve) { + sky_curve = p_curve; + RS::get_singleton()->material_set_param(_get_material(), "sky_curve", sky_curve); +} + +float ProceduralSkyMaterial::get_sky_curve() const { + return sky_curve; +} + +void ProceduralSkyMaterial::set_sky_energy(float p_energy) { + sky_energy = p_energy; + RS::get_singleton()->material_set_param(_get_material(), "sky_energy", sky_energy); +} + +float ProceduralSkyMaterial::get_sky_energy() const { + return sky_energy; +} + +void ProceduralSkyMaterial::set_ground_bottom_color(const Color &p_ground_bottom) { + ground_bottom_color = p_ground_bottom; + RS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color", ground_bottom_color.to_linear()); +} + +Color ProceduralSkyMaterial::get_ground_bottom_color() const { + return ground_bottom_color; +} + +void ProceduralSkyMaterial::set_ground_horizon_color(const Color &p_ground_horizon) { + ground_horizon_color = p_ground_horizon; + RS::get_singleton()->material_set_param(_get_material(), "ground_horizon_color", ground_horizon_color.to_linear()); +} + +Color ProceduralSkyMaterial::get_ground_horizon_color() const { + return ground_horizon_color; +} + +void ProceduralSkyMaterial::set_ground_curve(float p_curve) { + ground_curve = p_curve; + RS::get_singleton()->material_set_param(_get_material(), "ground_curve", ground_curve); +} + +float ProceduralSkyMaterial::get_ground_curve() const { + return ground_curve; +} + +void ProceduralSkyMaterial::set_ground_energy(float p_energy) { + ground_energy = p_energy; + RS::get_singleton()->material_set_param(_get_material(), "ground_energy", ground_energy); +} + +float ProceduralSkyMaterial::get_ground_energy() const { + return ground_energy; +} + +void ProceduralSkyMaterial::set_sun_angle_max(float p_angle) { + sun_angle_max = p_angle; + RS::get_singleton()->material_set_param(_get_material(), "sun_angle_max", Math::deg2rad(sun_angle_max)); +} + +float ProceduralSkyMaterial::get_sun_angle_max() const { + return sun_angle_max; +} + +void ProceduralSkyMaterial::set_sun_curve(float p_curve) { + sun_curve = p_curve; + RS::get_singleton()->material_set_param(_get_material(), "sun_curve", sun_curve); +} + +float ProceduralSkyMaterial::get_sun_curve() const { + return sun_curve; +} + +bool ProceduralSkyMaterial::_can_do_next_pass() const { + return false; +} + +Shader::Mode ProceduralSkyMaterial::get_shader_mode() const { + return Shader::MODE_SKY; +} + +RID ProceduralSkyMaterial::get_shader_rid() const { + return shader; +} + +void ProceduralSkyMaterial::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_sky_top_color", "color"), &ProceduralSkyMaterial::set_sky_top_color); + ClassDB::bind_method(D_METHOD("get_sky_top_color"), &ProceduralSkyMaterial::get_sky_top_color); + + ClassDB::bind_method(D_METHOD("set_sky_horizon_color", "color"), &ProceduralSkyMaterial::set_sky_horizon_color); + ClassDB::bind_method(D_METHOD("get_sky_horizon_color"), &ProceduralSkyMaterial::get_sky_horizon_color); + + ClassDB::bind_method(D_METHOD("set_sky_curve", "curve"), &ProceduralSkyMaterial::set_sky_curve); + ClassDB::bind_method(D_METHOD("get_sky_curve"), &ProceduralSkyMaterial::get_sky_curve); + + ClassDB::bind_method(D_METHOD("set_sky_energy", "energy"), &ProceduralSkyMaterial::set_sky_energy); + ClassDB::bind_method(D_METHOD("get_sky_energy"), &ProceduralSkyMaterial::get_sky_energy); + + ClassDB::bind_method(D_METHOD("set_ground_bottom_color", "color"), &ProceduralSkyMaterial::set_ground_bottom_color); + ClassDB::bind_method(D_METHOD("get_ground_bottom_color"), &ProceduralSkyMaterial::get_ground_bottom_color); + + ClassDB::bind_method(D_METHOD("set_ground_horizon_color", "color"), &ProceduralSkyMaterial::set_ground_horizon_color); + ClassDB::bind_method(D_METHOD("get_ground_horizon_color"), &ProceduralSkyMaterial::get_ground_horizon_color); + + ClassDB::bind_method(D_METHOD("set_ground_curve", "curve"), &ProceduralSkyMaterial::set_ground_curve); + ClassDB::bind_method(D_METHOD("get_ground_curve"), &ProceduralSkyMaterial::get_ground_curve); + + ClassDB::bind_method(D_METHOD("set_ground_energy", "energy"), &ProceduralSkyMaterial::set_ground_energy); + ClassDB::bind_method(D_METHOD("get_ground_energy"), &ProceduralSkyMaterial::get_ground_energy); + + ClassDB::bind_method(D_METHOD("set_sun_angle_max", "degrees"), &ProceduralSkyMaterial::set_sun_angle_max); + ClassDB::bind_method(D_METHOD("get_sun_angle_max"), &ProceduralSkyMaterial::get_sun_angle_max); + + ClassDB::bind_method(D_METHOD("set_sun_curve", "curve"), &ProceduralSkyMaterial::set_sun_curve); + ClassDB::bind_method(D_METHOD("get_sun_curve"), &ProceduralSkyMaterial::get_sun_curve); + + ADD_GROUP("Sky", "sky_"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_top_color"), "set_sky_top_color", "get_sky_top_color"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_horizon_color"), "set_sky_horizon_color", "get_sky_horizon_color"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_curve", PROPERTY_HINT_EXP_EASING), "set_sky_curve", "get_sky_curve"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sky_energy", "get_sky_energy"); + + ADD_GROUP("Ground", "ground_"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_bottom_color"), "set_ground_bottom_color", "get_ground_bottom_color"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_horizon_color"), "set_ground_horizon_color", "get_ground_horizon_color"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_curve", PROPERTY_HINT_EXP_EASING), "set_ground_curve", "get_ground_curve"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_ground_energy", "get_ground_energy"); + + ADD_GROUP("Sun", "sun_"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_angle_max", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_max", "get_sun_angle_max"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_curve", PROPERTY_HINT_EXP_EASING), "set_sun_curve", "get_sun_curve"); +} + +ProceduralSkyMaterial::ProceduralSkyMaterial() { + String code = "shader_type sky;\n\n"; + + code += "uniform vec4 sky_top_color : hint_color = vec4(0.35, 0.46, 0.71, 1.0);\n"; + code += "uniform vec4 sky_horizon_color : hint_color = vec4(0.55, 0.69, 0.81, 1.0);\n"; + code += "uniform float sky_curve : hint_range(0, 1) = 0.09;\n"; + code += "uniform float sky_energy = 1.0;\n\n"; + code += "uniform vec4 ground_bottom_color : hint_color = vec4(0.12, 0.12, 0.13, 1.0);\n"; + code += "uniform vec4 ground_horizon_color : hint_color = vec4(0.37, 0.33, 0.31, 1.0);\n"; + code += "uniform float ground_curve : hint_range(0, 1) = 0.02;\n"; + code += "uniform float ground_energy = 1.0;\n\n"; + code += "uniform float sun_angle_max = 1.74;\n"; + code += "uniform float sun_curve : hint_range(0, 1) = 0.05;\n\n"; + code += "const float PI = 3.1415926535897932384626433833;\n\n"; + code += "void fragment() {\n"; + code += "\tfloat v_angle = acos(clamp(EYEDIR.y, -1.0, 1.0));\n"; + code += "\tfloat c = (1.0 - v_angle / (PI * 0.5));\n"; + code += "\tvec3 sky = mix(sky_horizon_color.rgb, sky_top_color.rgb, clamp(1.0 - pow(1.0 - c, 1.0 / sky_curve), 0.0, 1.0));\n"; + code += "\tsky *= sky_energy;\n"; + code += "\tif (LIGHT0_ENABLED) {\n"; + code += "\t\tfloat sun_angle = acos(dot(LIGHT0_DIRECTION, EYEDIR));\n"; + code += "\t\tif (sun_angle < LIGHT0_SIZE) {\n"; + code += "\t\t\tsky = LIGHT0_COLOR * LIGHT0_ENERGY;\n"; + code += "\t\t} else if (sun_angle < sun_angle_max) {\n"; + code += "\t\t\tfloat c2 = (sun_angle - LIGHT0_SIZE) / (sun_angle_max - LIGHT0_SIZE);\n"; + code += "\t\t\tsky = mix(LIGHT0_COLOR * LIGHT0_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));\n"; + code += "\t\t}\n"; + code += "\t}\n"; + code += "\tif (LIGHT1_ENABLED) {\n"; + code += "\t\tfloat sun_angle = acos(dot(LIGHT1_DIRECTION, EYEDIR));\n"; + code += "\t\tif (sun_angle < LIGHT1_SIZE) {\n"; + code += "\t\t\tsky = LIGHT1_COLOR * LIGHT1_ENERGY;\n"; + code += "\t\t} else if (sun_angle < sun_angle_max) {\n"; + code += "\t\t\tfloat c2 = (sun_angle - LIGHT1_SIZE) / (sun_angle_max - LIGHT1_SIZE);\n"; + code += "\t\t\tsky = mix(LIGHT1_COLOR * LIGHT1_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));\n"; + code += "\t\t}\n"; + code += "\t}\n"; + code += "\tif (LIGHT2_ENABLED) {\n"; + code += "\t\tfloat sun_angle = acos(dot(LIGHT2_DIRECTION, EYEDIR));\n"; + code += "\t\tif (sun_angle < LIGHT2_SIZE) {\n"; + code += "\t\t\tsky = LIGHT2_COLOR * LIGHT2_ENERGY;\n"; + code += "\t\t} else if (sun_angle < sun_angle_max) {\n"; + code += "\t\t\tfloat c2 = (sun_angle - LIGHT2_SIZE) / (sun_angle_max - LIGHT2_SIZE);\n"; + code += "\t\t\tsky = mix(LIGHT2_COLOR * LIGHT2_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));\n"; + code += "\t\t}\n"; + code += "\t}\n"; + code += "\tif (LIGHT3_ENABLED) {\n"; + code += "\t\tfloat sun_angle = acos(dot(LIGHT3_DIRECTION, EYEDIR));\n"; + code += "\t\tif (sun_angle < LIGHT3_SIZE) {\n"; + code += "\t\t\tsky = LIGHT3_COLOR * LIGHT3_ENERGY;\n"; + code += "\t\t} else if (sun_angle < sun_angle_max) {\n"; + code += "\t\t\tfloat c2 = (sun_angle - LIGHT3_SIZE) / (sun_angle_max - LIGHT3_SIZE);\n"; + code += "\t\t\tsky = mix(LIGHT3_COLOR * LIGHT3_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));\n"; + code += "\t\t}\n"; + code += "\t}\n"; + code += "\tc = (v_angle - (PI * 0.5)) / (PI * 0.5);\n"; + code += "\tvec3 ground = mix(ground_horizon_color.rgb, ground_bottom_color.rgb, clamp(1.0 - pow(1.0 - c, 1.0 / ground_curve), 0.0, 1.0));\n"; + code += "\tground *= ground_energy;\n"; + code += "\tCOLOR = mix(ground, sky, step(0.0, EYEDIR.y));\n"; + code += "}\n"; + + shader = RS::get_singleton()->shader_create(); + + RS::get_singleton()->shader_set_code(shader, code); + + RS::get_singleton()->material_set_shader(_get_material(), shader); + + set_sky_top_color(Color(0.35, 0.46, 0.71)); + set_sky_horizon_color(Color(0.55, 0.69, 0.81)); + set_sky_curve(0.09); + set_sky_energy(1.0); + + set_ground_bottom_color(Color(0.12, 0.12, 0.13)); + set_ground_horizon_color(Color(0.37, 0.33, 0.31)); + set_ground_curve(0.02); + set_ground_energy(1.0); + + set_sun_angle_max(100.0); + set_sun_curve(0.05); +} + +ProceduralSkyMaterial::~ProceduralSkyMaterial() { + RS::get_singleton()->free(shader); + RS::get_singleton()->material_set_shader(_get_material(), RID()); +} + +///////////////////////////////////////// +/* PanoramaSkyMaterial */ + +void PanoramaSkyMaterial::set_panorama(const Ref<Texture2D> &p_panorama) { + panorama = p_panorama; + RS::get_singleton()->material_set_param(_get_material(), "source_panorama", panorama); +} + +Ref<Texture2D> PanoramaSkyMaterial::get_panorama() const { + return panorama; +} + +bool PanoramaSkyMaterial::_can_do_next_pass() const { + return false; +} + +Shader::Mode PanoramaSkyMaterial::get_shader_mode() const { + return Shader::MODE_SKY; +} + +RID PanoramaSkyMaterial::get_shader_rid() const { + return shader; +} + +void PanoramaSkyMaterial::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_panorama", "texture"), &PanoramaSkyMaterial::set_panorama); + ClassDB::bind_method(D_METHOD("get_panorama"), &PanoramaSkyMaterial::get_panorama); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_panorama", "get_panorama"); +} + +PanoramaSkyMaterial::PanoramaSkyMaterial() { + String code = "shader_type sky;\n\n"; + + code += "uniform sampler2D source_panorama : filter_linear;\n"; + code += "void fragment() {\n"; + code += "\tCOLOR = texture(source_panorama, SKY_COORDS).rgb;\n"; + code += "}"; + + shader = RS::get_singleton()->shader_create(); + + RS::get_singleton()->shader_set_code(shader, code); + + RS::get_singleton()->material_set_shader(_get_material(), shader); +} + +PanoramaSkyMaterial::~PanoramaSkyMaterial() { + RS::get_singleton()->free(shader); + RS::get_singleton()->material_set_shader(_get_material(), RID()); +} + +////////////////////////////////// +/* PhysicalSkyMaterial */ + +void PhysicalSkyMaterial::set_rayleigh_coefficient(float p_rayleigh) { + rayleigh = p_rayleigh; + RS::get_singleton()->material_set_param(_get_material(), "rayleigh", rayleigh); +} + +float PhysicalSkyMaterial::get_rayleigh_coefficient() const { + return rayleigh; +} + +void PhysicalSkyMaterial::set_rayleigh_color(Color p_rayleigh_color) { + rayleigh_color = p_rayleigh_color; + RS::get_singleton()->material_set_param(_get_material(), "rayleigh_color", rayleigh_color); +} + +Color PhysicalSkyMaterial::get_rayleigh_color() const { + return rayleigh_color; +} + +void PhysicalSkyMaterial::set_mie_coefficient(float p_mie) { + mie = p_mie; + RS::get_singleton()->material_set_param(_get_material(), "mie", mie); +} + +float PhysicalSkyMaterial::get_mie_coefficient() const { + return mie; +} + +void PhysicalSkyMaterial::set_mie_eccentricity(float p_eccentricity) { + mie_eccentricity = p_eccentricity; + RS::get_singleton()->material_set_param(_get_material(), "mie_eccentricity", mie_eccentricity); +} + +float PhysicalSkyMaterial::get_mie_eccentricity() const { + return mie_eccentricity; +} + +void PhysicalSkyMaterial::set_mie_color(Color p_mie_color) { + mie_color = p_mie_color; + RS::get_singleton()->material_set_param(_get_material(), "mie_color", mie_color); +} + +Color PhysicalSkyMaterial::get_mie_color() const { + return mie_color; +} + +void PhysicalSkyMaterial::set_turbidity(float p_turbidity) { + turbidity = p_turbidity; + RS::get_singleton()->material_set_param(_get_material(), "turbidity", turbidity); +} + +float PhysicalSkyMaterial::get_turbidity() const { + return turbidity; +} + +void PhysicalSkyMaterial::set_sun_disk_scale(float p_sun_disk_scale) { + sun_disk_scale = p_sun_disk_scale; + RS::get_singleton()->material_set_param(_get_material(), "sun_disk_scale", sun_disk_scale); +} + +float PhysicalSkyMaterial::get_sun_disk_scale() const { + return sun_disk_scale; +} + +void PhysicalSkyMaterial::set_ground_color(Color p_ground_color) { + ground_color = p_ground_color; + RS::get_singleton()->material_set_param(_get_material(), "ground_color", ground_color); +} + +Color PhysicalSkyMaterial::get_ground_color() const { + return ground_color; +} + +void PhysicalSkyMaterial::set_exposure(float p_exposure) { + exposure = p_exposure; + RS::get_singleton()->material_set_param(_get_material(), "exposure", exposure); +} + +float PhysicalSkyMaterial::get_exposure() const { + return exposure; +} + +void PhysicalSkyMaterial::set_dither_strength(float p_dither_strength) { + dither_strength = p_dither_strength; + RS::get_singleton()->material_set_param(_get_material(), "dither_strength", dither_strength); +} + +float PhysicalSkyMaterial::get_dither_strength() const { + return dither_strength; +} + +void PhysicalSkyMaterial::set_night_sky(const Ref<Texture2D> &p_night_sky) { + night_sky = p_night_sky; + RS::get_singleton()->material_set_param(_get_material(), "night_sky", night_sky); +} + +Ref<Texture2D> PhysicalSkyMaterial::get_night_sky() const { + return night_sky; +} + +bool PhysicalSkyMaterial::_can_do_next_pass() const { + return false; +} + +Shader::Mode PhysicalSkyMaterial::get_shader_mode() const { + return Shader::MODE_SKY; +} + +RID PhysicalSkyMaterial::get_shader_rid() const { + return shader; +} + +void PhysicalSkyMaterial::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_rayleigh_coefficient", "rayleigh"), &PhysicalSkyMaterial::set_rayleigh_coefficient); + ClassDB::bind_method(D_METHOD("get_rayleigh_coefficient"), &PhysicalSkyMaterial::get_rayleigh_coefficient); + + ClassDB::bind_method(D_METHOD("set_rayleigh_color", "color"), &PhysicalSkyMaterial::set_rayleigh_color); + ClassDB::bind_method(D_METHOD("get_rayleigh_color"), &PhysicalSkyMaterial::get_rayleigh_color); + + ClassDB::bind_method(D_METHOD("set_mie_coefficient", "mie"), &PhysicalSkyMaterial::set_mie_coefficient); + ClassDB::bind_method(D_METHOD("get_mie_coefficient"), &PhysicalSkyMaterial::get_mie_coefficient); + + ClassDB::bind_method(D_METHOD("set_mie_eccentricity", "eccentricity"), &PhysicalSkyMaterial::set_mie_eccentricity); + ClassDB::bind_method(D_METHOD("get_mie_eccentricity"), &PhysicalSkyMaterial::get_mie_eccentricity); + + ClassDB::bind_method(D_METHOD("set_mie_color", "color"), &PhysicalSkyMaterial::set_mie_color); + ClassDB::bind_method(D_METHOD("get_mie_color"), &PhysicalSkyMaterial::get_mie_color); + + ClassDB::bind_method(D_METHOD("set_turbidity", "turbidity"), &PhysicalSkyMaterial::set_turbidity); + ClassDB::bind_method(D_METHOD("get_turbidity"), &PhysicalSkyMaterial::get_turbidity); + + ClassDB::bind_method(D_METHOD("set_sun_disk_scale", "scale"), &PhysicalSkyMaterial::set_sun_disk_scale); + ClassDB::bind_method(D_METHOD("get_sun_disk_scale"), &PhysicalSkyMaterial::get_sun_disk_scale); + + ClassDB::bind_method(D_METHOD("set_ground_color", "color"), &PhysicalSkyMaterial::set_ground_color); + ClassDB::bind_method(D_METHOD("get_ground_color"), &PhysicalSkyMaterial::get_ground_color); + + ClassDB::bind_method(D_METHOD("set_exposure", "exposure"), &PhysicalSkyMaterial::set_exposure); + ClassDB::bind_method(D_METHOD("get_exposure"), &PhysicalSkyMaterial::get_exposure); + + ClassDB::bind_method(D_METHOD("set_dither_strength", "strength"), &PhysicalSkyMaterial::set_dither_strength); + ClassDB::bind_method(D_METHOD("get_dither_strength"), &PhysicalSkyMaterial::get_dither_strength); + + ClassDB::bind_method(D_METHOD("set_night_sky", "night_sky"), &PhysicalSkyMaterial::set_night_sky); + ClassDB::bind_method(D_METHOD("get_night_sky"), &PhysicalSkyMaterial::get_night_sky); + + ADD_GROUP("Rayleigh", "rayleigh_"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rayleigh_coefficient", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_rayleigh_coefficient", "get_rayleigh_coefficient"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "rayleigh_color"), "set_rayleigh_color", "get_rayleigh_color"); + + ADD_GROUP("Mie", "mie_"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mie_coefficient", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_mie_coefficient", "get_mie_coefficient"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mie_eccentricity", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_mie_eccentricity", "get_mie_eccentricity"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "mie_color"), "set_mie_color", "get_mie_color"); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbidity", PROPERTY_HINT_RANGE, "0,1000,0.01"), "set_turbidity", "get_turbidity"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_disk_scale", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_disk_scale", "get_sun_disk_scale"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_color"), "set_ground_color", "get_ground_color"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_exposure", "get_exposure"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dither_strength", PROPERTY_HINT_RANGE, "0,10,0.01"), "set_dither_strength", "get_dither_strength"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "night_sky", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_night_sky", "get_night_sky"); +} + +PhysicalSkyMaterial::PhysicalSkyMaterial() { + String code = "shader_type sky;\n\n"; + + code += "uniform float rayleigh : hint_range(0, 64) = 2.0;\n"; + code += "uniform vec4 rayleigh_color : hint_color = vec4(0.056, 0.14, 0.3, 1.0);\n"; + code += "uniform float mie : hint_range(0, 1) = 0.005;\n"; + code += "uniform float mie_eccentricity : hint_range(-1, 1) = 0.8;\n"; + code += "uniform vec4 mie_color : hint_color = vec4(0.36, 0.56, 0.82, 1.0);\n\n"; + + code += "uniform float turbidity : hint_range(0, 1000) = 10.0;\n"; + code += "uniform float sun_disk_scale : hint_range(0, 360) = 1.0;\n"; + code += "uniform vec4 ground_color : hint_color = vec4(1.0);\n"; + code += "uniform float exposure : hint_range(0, 128) = 0.1;\n"; + code += "uniform float dither_strength : hint_range(0, 10) = 1.0;\n\n"; + + code += "uniform sampler2D night_sky : hint_black;"; + + code += "const float PI = 3.141592653589793238462643383279502884197169;\n"; + code += "const vec3 UP = vec3( 0.0, 1.0, 0.0 );\n\n"; + + code += "// Sun constants\n"; + code += "const float SUN_ENERGY = 1000.0;\n\n"; + + code += "// optical length at zenith for molecules\n"; + code += "const float rayleigh_zenith_size = 8.4e3;\n"; + code += "const float mie_zenith_size = 1.25e3;\n\n"; + + code += "float henyey_greenstein(float cos_theta, float g) {\n"; + code += "\tconst float k = 0.0795774715459;\n"; + code += "\treturn k * (1.0 - g * g) / (pow(1.0 + g * g - 2.0 * g * cos_theta, 1.5));\n"; + code += "}\n\n"; + + code += "// From: https://www.shadertoy.com/view/4sfGzS credit to iq\n"; + code += "float hash(vec3 p) {\n"; + code += "\tp = fract( p * 0.3183099 + 0.1 );\n"; + code += "\tp *= 17.0;\n"; + code += "\treturn fract(p.x * p.y * p.z * (p.x + p.y + p.z));\n"; + code += "}\n\n"; + + code += "void fragment() {\n"; + code += "\tfloat zenith_angle = clamp( dot(UP, normalize(LIGHT0_DIRECTION)), -1.0, 1.0 );\n"; + code += "\tfloat sun_energy = max(0.0, 1.0 - exp(-((PI * 0.5) - acos(zenith_angle)))) * SUN_ENERGY * LIGHT0_ENERGY;\n"; + code += "\tfloat sun_fade = 1.0 - clamp(1.0 - exp(LIGHT0_DIRECTION.y), 0.0, 1.0);\n\n"; + + code += "\t// rayleigh coefficients\n"; + code += "\tfloat rayleigh_coefficient = rayleigh - ( 1.0 * ( 1.0 - sun_fade ) );\n"; + code += "\tvec3 rayleigh_beta = rayleigh_coefficient * rayleigh_color.rgb * 0.0001;\n"; + code += "\t// mie coefficients from Preetham\n"; + code += "\tvec3 mie_beta = turbidity * mie * mie_color.rgb * 0.000434;\n\n"; + + code += "\t// optical length\n"; + code += "\tfloat zenith = acos(max(0.0, dot(UP, EYEDIR)));\n"; + code += "\tfloat optical_mass = 1.0 / (cos(zenith) + 0.15 * pow(93.885 - degrees(zenith), -1.253));\n"; + code += "\tfloat rayleigh_scatter = rayleigh_zenith_size * optical_mass;\n"; + code += "\tfloat mie_scatter = mie_zenith_size * optical_mass;\n\n"; + + code += "\t// light extinction based on thickness of atmosphere\n"; + code += "\tvec3 extinction = exp(-(rayleigh_beta * rayleigh_scatter + mie_beta * mie_scatter));\n\n"; + + code += "\t// in scattering\n"; + code += "\tfloat cos_theta = dot(EYEDIR, normalize(LIGHT0_DIRECTION));\n\n"; + + code += "\tfloat rayleigh_phase = (3.0 / (16.0 * PI)) * (1.0 + pow(cos_theta * 0.5 + 0.5, 2.0));\n"; + code += "\tvec3 betaRTheta = rayleigh_beta * rayleigh_phase;\n\n"; + + code += "\tfloat mie_phase = henyey_greenstein(cos_theta, mie_eccentricity);\n"; + code += "\tvec3 betaMTheta = mie_beta * mie_phase;\n\n"; + + code += "\tvec3 Lin = pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * (1.0 - extinction), vec3(1.5));\n"; + code += "\t// Hack from https://github.com/mrdoob/three.js/blob/master/examples/jsm/objects/Sky.js\n"; + code += "\tLin *= mix(vec3(1.0), pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * extinction, vec3(0.5)), clamp(pow(1.0 - zenith_angle, 5.0), 0.0, 1.0));\n\n"; + + code += "\t// Hack in the ground color\n"; + code += "\tLin *= mix(ground_color.rgb, vec3(1.0), smoothstep(-0.1, 0.1, dot(UP, EYEDIR)));\n\n"; + + code += "\t// Solar disk and out-scattering\n"; + code += "\tfloat sunAngularDiameterCos = cos(LIGHT0_SIZE * sun_disk_scale);\n"; + code += "\tfloat sunAngularDiameterCos2 = cos(LIGHT0_SIZE * sun_disk_scale*0.5);\n"; + code += "\tfloat sundisk = smoothstep(sunAngularDiameterCos, sunAngularDiameterCos2, cos_theta);\n"; + code += "\tvec3 L0 = (sun_energy * 1900.0 * extinction) * sundisk * LIGHT0_COLOR;\n"; + code += "\tL0 += texture(night_sky, SKY_COORDS).xyz * extinction;\n\n"; + + code += "\tvec3 color = (Lin + L0) * 0.04;\n"; + code += "\tCOLOR = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade))));\n"; + code += "\tCOLOR *= exposure;\n"; + code += "\t// Make optional, eliminates banding\n"; + code += "\tCOLOR += (hash(EYEDIR * 1741.9782) * 0.08 - 0.04) * 0.008 * dither_strength;\n"; + code += "}\n"; + + shader = RS::get_singleton()->shader_create(); + + RS::get_singleton()->shader_set_code(shader, code); + + RS::get_singleton()->material_set_shader(_get_material(), shader); + + set_rayleigh_coefficient(2.0); + set_rayleigh_color(Color(0.056, 0.14, 0.3)); + set_mie_coefficient(0.005); + set_mie_eccentricity(0.8); + set_mie_color(Color(0.36, 0.56, 0.82)); + set_turbidity(10.0); + set_sun_disk_scale(1.0); + set_ground_color(Color(1.0, 1.0, 1.0)); + set_exposure(0.1); + set_dither_strength(1.0); +} + +PhysicalSkyMaterial::~PhysicalSkyMaterial() { + RS::get_singleton()->free(shader); + RS::get_singleton()->material_set_shader(_get_material(), RID()); +} diff --git a/scene/resources/sky_material.h b/scene/resources/sky_material.h new file mode 100644 index 0000000000..5e23020d66 --- /dev/null +++ b/scene/resources/sky_material.h @@ -0,0 +1,189 @@ +/*************************************************************************/ +/* sky_material.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "core/rid.h" +#include "scene/resources/material.h" + +#ifndef SKY_MATERIAL_H +#define SKY_MATERIAL_H + +class ProceduralSkyMaterial : public Material { + GDCLASS(ProceduralSkyMaterial, Material); + +private: + Color sky_top_color; + Color sky_horizon_color; + float sky_curve; + float sky_energy; + + Color ground_bottom_color; + Color ground_horizon_color; + float ground_curve; + float ground_energy; + + float sun_angle_max; + float sun_curve; + + RID shader; + +protected: + static void _bind_methods(); + virtual bool _can_do_next_pass() const override; + +public: + void set_sky_top_color(const Color &p_sky_top); + Color get_sky_top_color() const; + + void set_sky_horizon_color(const Color &p_sky_horizon); + Color get_sky_horizon_color() const; + + void set_sky_curve(float p_curve); + float get_sky_curve() const; + + void set_sky_energy(float p_energy); + float get_sky_energy() const; + + void set_ground_bottom_color(const Color &p_ground_bottom); + Color get_ground_bottom_color() const; + + void set_ground_horizon_color(const Color &p_ground_horizon); + Color get_ground_horizon_color() const; + + void set_ground_curve(float p_curve); + float get_ground_curve() const; + + void set_ground_energy(float p_energy); + float get_ground_energy() const; + + void set_sun_angle_max(float p_angle); + float get_sun_angle_max() const; + + void set_sun_curve(float p_curve); + float get_sun_curve() const; + + virtual Shader::Mode get_shader_mode() const override; + RID get_shader_rid() const; + + ProceduralSkyMaterial(); + ~ProceduralSkyMaterial(); +}; + +////////////////////////////////////////////////////// +/* PanoramaSkyMaterial */ + +class PanoramaSkyMaterial : public Material { + GDCLASS(PanoramaSkyMaterial, Material); + +private: + Ref<Texture2D> panorama; + RID shader; + +protected: + static void _bind_methods(); + virtual bool _can_do_next_pass() const override; + +public: + void set_panorama(const Ref<Texture2D> &p_panorama); + Ref<Texture2D> get_panorama() const; + + virtual Shader::Mode get_shader_mode() const override; + RID get_shader_rid() const; + + PanoramaSkyMaterial(); + ~PanoramaSkyMaterial(); +}; + +////////////////////////////////////////////////////// +/* PanoramaSkyMaterial */ + +class PhysicalSkyMaterial : public Material { + GDCLASS(PhysicalSkyMaterial, Material); + +private: + RID shader; + + float rayleigh; + Color rayleigh_color; + float mie; + float mie_eccentricity; + Color mie_color; + float turbidity; + float sun_disk_scale; + Color ground_color; + float exposure; + float dither_strength; + Ref<Texture2D> night_sky; + +protected: + static void _bind_methods(); + virtual bool _can_do_next_pass() const override; + +public: + void set_rayleigh_coefficient(float p_rayleigh); + float get_rayleigh_coefficient() const; + + void set_rayleigh_color(Color p_rayleigh_color); + Color get_rayleigh_color() const; + + void set_turbidity(float p_turbidity); + float get_turbidity() const; + + void set_mie_coefficient(float p_mie); + float get_mie_coefficient() const; + + void set_mie_eccentricity(float p_eccentricity); + float get_mie_eccentricity() const; + + void set_mie_color(Color p_mie_color); + Color get_mie_color() const; + + void set_sun_disk_scale(float p_sun_disk_scale); + float get_sun_disk_scale() const; + + void set_ground_color(Color p_ground_color); + Color get_ground_color() const; + + void set_exposure(float p_exposure); + float get_exposure() const; + + void set_dither_strength(float p_dither_strength); + float get_dither_strength() const; + + void set_night_sky(const Ref<Texture2D> &p_night_sky); + Ref<Texture2D> get_night_sky() const; + + virtual Shader::Mode get_shader_mode() const override; + RID get_shader_rid() const; + + PhysicalSkyMaterial(); + ~PhysicalSkyMaterial(); +}; + +#endif /* !SKY_MATERIAL_H */ diff --git a/scene/resources/space_2d.cpp b/scene/resources/space_2d.cpp deleted file mode 100644 index 376e926548..0000000000 --- a/scene/resources/space_2d.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/*************************************************************************/ -/* space_2d.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "space_2d.h" - -RID Space2D::get_rid() const { - - return space; -} - -void Space2D::set_active(bool p_active) { - - active = p_active; - Physics2DServer::get_singleton()->space_set_active(space, active); -} - -bool Space2D::is_active() const { - - return active; -} - -void Space2D::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_active", "active"), &Space2D::set_active); - ClassDB::bind_method(D_METHOD("is_active"), &Space2D::is_active); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "active"), "set_active", "is_active"); -} - -Space2D::Space2D() { - - active = false; - space = Physics2DServer::get_singleton()->space_create(); -} - -Space2D::~Space2D() { - - Physics2DServer::get_singleton()->free(space); -} diff --git a/scene/resources/sphere_shape.cpp b/scene/resources/sphere_shape_3d.cpp index f408717834..fd33387df6 100644 --- a/scene/resources/sphere_shape.cpp +++ b/scene/resources/sphere_shape_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* sphere_shape.cpp */ +/* sphere_shape_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,17 +28,15 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "sphere_shape.h" -#include "servers/physics_server.h" - -Vector<Vector3> SphereShape::get_debug_mesh_lines() { +#include "sphere_shape_3d.h" +#include "servers/physics_server_3d.h" +Vector<Vector3> SphereShape3D::get_debug_mesh_lines() const { float r = get_radius(); Vector<Vector3> points; for (int i = 0; i <= 360; i++) { - float ra = Math::deg2rad((float)i); float rb = Math::deg2rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r; @@ -55,35 +53,34 @@ Vector<Vector3> SphereShape::get_debug_mesh_lines() { return points; } -void SphereShape::_update_shape() { - - PhysicsServer::get_singleton()->shape_set_data(get_shape(), radius); - Shape::_update_shape(); +real_t SphereShape3D::get_enclosing_radius() const { + return radius; } -void SphereShape::set_radius(float p_radius) { +void SphereShape3D::_update_shape() { + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), radius); + Shape3D::_update_shape(); +} +void SphereShape3D::set_radius(float p_radius) { radius = p_radius; _update_shape(); notify_change_to_owners(); _change_notify("radius"); } -float SphereShape::get_radius() const { - +float SphereShape3D::get_radius() const { return radius; } -void SphereShape::_bind_methods() { +void SphereShape3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &SphereShape3D::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &SphereShape3D::get_radius); - ClassDB::bind_method(D_METHOD("set_radius", "radius"), &SphereShape::set_radius); - ClassDB::bind_method(D_METHOD("get_radius"), &SphereShape::get_radius); - - ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_radius", "get_radius"); } -SphereShape::SphereShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_SPHERE)) { - +SphereShape3D::SphereShape3D() : + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_SPHERE)) { set_radius(1.0); } diff --git a/scene/resources/sphere_shape.h b/scene/resources/sphere_shape_3d.h index 6002a3baeb..5cad67aea5 100644 --- a/scene/resources/sphere_shape.h +++ b/scene/resources/sphere_shape_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* sphere_shape.h */ +/* sphere_shape_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,28 +28,28 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SPHERE_SHAPE_H -#define SPHERE_SHAPE_H +#ifndef SPHERE_SHAPE_3D_H +#define SPHERE_SHAPE_3D_H -#include "scene/resources/shape.h" +#include "scene/resources/shape_3d.h" -class SphereShape : public Shape { - - GDCLASS(SphereShape, Shape); +class SphereShape3D : public Shape3D { + GDCLASS(SphereShape3D, Shape3D); float radius; protected: static void _bind_methods(); - virtual void _update_shape(); + virtual void _update_shape() override; public: void set_radius(float p_radius); float get_radius() const; - virtual Vector<Vector3> get_debug_mesh_lines(); + virtual Vector<Vector3> get_debug_mesh_lines() const override; + virtual real_t get_enclosing_radius() const override; - SphereShape(); + SphereShape3D(); }; #endif // SPHERE_SHAPE_H diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp index 9408d1aa71..cdb0ec5111 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -29,37 +29,36 @@ /*************************************************************************/ #include "style_box.h" -#include "scene/2d/canvas_item.h" + +#include "scene/main/canvas_item.h" #include <limits.h> bool StyleBox::test_mask(const Point2 &p_point, const Rect2 &p_rect) const { - return true; } void StyleBox::set_default_margin(Margin p_margin, float p_value) { - ERR_FAIL_INDEX((int)p_margin, 4); margin[p_margin] = p_value; emit_changed(); } -float StyleBox::get_default_margin(Margin p_margin) const { +float StyleBox::get_default_margin(Margin p_margin) const { ERR_FAIL_INDEX_V((int)p_margin, 4, 0.0); return margin[p_margin]; } float StyleBox::get_margin(Margin p_margin) const { - ERR_FAIL_INDEX_V((int)p_margin, 4, 0.0); - if (margin[p_margin] < 0) + if (margin[p_margin] < 0) { return get_style_margin(p_margin); - else + } else { return margin[p_margin]; + } } CanvasItem *StyleBox::get_current_item_drawn() const { @@ -67,17 +66,14 @@ CanvasItem *StyleBox::get_current_item_drawn() const { } Size2 StyleBox::get_minimum_size() const { - return Size2(get_margin(MARGIN_LEFT) + get_margin(MARGIN_RIGHT), get_margin(MARGIN_TOP) + get_margin(MARGIN_BOTTOM)); } Point2 StyleBox::get_offset() const { - return Point2(get_margin(MARGIN_LEFT), get_margin(MARGIN_TOP)); } Size2 StyleBox::get_center_size() const { - return Size2(); } @@ -86,7 +82,6 @@ Rect2 StyleBox::get_draw_rect(const Rect2 &p_rect) const { } void StyleBox::_bind_methods() { - ClassDB::bind_method(D_METHOD("test_mask", "point", "rect"), &StyleBox::test_mask); ClassDB::bind_method(D_METHOD("set_default_margin", "margin", "offset"), &StyleBox::set_default_margin); @@ -104,24 +99,22 @@ void StyleBox::_bind_methods() { ClassDB::bind_method(D_METHOD("draw", "canvas_item", "rect"), &StyleBox::draw); ADD_GROUP("Content Margin", "content_margin_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "content_margin_left", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", MARGIN_LEFT); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "content_margin_right", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", MARGIN_RIGHT); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "content_margin_top", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", MARGIN_TOP); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "content_margin_bottom", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", MARGIN_BOTTOM); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_left", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", MARGIN_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_right", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", MARGIN_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_top", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", MARGIN_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_bottom", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", MARGIN_BOTTOM); } StyleBox::StyleBox() { - for (int i = 0; i < 4; i++) { - margin[i] = -1; } } -void StyleBoxTexture::set_texture(Ref<Texture> p_texture) { - - if (texture == p_texture) +void StyleBoxTexture::set_texture(Ref<Texture2D> p_texture) { + if (texture == p_texture) { return; + } texture = p_texture; if (p_texture.is_null()) { region_rect = Rect2(0, 0, 0, 0); @@ -133,26 +126,23 @@ void StyleBoxTexture::set_texture(Ref<Texture> p_texture) { _change_notify("texture"); } -Ref<Texture> StyleBoxTexture::get_texture() const { - +Ref<Texture2D> StyleBoxTexture::get_texture() const { return texture; } -void StyleBoxTexture::set_normal_map(Ref<Texture> p_normal_map) { - - if (normal_map == p_normal_map) +void StyleBoxTexture::set_normal_map(Ref<Texture2D> p_normal_map) { + if (normal_map == p_normal_map) { return; + } normal_map = p_normal_map; emit_changed(); } -Ref<Texture> StyleBoxTexture::get_normal_map() const { - +Ref<Texture2D> StyleBoxTexture::get_normal_map() const { return normal_map; } void StyleBoxTexture::set_margin_size(Margin p_margin, float p_size) { - ERR_FAIL_INDEX((int)p_margin, 4); margin[p_margin] = p_size; @@ -165,15 +155,14 @@ void StyleBoxTexture::set_margin_size(Margin p_margin, float p_size) { }; _change_notify(margin_prop[p_margin]); } -float StyleBoxTexture::get_margin_size(Margin p_margin) const { +float StyleBoxTexture::get_margin_size(Margin p_margin) const { ERR_FAIL_INDEX_V((int)p_margin, 4, 0.0); return margin[p_margin]; } float StyleBoxTexture::get_style_margin(Margin p_margin) const { - ERR_FAIL_INDEX_V((int)p_margin, 4, 0.0); return margin[p_margin]; @@ -184,8 +173,9 @@ Rect2 StyleBoxTexture::get_draw_rect(const Rect2 &p_rect) const { } void StyleBoxTexture::draw(RID p_canvas_item, const Rect2 &p_rect) const { - if (texture.is_null()) + if (texture.is_null()) { return; + } Rect2 rect = p_rect; Rect2 src_rect = region_rect; @@ -198,33 +188,31 @@ void StyleBoxTexture::draw(RID p_canvas_item, const Rect2 &p_rect) const { rect.size.y += expand_margin[MARGIN_TOP] + expand_margin[MARGIN_BOTTOM]; RID normal_rid; - if (normal_map.is_valid()) + if (normal_map.is_valid()) { normal_rid = normal_map->get_rid(); + } - VisualServer::get_singleton()->canvas_item_add_nine_patch(p_canvas_item, rect, src_rect, texture->get_rid(), Vector2(margin[MARGIN_LEFT], margin[MARGIN_TOP]), Vector2(margin[MARGIN_RIGHT], margin[MARGIN_BOTTOM]), VS::NinePatchAxisMode(axis_h), VS::NinePatchAxisMode(axis_v), draw_center, modulate, normal_rid); + RenderingServer::get_singleton()->canvas_item_add_nine_patch(p_canvas_item, rect, src_rect, texture->get_rid(), Vector2(margin[MARGIN_LEFT], margin[MARGIN_TOP]), Vector2(margin[MARGIN_RIGHT], margin[MARGIN_BOTTOM]), RS::NinePatchAxisMode(axis_h), RS::NinePatchAxisMode(axis_v), draw_center, modulate, normal_rid); } void StyleBoxTexture::set_draw_center(bool p_enabled) { - draw_center = p_enabled; emit_changed(); } bool StyleBoxTexture::is_draw_center_enabled() const { - return draw_center; } Size2 StyleBoxTexture::get_center_size() const { - - if (texture.is_null()) + if (texture.is_null()) { return Size2(); + } return region_rect.size - get_minimum_size(); } void StyleBoxTexture::set_expand_margin_size(Margin p_expand_margin, float p_size) { - ERR_FAIL_INDEX((int)p_expand_margin, 4); expand_margin[p_expand_margin] = p_size; emit_changed(); @@ -240,70 +228,63 @@ void StyleBoxTexture::set_expand_margin_size_individual(float p_left, float p_to void StyleBoxTexture::set_expand_margin_size_all(float p_expand_margin_size) { for (int i = 0; i < 4; i++) { - expand_margin[i] = p_expand_margin_size; } emit_changed(); } float StyleBoxTexture::get_expand_margin_size(Margin p_expand_margin) const { - ERR_FAIL_INDEX_V((int)p_expand_margin, 4, 0); return expand_margin[p_expand_margin]; } void StyleBoxTexture::set_region_rect(const Rect2 &p_region_rect) { - - if (region_rect == p_region_rect) + if (region_rect == p_region_rect) { return; + } region_rect = p_region_rect; emit_changed(); + _change_notify("region"); } Rect2 StyleBoxTexture::get_region_rect() const { - return region_rect; } void StyleBoxTexture::set_h_axis_stretch_mode(AxisStretchMode p_mode) { - ERR_FAIL_INDEX((int)p_mode, 3); axis_h = p_mode; emit_changed(); } StyleBoxTexture::AxisStretchMode StyleBoxTexture::get_h_axis_stretch_mode() const { - return axis_h; } void StyleBoxTexture::set_v_axis_stretch_mode(AxisStretchMode p_mode) { - ERR_FAIL_INDEX((int)p_mode, 3); axis_v = p_mode; emit_changed(); } StyleBoxTexture::AxisStretchMode StyleBoxTexture::get_v_axis_stretch_mode() const { - return axis_v; } void StyleBoxTexture::set_modulate(const Color &p_modulate) { - if (modulate == p_modulate) + if (modulate == p_modulate) { return; + } modulate = p_modulate; emit_changed(); } Color StyleBoxTexture::get_modulate() const { - return modulate; } void StyleBoxTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_texture", "texture"), &StyleBoxTexture::set_texture); ClassDB::bind_method(D_METHOD("get_texture"), &StyleBoxTexture::get_texture); @@ -335,19 +316,19 @@ void StyleBoxTexture::_bind_methods() { ADD_SIGNAL(MethodInfo("texture_changed")); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_normal_map", "get_normal_map"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_normal_map", "get_normal_map"); ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect"); ADD_GROUP("Margin", "margin_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "margin_left", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", MARGIN_LEFT); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "margin_right", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", MARGIN_RIGHT); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "margin_top", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", MARGIN_TOP); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", MARGIN_BOTTOM); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "margin_left", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", MARGIN_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "margin_right", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", MARGIN_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "margin_top", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", MARGIN_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1"), "set_margin_size", "get_margin_size", MARGIN_BOTTOM); ADD_GROUP("Expand Margin", "expand_margin_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "expand_margin_left", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", MARGIN_LEFT); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "expand_margin_right", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", MARGIN_RIGHT); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "expand_margin_top", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", MARGIN_TOP); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "expand_margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", MARGIN_BOTTOM); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_left", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", MARGIN_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_right", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", MARGIN_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_top", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", MARGIN_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin_size", "get_expand_margin_size", MARGIN_BOTTOM); ADD_GROUP("Axis Stretch", "axis_stretch_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "axis_stretch_horizontal", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_h_axis_stretch_mode", "get_h_axis_stretch_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "axis_stretch_vertical", PROPERTY_HINT_ENUM, "Stretch,Tile,Tile Fit"), "set_v_axis_stretch_mode", "get_v_axis_stretch_mode"); @@ -361,7 +342,6 @@ void StyleBoxTexture::_bind_methods() { } StyleBoxTexture::StyleBoxTexture() { - for (int i = 0; i < 4; i++) { margin[i] = 0; expand_margin[i] = 0; @@ -372,29 +352,27 @@ StyleBoxTexture::StyleBoxTexture() { axis_h = AXIS_STRETCH_MODE_STRETCH; axis_v = AXIS_STRETCH_MODE_STRETCH; } + StyleBoxTexture::~StyleBoxTexture() { } //////////////// void StyleBoxFlat::set_bg_color(const Color &p_color) { - bg_color = p_color; emit_changed(); } Color StyleBoxFlat::get_bg_color() const { - return bg_color; } void StyleBoxFlat::set_border_color(const Color &p_color) { - border_color = p_color; emit_changed(); } -Color StyleBoxFlat::get_border_color() const { +Color StyleBoxFlat::get_border_color() const { return border_color; } @@ -405,8 +383,8 @@ void StyleBoxFlat::set_border_width_all(int p_size) { border_width[3] = p_size; emit_changed(); } -int StyleBoxFlat::get_border_width_min() const { +int StyleBoxFlat::get_border_width_min() const { return MIN(MIN(border_width[0], border_width[1]), MIN(border_width[2], border_width[3])); } @@ -422,23 +400,22 @@ int StyleBoxFlat::get_border_width(Margin p_margin) const { } void StyleBoxFlat::set_border_blend(bool p_blend) { - blend_border = p_blend; emit_changed(); } -bool StyleBoxFlat::get_border_blend() const { +bool StyleBoxFlat::get_border_blend() const { return blend_border; } void StyleBoxFlat::set_corner_radius_all(int radius) { - for (int i = 0; i < 4; i++) { corner_radius[i] = radius; } emit_changed(); } + void StyleBoxFlat::set_corner_radius_individual(const int radius_top_left, const int radius_top_right, const int radius_botton_right, const int radius_bottom_left) { corner_radius[0] = radius_top_left; corner_radius[1] = radius_top_right; @@ -447,6 +424,7 @@ void StyleBoxFlat::set_corner_radius_individual(const int radius_top_left, const emit_changed(); } + int StyleBoxFlat::get_corner_radius_min() const { int smallest = corner_radius[0]; for (int i = 1; i < 4; i++) { @@ -458,19 +436,17 @@ int StyleBoxFlat::get_corner_radius_min() const { } void StyleBoxFlat::set_corner_radius(const Corner p_corner, const int radius) { - ERR_FAIL_INDEX((int)p_corner, 4); corner_radius[p_corner] = radius; emit_changed(); } -int StyleBoxFlat::get_corner_radius(const Corner p_corner) const { +int StyleBoxFlat::get_corner_radius(const Corner p_corner) const { ERR_FAIL_INDEX_V((int)p_corner, 4, 0); return corner_radius[p_corner]; } void StyleBoxFlat::set_expand_margin_size(Margin p_expand_margin, float p_size) { - ERR_FAIL_INDEX((int)p_expand_margin, 4); expand_margin[p_expand_margin] = p_size; emit_changed(); @@ -486,54 +462,49 @@ void StyleBoxFlat::set_expand_margin_size_individual(float p_left, float p_top, void StyleBoxFlat::set_expand_margin_size_all(float p_expand_margin_size) { for (int i = 0; i < 4; i++) { - expand_margin[i] = p_expand_margin_size; } emit_changed(); } float StyleBoxFlat::get_expand_margin_size(Margin p_expand_margin) const { - ERR_FAIL_INDEX_V((int)p_expand_margin, 4, 0.0); return expand_margin[p_expand_margin]; } -void StyleBoxFlat::set_draw_center(bool p_enabled) { +void StyleBoxFlat::set_draw_center(bool p_enabled) { draw_center = p_enabled; emit_changed(); } -bool StyleBoxFlat::is_draw_center_enabled() const { +bool StyleBoxFlat::is_draw_center_enabled() const { return draw_center; } void StyleBoxFlat::set_shadow_color(const Color &p_color) { - shadow_color = p_color; emit_changed(); } -Color StyleBoxFlat::get_shadow_color() const { +Color StyleBoxFlat::get_shadow_color() const { return shadow_color; } void StyleBoxFlat::set_shadow_size(const int &p_size) { - shadow_size = p_size; emit_changed(); } -int StyleBoxFlat::get_shadow_size() const { +int StyleBoxFlat::get_shadow_size() const { return shadow_size; } void StyleBoxFlat::set_shadow_offset(const Point2 &p_offset) { - shadow_offset = p_offset; emit_changed(); } -Point2 StyleBoxFlat::get_shadow_offset() const { +Point2 StyleBoxFlat::get_shadow_offset() const { return shadow_offset; } @@ -541,6 +512,7 @@ void StyleBoxFlat::set_anti_aliased(const bool &p_anti_aliased) { anti_aliased = p_anti_aliased; emit_changed(); } + bool StyleBoxFlat::is_anti_aliased() const { return anti_aliased; } @@ -549,6 +521,7 @@ void StyleBoxFlat::set_aa_size(const int &p_aa_size) { aa_size = CLAMP(p_aa_size, 1, 5); emit_changed(); } + int StyleBoxFlat::get_aa_size() const { return aa_size; } @@ -557,12 +530,12 @@ void StyleBoxFlat::set_corner_detail(const int &p_corner_detail) { corner_detail = CLAMP(p_corner_detail, 1, 20); emit_changed(); } + int StyleBoxFlat::get_corner_detail() const { return corner_detail; } Size2 StyleBoxFlat::get_center_size() const { - return Size2(); } @@ -592,7 +565,6 @@ inline void set_inner_corner_radius(const Rect2 style_rect, const Rect2 inner_re inline void draw_ring(Vector<Vector2> &verts, Vector<int> &indices, Vector<Color> &colors, const Rect2 &style_rect, const int corner_radius[4], const Rect2 &ring_rect, const Rect2 &inner_rect, const Color &inner_color, const Color &outer_color, const int corner_detail, const bool fill_center = false) { - int vert_offset = verts.size(); if (!vert_offset) { vert_offset = 0; @@ -704,7 +676,6 @@ Rect2 StyleBoxFlat::get_draw_rect(const Rect2 &p_rect) const { } void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const { - //PREPARATIONS bool draw_border = (border_width[0] > 0) || (border_width[1] > 0) || (border_width[2] > 0) || (border_width[3] > 0); bool draw_shadow = (shadow_size > 0); @@ -852,7 +823,7 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const { } //DRAWING - VisualServer *vs = VisualServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); vs->canvas_item_add_triangle_array(p_canvas_item, indices, verts, colors, uvs); } @@ -860,8 +831,8 @@ float StyleBoxFlat::get_style_margin(Margin p_margin) const { ERR_FAIL_INDEX_V((int)p_margin, 4, 0.0); return border_width[p_margin]; } -void StyleBoxFlat::_bind_methods() { +void StyleBoxFlat::_bind_methods() { ClassDB::bind_method(D_METHOD("set_bg_color", "color"), &StyleBoxFlat::set_bg_color); ClassDB::bind_method(D_METHOD("get_bg_color"), &StyleBoxFlat::get_bg_color); @@ -933,14 +904,14 @@ void StyleBoxFlat::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "corner_detail", PROPERTY_HINT_RANGE, "1,20,1"), "set_corner_detail", "get_corner_detail"); ADD_GROUP("Expand Margin", "expand_margin_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "expand_margin_left", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_LEFT); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "expand_margin_right", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_RIGHT); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "expand_margin_top", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_TOP); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "expand_margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_BOTTOM); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_left", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_LEFT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_right", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_RIGHT); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_top", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_TOP); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "expand_margin_bottom", PROPERTY_HINT_RANGE, "0,2048,1"), "set_expand_margin", "get_expand_margin", MARGIN_BOTTOM); ADD_GROUP("Shadow", "shadow_"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_size"), "set_shadow_size", "get_shadow_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_size", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_shadow_size", "get_shadow_size"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "shadow_offset"), "set_shadow_offset", "get_shadow_offset"); ADD_GROUP("Anti Aliasing", "anti_aliasing_"); @@ -949,7 +920,6 @@ void StyleBoxFlat::_bind_methods() { } StyleBoxFlat::StyleBoxFlat() { - bg_color = Color(0.6, 0.6, 0.6); shadow_color = Color(0, 0, 0, 0.6); border_color = Color(0.8, 0.8, 0.8); @@ -978,6 +948,7 @@ StyleBoxFlat::StyleBoxFlat() { corner_radius[2] = 0; corner_radius[3] = 0; } + StyleBoxFlat::~StyleBoxFlat() { } @@ -985,6 +956,7 @@ void StyleBoxLine::set_color(const Color &p_color) { color = p_color; emit_changed(); } + Color StyleBoxLine::get_color() const { return color; } @@ -993,6 +965,7 @@ void StyleBoxLine::set_thickness(int p_thickness) { thickness = p_thickness; emit_changed(); } + int StyleBoxLine::get_thickness() const { return thickness; } @@ -1001,6 +974,7 @@ void StyleBoxLine::set_vertical(bool p_vertical) { vertical = p_vertical; emit_changed(); } + bool StyleBoxLine::is_vertical() const { return vertical; } @@ -1009,6 +983,7 @@ void StyleBoxLine::set_grow_end(float p_grow_end) { grow_end = p_grow_end; emit_changed(); } + float StyleBoxLine::get_grow_end() const { return grow_end; } @@ -1017,12 +992,12 @@ void StyleBoxLine::set_grow_begin(float p_grow_begin) { grow_begin = p_grow_begin; emit_changed(); } + float StyleBoxLine::get_grow_begin() const { return grow_begin; } void StyleBoxLine::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_color", "color"), &StyleBoxLine::set_color); ClassDB::bind_method(D_METHOD("get_color"), &StyleBoxLine::get_color); ClassDB::bind_method(D_METHOD("set_thickness", "thickness"), &StyleBoxLine::set_thickness); @@ -1035,21 +1010,23 @@ void StyleBoxLine::_bind_methods() { ClassDB::bind_method(D_METHOD("is_vertical"), &StyleBoxLine::is_vertical); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "grow_begin", PROPERTY_HINT_RANGE, "-300,300,1"), "set_grow_begin", "get_grow_begin"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "grow_end", PROPERTY_HINT_RANGE, "-300,300,1"), "set_grow_end", "get_grow_end"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "grow_begin", PROPERTY_HINT_RANGE, "-300,300,1"), "set_grow_begin", "get_grow_begin"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "grow_end", PROPERTY_HINT_RANGE, "-300,300,1"), "set_grow_end", "get_grow_end"); ADD_PROPERTY(PropertyInfo(Variant::INT, "thickness", PROPERTY_HINT_RANGE, "0,10"), "set_thickness", "get_thickness"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "vertical"), "set_vertical", "is_vertical"); } + float StyleBoxLine::get_style_margin(Margin p_margin) const { ERR_FAIL_INDEX_V((int)p_margin, 4, thickness); return thickness; } + Size2 StyleBoxLine::get_center_size() const { return Size2(); } void StyleBoxLine::draw(RID p_canvas_item, const Rect2 &p_rect) const { - VisualServer *vs = VisualServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); Rect2i r = p_rect; if (vertical) { @@ -1072,4 +1049,5 @@ StyleBoxLine::StyleBoxLine() { color = Color(0.0, 0.0, 0.0); vertical = false; } + StyleBoxLine::~StyleBoxLine() {} diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h index 3e0fffdcd9..3d29e3bd0f 100644 --- a/scene/resources/style_box.h +++ b/scene/resources/style_box.h @@ -33,12 +33,11 @@ #include "core/resource.h" #include "scene/resources/texture.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" class CanvasItem; class StyleBox : public Resource { - GDCLASS(StyleBox, Resource); RES_BASE_EXTENSION("stylebox"); OBJ_SAVE_TYPE(StyleBox); @@ -68,17 +67,15 @@ public: }; class StyleBoxEmpty : public StyleBox { - GDCLASS(StyleBoxEmpty, StyleBox); - virtual float get_style_margin(Margin p_margin) const { return 0; } + virtual float get_style_margin(Margin p_margin) const override { return 0; } public: - virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const {} + virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const override {} StyleBoxEmpty() {} }; class StyleBoxTexture : public StyleBox { - GDCLASS(StyleBoxTexture, StyleBox); public: @@ -92,15 +89,15 @@ private: float expand_margin[4]; float margin[4]; Rect2 region_rect; - Ref<Texture> texture; - Ref<Texture> normal_map; + Ref<Texture2D> texture; + Ref<Texture2D> normal_map; bool draw_center; Color modulate; AxisStretchMode axis_h; AxisStretchMode axis_v; protected: - virtual float get_style_margin(Margin p_margin) const; + virtual float get_style_margin(Margin p_margin) const override; static void _bind_methods(); public: @@ -115,15 +112,15 @@ public: void set_region_rect(const Rect2 &p_region_rect); Rect2 get_region_rect() const; - void set_texture(Ref<Texture> p_texture); - Ref<Texture> get_texture() const; + void set_texture(Ref<Texture2D> p_texture); + Ref<Texture2D> get_texture() const; - void set_normal_map(Ref<Texture> p_normal_map); - Ref<Texture> get_normal_map() const; + void set_normal_map(Ref<Texture2D> p_normal_map); + Ref<Texture2D> get_normal_map() const; void set_draw_center(bool p_enabled); bool is_draw_center_enabled() const; - virtual Size2 get_center_size() const; + virtual Size2 get_center_size() const override; void set_h_axis_stretch_mode(AxisStretchMode p_mode); AxisStretchMode get_h_axis_stretch_mode() const; @@ -134,8 +131,8 @@ public: void set_modulate(const Color &p_modulate); Color get_modulate() const; - virtual Rect2 get_draw_rect(const Rect2 &p_rect) const; - virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const; + virtual Rect2 get_draw_rect(const Rect2 &p_rect) const override; + virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const override; StyleBoxTexture(); ~StyleBoxTexture(); @@ -144,7 +141,6 @@ public: VARIANT_ENUM_CAST(StyleBoxTexture::AxisStretchMode) class StyleBoxFlat : public StyleBox { - GDCLASS(StyleBoxFlat, StyleBox); Color bg_color; @@ -165,7 +161,7 @@ class StyleBoxFlat : public StyleBox { int aa_size; protected: - virtual float get_style_margin(Margin p_margin) const; + virtual float get_style_margin(Margin p_margin) const override; static void _bind_methods(); public: @@ -227,10 +223,10 @@ public: void set_aa_size(const int &p_aa_size); int get_aa_size() const; - virtual Size2 get_center_size() const; + virtual Size2 get_center_size() const override; - virtual Rect2 get_draw_rect(const Rect2 &p_rect) const; - virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const; + virtual Rect2 get_draw_rect(const Rect2 &p_rect) const override; + virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const override; StyleBoxFlat(); ~StyleBoxFlat(); @@ -238,7 +234,6 @@ public: // just used to draw lines. class StyleBoxLine : public StyleBox { - GDCLASS(StyleBoxLine, StyleBox); Color color; int thickness; @@ -247,7 +242,7 @@ class StyleBoxLine : public StyleBox { float grow_end; protected: - virtual float get_style_margin(Margin p_margin) const; + virtual float get_style_margin(Margin p_margin) const override; static void _bind_methods(); public: @@ -266,9 +261,9 @@ public: void set_grow_end(float p_grow); float get_grow_end() const; - virtual Size2 get_center_size() const; + virtual Size2 get_center_size() const override; - virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const; + virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const override; StyleBoxLine(); ~StyleBoxLine(); diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index f921a9695c..1a2dcc84bb 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -36,43 +36,50 @@ #define EQ_VERTEX_DIST 0.00001 bool SurfaceTool::Vertex::operator==(const Vertex &p_vertex) const { - - if (vertex != p_vertex.vertex) + if (vertex != p_vertex.vertex) { return false; + } - if (uv != p_vertex.uv) + if (uv != p_vertex.uv) { return false; + } - if (uv2 != p_vertex.uv2) + if (uv2 != p_vertex.uv2) { return false; + } - if (normal != p_vertex.normal) + if (normal != p_vertex.normal) { return false; + } - if (binormal != p_vertex.binormal) + if (binormal != p_vertex.binormal) { return false; + } - if (color != p_vertex.color) + if (color != p_vertex.color) { return false; + } - if (bones.size() != p_vertex.bones.size()) + if (bones.size() != p_vertex.bones.size()) { return false; + } for (int i = 0; i < bones.size(); i++) { - if (bones[i] != p_vertex.bones[i]) + if (bones[i] != p_vertex.bones[i]) { return false; + } } for (int i = 0; i < weights.size(); i++) { - if (weights[i] != p_vertex.weights[i]) + if (weights[i] != p_vertex.weights[i]) { return false; + } } return true; } uint32_t SurfaceTool::VertexHasher::hash(const Vertex &p_vtx) { - uint32_t h = hash_djb2_buffer((const uint8_t *)&p_vtx.vertex, sizeof(real_t) * 3); h = hash_djb2_buffer((const uint8_t *)&p_vtx.normal, sizeof(real_t) * 3, h); h = hash_djb2_buffer((const uint8_t *)&p_vtx.binormal, sizeof(real_t) * 3, h); @@ -86,7 +93,6 @@ uint32_t SurfaceTool::VertexHasher::hash(const Vertex &p_vtx) { } void SurfaceTool::begin(Mesh::PrimitiveType p_primitive) { - clear(); primitive = p_primitive; @@ -95,7 +101,6 @@ void SurfaceTool::begin(Mesh::PrimitiveType p_primitive) { } void SurfaceTool::add_vertex(const Vector3 &p_vertex) { - ERR_FAIL_COND(!begun); Vertex vtx; @@ -159,8 +164,8 @@ void SurfaceTool::add_vertex(const Vector3 &p_vertex) { format |= Mesh::ARRAY_FORMAT_VERTEX; } -void SurfaceTool::add_color(Color p_color) { +void SurfaceTool::add_color(Color p_color) { ERR_FAIL_COND(!begun); ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_COLOR)); @@ -168,8 +173,8 @@ void SurfaceTool::add_color(Color p_color) { format |= Mesh::ARRAY_FORMAT_COLOR; last_color = p_color; } -void SurfaceTool::add_normal(const Vector3 &p_normal) { +void SurfaceTool::add_normal(const Vector3 &p_normal) { ERR_FAIL_COND(!begun); ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_NORMAL)); @@ -179,7 +184,6 @@ void SurfaceTool::add_normal(const Vector3 &p_normal) { } void SurfaceTool::add_tangent(const Plane &p_tangent) { - ERR_FAIL_COND(!begun); ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_TANGENT)); @@ -188,7 +192,6 @@ void SurfaceTool::add_tangent(const Plane &p_tangent) { } void SurfaceTool::add_uv(const Vector2 &p_uv) { - ERR_FAIL_COND(!begun); ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_TEX_UV)); @@ -197,7 +200,6 @@ void SurfaceTool::add_uv(const Vector2 &p_uv) { } void SurfaceTool::add_uv2(const Vector2 &p_uv2) { - ERR_FAIL_COND(!begun); ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_TEX_UV2)); @@ -206,7 +208,6 @@ void SurfaceTool::add_uv2(const Vector2 &p_uv2) { } void SurfaceTool::add_bones(const Vector<int> &p_bones) { - ERR_FAIL_COND(!begun); ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_BONES)); @@ -215,7 +216,6 @@ void SurfaceTool::add_bones(const Vector<int> &p_bones) { } void SurfaceTool::add_weights(const Vector<float> &p_weights) { - ERR_FAIL_COND(!begun); ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_WEIGHTS)); @@ -224,12 +224,10 @@ void SurfaceTool::add_weights(const Vector<float> &p_weights) { } void SurfaceTool::add_smooth_group(bool p_smooth) { - ERR_FAIL_COND(!begun); if (index_array.size()) { smooth_groups[index_array.size()] = p_smooth; } else { - smooth_groups[vertex_array.size()] = p_smooth; } } @@ -264,7 +262,6 @@ void SurfaceTool::add_triangle_fan(const Vector<Vector3> &p_vertices, const Vect } void SurfaceTool::add_index(int p_index) { - ERR_FAIL_COND(!begun); format |= Mesh::ARRAY_FORMAT_INDEX; @@ -272,29 +269,25 @@ void SurfaceTool::add_index(int p_index) { } Array SurfaceTool::commit_to_arrays() { - int varr_len = vertex_array.size(); Array a; a.resize(Mesh::ARRAY_MAX); for (int i = 0; i < Mesh::ARRAY_MAX; i++) { - - if (!(format & (1 << i))) + if (!(format & (1 << i))) { continue; //not in format + } switch (i) { - case Mesh::ARRAY_VERTEX: case Mesh::ARRAY_NORMAL: { - - PoolVector<Vector3> array; + Vector<Vector3> array; array.resize(varr_len); - PoolVector<Vector3>::Write w = array.write(); + Vector3 *w = array.ptrw(); int idx = 0; for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) { - const Vertex &v = E->get(); switch (i) { @@ -307,25 +300,21 @@ Array SurfaceTool::commit_to_arrays() { } } - w.release(); a[i] = array; } break; case Mesh::ARRAY_TEX_UV: case Mesh::ARRAY_TEX_UV2: { - - PoolVector<Vector2> array; + Vector<Vector2> array; array.resize(varr_len); - PoolVector<Vector2>::Write w = array.write(); + Vector2 *w = array.ptrw(); int idx = 0; for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) { - const Vertex &v = E->get(); switch (i) { - case Mesh::ARRAY_TEX_UV: { w[idx] = v.uv; } break; @@ -335,18 +324,15 @@ Array SurfaceTool::commit_to_arrays() { } } - w.release(); a[i] = array; } break; case Mesh::ARRAY_TANGENT: { - - PoolVector<float> array; + Vector<float> array; array.resize(varr_len * 4); - PoolVector<float>::Write w = array.write(); + float *w = array.ptrw(); int idx = 0; for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx += 4) { - const Vertex &v = E->get(); w[idx + 0] = v.tangent.x; @@ -358,35 +344,29 @@ Array SurfaceTool::commit_to_arrays() { w[idx + 3] = d < 0 ? -1 : 1; } - w.release(); a[i] = array; } break; case Mesh::ARRAY_COLOR: { - - PoolVector<Color> array; + Vector<Color> array; array.resize(varr_len); - PoolVector<Color>::Write w = array.write(); + Color *w = array.ptrw(); int idx = 0; for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx++) { - const Vertex &v = E->get(); w[idx] = v.color; } - w.release(); a[i] = array; } break; case Mesh::ARRAY_BONES: { - - PoolVector<int> array; + Vector<int> array; array.resize(varr_len * 4); - PoolVector<int>::Write w = array.write(); + int *w = array.ptrw(); int idx = 0; for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx += 4) { - const Vertex &v = E->get(); ERR_CONTINUE(v.bones.size() != 4); @@ -396,48 +376,39 @@ Array SurfaceTool::commit_to_arrays() { } } - w.release(); a[i] = array; } break; case Mesh::ARRAY_WEIGHTS: { - - PoolVector<float> array; + Vector<float> array; array.resize(varr_len * 4); - PoolVector<float>::Write w = array.write(); + float *w = array.ptrw(); int idx = 0; for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next(), idx += 4) { - const Vertex &v = E->get(); ERR_CONTINUE(v.weights.size() != 4); for (int j = 0; j < 4; j++) { - w[idx + j] = v.weights[j]; } } - w.release(); a[i] = array; } break; case Mesh::ARRAY_INDEX: { - ERR_CONTINUE(index_array.size() == 0); - PoolVector<int> array; + Vector<int> array; array.resize(index_array.size()); - PoolVector<int>::Write w = array.write(); + int *w = array.ptrw(); int idx = 0; for (List<int>::Element *E = index_array.front(); E; E = E->next(), idx++) { - w[idx] = E->get(); } - w.release(); - a[i] = array; } break; @@ -450,40 +421,41 @@ Array SurfaceTool::commit_to_arrays() { } Ref<ArrayMesh> SurfaceTool::commit(const Ref<ArrayMesh> &p_existing, uint32_t p_flags) { - Ref<ArrayMesh> mesh; - if (p_existing.is_valid()) + if (p_existing.is_valid()) { mesh = p_existing; - else + } else { mesh.instance(); + } int varr_len = vertex_array.size(); - if (varr_len == 0) + if (varr_len == 0) { return mesh; + } int surface = mesh->get_surface_count(); Array a = commit_to_arrays(); - mesh->add_surface_from_arrays(primitive, a, Array(), p_flags); + mesh->add_surface_from_arrays(primitive, a, Array(), Dictionary(), p_flags); - if (material.is_valid()) + if (material.is_valid()) { mesh->surface_set_material(surface, material); + } return mesh; } void SurfaceTool::index() { - - if (index_array.size()) + if (index_array.size()) { return; //already indexed + } HashMap<Vertex, int, VertexHasher> indices; List<Vertex> new_vertices; for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next()) { - int *idxptr = indices.getptr(E->get()); int idx; if (!idxptr) { @@ -504,19 +476,17 @@ void SurfaceTool::index() { } void SurfaceTool::deindex() { - - if (index_array.size() == 0) + if (index_array.size() == 0) { return; //nothing to deindex + } Vector<Vertex> varr; varr.resize(vertex_array.size()); int idx = 0; for (List<Vertex>::Element *E = vertex_array.front(); E; E = E->next()) { - varr.write[idx++] = E->get(); } vertex_array.clear(); for (List<int>::Element *E = index_array.front(); E; E = E->next()) { - ERR_FAIL_INDEX(E->get(), varr.size()); vertex_array.push_back(varr[E->get()]); } @@ -525,95 +495,77 @@ void SurfaceTool::deindex() { } void SurfaceTool::_create_list(const Ref<Mesh> &p_existing, int p_surface, List<Vertex> *r_vertex, List<int> *r_index, int &lformat) { - Array arr = p_existing->surface_get_arrays(p_surface); - ERR_FAIL_COND(arr.size() != VS::ARRAY_MAX); + ERR_FAIL_COND(arr.size() != RS::ARRAY_MAX); _create_list_from_arrays(arr, r_vertex, r_index, lformat); } Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_arrays(const Array &p_arrays) { - Vector<SurfaceTool::Vertex> ret; - PoolVector<Vector3> varr = p_arrays[VS::ARRAY_VERTEX]; - PoolVector<Vector3> narr = p_arrays[VS::ARRAY_NORMAL]; - PoolVector<float> tarr = p_arrays[VS::ARRAY_TANGENT]; - PoolVector<Color> carr = p_arrays[VS::ARRAY_COLOR]; - PoolVector<Vector2> uvarr = p_arrays[VS::ARRAY_TEX_UV]; - PoolVector<Vector2> uv2arr = p_arrays[VS::ARRAY_TEX_UV2]; - PoolVector<int> barr = p_arrays[VS::ARRAY_BONES]; - PoolVector<float> warr = p_arrays[VS::ARRAY_WEIGHTS]; + Vector<Vector3> varr = p_arrays[RS::ARRAY_VERTEX]; + Vector<Vector3> narr = p_arrays[RS::ARRAY_NORMAL]; + Vector<float> tarr = p_arrays[RS::ARRAY_TANGENT]; + Vector<Color> carr = p_arrays[RS::ARRAY_COLOR]; + Vector<Vector2> uvarr = p_arrays[RS::ARRAY_TEX_UV]; + Vector<Vector2> uv2arr = p_arrays[RS::ARRAY_TEX_UV2]; + Vector<int> barr = p_arrays[RS::ARRAY_BONES]; + Vector<float> warr = p_arrays[RS::ARRAY_WEIGHTS]; int vc = varr.size(); - - if (vc == 0) + if (vc == 0) { return ret; - int lformat = 0; + } - PoolVector<Vector3>::Read rv; + int lformat = 0; if (varr.size()) { - lformat |= VS::ARRAY_FORMAT_VERTEX; - rv = varr.read(); + lformat |= RS::ARRAY_FORMAT_VERTEX; } - PoolVector<Vector3>::Read rn; if (narr.size()) { - lformat |= VS::ARRAY_FORMAT_NORMAL; - rn = narr.read(); + lformat |= RS::ARRAY_FORMAT_NORMAL; } - PoolVector<float>::Read rt; if (tarr.size()) { - lformat |= VS::ARRAY_FORMAT_TANGENT; - rt = tarr.read(); + lformat |= RS::ARRAY_FORMAT_TANGENT; } - PoolVector<Color>::Read rc; if (carr.size()) { - lformat |= VS::ARRAY_FORMAT_COLOR; - rc = carr.read(); + lformat |= RS::ARRAY_FORMAT_COLOR; } - - PoolVector<Vector2>::Read ruv; if (uvarr.size()) { - lformat |= VS::ARRAY_FORMAT_TEX_UV; - ruv = uvarr.read(); + lformat |= RS::ARRAY_FORMAT_TEX_UV; } - - PoolVector<Vector2>::Read ruv2; if (uv2arr.size()) { - lformat |= VS::ARRAY_FORMAT_TEX_UV2; - ruv2 = uv2arr.read(); + lformat |= RS::ARRAY_FORMAT_TEX_UV2; } - - PoolVector<int>::Read rb; if (barr.size()) { - lformat |= VS::ARRAY_FORMAT_BONES; - rb = barr.read(); + lformat |= RS::ARRAY_FORMAT_BONES; } - - PoolVector<float>::Read rw; if (warr.size()) { - lformat |= VS::ARRAY_FORMAT_WEIGHTS; - rw = warr.read(); + lformat |= RS::ARRAY_FORMAT_WEIGHTS; } for (int i = 0; i < vc; i++) { - Vertex v; - if (lformat & VS::ARRAY_FORMAT_VERTEX) + if (lformat & RS::ARRAY_FORMAT_VERTEX) { v.vertex = varr[i]; - if (lformat & VS::ARRAY_FORMAT_NORMAL) + } + if (lformat & RS::ARRAY_FORMAT_NORMAL) { v.normal = narr[i]; - if (lformat & VS::ARRAY_FORMAT_TANGENT) { + } + if (lformat & RS::ARRAY_FORMAT_TANGENT) { Plane p(tarr[i * 4 + 0], tarr[i * 4 + 1], tarr[i * 4 + 2], tarr[i * 4 + 3]); v.tangent = p.normal; v.binormal = p.normal.cross(v.tangent).normalized() * p.d; } - if (lformat & VS::ARRAY_FORMAT_COLOR) + if (lformat & RS::ARRAY_FORMAT_COLOR) { v.color = carr[i]; - if (lformat & VS::ARRAY_FORMAT_TEX_UV) + } + if (lformat & RS::ARRAY_FORMAT_TEX_UV) { v.uv = uvarr[i]; - if (lformat & VS::ARRAY_FORMAT_TEX_UV2) + } + if (lformat & RS::ARRAY_FORMAT_TEX_UV2) { v.uv2 = uv2arr[i]; - if (lformat & VS::ARRAY_FORMAT_BONES) { + } + if (lformat & RS::ARRAY_FORMAT_BONES) { Vector<int> b; b.resize(4); b.write[0] = barr[i * 4 + 0]; @@ -622,7 +574,7 @@ Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_array b.write[3] = barr[i * 4 + 3]; v.bones = b; } - if (lformat & VS::ARRAY_FORMAT_WEIGHTS) { + if (lformat & RS::ARRAY_FORMAT_WEIGHTS) { Vector<float> w; w.resize(4); w.write[0] = warr[i * 4 + 0]; @@ -639,86 +591,69 @@ Vector<SurfaceTool::Vertex> SurfaceTool::create_vertex_array_from_triangle_array } void SurfaceTool::_create_list_from_arrays(Array arr, List<Vertex> *r_vertex, List<int> *r_index, int &lformat) { - - PoolVector<Vector3> varr = arr[VS::ARRAY_VERTEX]; - PoolVector<Vector3> narr = arr[VS::ARRAY_NORMAL]; - PoolVector<float> tarr = arr[VS::ARRAY_TANGENT]; - PoolVector<Color> carr = arr[VS::ARRAY_COLOR]; - PoolVector<Vector2> uvarr = arr[VS::ARRAY_TEX_UV]; - PoolVector<Vector2> uv2arr = arr[VS::ARRAY_TEX_UV2]; - PoolVector<int> barr = arr[VS::ARRAY_BONES]; - PoolVector<float> warr = arr[VS::ARRAY_WEIGHTS]; + Vector<Vector3> varr = arr[RS::ARRAY_VERTEX]; + Vector<Vector3> narr = arr[RS::ARRAY_NORMAL]; + Vector<float> tarr = arr[RS::ARRAY_TANGENT]; + Vector<Color> carr = arr[RS::ARRAY_COLOR]; + Vector<Vector2> uvarr = arr[RS::ARRAY_TEX_UV]; + Vector<Vector2> uv2arr = arr[RS::ARRAY_TEX_UV2]; + Vector<int> barr = arr[RS::ARRAY_BONES]; + Vector<float> warr = arr[RS::ARRAY_WEIGHTS]; int vc = varr.size(); - - if (vc == 0) + if (vc == 0) { return; - lformat = 0; + } - PoolVector<Vector3>::Read rv; + lformat = 0; if (varr.size()) { - lformat |= VS::ARRAY_FORMAT_VERTEX; - rv = varr.read(); + lformat |= RS::ARRAY_FORMAT_VERTEX; } - PoolVector<Vector3>::Read rn; if (narr.size()) { - lformat |= VS::ARRAY_FORMAT_NORMAL; - rn = narr.read(); + lformat |= RS::ARRAY_FORMAT_NORMAL; } - PoolVector<float>::Read rt; if (tarr.size()) { - lformat |= VS::ARRAY_FORMAT_TANGENT; - rt = tarr.read(); + lformat |= RS::ARRAY_FORMAT_TANGENT; } - PoolVector<Color>::Read rc; if (carr.size()) { - lformat |= VS::ARRAY_FORMAT_COLOR; - rc = carr.read(); + lformat |= RS::ARRAY_FORMAT_COLOR; } - - PoolVector<Vector2>::Read ruv; if (uvarr.size()) { - lformat |= VS::ARRAY_FORMAT_TEX_UV; - ruv = uvarr.read(); + lformat |= RS::ARRAY_FORMAT_TEX_UV; } - - PoolVector<Vector2>::Read ruv2; if (uv2arr.size()) { - lformat |= VS::ARRAY_FORMAT_TEX_UV2; - ruv2 = uv2arr.read(); + lformat |= RS::ARRAY_FORMAT_TEX_UV2; } - - PoolVector<int>::Read rb; if (barr.size()) { - lformat |= VS::ARRAY_FORMAT_BONES; - rb = barr.read(); + lformat |= RS::ARRAY_FORMAT_BONES; } - - PoolVector<float>::Read rw; if (warr.size()) { - lformat |= VS::ARRAY_FORMAT_WEIGHTS; - rw = warr.read(); + lformat |= RS::ARRAY_FORMAT_WEIGHTS; } for (int i = 0; i < vc; i++) { - Vertex v; - if (lformat & VS::ARRAY_FORMAT_VERTEX) + if (lformat & RS::ARRAY_FORMAT_VERTEX) { v.vertex = varr[i]; - if (lformat & VS::ARRAY_FORMAT_NORMAL) + } + if (lformat & RS::ARRAY_FORMAT_NORMAL) { v.normal = narr[i]; - if (lformat & VS::ARRAY_FORMAT_TANGENT) { + } + if (lformat & RS::ARRAY_FORMAT_TANGENT) { Plane p(tarr[i * 4 + 0], tarr[i * 4 + 1], tarr[i * 4 + 2], tarr[i * 4 + 3]); v.tangent = p.normal; v.binormal = p.normal.cross(v.tangent).normalized() * p.d; } - if (lformat & VS::ARRAY_FORMAT_COLOR) + if (lformat & RS::ARRAY_FORMAT_COLOR) { v.color = carr[i]; - if (lformat & VS::ARRAY_FORMAT_TEX_UV) + } + if (lformat & RS::ARRAY_FORMAT_TEX_UV) { v.uv = uvarr[i]; - if (lformat & VS::ARRAY_FORMAT_TEX_UV2) + } + if (lformat & RS::ARRAY_FORMAT_TEX_UV2) { v.uv2 = uv2arr[i]; - if (lformat & VS::ARRAY_FORMAT_BONES) { + } + if (lformat & RS::ARRAY_FORMAT_BONES) { Vector<int> b; b.resize(4); b.write[0] = barr[i * 4 + 0]; @@ -727,7 +662,7 @@ void SurfaceTool::_create_list_from_arrays(Array arr, List<Vertex> *r_vertex, Li b.write[3] = barr[i * 4 + 3]; v.bones = b; } - if (lformat & VS::ARRAY_FORMAT_WEIGHTS) { + if (lformat & RS::ARRAY_FORMAT_WEIGHTS) { Vector<float> w; w.resize(4); w.write[0] = warr[i * 4 + 0]; @@ -742,12 +677,11 @@ void SurfaceTool::_create_list_from_arrays(Array arr, List<Vertex> *r_vertex, Li //indices - PoolVector<int> idx = arr[VS::ARRAY_INDEX]; + Vector<int> idx = arr[RS::ARRAY_INDEX]; int is = idx.size(); if (is) { - - lformat |= VS::ARRAY_FORMAT_INDEX; - PoolVector<int>::Read iarr = idx.read(); + lformat |= RS::ARRAY_FORMAT_INDEX; + const int *iarr = idx.ptr(); for (int i = 0; i < is; i++) { r_index->push_back(iarr[i]); } @@ -755,14 +689,12 @@ void SurfaceTool::_create_list_from_arrays(Array arr, List<Vertex> *r_vertex, Li } void SurfaceTool::create_from_triangle_arrays(const Array &p_arrays) { - clear(); primitive = Mesh::PRIMITIVE_TRIANGLES; _create_list_from_arrays(p_arrays, &vertex_array, &index_array, format); } void SurfaceTool::create_from(const Ref<Mesh> &p_existing, int p_surface) { - clear(); primitive = p_existing->surface_get_primitive_type(p_surface); _create_list(p_existing, p_surface, &vertex_array, &index_array, format); @@ -785,12 +717,11 @@ void SurfaceTool::create_from_blend_shape(const Ref<Mesh> &p_existing, int p_sur ERR_FAIL_COND(shape_idx == -1); ERR_FAIL_COND(shape_idx >= arr.size()); Array mesh = arr[shape_idx]; - ERR_FAIL_COND(mesh.size() != VS::ARRAY_MAX); + ERR_FAIL_COND(mesh.size() != RS::ARRAY_MAX); _create_list_from_arrays(arr[shape_idx], &vertex_array, &index_array, format); } void SurfaceTool::append_from(const Ref<Mesh> &p_existing, int p_surface, const Transform &p_xform) { - if (vertex_array.size() == 0) { primitive = p_existing->surface_get_primitive_type(p_surface); format = 0; @@ -804,13 +735,12 @@ void SurfaceTool::append_from(const Ref<Mesh> &p_existing, int p_surface, const int vfrom = vertex_array.size(); for (List<Vertex>::Element *E = nvertices.front(); E; E = E->next()) { - Vertex v = E->get(); v.vertex = p_xform.xform(v.vertex); - if (nformat & VS::ARRAY_FORMAT_NORMAL) { + if (nformat & RS::ARRAY_FORMAT_NORMAL) { v.normal = p_xform.basis.xform(v.normal); } - if (nformat & VS::ARRAY_FORMAT_TANGENT) { + if (nformat & RS::ARRAY_FORMAT_TANGENT) { v.tangent = p_xform.basis.xform(v.tangent); v.binormal = p_xform.basis.xform(v.binormal); } @@ -819,7 +749,6 @@ void SurfaceTool::append_from(const Ref<Mesh> &p_existing, int p_surface, const } for (List<int>::Element *E = nindices.front(); E; E = E->next()) { - int dst_index = E->get() + vfrom; index_array.push_back(dst_index); } @@ -837,7 +766,6 @@ struct TangentGenerationContextUserData { } // namespace int SurfaceTool::mikktGetNumFaces(const SMikkTSpaceContext *pContext) { - TangentGenerationContextUserData &triangle_data = *reinterpret_cast<TangentGenerationContextUserData *>(pContext->m_pUserData); if (triangle_data.indices.size() > 0) { @@ -846,12 +774,12 @@ int SurfaceTool::mikktGetNumFaces(const SMikkTSpaceContext *pContext) { return triangle_data.vertices.size() / 3; } } -int SurfaceTool::mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace) { +int SurfaceTool::mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace) { return 3; //always 3 } -void SurfaceTool::mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert) { +void SurfaceTool::mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert) { TangentGenerationContextUserData &triangle_data = *reinterpret_cast<TangentGenerationContextUserData *>(pContext->m_pUserData); Vector3 v; if (triangle_data.indices.size() > 0) { @@ -869,7 +797,6 @@ void SurfaceTool::mikktGetPosition(const SMikkTSpaceContext *pContext, float fvP } void SurfaceTool::mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert) { - TangentGenerationContextUserData &triangle_data = *reinterpret_cast<TangentGenerationContextUserData *>(pContext->m_pUserData); Vector3 v; if (triangle_data.indices.size() > 0) { @@ -885,8 +812,8 @@ void SurfaceTool::mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNor fvNormOut[1] = v.y; fvNormOut[2] = v.z; } -void SurfaceTool::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert) { +void SurfaceTool::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert) { TangentGenerationContextUserData &triangle_data = *reinterpret_cast<TangentGenerationContextUserData *>(pContext->m_pUserData); Vector2 v; if (triangle_data.indices.size() > 0) { @@ -904,9 +831,8 @@ void SurfaceTool::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvT void SurfaceTool::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT, const tbool bIsOrientationPreserving, const int iFace, const int iVert) { - TangentGenerationContextUserData &triangle_data = *reinterpret_cast<TangentGenerationContextUserData *>(pContext->m_pUserData); - Vertex *vtx = NULL; + Vertex *vtx = nullptr; if (triangle_data.indices.size() > 0) { int index = triangle_data.indices[iFace * 3 + iVert]->get(); if (index < triangle_data.vertices.size()) { @@ -916,14 +842,13 @@ void SurfaceTool::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, cons vtx = &triangle_data.vertices[iFace * 3 + iVert]->get(); } - if (vtx != NULL) { + if (vtx != nullptr) { vtx->tangent = Vector3(fvTangent[0], fvTangent[1], fvTangent[2]); vtx->binormal = Vector3(-fvBiTangent[0], -fvBiTangent[1], -fvBiTangent[2]); // for some reason these are reversed, something with the coordinate system in Godot } } void SurfaceTool::generate_tangents() { - ERR_FAIL_COND(!(format & Mesh::ARRAY_FORMAT_TEX_UV)); ERR_FAIL_COND(!(format & Mesh::ARRAY_FORMAT_NORMAL)); @@ -934,7 +859,7 @@ void SurfaceTool::generate_tangents() { mkif.m_getPosition = mikktGetPosition; mkif.m_getTexCoord = mikktGetTexCoord; mkif.m_setTSpace = mikktSetTSpaceDefault; - mkif.m_setTSpaceBasic = NULL; + mkif.m_setTSpaceBasic = nullptr; SMikkTSpaceContext msc; msc.m_pInterface = &mkif; @@ -961,7 +886,6 @@ void SurfaceTool::generate_tangents() { } void SurfaceTool::generate_normals(bool p_flip) { - ERR_FAIL_COND(primitive != Mesh::PRIMITIVE_TRIANGLES); bool was_indexed = index_array.size(); @@ -972,12 +896,12 @@ void SurfaceTool::generate_normals(bool p_flip) { int count = 0; bool smooth = false; - if (smooth_groups.has(0)) + if (smooth_groups.has(0)) { smooth = smooth_groups[0]; + } List<Vertex>::Element *B = vertex_array.front(); for (List<Vertex>::Element *E = B; E;) { - List<Vertex>::Element *v[3]; v[0] = E; v[1] = v[0]->next(); @@ -987,15 +911,14 @@ void SurfaceTool::generate_normals(bool p_flip) { E = v[2]->next(); Vector3 normal; - if (!p_flip) + if (!p_flip) { normal = Plane(v[0]->get().vertex, v[1]->get().vertex, v[2]->get().vertex).normal; - else + } else { normal = Plane(v[2]->get().vertex, v[1]->get().vertex, v[0]->get().vertex).normal; + } if (smooth) { - for (int i = 0; i < 3; i++) { - Vector3 *lv = vertex_hash.getptr(v[i]->get()); if (!lv) { vertex_hash.set(v[i]->get(), normal); @@ -1004,20 +927,15 @@ void SurfaceTool::generate_normals(bool p_flip) { } } } else { - for (int i = 0; i < 3; i++) { - v[i]->get().normal = normal; } } count += 3; if (smooth_groups.has(count) || !E) { - if (vertex_hash.size()) { - while (B != E) { - Vector3 *lv = vertex_hash.getptr(B->get()); if (lv) { B->get().normal = lv->normalized(); @@ -1046,12 +964,10 @@ void SurfaceTool::generate_normals(bool p_flip) { } void SurfaceTool::set_material(const Ref<Material> &p_material) { - material = p_material; } void SurfaceTool::clear() { - begun = false; primitive = Mesh::PRIMITIVE_LINES; format = 0; @@ -1064,7 +980,6 @@ void SurfaceTool::clear() { } void SurfaceTool::_bind_methods() { - ClassDB::bind_method(D_METHOD("begin", "primitive"), &SurfaceTool::begin); ClassDB::bind_method(D_METHOD("add_vertex", "vertex"), &SurfaceTool::add_vertex); @@ -1098,7 +1013,6 @@ void SurfaceTool::_bind_methods() { } SurfaceTool::SurfaceTool() { - first = false; begun = false; primitive = Mesh::PRIMITIVE_LINES; diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index 89034f656d..d7b255e695 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -36,12 +36,10 @@ #include "thirdparty/misc/mikktspace.h" class SurfaceTool : public Reference { - GDCLASS(SurfaceTool, Reference); public: struct Vertex { - Vector3 vertex; Color color; Vector3 normal; // normal, binormal, tangent diff --git a/scene/resources/syntax_highlighter.cpp b/scene/resources/syntax_highlighter.cpp new file mode 100644 index 0000000000..5d58e71fc5 --- /dev/null +++ b/scene/resources/syntax_highlighter.cpp @@ -0,0 +1,636 @@ +/*************************************************************************/ +/* syntax_highlighter.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "syntax_highlighter.h" + +#include "core/script_language.h" +#include "scene/gui/text_edit.h" + +Dictionary SyntaxHighlighter::get_line_syntax_highlighting(int p_line) { + if (highlighting_cache.has(p_line)) { + return highlighting_cache[p_line]; + } + + Dictionary color_map; + if (text_edit == nullptr) { + return color_map; + } + + ScriptInstance *si = get_script_instance(); + if (si && si->has_method("_get_line_syntax_highlighting")) { + color_map = si->call("_get_line_syntax_highlighting", p_line); + } else { + color_map = _get_line_syntax_highlighting(p_line); + } + highlighting_cache[p_line] = color_map; + return color_map; +} + +void SyntaxHighlighter::_lines_edited_from(int p_from_line, int p_to_line) { + if (highlighting_cache.size() < 1) { + return; + } + + int cache_size = highlighting_cache.back()->key(); + for (int i = MIN(p_from_line, p_to_line) - 1; i <= cache_size; i++) { + if (highlighting_cache.has(i)) { + highlighting_cache.erase(i); + } + } +} + +void SyntaxHighlighter::clear_highlighting_cache() { + highlighting_cache.clear(); + + ScriptInstance *si = get_script_instance(); + if (si && si->has_method("_clear_highlighting_cache")) { + si->call("_clear_highlighting_cache"); + return; + } + _clear_highlighting_cache(); +} + +void SyntaxHighlighter::update_cache() { + clear_highlighting_cache(); + + if (text_edit == nullptr) { + return; + } + ScriptInstance *si = get_script_instance(); + if (si && si->has_method("_update_cache")) { + si->call("_update_cache"); + return; + } + _update_cache(); +} + +void SyntaxHighlighter::set_text_edit(TextEdit *p_text_edit) { + if (text_edit && ObjectDB::get_instance(text_edit_instance_id)) { + text_edit->disconnect("lines_edited_from", callable_mp(this, &SyntaxHighlighter::_lines_edited_from)); + } + + text_edit = p_text_edit; + if (p_text_edit == nullptr) { + return; + } + text_edit_instance_id = text_edit->get_instance_id(); + text_edit->connect("lines_edited_from", callable_mp(this, &SyntaxHighlighter::_lines_edited_from)); + update_cache(); +} + +TextEdit *SyntaxHighlighter::get_text_edit() { + return text_edit; +} + +void SyntaxHighlighter::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_line_syntax_highlighting", "p_line"), &SyntaxHighlighter::get_line_syntax_highlighting); + ClassDB::bind_method(D_METHOD("update_cache"), &SyntaxHighlighter::update_cache); + ClassDB::bind_method(D_METHOD("clear_highlighting_cache"), &SyntaxHighlighter::clear_highlighting_cache); + ClassDB::bind_method(D_METHOD("get_text_edit"), &SyntaxHighlighter::get_text_edit); + + ClassDB::bind_method(D_METHOD("_get_line_syntax_highlighting", "p_line"), &SyntaxHighlighter::_get_line_syntax_highlighting); + ClassDB::bind_method(D_METHOD("_update_cache"), &SyntaxHighlighter::_update_cache); + ClassDB::bind_method(D_METHOD("_clear_highlighting_cache"), &SyntaxHighlighter::_clear_highlighting_cache); + + BIND_VMETHOD(MethodInfo(Variant::DICTIONARY, "_get_line_syntax_highlighting", PropertyInfo(Variant::INT, "p_line"))); + BIND_VMETHOD(MethodInfo("_update_cache")); +} + +//////////////////////////////////////////////////////////////////////////////// + +static bool _is_char(char32_t c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; +} + +static bool _is_hex_symbol(char32_t c) { + return ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); +} + +Dictionary CodeHighlighter::_get_line_syntax_highlighting(int p_line) { + Dictionary color_map; + + bool prev_is_char = false; + bool prev_is_number = false; + bool in_keyword = false; + bool in_word = false; + bool in_function_name = false; + bool in_member_variable = false; + bool is_hex_notation = false; + Color keyword_color; + Color color; + + color_region_cache[p_line] = -1; + int in_region = -1; + if (p_line != 0) { + if (!color_region_cache.has(p_line - 1)) { + get_line_syntax_highlighting(p_line - 1); + } + in_region = color_region_cache[p_line - 1]; + } + + const String &str = text_edit->get_line(p_line); + const int line_length = str.length(); + Color prev_color; + + if (in_region != -1 && str.length() == 0) { + color_region_cache[p_line] = in_region; + } + for (int j = 0; j < line_length; j++) { + Dictionary highlighter_info; + + color = font_color; + bool is_char = !is_symbol(str[j]); + bool is_a_symbol = is_symbol(str[j]); + bool is_number = (str[j] >= '0' && str[j] <= '9'); + + /* color regions */ + if (is_a_symbol || in_region != -1) { + int from = j; + for (; from < line_length; from++) { + if (str[from] == '\\') { + from++; + continue; + } + break; + } + + if (from != line_length) { + /* check if we are in entering a region */ + if (in_region == -1) { + for (int c = 0; c < color_regions.size(); c++) { + /* check there is enough room */ + int chars_left = line_length - from; + int start_key_length = color_regions[c].start_key.length(); + int end_key_length = color_regions[c].end_key.length(); + if (chars_left < start_key_length) { + continue; + } + + /* search the line */ + bool match = true; + const char32_t *start_key = color_regions[c].start_key.get_data(); + for (int k = 0; k < start_key_length; k++) { + if (start_key[k] != str[from + k]) { + match = false; + break; + } + } + if (!match) { + continue; + } + in_region = c; + from += start_key_length; + + /* check if it's the whole line */ + if (end_key_length == 0 || color_regions[c].line_only || from + end_key_length > line_length) { + prev_color = color_regions[in_region].color; + highlighter_info["color"] = color_regions[c].color; + color_map[j] = highlighter_info; + + j = line_length; + if (!color_regions[c].line_only) { + color_region_cache[p_line] = c; + } + } + break; + } + + if (j == line_length) { + continue; + } + } + + /* if we are in one find the end key */ + if (in_region != -1) { + /* search the line */ + int region_end_index = -1; + int end_key_length = color_regions[in_region].end_key.length(); + const char32_t *end_key = color_regions[in_region].end_key.get_data(); + for (; from < line_length; from++) { + if (line_length - from < end_key_length) { + break; + } + + if (!is_symbol(str[from])) { + continue; + } + + if (str[from] == '\\') { + from++; + continue; + } + + region_end_index = from; + for (int k = 0; k < end_key_length; k++) { + if (end_key[k] != str[from + k]) { + region_end_index = -1; + break; + } + } + + if (region_end_index != -1) { + break; + } + } + + prev_color = color_regions[in_region].color; + highlighter_info["color"] = color_regions[in_region].color; + color_map[j] = highlighter_info; + + j = from + (end_key_length - 1); + if (region_end_index == -1) { + color_region_cache[p_line] = in_region; + } + + in_region = -1; + prev_is_char = false; + prev_is_number = false; + continue; + } + } + } + + // Allow ABCDEF in hex notation. + if (is_hex_notation && (_is_hex_symbol(str[j]) || is_number)) { + is_number = true; + } else { + is_hex_notation = false; + } + + // Check for dot or underscore or 'x' for hex notation in floating point number or 'e' for scientific notation. + if ((str[j] == '.' || str[j] == 'x' || str[j] == '_' || str[j] == 'f' || str[j] == 'e') && !in_word && prev_is_number && !is_number) { + is_number = true; + is_a_symbol = false; + is_char = false; + + if (str[j] == 'x' && str[j - 1] == '0') { + is_hex_notation = true; + } + } + + if (!in_word && _is_char(str[j]) && !is_number) { + in_word = true; + } + + if ((in_keyword || in_word) && !is_hex_notation) { + is_number = false; + } + + if (is_a_symbol && str[j] != '.' && in_word) { + in_word = false; + } + + if (!is_char) { + in_keyword = false; + } + + if (!in_keyword && is_char && !prev_is_char) { + int to = j; + while (to < line_length && !is_symbol(str[to])) { + to++; + } + + String word = str.substr(j, to - j); + Color col = Color(); + if (keywords.has(word)) { + col = keywords[word]; + } else if (member_keywords.has(word)) { + col = member_keywords[word]; + for (int k = j - 1; k >= 0; k--) { + if (str[k] == '.') { + col = Color(); //member indexing not allowed + break; + } else if (str[k] > 32) { + break; + } + } + } + + if (col != Color()) { + in_keyword = true; + keyword_color = col; + } + } + + if (!in_function_name && in_word && !in_keyword) { + int k = j; + while (k < line_length && !is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') { + k++; + } + + // Check for space between name and bracket. + while (k < line_length && (str[k] == '\t' || str[k] == ' ')) { + k++; + } + + if (str[k] == '(') { + in_function_name = true; + } + } + + if (!in_function_name && !in_member_variable && !in_keyword && !is_number && in_word) { + int k = j; + while (k > 0 && !is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') { + k--; + } + + if (str[k] == '.') { + in_member_variable = true; + } + } + + if (is_a_symbol) { + in_function_name = false; + in_member_variable = false; + } + + if (in_keyword) { + color = keyword_color; + } else if (in_member_variable) { + color = member_color; + } else if (in_function_name) { + color = function_color; + } else if (is_a_symbol) { + color = symbol_color; + } else if (is_number) { + color = number_color; + } + + prev_is_char = is_char; + prev_is_number = is_number; + + if (color != prev_color) { + prev_color = color; + highlighter_info["color"] = color; + color_map[j] = highlighter_info; + } + } + + return color_map; +} + +void CodeHighlighter::_clear_highlighting_cache() { + color_region_cache.clear(); +} + +void CodeHighlighter::_update_cache() { + font_color = text_edit->get_theme_color("font_color"); +} + +void CodeHighlighter::add_keyword_color(const String &p_keyword, const Color &p_color) { + keywords[p_keyword] = p_color; + clear_highlighting_cache(); +} + +void CodeHighlighter::remove_keyword_color(const String &p_keyword) { + keywords.erase(p_keyword); + clear_highlighting_cache(); +} + +bool CodeHighlighter::has_keyword_color(const String &p_keyword) const { + return keywords.has(p_keyword); +} + +Color CodeHighlighter::get_keyword_color(const String &p_keyword) const { + ERR_FAIL_COND_V(!keywords.has(p_keyword), Color()); + return keywords[p_keyword]; +} + +void CodeHighlighter::set_keyword_colors(const Dictionary p_keywords) { + keywords.clear(); + keywords = p_keywords; + clear_highlighting_cache(); +} + +void CodeHighlighter::clear_keyword_colors() { + keywords.clear(); + clear_highlighting_cache(); +} + +Dictionary CodeHighlighter::get_keyword_colors() const { + return keywords; +} + +void CodeHighlighter::add_member_keyword_color(const String &p_member_keyword, const Color &p_color) { + member_keywords[p_member_keyword] = p_color; + clear_highlighting_cache(); +} + +void CodeHighlighter::remove_member_keyword_color(const String &p_member_keyword) { + member_keywords.erase(p_member_keyword); + clear_highlighting_cache(); +} + +bool CodeHighlighter::has_member_keyword_color(const String &p_member_keyword) const { + return member_keywords.has(p_member_keyword); +} + +Color CodeHighlighter::get_member_keyword_color(const String &p_member_keyword) const { + ERR_FAIL_COND_V(!member_keywords.has(p_member_keyword), Color()); + return member_keywords[p_member_keyword]; +} + +void CodeHighlighter::set_member_keyword_colors(const Dictionary &p_member_keywords) { + member_keywords.clear(); + member_keywords = p_member_keywords; + clear_highlighting_cache(); +} + +void CodeHighlighter::clear_member_keyword_colors() { + member_keywords.clear(); + clear_highlighting_cache(); +} + +Dictionary CodeHighlighter::get_member_keyword_colors() const { + return member_keywords; +} + +void CodeHighlighter::add_color_region(const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only) { + for (int i = 0; i < p_start_key.length(); i++) { + ERR_FAIL_COND_MSG(!is_symbol(p_start_key[i]), "color regions must start with a symbol"); + } + + if (p_end_key.length() > 0) { + for (int i = 0; i < p_end_key.length(); i++) { + ERR_FAIL_COND_MSG(!is_symbol(p_end_key[i]), "color regions must end with a symbol"); + } + } + + int at = 0; + for (int i = 0; i < color_regions.size(); i++) { + ERR_FAIL_COND_MSG(color_regions[i].start_key == p_start_key, "color region with start key '" + p_start_key + "' already exists."); + if (p_start_key.length() < color_regions[i].start_key.length()) { + at++; + } + } + + ColorRegion color_region; + color_region.color = p_color; + color_region.start_key = p_start_key; + color_region.end_key = p_end_key; + color_region.line_only = p_line_only || p_end_key == ""; + color_regions.insert(at, color_region); + clear_highlighting_cache(); +} + +void CodeHighlighter::remove_color_region(const String &p_start_key) { + for (int i = 0; i < color_regions.size(); i++) { + if (color_regions[i].start_key == p_start_key) { + color_regions.remove(i); + break; + } + } + clear_highlighting_cache(); +} + +bool CodeHighlighter::has_color_region(const String &p_start_key) const { + for (int i = 0; i < color_regions.size(); i++) { + if (color_regions[i].start_key == p_start_key) { + return true; + } + } + return false; +} + +void CodeHighlighter::set_color_regions(const Dictionary &p_color_regions) { + color_regions.clear(); + + List<Variant> keys; + p_color_regions.get_key_list(&keys); + + for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { + String key = E->get(); + + String start_key = key.get_slice(" ", 0); + String end_key = key.get_slice_count(" ") > 1 ? key.get_slice(" ", 1) : String(); + + add_color_region(start_key, end_key, p_color_regions[key], end_key == ""); + } + clear_highlighting_cache(); +} + +void CodeHighlighter::clear_color_regions() { + color_regions.clear(); + clear_highlighting_cache(); +} + +Dictionary CodeHighlighter::get_color_regions() const { + Dictionary r_color_regions; + for (int i = 0; i < color_regions.size(); i++) { + ColorRegion region = color_regions[i]; + r_color_regions[region.start_key + (region.end_key.empty() ? "" : " " + region.end_key)] = region.color; + } + return r_color_regions; +} + +void CodeHighlighter::_bind_methods() { + ClassDB::bind_method(D_METHOD("add_keyword_color", "keyword", "color"), &CodeHighlighter::add_keyword_color); + ClassDB::bind_method(D_METHOD("remove_keyword_color", "keyword"), &CodeHighlighter::remove_keyword_color); + ClassDB::bind_method(D_METHOD("has_keyword_color", "keyword"), &CodeHighlighter::has_keyword_color); + ClassDB::bind_method(D_METHOD("get_keyword_color", "keyword"), &CodeHighlighter::get_keyword_color); + + ClassDB::bind_method(D_METHOD("set_keyword_colors", "keywords"), &CodeHighlighter::set_keyword_colors); + ClassDB::bind_method(D_METHOD("clear_keyword_colors"), &CodeHighlighter::clear_keyword_colors); + ClassDB::bind_method(D_METHOD("get_keyword_colors"), &CodeHighlighter::get_keyword_colors); + + ClassDB::bind_method(D_METHOD("add_member_keyword_color", "member_keyword", "color"), &CodeHighlighter::add_member_keyword_color); + ClassDB::bind_method(D_METHOD("remove_member_keyword_color", "member_keyword"), &CodeHighlighter::remove_member_keyword_color); + ClassDB::bind_method(D_METHOD("has_member_keyword_color", "member_keyword"), &CodeHighlighter::has_member_keyword_color); + ClassDB::bind_method(D_METHOD("get_member_keyword_color", "member_keyword"), &CodeHighlighter::get_member_keyword_color); + + ClassDB::bind_method(D_METHOD("set_member_keyword_colors", "member_keyword"), &CodeHighlighter::set_member_keyword_colors); + ClassDB::bind_method(D_METHOD("clear_member_keyword_colors"), &CodeHighlighter::clear_member_keyword_colors); + ClassDB::bind_method(D_METHOD("get_member_keyword_colors"), &CodeHighlighter::get_member_keyword_colors); + + ClassDB::bind_method(D_METHOD("add_color_region", "p_start_key", "p_end_key", "p_color", "p_line_only"), &CodeHighlighter::add_color_region, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("remove_color_region", "p_start_key"), &CodeHighlighter::remove_color_region); + ClassDB::bind_method(D_METHOD("has_color_region", "p_start_key"), &CodeHighlighter::has_color_region); + + ClassDB::bind_method(D_METHOD("set_color_regions", "p_color_regions"), &CodeHighlighter::set_color_regions); + ClassDB::bind_method(D_METHOD("clear_color_regions"), &CodeHighlighter::clear_color_regions); + ClassDB::bind_method(D_METHOD("get_color_regions"), &CodeHighlighter::get_color_regions); + + ClassDB::bind_method(D_METHOD("set_function_color", "color"), &CodeHighlighter::set_function_color); + ClassDB::bind_method(D_METHOD("get_function_color"), &CodeHighlighter::get_function_color); + + ClassDB::bind_method(D_METHOD("set_number_color", "color"), &CodeHighlighter::set_number_color); + ClassDB::bind_method(D_METHOD("get_number_color"), &CodeHighlighter::get_number_color); + + ClassDB::bind_method(D_METHOD("set_symbol_color", "color"), &CodeHighlighter::set_symbol_color); + ClassDB::bind_method(D_METHOD("get_symbol_color"), &CodeHighlighter::get_symbol_color); + + ClassDB::bind_method(D_METHOD("set_member_variable_color", "color"), &CodeHighlighter::set_member_variable_color); + ClassDB::bind_method(D_METHOD("get_member_variable_color"), &CodeHighlighter::get_member_variable_color); + + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "number_color"), "set_number_color", "get_number_color"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "symbol_color"), "set_symbol_color", "get_symbol_color"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "function_color"), "set_function_color", "get_function_color"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "member_variable_color"), "set_member_variable_color", "get_member_variable_color"); + + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "keyword_colors"), "set_keyword_colors", "get_keyword_colors"); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "member_keyword_colors"), "set_member_keyword_colors", "get_member_keyword_colors"); + ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "color_regions"), "set_color_regions", "get_color_regions"); +} + +void CodeHighlighter::set_number_color(Color p_color) { + number_color = p_color; + clear_highlighting_cache(); +} + +Color CodeHighlighter::get_number_color() const { + return number_color; +} + +void CodeHighlighter::set_symbol_color(Color p_color) { + symbol_color = p_color; + clear_highlighting_cache(); +} + +Color CodeHighlighter::get_symbol_color() const { + return symbol_color; +} + +void CodeHighlighter::set_function_color(Color p_color) { + function_color = p_color; + clear_highlighting_cache(); +} + +Color CodeHighlighter::get_function_color() const { + return function_color; +} + +void CodeHighlighter::set_member_variable_color(Color p_color) { + member_color = p_color; + clear_highlighting_cache(); +} + +Color CodeHighlighter::get_member_variable_color() const { + return member_color; +} diff --git a/scene/resources/syntax_highlighter.h b/scene/resources/syntax_highlighter.h new file mode 100644 index 0000000000..720227a256 --- /dev/null +++ b/scene/resources/syntax_highlighter.h @@ -0,0 +1,140 @@ +/*************************************************************************/ +/* syntax_highlighter.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SYNTAX_HIGHLIGHTER_H +#define SYNTAX_HIGHLIGHTER_H + +#include "core/resource.h" + +class TextEdit; + +class SyntaxHighlighter : public Resource { + GDCLASS(SyntaxHighlighter, Resource) + +private: + Map<int, Dictionary> highlighting_cache; + void _lines_edited_from(int p_from_line, int p_to_line); + +protected: + ObjectID text_edit_instance_id; // For validity check + TextEdit *text_edit = nullptr; + + static void _bind_methods(); + +public: + Dictionary get_line_syntax_highlighting(int p_line); + virtual Dictionary _get_line_syntax_highlighting(int p_line) { return Dictionary(); } + + void clear_highlighting_cache(); + virtual void _clear_highlighting_cache() {} + + void update_cache(); + virtual void _update_cache() {} + + void set_text_edit(TextEdit *p_text_edit); + TextEdit *get_text_edit(); + + SyntaxHighlighter() {} + virtual ~SyntaxHighlighter() {} +}; + +/////////////////////////////////////////////////////////////////////////////// + +class CodeHighlighter : public SyntaxHighlighter { + GDCLASS(CodeHighlighter, SyntaxHighlighter) + +private: + struct ColorRegion { + Color color; + String start_key; + String end_key; + bool line_only; + }; + Vector<ColorRegion> color_regions; + Map<int, int> color_region_cache; + + Dictionary keywords; + Dictionary member_keywords; + + Color font_color; + Color member_color; + Color function_color; + Color symbol_color; + Color number_color; + +protected: + static void _bind_methods(); + +public: + virtual Dictionary _get_line_syntax_highlighting(int p_line) override; + + virtual void _clear_highlighting_cache() override; + virtual void _update_cache() override; + + void add_keyword_color(const String &p_keyword, const Color &p_color); + void remove_keyword_color(const String &p_keyword); + bool has_keyword_color(const String &p_keyword) const; + Color get_keyword_color(const String &p_keyword) const; + + void set_keyword_colors(const Dictionary p_keywords); + void clear_keyword_colors(); + Dictionary get_keyword_colors() const; + + void add_member_keyword_color(const String &p_member_keyword, const Color &p_color); + void remove_member_keyword_color(const String &p_member_keyword); + bool has_member_keyword_color(const String &p_member_keyword) const; + Color get_member_keyword_color(const String &p_member_keyword) const; + + void set_member_keyword_colors(const Dictionary &p_color_regions); + void clear_member_keyword_colors(); + Dictionary get_member_keyword_colors() const; + + void add_color_region(const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only = false); + void remove_color_region(const String &p_start_key); + bool has_color_region(const String &p_start_key) const; + + void set_color_regions(const Dictionary &p_member_keyword); + void clear_color_regions(); + Dictionary get_color_regions() const; + + void set_number_color(Color p_color); + Color get_number_color() const; + + void set_symbol_color(Color p_color); + Color get_symbol_color() const; + + void set_function_color(Color p_color); + Color get_function_color() const; + + void set_member_variable_color(Color p_color); + Color get_member_variable_color() const; +}; + +#endif diff --git a/scene/resources/text_file.cpp b/scene/resources/text_file.cpp index af55d2dde3..e3bd5ce0ae 100644 --- a/scene/resources/text_file.cpp +++ b/scene/resources/text_file.cpp @@ -49,8 +49,7 @@ void TextFile::reload_from_file() { } Error TextFile::load_text(const String &p_path) { - - PoolVector<uint8_t> sourcef; + Vector<uint8_t> sourcef; Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); @@ -58,15 +57,15 @@ Error TextFile::load_text(const String &p_path) { int len = f->get_len(); sourcef.resize(len + 1); - PoolVector<uint8_t>::Write w = sourcef.write(); - int r = f->get_buffer(w.ptr(), len); + uint8_t *w = sourcef.ptrw(); + int r = f->get_buffer(w, len); f->close(); memdelete(f); ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN); w[len] = 0; String s; - ERR_FAIL_COND_V_MSG(s.parse_utf8((const char *)w.ptr()), ERR_INVALID_DATA, "Script '" + p_path + "' contains invalid unicode (UTF-8), so it was not loaded. Please ensure that scripts are saved in valid UTF-8 unicode."); + ERR_FAIL_COND_V_MSG(s.parse_utf8((const char *)w), ERR_INVALID_DATA, "Script '" + p_path + "' contains invalid unicode (UTF-8), so it was not loaded. Please ensure that scripts are saved in valid UTF-8 unicode."); text = s; path = p_path; return OK; diff --git a/scene/resources/text_file.h b/scene/resources/text_file.h index 666c088d04..fa812b1e67 100644 --- a/scene/resources/text_file.h +++ b/scene/resources/text_file.h @@ -35,7 +35,6 @@ #include "core/io/resource_saver.h" class TextFile : public Resource { - GDCLASS(TextFile, Resource); private: @@ -46,7 +45,7 @@ public: virtual bool has_text() const; virtual String get_text() const; virtual void set_text(const String &p_code); - virtual void reload_from_file(); + virtual void reload_from_file() override; void set_file_path(const String &p_path) { path = p_path; } Error load_text(const String &p_path); diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 4d23f0eb41..39237e1a33 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -38,82 +38,68 @@ #include "scene/resources/bit_map.h" #include "servers/camera/camera_feed.h" -Size2 Texture::get_size() const { - +Size2 Texture2D::get_size() const { return Size2(get_width(), get_height()); } -bool Texture::is_pixel_opaque(int p_x, int p_y) const { +bool Texture2D::is_pixel_opaque(int p_x, int p_y) const { return true; } -void Texture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { +void Texture2D::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, get_size()), get_rid(), false, p_modulate, p_transpose, normal_rid); + RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, get_size()), get_rid(), false, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void Texture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { +void Texture2D::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, get_rid(), p_tile, p_modulate, p_transpose, normal_rid); + RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, get_rid(), p_tile, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void Texture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const { +void Texture2D::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, get_rid(), p_src_rect, p_modulate, p_transpose, normal_rid, p_clip_uv); + RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, get_rid(), p_src_rect, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_clip_uv, p_texture_filter, p_texture_repeat); } -bool Texture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const { - +bool Texture2D::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const { r_rect = p_rect; r_src_rect = p_src_rect; return true; } -void Texture::_bind_methods() { +void Texture2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_width"), &Texture2D::get_width); + ClassDB::bind_method(D_METHOD("get_height"), &Texture2D::get_height); + ClassDB::bind_method(D_METHOD("get_size"), &Texture2D::get_size); + ClassDB::bind_method(D_METHOD("has_alpha"), &Texture2D::has_alpha); + ClassDB::bind_method(D_METHOD("draw", "canvas_item", "position", "modulate", "transpose", "normal_map", "specular_map", "specular_color_shininess", "texture_filter", "texture_repeat"), &Texture2D::draw, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT), DEFVAL(RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT)); + ClassDB::bind_method(D_METHOD("draw_rect", "canvas_item", "rect", "tile", "modulate", "transpose", "normal_map", "specular_map", "specular_color_shininess", "texture_filter", "texture_repeat"), &Texture2D::draw_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT), DEFVAL(RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT)); + ClassDB::bind_method(D_METHOD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose", "normal_map", "specular_map", "specular_color_shininess", "texture_filter", "texture_repeat", "clip_uv"), &Texture2D::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT), DEFVAL(RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("get_data"), &Texture2D::get_data); - ClassDB::bind_method(D_METHOD("get_width"), &Texture::get_width); - ClassDB::bind_method(D_METHOD("get_height"), &Texture::get_height); - ClassDB::bind_method(D_METHOD("get_size"), &Texture::get_size); - ClassDB::bind_method(D_METHOD("has_alpha"), &Texture::has_alpha); - ClassDB::bind_method(D_METHOD("set_flags", "flags"), &Texture::set_flags); - ClassDB::bind_method(D_METHOD("get_flags"), &Texture::get_flags); - ClassDB::bind_method(D_METHOD("draw", "canvas_item", "position", "modulate", "transpose", "normal_map"), &Texture::draw, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("draw_rect", "canvas_item", "rect", "tile", "modulate", "transpose", "normal_map"), &Texture::draw_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose", "normal_map", "clip_uv"), &Texture::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(true)); - ClassDB::bind_method(D_METHOD("get_data"), &Texture::get_data); - - ADD_GROUP("Flags", ""); - ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Mipmaps,Repeat,Filter,Anisotropic Linear,Convert to Linear,Mirrored Repeat,Video Surface"), "set_flags", "get_flags"); ADD_GROUP("", ""); - - BIND_ENUM_CONSTANT(FLAGS_DEFAULT); - BIND_ENUM_CONSTANT(FLAG_MIPMAPS); - BIND_ENUM_CONSTANT(FLAG_REPEAT); - BIND_ENUM_CONSTANT(FLAG_FILTER); - BIND_ENUM_CONSTANT(FLAG_ANISOTROPIC_FILTER); - BIND_ENUM_CONSTANT(FLAG_CONVERT_TO_LINEAR); - BIND_ENUM_CONSTANT(FLAG_MIRRORED_REPEAT); - BIND_ENUM_CONSTANT(FLAG_VIDEO_SURFACE); } -Texture::Texture() { +Texture2D::Texture2D() { } ///////////////////// void ImageTexture::reload_from_file() { - String path = ResourceLoader::path_remap(get_path()); - if (!path.is_resource_file()) + if (!path.is_resource_file()) { return; + } - uint32_t flags = get_flags(); Ref<Image> img; img.instance(); if (ImageLoader::load_image(path, img) == OK) { - create_from_image(img, flags); + create_from_image(img); } else { Resource::reload_from_file(); _change_notify(); @@ -122,55 +108,42 @@ void ImageTexture::reload_from_file() { } bool ImageTexture::_set(const StringName &p_name, const Variant &p_value) { - - if (p_name == "image") - create_from_image(p_value, flags); - else if (p_name == "flags") - if (w * h == 0) - flags = p_value; - else - set_flags(p_value); - else if (p_name == "size") { + if (p_name == "image") { + create_from_image(p_value); + } else if (p_name == "size") { Size2 s = p_value; w = s.width; h = s.height; - VisualServer::get_singleton()->texture_set_size_override(texture, w, h, 0); - } else if (p_name == "_data") { - _set_data(p_value); - } else + RenderingServer::get_singleton()->texture_set_size_override(texture, w, h); + } else { return false; + } return true; } bool ImageTexture::_get(const StringName &p_name, Variant &r_ret) const { - - if (p_name == "image_data") { - - } else if (p_name == "image") + if (p_name == "image") { r_ret = get_data(); - else if (p_name == "flags") - r_ret = flags; - else if (p_name == "size") + } else if (p_name == "size") { r_ret = Size2(w, h); - else + } else { return false; + } return true; } void ImageTexture::_get_property_list(List<PropertyInfo> *p_list) const { - - p_list->push_back(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Mipmaps,Repeat,Filter,Anisotropic,sRGB,Mirrored Repeat")); p_list->push_back(PropertyInfo(Variant::OBJECT, "image", PROPERTY_HINT_RESOURCE_TYPE, "Image", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT)); p_list->push_back(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "")); } void ImageTexture::_reload_hook(const RID &p_hook) { - String path = get_path(); - if (!path.is_resource_file()) + if (!path.is_resource_file()) { return; + } Ref<Image> img; img.instance(); @@ -178,79 +151,48 @@ void ImageTexture::_reload_hook(const RID &p_hook) { ERR_FAIL_COND_MSG(err != OK, "Cannot load image from path '" + path + "'."); - VisualServer::get_singleton()->texture_set_data(texture, img); - - _change_notify(); - emit_changed(); -} - -void ImageTexture::create(int p_width, int p_height, Image::Format p_format, uint32_t p_flags) { + RID new_texture = RenderingServer::get_singleton()->texture_2d_create(img); + RenderingServer::get_singleton()->texture_replace(texture, new_texture); - flags = p_flags; - VisualServer::get_singleton()->texture_allocate(texture, p_width, p_height, 0, p_format, VS::TEXTURE_TYPE_2D, p_flags); - format = p_format; - w = p_width; - h = p_height; _change_notify(); emit_changed(); } -void ImageTexture::create_from_image(const Ref<Image> &p_image, uint32_t p_flags) { +void ImageTexture::create_from_image(const Ref<Image> &p_image) { ERR_FAIL_COND(p_image.is_null()); - flags = p_flags; w = p_image->get_width(); h = p_image->get_height(); format = p_image->get_format(); + mipmaps = p_image->has_mipmaps(); - VisualServer::get_singleton()->texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_flags); - VisualServer::get_singleton()->texture_set_data(texture, p_image); + if (texture.is_null()) { + texture = RenderingServer::get_singleton()->texture_2d_create(p_image); + } else { + RID new_texture = RenderingServer::get_singleton()->texture_2d_create(p_image); + RenderingServer::get_singleton()->texture_replace(texture, new_texture); + } _change_notify(); emit_changed(); image_stored = true; } -void ImageTexture::set_flags(uint32_t p_flags) { - - if (flags == p_flags) - return; - - flags = p_flags; - if (w == 0 || h == 0) { - return; //uninitialized, do not set to texture - } - VisualServer::get_singleton()->texture_set_flags(texture, p_flags); - _change_notify("flags"); - emit_changed(); -} - -uint32_t ImageTexture::get_flags() const { - - return ImageTexture::flags; -} - Image::Format ImageTexture::get_format() const { - return format; } -#ifndef DISABLE_DEPRECATED -Error ImageTexture::load(const String &p_path) { - - WARN_DEPRECATED; - Ref<Image> img; - img.instance(); - Error err = img->load(p_path); - if (err == OK) { - create_from_image(img); - } - return err; -} -#endif -void ImageTexture::set_data(const Ref<Image> &p_image) { +void ImageTexture::update(const Ref<Image> &p_image, bool p_immediate) { ERR_FAIL_COND(p_image.is_null()); + ERR_FAIL_COND(texture.is_null()); + ERR_FAIL_COND(p_image->get_width() != w || p_image->get_height() != h); + ERR_FAIL_COND(p_image->get_format() != format); + ERR_FAIL_COND(mipmaps != p_image->has_mipmaps()); - VisualServer::get_singleton()->texture_set_data(texture, p_image); + if (p_immediate) { + RenderingServer::get_singleton()->texture_2d_update_immediate(texture, p_image); + } else { + RenderingServer::get_singleton()->texture_2d_update(texture, p_image); + } _change_notify(); emit_changed(); @@ -260,63 +202,65 @@ void ImageTexture::set_data(const Ref<Image> &p_image) { } void ImageTexture::_resource_path_changed() { - String path = get_path(); } Ref<Image> ImageTexture::get_data() const { - if (image_stored) { - return VisualServer::get_singleton()->texture_get_data(texture); + return RenderingServer::get_singleton()->texture_2d_get(texture); } else { return Ref<Image>(); } } int ImageTexture::get_width() const { - return w; } int ImageTexture::get_height() const { - return h; } RID ImageTexture::get_rid() const { - + if (texture.is_null()) { + //we are in trouble, create something temporary + texture = RenderingServer::get_singleton()->texture_2d_placeholder_create(); + } return texture; } bool ImageTexture::has_alpha() const { - return (format == Image::FORMAT_LA8 || format == Image::FORMAT_RGBA8); } -void ImageTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { - - if ((w | h) == 0) +void ImageTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { + if ((w | h) == 0) { return; + } RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose, normal_rid); + RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void ImageTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { - if ((w | h) == 0) +void ImageTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { + if ((w | h) == 0) { return; + } RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose, normal_rid); + RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void ImageTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const { - if ((w | h) == 0) +void ImageTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { + if ((w | h) == 0) { return; + } RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid, p_clip_uv); + RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_clip_uv, p_texture_filter, p_texture_repeat); } bool ImageTexture::is_pixel_opaque(int p_x, int p_y) const { - if (!alpha_cache.is_valid()) { Ref<Image> img = get_data(); if (img.is_valid()) { @@ -331,7 +275,6 @@ bool ImageTexture::is_pixel_opaque(int p_x, int p_y) const { } if (alpha_cache.is_valid()) { - int aw = int(alpha_cache->get_size().width); int ah = int(alpha_cache->get_size().height); if (aw == 0 || ah == 0) { @@ -351,451 +294,404 @@ bool ImageTexture::is_pixel_opaque(int p_x, int p_y) const { } void ImageTexture::set_size_override(const Size2 &p_size) { - Size2 s = p_size; - if (s.x != 0) + if (s.x != 0) { w = s.x; - if (s.y != 0) + } + if (s.y != 0) { h = s.y; - VisualServer::get_singleton()->texture_set_size_override(texture, w, h, 0); + } + RenderingServer::get_singleton()->texture_set_size_override(texture, w, h); } void ImageTexture::set_path(const String &p_path, bool p_take_over) { - if (texture.is_valid()) { - VisualServer::get_singleton()->texture_set_path(texture, p_path); + RenderingServer::get_singleton()->texture_set_path(texture, p_path); } Resource::set_path(p_path, p_take_over); } -void ImageTexture::set_storage(Storage p_storage) { - - storage = p_storage; -} - -ImageTexture::Storage ImageTexture::get_storage() const { - - return storage; -} - -void ImageTexture::set_lossy_storage_quality(float p_lossy_storage_quality) { - - lossy_storage_quality = p_lossy_storage_quality; -} - -float ImageTexture::get_lossy_storage_quality() const { - - return lossy_storage_quality; -} - -void ImageTexture::_set_data(Dictionary p_data) { - - Ref<Image> img = p_data["image"]; - ERR_FAIL_COND(!img.is_valid()); - uint32_t flags = p_data["flags"]; - - create_from_image(img, flags); - - set_storage(Storage(p_data["storage"].operator int())); - set_lossy_storage_quality(p_data["lossy_quality"]); - - set_size_override(p_data["size"]); -}; - void ImageTexture::_bind_methods() { - - ClassDB::bind_method(D_METHOD("create", "width", "height", "format", "flags"), &ImageTexture::create, DEFVAL(FLAGS_DEFAULT)); - ClassDB::bind_method(D_METHOD("create_from_image", "image", "flags"), &ImageTexture::create_from_image, DEFVAL(FLAGS_DEFAULT)); + ClassDB::bind_method(D_METHOD("create_from_image", "image"), &ImageTexture::create_from_image); ClassDB::bind_method(D_METHOD("get_format"), &ImageTexture::get_format); -#ifndef DISABLE_DEPRECATED - ClassDB::bind_method(D_METHOD("load", "path"), &ImageTexture::load); -#endif - ClassDB::bind_method(D_METHOD("set_data", "image"), &ImageTexture::set_data); - ClassDB::bind_method(D_METHOD("set_storage", "mode"), &ImageTexture::set_storage); - ClassDB::bind_method(D_METHOD("get_storage"), &ImageTexture::get_storage); - ClassDB::bind_method(D_METHOD("set_lossy_storage_quality", "quality"), &ImageTexture::set_lossy_storage_quality); - ClassDB::bind_method(D_METHOD("get_lossy_storage_quality"), &ImageTexture::get_lossy_storage_quality); + ClassDB::bind_method(D_METHOD("update", "image", "immediate"), &ImageTexture::update, DEFVAL(false)); ClassDB::bind_method(D_METHOD("set_size_override", "size"), &ImageTexture::set_size_override); ClassDB::bind_method(D_METHOD("_reload_hook", "rid"), &ImageTexture::_reload_hook); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "storage", PROPERTY_HINT_ENUM, "Uncompressed,Compress Lossy,Compress Lossless"), "set_storage", "get_storage"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "lossy_quality", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_lossy_storage_quality", "get_lossy_storage_quality"); - - BIND_ENUM_CONSTANT(STORAGE_RAW); - BIND_ENUM_CONSTANT(STORAGE_COMPRESS_LOSSY); - BIND_ENUM_CONSTANT(STORAGE_COMPRESS_LOSSLESS); } ImageTexture::ImageTexture() { - w = h = 0; - flags = FLAGS_DEFAULT; - texture = VisualServer::get_singleton()->texture_create(); - storage = STORAGE_RAW; - lossy_storage_quality = 0.7; image_stored = false; + mipmaps = false; format = Image::FORMAT_L8; } ImageTexture::~ImageTexture() { - - VisualServer::get_singleton()->free(texture); -} - -////////////////////////////////////////// - -void StreamTexture::set_path(const String &p_path, bool p_take_over) { - if (texture.is_valid()) { - VisualServer::get_singleton()->texture_set_path(texture, p_path); + RenderingServer::get_singleton()->free(texture); } - - Resource::set_path(p_path, p_take_over); -} - -void StreamTexture::_requested_3d(void *p_ud) { - - StreamTexture *st = (StreamTexture *)p_ud; - Ref<StreamTexture> stex(st); - ERR_FAIL_COND(!request_3d_callback); - request_3d_callback(stex); -} - -void StreamTexture::_requested_srgb(void *p_ud) { - - StreamTexture *st = (StreamTexture *)p_ud; - Ref<StreamTexture> stex(st); - ERR_FAIL_COND(!request_srgb_callback); - request_srgb_callback(stex); -} - -void StreamTexture::_requested_normal(void *p_ud) { - - StreamTexture *st = (StreamTexture *)p_ud; - Ref<StreamTexture> stex(st); - ERR_FAIL_COND(!request_normal_callback); - request_normal_callback(stex); -} - -StreamTexture::TextureFormatRequestCallback StreamTexture::request_3d_callback = NULL; -StreamTexture::TextureFormatRequestCallback StreamTexture::request_srgb_callback = NULL; -StreamTexture::TextureFormatRequestCallback StreamTexture::request_normal_callback = NULL; - -uint32_t StreamTexture::get_flags() const { - - return flags; -} -Image::Format StreamTexture::get_format() const { - - return format; } -Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, int &flags, Ref<Image> &image, int p_size_limit) { - - alpha_cache.unref(); - - ERR_FAIL_COND_V(image.is_null(), ERR_INVALID_PARAMETER); - - FileAccess *f = FileAccess::open(p_path, FileAccess::READ); - ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); - - uint8_t header[4]; - f->get_buffer(header, 4); - if (header[0] != 'G' || header[1] != 'D' || header[2] != 'S' || header[3] != 'T') { - memdelete(f); - ERR_FAIL_COND_V(header[0] != 'G' || header[1] != 'D' || header[2] != 'S' || header[3] != 'T', ERR_FILE_CORRUPT); - } - - tw = f->get_16(); - tw_custom = f->get_16(); - th = f->get_16(); - th_custom = f->get_16(); - - flags = f->get_32(); //texture flags! - uint32_t df = f->get_32(); //data format - - /* - print_line("width: " + itos(tw)); - print_line("height: " + itos(th)); - print_line("flags: " + itos(flags)); - print_line("df: " + itos(df)); - */ -#ifdef TOOLS_ENABLED - - if (request_3d_callback && df & FORMAT_BIT_DETECT_3D) { - //print_line("request detect 3D at " + p_path); - VS::get_singleton()->texture_set_detect_3d_callback(texture, _requested_3d, this); - } else { - //print_line("not requesting detect 3D at " + p_path); - VS::get_singleton()->texture_set_detect_3d_callback(texture, NULL, NULL); - } - - if (request_srgb_callback && df & FORMAT_BIT_DETECT_SRGB) { - //print_line("request detect srgb at " + p_path); - VS::get_singleton()->texture_set_detect_srgb_callback(texture, _requested_srgb, this); - } else { - //print_line("not requesting detect srgb at " + p_path); - VS::get_singleton()->texture_set_detect_srgb_callback(texture, NULL, NULL); - } +////////////////////////////////////////// - if (request_srgb_callback && df & FORMAT_BIT_DETECT_NORMAL) { - //print_line("request detect srgb at " + p_path); - VS::get_singleton()->texture_set_detect_normal_callback(texture, _requested_normal, this); - } else { - //print_line("not requesting detect normal at " + p_path); - VS::get_singleton()->texture_set_detect_normal_callback(texture, NULL, NULL); - } -#endif - if (!(df & FORMAT_BIT_STREAM)) { - p_size_limit = 0; - } +Ref<Image> StreamTexture2D::load_image_from_file(FileAccess *f, int p_size_limit) { + uint32_t data_format = f->get_32(); + uint32_t w = f->get_16(); + uint32_t h = f->get_16(); + uint32_t mipmaps = f->get_32(); + Image::Format format = Image::Format(f->get_32()); - if (df & FORMAT_BIT_LOSSLESS || df & FORMAT_BIT_LOSSY) { + if (data_format == DATA_FORMAT_LOSSLESS || data_format == DATA_FORMAT_LOSSY || data_format == DATA_FORMAT_BASIS_UNIVERSAL) { //look for a PNG or WEBP file inside - int sw = tw; - int sh = th; - - uint32_t mipmaps = f->get_32(); - uint32_t size = f->get_32(); - - //print_line("mipmaps: " + itos(mipmaps)); - - while (mipmaps > 1 && p_size_limit > 0 && (sw > p_size_limit || sh > p_size_limit)) { - - f->seek(f->get_position() + size); - mipmaps = f->get_32(); - size = f->get_32(); - - sw = MAX(sw >> 1, 1); - sh = MAX(sh >> 1, 1); - mipmaps--; - } + int sw = w; + int sh = h; //mipmaps need to be read independently, they will be later combined - Vector<Ref<Image> > mipmap_images; + Vector<Ref<Image>> mipmap_images; int total_size = 0; - for (uint32_t i = 0; i < mipmaps; i++) { + bool first = true; + + for (uint32_t i = 0; i < mipmaps + 1; i++) { + uint32_t size = f->get_32(); - if (i) { - size = f->get_32(); + if (p_size_limit > 0 && i < (mipmaps - 1) && (sw > p_size_limit || sh > p_size_limit)) { + //can't load this due to size limit + sw = MAX(sw >> 1, 1); + sh = MAX(sh >> 1, 1); + f->seek(f->get_position() + size); + continue; } - PoolVector<uint8_t> pv; + Vector<uint8_t> pv; pv.resize(size); { - PoolVector<uint8_t>::Write w = pv.write(); - f->get_buffer(w.ptr(), size); + uint8_t *wr = pv.ptrw(); + f->get_buffer(wr, size); } Ref<Image> img; - if (df & FORMAT_BIT_LOSSLESS) { + if (data_format == DATA_FORMAT_BASIS_UNIVERSAL) { + img = Image::basis_universal_unpacker(pv); + } else if (data_format == DATA_FORMAT_LOSSLESS) { img = Image::lossless_unpacker(pv); } else { img = Image::lossy_unpacker(pv); } if (img.is_null() || img->empty()) { - memdelete(f); - ERR_FAIL_COND_V(img.is_null() || img->empty(), ERR_FILE_CORRUPT); + ERR_FAIL_COND_V(img.is_null() || img->empty(), Ref<Image>()); + } + + if (first) { + //format will actually be the format of the first image, + //as it may have changed on compression + format = img->get_format(); + first = false; + } else if (img->get_format() != format) { + img->convert(format); //all needs to be the same format } total_size += img->get_data().size(); mipmap_images.push_back(img); + + sw = MAX(sw >> 1, 1); + sh = MAX(sh >> 1, 1); } //print_line("mipmap read total: " + itos(mipmap_images.size())); - memdelete(f); //no longer needed + Ref<Image> image; + image.instance(); if (mipmap_images.size() == 1) { - + //only one image (which will most likely be the case anyway for this format) image = mipmap_images[0]; - return OK; + return image; } else { - PoolVector<uint8_t> img_data; + //rarer use case, but needs to be supported + Vector<uint8_t> img_data; img_data.resize(total_size); { - PoolVector<uint8_t>::Write w = img_data.write(); + uint8_t *wr = img_data.ptrw(); int ofs = 0; for (int i = 0; i < mipmap_images.size(); i++) { - - PoolVector<uint8_t> id = mipmap_images[i]->get_data(); + Vector<uint8_t> id = mipmap_images[i]->get_data(); int len = id.size(); - PoolVector<uint8_t>::Read r = id.read(); - copymem(&w[ofs], r.ptr(), len); + const uint8_t *r = id.ptr(); + copymem(&wr[ofs], r, len); ofs += len; } } - image->create(sw, sh, true, mipmap_images[0]->get_format(), img_data); - return OK; + image->create(w, h, true, mipmap_images[0]->get_format(), img_data); + return image; } - } else { + } else if (data_format == DATA_FORMAT_IMAGE) { + int size = Image::get_image_data_size(w, h, format, mipmaps ? true : false); - //look for regular format - Image::Format format = (Image::Format)(df & FORMAT_MASK_IMAGE_FORMAT); - bool mipmaps = df & FORMAT_BIT_HAS_MIPMAPS; + for (uint32_t i = 0; i < mipmaps + 1; i++) { + int tw, th; + int ofs = Image::get_image_mipmap_offset_and_dimensions(w, h, format, i, tw, th); - if (!mipmaps) { - int size = Image::get_image_data_size(tw, th, format, false); + if (p_size_limit > 0 && i < mipmaps && (p_size_limit > tw || p_size_limit > th)) { + if (ofs) { + f->seek(f->get_position() + ofs); + } + continue; //oops, size limit enforced, go to next + } - PoolVector<uint8_t> img_data; - img_data.resize(size); + Vector<uint8_t> data; + data.resize(size - ofs); { - PoolVector<uint8_t>::Write w = img_data.write(); - f->get_buffer(w.ptr(), size); + uint8_t *wr = data.ptrw(); + f->get_buffer(wr, data.size()); } - memdelete(f); + Ref<Image> image; + image.instance(); - image->create(tw, th, false, format, img_data); - return OK; - } else { + image->create(tw, th, mipmaps - i ? true : false, format, data); - int sw = tw; - int sh = th; + return image; + } + } - int mipmaps2 = Image::get_image_required_mipmaps(tw, th, format); - int total_size = Image::get_image_data_size(tw, th, format, true); - int idx = 0; + return Ref<Image>(); +} - while (mipmaps2 > 1 && p_size_limit > 0 && (sw > p_size_limit || sh > p_size_limit)) { +void StreamTexture2D::set_path(const String &p_path, bool p_take_over) { + if (texture.is_valid()) { + RenderingServer::get_singleton()->texture_set_path(texture, p_path); + } - sw = MAX(sw >> 1, 1); - sh = MAX(sh >> 1, 1); - mipmaps2--; - idx++; - } + Resource::set_path(p_path, p_take_over); +} - int ofs = Image::get_image_mipmap_offset(tw, th, format, idx); +void StreamTexture2D::_requested_3d(void *p_ud) { + StreamTexture2D *st = (StreamTexture2D *)p_ud; + Ref<StreamTexture2D> stex(st); + ERR_FAIL_COND(!request_3d_callback); + request_3d_callback(stex); +} - if (total_size - ofs <= 0) { - memdelete(f); - ERR_FAIL_V(ERR_FILE_CORRUPT); - } +void StreamTexture2D::_requested_roughness(void *p_ud, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel) { + StreamTexture2D *st = (StreamTexture2D *)p_ud; + Ref<StreamTexture2D> stex(st); + ERR_FAIL_COND(!request_roughness_callback); + request_roughness_callback(stex, p_normal_path, p_roughness_channel); +} - f->seek(f->get_position() + ofs); +void StreamTexture2D::_requested_normal(void *p_ud) { + StreamTexture2D *st = (StreamTexture2D *)p_ud; + Ref<StreamTexture2D> stex(st); + ERR_FAIL_COND(!request_normal_callback); + request_normal_callback(stex); +} - PoolVector<uint8_t> img_data; - img_data.resize(total_size - ofs); +StreamTexture2D::TextureFormatRequestCallback StreamTexture2D::request_3d_callback = nullptr; +StreamTexture2D::TextureFormatRoughnessRequestCallback StreamTexture2D::request_roughness_callback = nullptr; +StreamTexture2D::TextureFormatRequestCallback StreamTexture2D::request_normal_callback = nullptr; - { - PoolVector<uint8_t>::Write w = img_data.write(); - int bytes = f->get_buffer(w.ptr(), total_size - ofs); - //print_line("requested read: " + itos(total_size - ofs) + " but got: " + itos(bytes)); - - memdelete(f); - - int expected = total_size - ofs; - if (bytes < expected) { - //this is a compatibility workaround for older format, which saved less mipmaps2. It is still recommended the image is reimported. - zeromem(w.ptr() + bytes, (expected - bytes)); - } else if (bytes != expected) { - ERR_FAIL_V(ERR_FILE_CORRUPT); - } - } +Image::Format StreamTexture2D::get_format() const { + return format; +} - image->create(sw, sh, true, format, img_data); +Error StreamTexture2D::_load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, Ref<Image> &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int &mipmap_limit, int p_size_limit) { + alpha_cache.unref(); - return OK; - } + ERR_FAIL_COND_V(image.is_null(), ERR_INVALID_PARAMETER); + + FileAccess *f = FileAccess::open(p_path, FileAccess::READ); + ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); + + uint8_t header[4]; + f->get_buffer(header, 4); + if (header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != '2') { + memdelete(f); + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is corrupt (Bad header)."); } - return ERR_BUG; //unreachable -} + uint32_t version = f->get_32(); + + if (version > FORMAT_VERSION) { + memdelete(f); + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new."); + } + tw_custom = f->get_32(); + th_custom = f->get_32(); + uint32_t df = f->get_32(); //data format + + //skip reserved + mipmap_limit = int(f->get_32()); + //reserved + f->get_32(); + f->get_32(); + f->get_32(); + +#ifdef TOOLS_ENABLED + + r_request_3d = request_3d_callback && df & FORMAT_BIT_DETECT_3D; + r_request_roughness = request_roughness_callback && df & FORMAT_BIT_DETECT_ROUGNESS; + r_request_normal = request_normal_callback && df & FORMAT_BIT_DETECT_NORMAL; + +#else + + r_request_3d = false; + r_request_roughness = false; + r_request_normal = false; + +#endif + if (!(df & FORMAT_BIT_STREAM)) { + p_size_limit = 0; + } + + image = load_image_from_file(f, p_size_limit); -Error StreamTexture::load(const String &p_path) { + memdelete(f); + + if (image.is_null() || image->empty()) { + return ERR_CANT_OPEN; + } + + return OK; +} - int lw, lh, lwc, lhc, lflags; +Error StreamTexture2D::load(const String &p_path) { + int lw, lh, lwc, lhc; Ref<Image> image; image.instance(); - Error err = _load_data(p_path, lw, lh, lwc, lhc, lflags, image); - if (err) + + bool request_3d; + bool request_normal; + bool request_roughness; + int mipmap_limit; + + Error err = _load_data(p_path, lw, lh, lwc, lhc, image, request_3d, request_normal, request_roughness, mipmap_limit); + if (err) { return err; + } - if (get_path() == String()) { - //temporarily set path if no path set for resource, helps find errors - VisualServer::get_singleton()->texture_set_path(texture, p_path); + if (texture.is_valid()) { + RID new_texture = RS::get_singleton()->texture_2d_create(image); + RS::get_singleton()->texture_replace(texture, new_texture); + } else { + texture = RS::get_singleton()->texture_2d_create(image); } - VS::get_singleton()->texture_allocate(texture, image->get_width(), image->get_height(), 0, image->get_format(), VS::TEXTURE_TYPE_2D, lflags); - VS::get_singleton()->texture_set_data(texture, image); if (lwc || lhc) { - VS::get_singleton()->texture_set_size_override(texture, lwc, lhc, 0); - } else { + RS::get_singleton()->texture_set_size_override(texture, lwc, lhc); } w = lwc ? lwc : lw; h = lhc ? lhc : lh; - flags = lflags; path_to_file = p_path; format = image->get_format(); + if (get_path() == String()) { + //temporarily set path if no path set for resource, helps find errors + RenderingServer::get_singleton()->texture_set_path(texture, p_path); + } + +#ifdef TOOLS_ENABLED + + if (request_3d) { + //print_line("request detect 3D at " + p_path); + RS::get_singleton()->texture_set_detect_3d_callback(texture, _requested_3d, this); + } else { + //print_line("not requesting detect 3D at " + p_path); + RS::get_singleton()->texture_set_detect_3d_callback(texture, nullptr, nullptr); + } + + if (request_roughness) { + //print_line("request detect srgb at " + p_path); + RS::get_singleton()->texture_set_detect_roughness_callback(texture, _requested_roughness, this); + } else { + //print_line("not requesting detect srgb at " + p_path); + RS::get_singleton()->texture_set_detect_roughness_callback(texture, nullptr, nullptr); + } + + if (request_normal) { + //print_line("request detect srgb at " + p_path); + RS::get_singleton()->texture_set_detect_normal_callback(texture, _requested_normal, this); + } else { + //print_line("not requesting detect normal at " + p_path); + RS::get_singleton()->texture_set_detect_normal_callback(texture, nullptr, nullptr); + } + +#endif _change_notify(); emit_changed(); return OK; } -String StreamTexture::get_load_path() const { +String StreamTexture2D::get_load_path() const { return path_to_file; } -int StreamTexture::get_width() const { - +int StreamTexture2D::get_width() const { return w; } -int StreamTexture::get_height() const { +int StreamTexture2D::get_height() const { return h; } -RID StreamTexture::get_rid() const { +RID StreamTexture2D::get_rid() const { + if (!texture.is_valid()) { + texture = RS::get_singleton()->texture_2d_placeholder_create(); + } return texture; } -void StreamTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { - - if ((w | h) == 0) +void StreamTexture2D::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { + if ((w | h) == 0) { return; + } RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose, normal_rid); + RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void StreamTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { - if ((w | h) == 0) +void StreamTexture2D::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { + if ((w | h) == 0) { return; + } RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose, normal_rid); + RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void StreamTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const { - if ((w | h) == 0) +void StreamTexture2D::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { + if ((w | h) == 0) { return; + } RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid, p_clip_uv); + RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_clip_uv, p_texture_filter, p_texture_repeat); } -bool StreamTexture::has_alpha() const { - +bool StreamTexture2D::has_alpha() const { return false; } -Ref<Image> StreamTexture::get_data() const { - - return VS::get_singleton()->texture_get_data(texture); +Ref<Image> StreamTexture2D::get_data() const { + if (texture.is_valid()) { + return RS::get_singleton()->texture_2d_get(texture); + } else { + return Ref<Image>(); + } } -bool StreamTexture::is_pixel_opaque(int p_x, int p_y) const { - +bool StreamTexture2D::is_pixel_opaque(int p_x, int p_y) const { if (!alpha_cache.is_valid()) { Ref<Image> img = get_data(); if (img.is_valid()) { @@ -811,7 +707,6 @@ bool StreamTexture::is_pixel_opaque(int p_x, int p_y) const { } if (alpha_cache.is_valid()) { - int aw = int(alpha_cache->get_size().width); int ah = int(alpha_cache->get_size().height); if (aw == 0 || ah == 0) { @@ -829,191 +724,468 @@ bool StreamTexture::is_pixel_opaque(int p_x, int p_y) const { return true; } -void StreamTexture::set_flags(uint32_t p_flags) { - flags = p_flags; - VS::get_singleton()->texture_set_flags(texture, flags); - _change_notify("flags"); + +void StreamTexture2D::reload_from_file() { + String path = get_path(); + if (!path.is_resource_file()) { + return; + } + + path = ResourceLoader::path_remap(path); //remap for translation + path = ResourceLoader::import_remap(path); //remap for import + if (!path.is_resource_file()) { + return; + } + + load(path); +} + +void StreamTexture2D::_validate_property(PropertyInfo &property) const { +} + +void StreamTexture2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("load", "path"), &StreamTexture2D::load); + ClassDB::bind_method(D_METHOD("get_load_path"), &StreamTexture2D::get_load_path); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.stex"), "load", "get_load_path"); +} + +StreamTexture2D::StreamTexture2D() { + format = Image::FORMAT_MAX; + w = 0; + h = 0; +} + +StreamTexture2D::~StreamTexture2D() { + if (texture.is_valid()) { + RS::get_singleton()->free(texture); + } +} + +RES ResourceFormatLoaderStreamTexture2D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { + Ref<StreamTexture2D> st; + st.instance(); + Error err = st->load(p_path); + if (r_error) { + *r_error = err; + } + if (err != OK) { + return RES(); + } + + return st; +} + +void ResourceFormatLoaderStreamTexture2D::get_recognized_extensions(List<String> *p_extensions) const { + p_extensions->push_back("stex"); +} + +bool ResourceFormatLoaderStreamTexture2D::handles_type(const String &p_type) const { + return p_type == "StreamTexture2D"; +} + +String ResourceFormatLoaderStreamTexture2D::get_resource_type(const String &p_path) const { + if (p_path.get_extension().to_lower() == "stex") { + return "StreamTexture2D"; + } + return ""; +} + +//////////////////////////////////// + +TypedArray<Image> Texture3D::_get_data() const { + Vector<Ref<Image>> data = get_data(); + + TypedArray<Image> ret; + ret.resize(data.size()); + for (int i = 0; i < data.size(); i++) { + ret[i] = data[i]; + } + return ret; +} + +void Texture3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_format"), &Texture3D::get_format); + ClassDB::bind_method(D_METHOD("get_width"), &Texture3D::get_width); + ClassDB::bind_method(D_METHOD("get_height"), &Texture3D::get_height); + ClassDB::bind_method(D_METHOD("get_depth"), &Texture3D::get_depth); + ClassDB::bind_method(D_METHOD("has_mipmaps"), &Texture3D::has_mipmaps); + ClassDB::bind_method(D_METHOD("get_data"), &Texture3D::_get_data); +} +////////////////////////////////////////// + +Image::Format ImageTexture3D::get_format() const { + return format; +} +int ImageTexture3D::get_width() const { + return width; +} +int ImageTexture3D::get_height() const { + return height; +} +int ImageTexture3D::get_depth() const { + return depth; +} +bool ImageTexture3D::has_mipmaps() const { + return mipmaps; +} + +Error ImageTexture3D::_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const TypedArray<Image> &p_data) { + Vector<Ref<Image>> images; + images.resize(p_data.size()); + for (int i = 0; i < images.size(); i++) { + images.write[i] = p_data[i]; + } + return create(p_format, p_width, p_height, p_depth, p_mipmaps, images); +} + +void ImageTexture3D::_update(const TypedArray<Image> &p_data) { + Vector<Ref<Image>> images; + images.resize(p_data.size()); + for (int i = 0; i < images.size(); i++) { + images.write[i] = p_data[i]; + } + return update(images); +} + +Error ImageTexture3D::create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { + RID tex = RenderingServer::get_singleton()->texture_3d_create(p_format, p_width, p_height, p_depth, p_mipmaps, p_data); + ERR_FAIL_COND_V(tex.is_null(), ERR_CANT_CREATE); + + if (texture.is_valid()) { + RenderingServer::get_singleton()->texture_replace(texture, tex); + } + + return OK; +} + +void ImageTexture3D::update(const Vector<Ref<Image>> &p_data) { + ERR_FAIL_COND(!texture.is_valid()); + RenderingServer::get_singleton()->texture_3d_update(texture, p_data); +} + +Vector<Ref<Image>> ImageTexture3D::get_data() const { + ERR_FAIL_COND_V(!texture.is_valid(), Vector<Ref<Image>>()); + return RS::get_singleton()->texture_3d_get(texture); +} + +RID ImageTexture3D::get_rid() const { + if (!texture.is_valid()) { + texture = RS::get_singleton()->texture_3d_placeholder_create(); + } + return texture; +} +void ImageTexture3D::set_path(const String &p_path, bool p_take_over) { + if (texture.is_valid()) { + RenderingServer::get_singleton()->texture_set_path(texture, p_path); + } + + Resource::set_path(p_path, p_take_over); +} + +void ImageTexture3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("create", "format", "width", "height", "depth", "use_mipmaps", "data"), &ImageTexture3D::_create); + ClassDB::bind_method(D_METHOD("update", "data"), &ImageTexture3D::_update); +} + +ImageTexture3D::ImageTexture3D() { +} + +ImageTexture3D::~ImageTexture3D() { + if (texture.is_valid()) { + RS::get_singleton()->free(texture); + } +} + +//////////////////////////////////////////// + +void StreamTexture3D::set_path(const String &p_path, bool p_take_over) { + if (texture.is_valid()) { + RenderingServer::get_singleton()->texture_set_path(texture, p_path); + } + + Resource::set_path(p_path, p_take_over); +} + +Image::Format StreamTexture3D::get_format() const { + return format; +} + +Error StreamTexture3D::_load_data(const String &p_path, Vector<Ref<Image>> &r_data, Image::Format &r_format, int &r_width, int &r_height, int &r_depth, bool &r_mipmaps) { + FileAccessRef f = FileAccess::open(p_path, FileAccess::READ); + ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); + + uint8_t header[4]; + f->get_buffer(header, 4); + ERR_FAIL_COND_V(header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != 'L', ERR_FILE_UNRECOGNIZED); + + //stored as stream textures (used for lossless and lossy compression) + uint32_t version = f->get_32(); + + if (version > FORMAT_VERSION) { + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new."); + } + + r_depth = f->get_32(); //depth + f->get_32(); //ignored (mode) + f->get_32(); // ignored (data format) + + f->get_32(); //ignored + int mipmaps = f->get_32(); + f->get_32(); //ignored + f->get_32(); //ignored + + r_mipmaps = mipmaps != 0; + + r_data.clear(); + + for (int i = 0; i < (r_depth + mipmaps); i++) { + Ref<Image> image = StreamTexture2D::load_image_from_file(f, 0); + ERR_FAIL_COND_V(image.is_null() || image->empty(), ERR_CANT_OPEN); + if (i == 0) { + r_format = image->get_format(); + r_width = image->get_width(); + r_height = image->get_height(); + } + r_data.push_back(image); + } + + return OK; +} + +Error StreamTexture3D::load(const String &p_path) { + Vector<Ref<Image>> data; + + int tw, th, td; + Image::Format tfmt; + bool tmm; + + Error err = _load_data(p_path, data, tfmt, tw, th, td, tmm); + if (err) { + return err; + } + + if (texture.is_valid()) { + RID new_texture = RS::get_singleton()->texture_3d_create(tfmt, tw, th, td, tmm, data); + RS::get_singleton()->texture_replace(texture, new_texture); + } else { + texture = RS::get_singleton()->texture_3d_create(tfmt, tw, th, td, tmm, data); + } + + w = tw; + h = th; + d = td; + mipmaps = tmm; + format = tfmt; + + path_to_file = p_path; + + if (get_path() == String()) { + //temporarily set path if no path set for resource, helps find errors + RenderingServer::get_singleton()->texture_set_path(texture, p_path); + } + + _change_notify(); emit_changed(); + return OK; +} + +String StreamTexture3D::get_load_path() const { + return path_to_file; +} + +int StreamTexture3D::get_width() const { + return w; } -void StreamTexture::reload_from_file() { +int StreamTexture3D::get_height() const { + return h; +} +int StreamTexture3D::get_depth() const { + return d; +} + +bool StreamTexture3D::has_mipmaps() const { + return mipmaps; +} + +RID StreamTexture3D::get_rid() const { + if (!texture.is_valid()) { + texture = RS::get_singleton()->texture_3d_placeholder_create(); + } + return texture; +} + +Vector<Ref<Image>> StreamTexture3D::get_data() const { + if (texture.is_valid()) { + return RS::get_singleton()->texture_3d_get(texture); + } else { + return Vector<Ref<Image>>(); + } +} + +void StreamTexture3D::reload_from_file() { String path = get_path(); - if (!path.is_resource_file()) + if (!path.is_resource_file()) { return; + } path = ResourceLoader::path_remap(path); //remap for translation path = ResourceLoader::import_remap(path); //remap for import - if (!path.is_resource_file()) + if (!path.is_resource_file()) { return; + } load(path); } -void StreamTexture::_validate_property(PropertyInfo &property) const { - if (property.name == "flags") { - property.usage = PROPERTY_USAGE_NOEDITOR; - } +void StreamTexture3D::_validate_property(PropertyInfo &property) const { } -void StreamTexture::_bind_methods() { - - ClassDB::bind_method(D_METHOD("load", "path"), &StreamTexture::load); - ClassDB::bind_method(D_METHOD("get_load_path"), &StreamTexture::get_load_path); +void StreamTexture3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("load", "path"), &StreamTexture3D::load); + ClassDB::bind_method(D_METHOD("get_load_path"), &StreamTexture3D::get_load_path); ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.stex"), "load", "get_load_path"); } -StreamTexture::StreamTexture() { - +StreamTexture3D::StreamTexture3D() { format = Image::FORMAT_MAX; - flags = 0; w = 0; h = 0; - - texture = VS::get_singleton()->texture_create(); + d = 0; + mipmaps = false; } -StreamTexture::~StreamTexture() { - - VS::get_singleton()->free(texture); +StreamTexture3D::~StreamTexture3D() { + if (texture.is_valid()) { + RS::get_singleton()->free(texture); + } } -RES ResourceFormatLoaderStreamTexture::load(const String &p_path, const String &p_original_path, Error *r_error) { +///////////////////////////// - Ref<StreamTexture> st; +RES ResourceFormatLoaderStreamTexture3D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { + Ref<StreamTexture3D> st; st.instance(); Error err = st->load(p_path); - if (r_error) + if (r_error) { *r_error = err; - if (err != OK) + } + if (err != OK) { return RES(); + } return st; } -void ResourceFormatLoaderStreamTexture::get_recognized_extensions(List<String> *p_extensions) const { - - p_extensions->push_back("stex"); +void ResourceFormatLoaderStreamTexture3D::get_recognized_extensions(List<String> *p_extensions) const { + p_extensions->push_back("stex3d"); } -bool ResourceFormatLoaderStreamTexture::handles_type(const String &p_type) const { - return p_type == "StreamTexture"; + +bool ResourceFormatLoaderStreamTexture3D::handles_type(const String &p_type) const { + return p_type == "StreamTexture3D"; } -String ResourceFormatLoaderStreamTexture::get_resource_type(const String &p_path) const { - if (p_path.get_extension().to_lower() == "stex") - return "StreamTexture"; +String ResourceFormatLoaderStreamTexture3D::get_resource_type(const String &p_path) const { + if (p_path.get_extension().to_lower() == "stex3d") { + return "StreamTexture3D"; + } return ""; } -////////////////////////////////////////// +//////////////////////////////////////////// int AtlasTexture::get_width() const { - if (region.size.width == 0) { - if (atlas.is_valid()) + if (atlas.is_valid()) { return atlas->get_width(); + } return 1; } else { return region.size.width + margin.size.width; } } -int AtlasTexture::get_height() const { +int AtlasTexture::get_height() const { if (region.size.height == 0) { - if (atlas.is_valid()) + if (atlas.is_valid()) { return atlas->get_height(); + } return 1; } else { return region.size.height + margin.size.height; } } -RID AtlasTexture::get_rid() const { - if (atlas.is_valid()) +RID AtlasTexture::get_rid() const { + if (atlas.is_valid()) { return atlas->get_rid(); + } return RID(); } bool AtlasTexture::has_alpha() const { - - if (atlas.is_valid()) + if (atlas.is_valid()) { return atlas->has_alpha(); + } return false; } -void AtlasTexture::set_flags(uint32_t p_flags) { - - if (atlas.is_valid()) - atlas->set_flags(p_flags); -} - -uint32_t AtlasTexture::get_flags() const { - - if (atlas.is_valid()) - return atlas->get_flags(); - - return 0; -} - -void AtlasTexture::set_atlas(const Ref<Texture> &p_atlas) { - +void AtlasTexture::set_atlas(const Ref<Texture2D> &p_atlas) { ERR_FAIL_COND(p_atlas == this); - if (atlas == p_atlas) + if (atlas == p_atlas) { return; + } atlas = p_atlas; emit_changed(); _change_notify("atlas"); } -Ref<Texture> AtlasTexture::get_atlas() const { +Ref<Texture2D> AtlasTexture::get_atlas() const { return atlas; } void AtlasTexture::set_region(const Rect2 &p_region) { - - if (region == p_region) + if (region == p_region) { return; + } region = p_region; emit_changed(); _change_notify("region"); } Rect2 AtlasTexture::get_region() const { - return region; } void AtlasTexture::set_margin(const Rect2 &p_margin) { - - if (margin == p_margin) + if (margin == p_margin) { return; + } margin = p_margin; emit_changed(); _change_notify("margin"); } Rect2 AtlasTexture::get_margin() const { - return margin; } void AtlasTexture::set_filter_clip(const bool p_enable) { - filter_clip = p_enable; emit_changed(); _change_notify("filter_clip"); } bool AtlasTexture::has_filter_clip() const { - return filter_clip; } void AtlasTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_atlas", "atlas"), &AtlasTexture::set_atlas); ClassDB::bind_method(D_METHOD("get_atlas"), &AtlasTexture::get_atlas); @@ -1026,16 +1198,16 @@ void AtlasTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_filter_clip", "enable"), &AtlasTexture::set_filter_clip); ClassDB::bind_method(D_METHOD("has_filter_clip"), &AtlasTexture::has_filter_clip); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "atlas", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_atlas", "get_atlas"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "atlas", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_atlas", "get_atlas"); ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region"), "set_region", "get_region"); ADD_PROPERTY(PropertyInfo(Variant::RECT2, "margin"), "set_margin", "get_margin"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter_clip"), "set_filter_clip", "has_filter_clip"); } -void AtlasTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { - - if (!atlas.is_valid()) +void AtlasTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { + if (!atlas.is_valid()) { return; + } Rect2 rc = region; @@ -1048,13 +1220,14 @@ void AtlasTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_m } RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(p_pos + margin.position, rc.size), atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid, filter_clip); + RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); + RS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(p_pos + margin.position, rc.size), atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, filter_clip, p_texture_filter, p_texture_repeat); } -void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { - - if (!atlas.is_valid()) +void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { + if (!atlas.is_valid()) { return; + } Rect2 rc = region; @@ -1070,26 +1243,29 @@ void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile Rect2 dr(p_rect.position + margin.position * scale, rc.size * scale); RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid, filter_clip); + RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); + RS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, filter_clip, p_texture_filter, p_texture_repeat); } -void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const { +void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { //this might not necessarily work well if using a rect, needs to be fixed properly - if (!atlas.is_valid()) + if (!atlas.is_valid()) { return; + } Rect2 dr; Rect2 src_c; get_rect_region(p_rect, p_src_rect, dr, src_c); RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), src_c, p_modulate, p_transpose, normal_rid, filter_clip); + RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); + RS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), src_c, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, filter_clip, p_texture_filter, p_texture_repeat); } bool AtlasTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const { - - if (!atlas.is_valid()) + if (!atlas.is_valid()) { return false; + } Rect2 rc = region; @@ -1101,8 +1277,9 @@ bool AtlasTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, src.position += (rc.position - margin.position); Rect2 src_c = rc.clip(src); - if (src_c.size == Size2()) + if (src_c.size == Size2()) { return false; + } Vector2 ofs = (src_c.position - src.position); if (scale.x < 0) { @@ -1123,16 +1300,20 @@ bool AtlasTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, } bool AtlasTexture::is_pixel_opaque(int p_x, int p_y) const { - - if (!atlas.is_valid()) + if (!atlas.is_valid()) { return true; + } int x = p_x + region.position.x - margin.position.x; int y = p_y + region.position.y - margin.position.y; // margin edge may outside of atlas - if (x < 0 || x >= atlas->get_width()) return false; - if (y < 0 || y >= atlas->get_height()) return false; + if (x < 0 || x >= atlas->get_width()) { + return false; + } + if (y < 0 || y >= atlas->get_height()) { + return false; + } return atlas->is_pixel_opaque(x, y); } @@ -1146,9 +1327,11 @@ AtlasTexture::AtlasTexture() { int MeshTexture::get_width() const { return size.width; } + int MeshTexture::get_height() const { return size.height; } + RID MeshTexture::get_rid() const { return RID(); } @@ -1157,16 +1340,10 @@ bool MeshTexture::has_alpha() const { return false; } -void MeshTexture::set_flags(uint32_t p_flags) { -} - -uint32_t MeshTexture::get_flags() const { - return 0; -} - void MeshTexture::set_mesh(const Ref<Mesh> &p_mesh) { mesh = p_mesh; } + Ref<Mesh> MeshTexture::get_mesh() const { return mesh; } @@ -1176,20 +1353,18 @@ void MeshTexture::set_image_size(const Size2 &p_size) { } Size2 MeshTexture::get_image_size() const { - return size; } -void MeshTexture::set_base_texture(const Ref<Texture> &p_texture) { +void MeshTexture::set_base_texture(const Ref<Texture2D> &p_texture) { base_texture = p_texture; } -Ref<Texture> MeshTexture::get_base_texture() const { +Ref<Texture2D> MeshTexture::get_base_texture() const { return base_texture; } -void MeshTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { - +void MeshTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { if (mesh.is_null() || base_texture.is_null()) { return; } @@ -1200,9 +1375,11 @@ void MeshTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_mo SWAP(xform.elements[0][0], xform.elements[1][1]); } RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid); + RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); + RenderingServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void MeshTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { + +void MeshTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { if (mesh.is_null() || base_texture.is_null()) { return; } @@ -1222,10 +1399,11 @@ void MeshTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, SWAP(xform.elements[0][0], xform.elements[1][1]); } RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid); + RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); + RenderingServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void MeshTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const { +void MeshTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { if (mesh.is_null() || base_texture.is_null()) { return; } @@ -1245,8 +1423,10 @@ void MeshTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const SWAP(xform.elements[0][0], xform.elements[1][1]); } RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid); + RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); + RenderingServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } + bool MeshTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const { r_rect = p_rect; r_src_rect = p_src_rect; @@ -1266,7 +1446,7 @@ void MeshTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("get_base_texture"), &MeshTexture::get_base_texture); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "base_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_base_texture", "get_base_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "base_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_base_texture", "get_base_texture"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "image_size", PROPERTY_HINT_RANGE, "0,16384,1"), "set_image_size", "get_image_size"); } @@ -1276,45 +1456,28 @@ MeshTexture::MeshTexture() { ////////////////////////////////////////// int LargeTexture::get_width() const { - return size.width; } -int LargeTexture::get_height() const { +int LargeTexture::get_height() const { return size.height; } -RID LargeTexture::get_rid() const { +RID LargeTexture::get_rid() const { return RID(); } bool LargeTexture::has_alpha() const { - for (int i = 0; i < pieces.size(); i++) { - if (pieces[i].texture->has_alpha()) + if (pieces[i].texture->has_alpha()) { return true; + } } return false; } -void LargeTexture::set_flags(uint32_t p_flags) { - - for (int i = 0; i < pieces.size(); i++) { - pieces.write[i].texture->set_flags(p_flags); - } -} - -uint32_t LargeTexture::get_flags() const { - - if (pieces.size()) - return pieces[0].texture->get_flags(); - - return 0; -} - -int LargeTexture::add_piece(const Point2 &p_offset, const Ref<Texture> &p_texture) { - +int LargeTexture::add_piece(const Point2 &p_offset, const Ref<Texture2D> &p_texture) { ERR_FAIL_COND_V(p_texture.is_null(), -1); Piece p; p.offset = p_offset; @@ -1325,13 +1488,11 @@ int LargeTexture::add_piece(const Point2 &p_offset, const Ref<Texture> &p_textur } void LargeTexture::set_piece_offset(int p_idx, const Point2 &p_offset) { - ERR_FAIL_INDEX(p_idx, pieces.size()); pieces.write[p_idx].offset = p_offset; }; -void LargeTexture::set_piece_texture(int p_idx, const Ref<Texture> &p_texture) { - +void LargeTexture::set_piece_texture(int p_idx, const Ref<Texture2D> &p_texture) { ERR_FAIL_COND(p_texture == this); ERR_FAIL_COND(p_texture.is_null()); ERR_FAIL_INDEX(p_idx, pieces.size()); @@ -1339,17 +1500,15 @@ void LargeTexture::set_piece_texture(int p_idx, const Ref<Texture> &p_texture) { }; void LargeTexture::set_size(const Size2 &p_size) { - size = p_size; } -void LargeTexture::clear() { +void LargeTexture::clear() { pieces.clear(); size = Size2i(); } Array LargeTexture::_get_data() const { - Array arr; for (int i = 0; i < pieces.size(); i++) { arr.push_back(pieces[i].offset); @@ -1358,8 +1517,8 @@ Array LargeTexture::_get_data() const { arr.push_back(Size2(size)); return arr; } -void LargeTexture::_set_data(const Array &p_array) { +void LargeTexture::_set_data(const Array &p_array) { ERR_FAIL_COND(p_array.size() < 1); ERR_FAIL_COND(!(p_array.size() & 1)); clear(); @@ -1370,24 +1529,22 @@ void LargeTexture::_set_data(const Array &p_array) { } int LargeTexture::get_piece_count() const { - return pieces.size(); } -Vector2 LargeTexture::get_piece_offset(int p_idx) const { +Vector2 LargeTexture::get_piece_offset(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, pieces.size(), Vector2()); return pieces[p_idx].offset; } -Ref<Texture> LargeTexture::get_piece_texture(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, pieces.size(), Ref<Texture>()); +Ref<Texture2D> LargeTexture::get_piece_texture(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, pieces.size(), Ref<Texture2D>()); return pieces[p_idx].texture; } -Ref<Image> LargeTexture::to_image() const { +Ref<Image> LargeTexture::to_image() const { Ref<Image> img = memnew(Image(this->get_width(), this->get_height(), false, Image::FORMAT_RGBA8)); for (int i = 0; i < pieces.size(); i++) { - Ref<Image> src_img = pieces[i].texture->get_data(); img->blit_rect(src_img, Rect2(0, 0, src_img->get_width(), src_img->get_height()), pieces[i].offset); } @@ -1396,7 +1553,6 @@ Ref<Image> LargeTexture::to_image() const { } void LargeTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_piece", "ofs", "texture"), &LargeTexture::add_piece); ClassDB::bind_method(D_METHOD("set_piece_offset", "idx", "ofs"), &LargeTexture::set_piece_offset); ClassDB::bind_method(D_METHOD("set_piece_texture", "idx", "texture"), &LargeTexture::set_piece_texture); @@ -1413,59 +1569,56 @@ void LargeTexture::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); } -void LargeTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { - +void LargeTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { for (int i = 0; i < pieces.size(); i++) { - // TODO - pieces[i].texture->draw(p_canvas_item, pieces[i].offset + p_pos, p_modulate, p_transpose, p_normal_map); + pieces[i].texture->draw(p_canvas_item, pieces[i].offset + p_pos, p_modulate, p_transpose, p_normal_map, p_specular_map, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } } -void LargeTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map) const { - +void LargeTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { //tiling not supported for this - if (size.x == 0 || size.y == 0) + if (size.x == 0 || size.y == 0) { return; + } Size2 scale = p_rect.size / size; for (int i = 0; i < pieces.size(); i++) { - // TODO - pieces[i].texture->draw_rect(p_canvas_item, Rect2(pieces[i].offset * scale + p_rect.position, pieces[i].texture->get_size() * scale), false, p_modulate, p_transpose, p_normal_map); + pieces[i].texture->draw_rect(p_canvas_item, Rect2(pieces[i].offset * scale + p_rect.position, pieces[i].texture->get_size() * scale), false, p_modulate, p_transpose, p_normal_map, p_specular_map, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } } -void LargeTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture> &p_normal_map, bool p_clip_uv) const { +void LargeTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref<Texture2D> &p_normal_map, const Ref<Texture2D> &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { //tiling not supported for this - if (p_src_rect.size.x == 0 || p_src_rect.size.y == 0) + if (p_src_rect.size.x == 0 || p_src_rect.size.y == 0) { return; + } Size2 scale = p_rect.size / p_src_rect.size; for (int i = 0; i < pieces.size(); i++) { - // TODO Rect2 rect(pieces[i].offset, pieces[i].texture->get_size()); - if (!p_src_rect.intersects(rect)) + if (!p_src_rect.intersects(rect)) { continue; + } Rect2 local = p_src_rect.clip(rect); Rect2 target = local; target.size *= scale; target.position = p_rect.position + (p_src_rect.position + rect.position) * scale; local.position -= rect.position; - pieces[i].texture->draw_rect_region(p_canvas_item, target, local, p_modulate, p_transpose, p_normal_map, false); + pieces[i].texture->draw_rect_region(p_canvas_item, target, local, p_modulate, p_transpose, p_normal_map, p_specular_map, p_specular_color_shininess, p_texture_filter, p_texture_repeat, false); } } bool LargeTexture::is_pixel_opaque(int p_x, int p_y) const { - for (int i = 0; i < pieces.size(); i++) { - // TODO - if (!pieces[i].texture.is_valid()) + if (!pieces[i].texture.is_valid()) { continue; + } Rect2 rect(pieces[i].offset, pieces[i].texture->get_size()); if (rect.has_point(Point2(p_x, p_y))) { @@ -1479,214 +1632,9 @@ bool LargeTexture::is_pixel_opaque(int p_x, int p_y) const { LargeTexture::LargeTexture() { } -/////////////////////////////////////////////// - -void CubeMap::set_flags(uint32_t p_flags) { - - flags = p_flags; - if (_is_valid()) - VS::get_singleton()->texture_set_flags(cubemap, flags); -} - -uint32_t CubeMap::get_flags() const { - - return flags; -} - -void CubeMap::set_side(Side p_side, const Ref<Image> &p_image) { - - ERR_FAIL_COND(p_image.is_null()); - ERR_FAIL_COND(p_image->empty()); - ERR_FAIL_INDEX(p_side, 6); - - if (!_is_valid()) { - format = p_image->get_format(); - w = p_image->get_width(); - h = p_image->get_height(); - VS::get_singleton()->texture_allocate(cubemap, w, h, 0, p_image->get_format(), VS::TEXTURE_TYPE_CUBEMAP, flags); - } - - VS::get_singleton()->texture_set_data(cubemap, p_image, VS::CubeMapSide(p_side)); - valid[p_side] = true; -} - -Ref<Image> CubeMap::get_side(Side p_side) const { - - ERR_FAIL_INDEX_V(p_side, 6, Ref<Image>()); - if (!valid[p_side]) - return Ref<Image>(); - return VS::get_singleton()->texture_get_data(cubemap, VS::CubeMapSide(p_side)); -} - -Image::Format CubeMap::get_format() const { - - return format; -} -int CubeMap::get_width() const { - - return w; -} -int CubeMap::get_height() const { - - return h; -} - -RID CubeMap::get_rid() const { - - return cubemap; -} - -void CubeMap::set_storage(Storage p_storage) { - - storage = p_storage; -} - -CubeMap::Storage CubeMap::get_storage() const { - - return storage; -} - -void CubeMap::set_lossy_storage_quality(float p_lossy_storage_quality) { - - lossy_storage_quality = p_lossy_storage_quality; -} - -float CubeMap::get_lossy_storage_quality() const { - - return lossy_storage_quality; -} - -void CubeMap::set_path(const String &p_path, bool p_take_over) { - - if (cubemap.is_valid()) { - VisualServer::get_singleton()->texture_set_path(cubemap, p_path); - } - - Resource::set_path(p_path, p_take_over); -} - -bool CubeMap::_set(const StringName &p_name, const Variant &p_value) { - - if (p_name == "side/left") { - set_side(SIDE_LEFT, p_value); - } else if (p_name == "side/right") { - set_side(SIDE_RIGHT, p_value); - } else if (p_name == "side/bottom") { - set_side(SIDE_BOTTOM, p_value); - } else if (p_name == "side/top") { - set_side(SIDE_TOP, p_value); - } else if (p_name == "side/front") { - set_side(SIDE_FRONT, p_value); - } else if (p_name == "side/back") { - set_side(SIDE_BACK, p_value); - } else if (p_name == "storage") { - storage = Storage(p_value.operator int()); - } else if (p_name == "lossy_quality") { - lossy_storage_quality = p_value; - } else - return false; - - return true; -} - -bool CubeMap::_get(const StringName &p_name, Variant &r_ret) const { - - if (p_name == "side/left") { - r_ret = get_side(SIDE_LEFT); - } else if (p_name == "side/right") { - r_ret = get_side(SIDE_RIGHT); - } else if (p_name == "side/bottom") { - r_ret = get_side(SIDE_BOTTOM); - } else if (p_name == "side/top") { - r_ret = get_side(SIDE_TOP); - } else if (p_name == "side/front") { - r_ret = get_side(SIDE_FRONT); - } else if (p_name == "side/back") { - r_ret = get_side(SIDE_BACK); - } else if (p_name == "storage") { - r_ret = storage; - } else if (p_name == "lossy_quality") { - r_ret = lossy_storage_quality; - } else - return false; - - return true; -} - -void CubeMap::_get_property_list(List<PropertyInfo> *p_list) const { - - p_list->push_back(PropertyInfo(Variant::OBJECT, "side/left", PROPERTY_HINT_RESOURCE_TYPE, "Image")); - p_list->push_back(PropertyInfo(Variant::OBJECT, "side/right", PROPERTY_HINT_RESOURCE_TYPE, "Image")); - p_list->push_back(PropertyInfo(Variant::OBJECT, "side/bottom", PROPERTY_HINT_RESOURCE_TYPE, "Image")); - p_list->push_back(PropertyInfo(Variant::OBJECT, "side/top", PROPERTY_HINT_RESOURCE_TYPE, "Image")); - p_list->push_back(PropertyInfo(Variant::OBJECT, "side/front", PROPERTY_HINT_RESOURCE_TYPE, "Image")); - p_list->push_back(PropertyInfo(Variant::OBJECT, "side/back", PROPERTY_HINT_RESOURCE_TYPE, "Image")); -} - -void CubeMap::_bind_methods() { - - ClassDB::bind_method(D_METHOD("get_width"), &CubeMap::get_width); - ClassDB::bind_method(D_METHOD("get_height"), &CubeMap::get_height); - ClassDB::bind_method(D_METHOD("set_flags", "flags"), &CubeMap::set_flags); - ClassDB::bind_method(D_METHOD("get_flags"), &CubeMap::get_flags); - ClassDB::bind_method(D_METHOD("set_side", "side", "image"), &CubeMap::set_side); - ClassDB::bind_method(D_METHOD("get_side", "side"), &CubeMap::get_side); - ClassDB::bind_method(D_METHOD("set_storage", "mode"), &CubeMap::set_storage); - ClassDB::bind_method(D_METHOD("get_storage"), &CubeMap::get_storage); - ClassDB::bind_method(D_METHOD("set_lossy_storage_quality", "quality"), &CubeMap::set_lossy_storage_quality); - ClassDB::bind_method(D_METHOD("get_lossy_storage_quality"), &CubeMap::get_lossy_storage_quality); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Mipmaps,Repeat,Filter"), "set_flags", "get_flags"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "storage_mode", PROPERTY_HINT_ENUM, "Raw,Lossy Compressed,Lossless Compressed"), "set_storage", "get_storage"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "lossy_storage_quality"), "set_lossy_storage_quality", "get_lossy_storage_quality"); - - BIND_ENUM_CONSTANT(STORAGE_RAW); - BIND_ENUM_CONSTANT(STORAGE_COMPRESS_LOSSY); - BIND_ENUM_CONSTANT(STORAGE_COMPRESS_LOSSLESS); - - BIND_ENUM_CONSTANT(SIDE_LEFT); - BIND_ENUM_CONSTANT(SIDE_RIGHT); - BIND_ENUM_CONSTANT(SIDE_BOTTOM); - BIND_ENUM_CONSTANT(SIDE_TOP); - BIND_ENUM_CONSTANT(SIDE_FRONT); - BIND_ENUM_CONSTANT(SIDE_BACK); - - BIND_ENUM_CONSTANT(FLAG_MIPMAPS); - BIND_ENUM_CONSTANT(FLAG_REPEAT); - BIND_ENUM_CONSTANT(FLAG_FILTER); - BIND_ENUM_CONSTANT(FLAGS_DEFAULT); -} - -CubeMap::CubeMap() { - - w = h = 0; - flags = FLAGS_DEFAULT; - for (int i = 0; i < 6; i++) - valid[i] = false; - cubemap = VisualServer::get_singleton()->texture_create(); - storage = STORAGE_RAW; - lossy_storage_quality = 0.7; - format = Image::FORMAT_BPTC_RGBA; -} - -CubeMap::~CubeMap() { - - VisualServer::get_singleton()->free(cubemap); -} - -/* BIND_ENUM(CubeMapSize); - BIND_ENUM_CONSTANT( FLAG_CUBEMAP ); - BIND_ENUM_CONSTANT( CUBEMAP_LEFT ); - BIND_ENUM_CONSTANT( CUBEMAP_RIGHT ); - BIND_ENUM_CONSTANT( CUBEMAP_BOTTOM ); - BIND_ENUM_CONSTANT( CUBEMAP_TOP ); - BIND_ENUM_CONSTANT( CUBEMAP_FRONT ); - BIND_ENUM_CONSTANT( CUBEMAP_BACK ); -*/ -/////////////////////////// +/////////////////// void CurveTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_width", "width"), &CurveTexture::set_width); ClassDB::bind_method(D_METHOD("set_curve", "curve"), &CurveTexture::set_curve); @@ -1699,14 +1647,12 @@ void CurveTexture::_bind_methods() { } void CurveTexture::set_width(int p_width) { - ERR_FAIL_COND(p_width < 32 || p_width > 4096); _width = p_width; _update(); } int CurveTexture::get_width() const { - return _width; } @@ -1725,25 +1671,24 @@ void CurveTexture::ensure_default_setup(float p_min, float p_max) { void CurveTexture::set_curve(Ref<Curve> p_curve) { if (_curve != p_curve) { if (_curve.is_valid()) { - _curve->disconnect(CoreStringNames::get_singleton()->changed, this, "_update"); + _curve->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveTexture::_update)); } _curve = p_curve; if (_curve.is_valid()) { - _curve->connect(CoreStringNames::get_singleton()->changed, this, "_update"); + _curve->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &CurveTexture::_update)); } _update(); } } void CurveTexture::_update() { - - PoolVector<uint8_t> data; + Vector<uint8_t> data; data.resize(_width * sizeof(float)); // The array is locked in that scope { - PoolVector<uint8_t>::Write wd8 = data.write(); - float *wd = (float *)wd8.ptr(); + uint8_t *wd8 = data.ptrw(); + float *wd = (float *)wd8; if (_curve.is_valid()) { Curve &curve = **_curve; @@ -1761,29 +1706,37 @@ void CurveTexture::_update() { Ref<Image> image = memnew(Image(_width, 1, false, Image::FORMAT_RF, data)); - VS::get_singleton()->texture_allocate(_texture, _width, 1, 0, Image::FORMAT_RF, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_FILTER); - VS::get_singleton()->texture_set_data(_texture, image); + if (_texture.is_valid()) { + RID new_texture = RS::get_singleton()->texture_2d_create(image); + RS::get_singleton()->texture_replace(_texture, new_texture); + } else { + _texture = RS::get_singleton()->texture_2d_create(image); + } emit_changed(); } Ref<Curve> CurveTexture::get_curve() const { - return _curve; } RID CurveTexture::get_rid() const { - + if (!_texture.is_valid()) { + _texture = RS::get_singleton()->texture_2d_placeholder_create(); + } return _texture; } CurveTexture::CurveTexture() { _width = 2048; - _texture = VS::get_singleton()->texture_create(); } + CurveTexture::~CurveTexture() { - VS::get_singleton()->free(_texture); + if (_texture.is_valid()) { + RS::get_singleton()->free(_texture); + } } + ////////////////// //setter and getter names for property serialization @@ -1796,16 +1749,16 @@ GradientTexture::GradientTexture() { update_pending = false; width = 2048; - texture = VS::get_singleton()->texture_create(); _queue_update(); } GradientTexture::~GradientTexture() { - VS::get_singleton()->free(texture); + if (texture.is_valid()) { + RS::get_singleton()->free(texture); + } } void GradientTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_gradient", "gradient"), &GradientTexture::set_gradient); ClassDB::bind_method(D_METHOD("get_gradient"), &GradientTexture::get_gradient); @@ -1818,14 +1771,15 @@ void GradientTexture::_bind_methods() { } void GradientTexture::set_gradient(Ref<Gradient> p_gradient) { - if (p_gradient == gradient) + if (p_gradient == gradient) { return; + } if (gradient.is_valid()) { - gradient->disconnect(CoreStringNames::get_singleton()->changed, this, "_update"); + gradient->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &GradientTexture::_update)); } gradient = p_gradient; if (gradient.is_valid()) { - gradient->connect(CoreStringNames::get_singleton()->changed, this, "_update"); + gradient->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &GradientTexture::_update)); } _update(); emit_changed(); @@ -1836,29 +1790,28 @@ Ref<Gradient> GradientTexture::get_gradient() const { } void GradientTexture::_queue_update() { - - if (update_pending) + if (update_pending) { return; + } update_pending = true; call_deferred("_update"); } void GradientTexture::_update() { - update_pending = false; - if (gradient.is_null()) + if (gradient.is_null()) { return; + } - PoolVector<uint8_t> data; + Vector<uint8_t> data; data.resize(width * 4); { - PoolVector<uint8_t>::Write wd8 = data.write(); + uint8_t *wd8 = data.ptrw(); Gradient &g = **gradient; for (int i = 0; i < width; i++) { - float ofs = float(i) / (width - 1); Color color = g.get_color_at_offset(ofs); @@ -1871,99 +1824,107 @@ void GradientTexture::_update() { Ref<Image> image = memnew(Image(width, 1, false, Image::FORMAT_RGBA8, data)); - VS::get_singleton()->texture_allocate(texture, width, 1, 0, Image::FORMAT_RGBA8, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_FILTER); - VS::get_singleton()->texture_set_data(texture, image); + if (texture.is_valid()) { + RID new_texture = RS::get_singleton()->texture_2d_create(image); + RS::get_singleton()->texture_replace(texture, new_texture); + } else { + texture = RS::get_singleton()->texture_2d_create(image); + } emit_changed(); } void GradientTexture::set_width(int p_width) { - width = p_width; _queue_update(); } -int GradientTexture::get_width() const { +int GradientTexture::get_width() const { return width; } Ref<Image> GradientTexture::get_data() const { - return VisualServer::get_singleton()->texture_get_data(texture); + if (!texture.is_valid()) { + return Ref<Image>(); + } + return RenderingServer::get_singleton()->texture_2d_get(texture); } ////////////////////////////////////// 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, "Texture"), "set_base", "get_base"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "base", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_base", "get_base"); } -void ProxyTexture::set_base(const Ref<Texture> &p_texture) { - +void ProxyTexture::set_base(const Ref<Texture2D> &p_texture) { ERR_FAIL_COND(p_texture == this); + base = p_texture; if (base.is_valid()) { - VS::get_singleton()->texture_set_proxy(proxy, base->get_rid()); - } else { - VS::get_singleton()->texture_set_proxy(proxy, RID()); + if (proxy_ph.is_valid()) { + RS::get_singleton()->texture_proxy_update(proxy, base->get_rid()); + RS::get_singleton()->free(proxy_ph); + proxy_ph = RID(); + } else if (proxy.is_valid()) { + RS::get_singleton()->texture_proxy_update(proxy, base->get_rid()); + } else { + proxy = RS::get_singleton()->texture_proxy_create(base->get_rid()); + } } } -Ref<Texture> ProxyTexture::get_base() const { - +Ref<Texture2D> ProxyTexture::get_base() const { return base; } int ProxyTexture::get_width() const { - - if (base.is_valid()) + if (base.is_valid()) { return base->get_width(); + } return 1; } -int ProxyTexture::get_height() const { - if (base.is_valid()) +int ProxyTexture::get_height() const { + if (base.is_valid()) { return base->get_height(); + } return 1; } -RID ProxyTexture::get_rid() const { +RID ProxyTexture::get_rid() const { + if (proxy.is_null()) { + proxy_ph = RS::get_singleton()->texture_2d_placeholder_create(); + proxy = RS::get_singleton()->texture_proxy_create(proxy_ph); + } return proxy; } bool ProxyTexture::has_alpha() const { - - if (base.is_valid()) + if (base.is_valid()) { return base->has_alpha(); + } return false; } -void ProxyTexture::set_flags(uint32_t p_flags) { -} - -uint32_t ProxyTexture::get_flags() const { - - if (base.is_valid()) - return base->get_flags(); - return 0; -} - ProxyTexture::ProxyTexture() { - - proxy = VS::get_singleton()->texture_create(); + //proxy = RS::get_singleton()->texture_create(); } ProxyTexture::~ProxyTexture() { - - VS::get_singleton()->free(proxy); + if (proxy_ph.is_valid()) { + RS::get_singleton()->free(proxy_ph); + } + if (proxy.is_valid()) { + RS::get_singleton()->free(proxy); + } } + ////////////////////////////////////////////// void AnimatedTexture::_update_proxy() { - RWLockRead r(rw_lock); float delta; @@ -1987,15 +1948,20 @@ void AnimatedTexture::_update_proxy() { } int iter_max = frame_count; - while (iter_max) { + while (iter_max && !pause) { float frame_limit = limit + frames[current_frame].delay_sec; if (time > frame_limit) { current_frame++; if (current_frame >= frame_count) { - current_frame = 0; + if (oneshot) { + current_frame = frame_count - 1; + } else { + current_frame = 0; + } } time -= frame_limit; + _change_notify("current_frame"); } else { break; } @@ -2003,7 +1969,7 @@ void AnimatedTexture::_update_proxy() { } if (frames[current_frame].texture.is_valid()) { - VisualServer::get_singleton()->texture_set_proxy(proxy, frames[current_frame].texture->get_rid()); + RenderingServer::get_singleton()->texture_proxy_update(proxy, frames[current_frame].texture->get_rid()); } } @@ -2014,12 +1980,42 @@ void AnimatedTexture::set_frames(int p_frames) { frame_count = p_frames; } + int AnimatedTexture::get_frames() const { return frame_count; } -void AnimatedTexture::set_frame_texture(int p_frame, const Ref<Texture> &p_texture) { +void AnimatedTexture::set_current_frame(int p_frame) { + ERR_FAIL_COND(p_frame < 0 || p_frame >= frame_count); + + RWLockWrite r(rw_lock); + + current_frame = p_frame; +} + +int AnimatedTexture::get_current_frame() const { + return current_frame; +} + +void AnimatedTexture::set_pause(bool p_pause) { + RWLockWrite r(rw_lock); + pause = p_pause; +} + +bool AnimatedTexture::get_pause() const { + return pause; +} + +void AnimatedTexture::set_oneshot(bool p_oneshot) { + RWLockWrite r(rw_lock); + oneshot = p_oneshot; +} + +bool AnimatedTexture::get_oneshot() const { + return oneshot; +} +void AnimatedTexture::set_frame_texture(int p_frame, const Ref<Texture2D> &p_texture) { ERR_FAIL_COND(p_texture == this); ERR_FAIL_INDEX(p_frame, MAX_FRAMES); @@ -2027,8 +2023,9 @@ void AnimatedTexture::set_frame_texture(int p_frame, const Ref<Texture> &p_textu frames[p_frame].texture = p_texture; } -Ref<Texture> AnimatedTexture::get_frame_texture(int p_frame) const { - ERR_FAIL_INDEX_V(p_frame, MAX_FRAMES, Ref<Texture>()); + +Ref<Texture2D> AnimatedTexture::get_frame_texture(int p_frame) const { + ERR_FAIL_INDEX_V(p_frame, MAX_FRAMES, Ref<Texture2D>()); RWLockRead r(rw_lock); @@ -2042,6 +2039,7 @@ void AnimatedTexture::set_frame_delay(int p_frame, float p_delay_sec) { frames[p_frame].delay_sec = p_delay_sec; } + float AnimatedTexture::get_frame_delay(int p_frame) const { ERR_FAIL_INDEX_V(p_frame, MAX_FRAMES, 0); @@ -2055,6 +2053,7 @@ void AnimatedTexture::set_fps(float p_fps) { fps = p_fps; } + float AnimatedTexture::get_fps() const { return fps; } @@ -2068,6 +2067,7 @@ int AnimatedTexture::get_width() const { return frames[current_frame].texture->get_width(); } + int AnimatedTexture::get_height() const { RWLockRead r(rw_lock); @@ -2077,12 +2077,12 @@ int AnimatedTexture::get_height() const { return frames[current_frame].texture->get_height(); } + RID AnimatedTexture::get_rid() const { return proxy; } bool AnimatedTexture::has_alpha() const { - RWLockRead r(rw_lock); if (!frames[current_frame].texture.is_valid()) { @@ -2093,7 +2093,6 @@ bool AnimatedTexture::has_alpha() const { } Ref<Image> AnimatedTexture::get_data() const { - RWLockRead r(rw_lock); if (!frames[current_frame].texture.is_valid()) { @@ -2104,7 +2103,6 @@ Ref<Image> AnimatedTexture::get_data() const { } bool AnimatedTexture::is_pixel_opaque(int p_x, int p_y) const { - RWLockRead r(rw_lock); if (frames[current_frame].texture.is_valid()) { @@ -2113,21 +2111,7 @@ bool AnimatedTexture::is_pixel_opaque(int p_x, int p_y) const { return true; } -void AnimatedTexture::set_flags(uint32_t p_flags) { -} -uint32_t AnimatedTexture::get_flags() const { - - RWLockRead r(rw_lock); - - if (!frames[current_frame].texture.is_valid()) { - return 0; - } - - return frames[current_frame].texture->get_flags(); -} - void AnimatedTexture::_validate_property(PropertyInfo &property) const { - String prop = property.name; if (prop.begins_with("frame_")) { int frame = prop.get_slicec('/', 0).get_slicec('_', 1).to_int(); @@ -2141,6 +2125,15 @@ void AnimatedTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_frames", "frames"), &AnimatedTexture::set_frames); ClassDB::bind_method(D_METHOD("get_frames"), &AnimatedTexture::get_frames); + ClassDB::bind_method(D_METHOD("set_current_frame", "frame"), &AnimatedTexture::set_current_frame); + ClassDB::bind_method(D_METHOD("get_current_frame"), &AnimatedTexture::get_current_frame); + + ClassDB::bind_method(D_METHOD("set_pause", "pause"), &AnimatedTexture::set_pause); + ClassDB::bind_method(D_METHOD("get_pause"), &AnimatedTexture::get_pause); + + ClassDB::bind_method(D_METHOD("set_oneshot", "oneshot"), &AnimatedTexture::set_oneshot); + ClassDB::bind_method(D_METHOD("get_oneshot"), &AnimatedTexture::get_oneshot); + ClassDB::bind_method(D_METHOD("set_fps", "fps"), &AnimatedTexture::set_fps); ClassDB::bind_method(D_METHOD("get_fps"), &AnimatedTexture::get_fps); @@ -2150,374 +2143,438 @@ void AnimatedTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_frame_delay", "frame", "delay"), &AnimatedTexture::set_frame_delay); ClassDB::bind_method(D_METHOD("get_frame_delay", "frame"), &AnimatedTexture::get_frame_delay); - ClassDB::bind_method(D_METHOD("_update_proxy"), &AnimatedTexture::_update_proxy); - ADD_PROPERTY(PropertyInfo(Variant::INT, "frames", PROPERTY_HINT_RANGE, "1," + itos(MAX_FRAMES), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_frames", "get_frames"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "fps", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_fps", "get_fps"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "current_frame", PROPERTY_HINT_NONE, "", 0), "set_current_frame", "get_current_frame"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pause"), "set_pause", "get_pause"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "oneshot"), "set_oneshot", "get_oneshot"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fps", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_fps", "get_fps"); for (int i = 0; i < MAX_FRAMES; i++) { - ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "frame_" + itos(i) + "/texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_frame_texture", "get_frame_texture", i); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "frame_" + itos(i) + "/delay_sec", PROPERTY_HINT_RANGE, "0.0,16.0,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_frame_delay", "get_frame_delay", i); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "frame_" + itos(i) + "/texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_frame_texture", "get_frame_texture", i); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "frame_" + itos(i) + "/delay_sec", PROPERTY_HINT_RANGE, "0.0,16.0,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_INTERNAL), "set_frame_delay", "get_frame_delay", i); } BIND_CONSTANT(MAX_FRAMES); } AnimatedTexture::AnimatedTexture() { - proxy = VS::get_singleton()->texture_create(); - VisualServer::get_singleton()->texture_set_force_redraw_if_visible(proxy, true); + //proxy = RS::get_singleton()->texture_create(); + proxy_ph = RS::get_singleton()->texture_2d_placeholder_create(); + proxy = RS::get_singleton()->texture_proxy_create(proxy_ph); + + RenderingServer::get_singleton()->texture_set_force_redraw_if_visible(proxy, true); time = 0; frame_count = 1; fps = 4; prev_ticks = 0; current_frame = 0; - VisualServer::get_singleton()->connect("frame_pre_draw", this, "_update_proxy"); + pause = false; + oneshot = false; + RenderingServer::get_singleton()->connect("frame_pre_draw", callable_mp(this, &AnimatedTexture::_update_proxy)); #ifndef NO_THREADS rw_lock = RWLock::create(); #else - rw_lock = NULL; + rw_lock = nullptr; #endif } AnimatedTexture::~AnimatedTexture() { - VS::get_singleton()->free(proxy); + RS::get_singleton()->free(proxy); + RS::get_singleton()->free(proxy_ph); if (rw_lock) { memdelete(rw_lock); } } -/////////////////////////////// -void TextureLayered::set_flags(uint32_t p_flags) { - flags = p_flags; +/////////////////////////////// - if (texture.is_valid()) { - VS::get_singleton()->texture_set_flags(texture, flags); - } -} +void TextureLayered::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_format"), &TextureLayered::get_format); + ClassDB::bind_method(D_METHOD("get_layered_type"), &TextureLayered::get_layered_type); + ClassDB::bind_method(D_METHOD("get_width"), &TextureLayered::get_width); + ClassDB::bind_method(D_METHOD("get_height"), &TextureLayered::get_height); + ClassDB::bind_method(D_METHOD("get_layers"), &TextureLayered::get_layers); + ClassDB::bind_method(D_METHOD("has_mipmaps"), &TextureLayered::has_mipmaps); + ClassDB::bind_method(D_METHOD("get_layer_data", "layer"), &TextureLayered::get_layer_data); -uint32_t TextureLayered::get_flags() const { - return flags; + BIND_ENUM_CONSTANT(LAYERED_TYPE_2D_ARRAY); + BIND_ENUM_CONSTANT(LAYERED_TYPE_CUBEMAP); + BIND_ENUM_CONSTANT(LAYERED_TYPE_CUBEMAP_ARRAY); } -Image::Format TextureLayered::get_format() const { +/////////////////////////////// +Image::Format ImageTextureLayered::get_format() const { return format; } -uint32_t TextureLayered::get_width() const { +int ImageTextureLayered::get_width() const { return width; } -uint32_t TextureLayered::get_height() const { +int ImageTextureLayered::get_height() const { return height; } -uint32_t TextureLayered::get_depth() const { - return depth; +int ImageTextureLayered::get_layers() const { + return layers; } -void TextureLayered::_set_data(const Dictionary &p_data) { - ERR_FAIL_COND(!p_data.has("width")); - ERR_FAIL_COND(!p_data.has("height")); - ERR_FAIL_COND(!p_data.has("depth")); - ERR_FAIL_COND(!p_data.has("format")); - ERR_FAIL_COND(!p_data.has("flags")); - ERR_FAIL_COND(!p_data.has("layers")); - int w = p_data["width"]; - int h = p_data["height"]; - int d = p_data["depth"]; - Image::Format format = Image::Format(int(p_data["format"])); - int flags = p_data["flags"]; - Array layers = p_data["layers"]; - ERR_FAIL_COND(layers.size() != d); - - create(w, h, d, format, flags); - - for (int i = 0; i < layers.size(); i++) { - Ref<Image> img = layers[i]; - ERR_CONTINUE(!img.is_valid()); - ERR_CONTINUE(img->get_format() != format); - ERR_CONTINUE(img->get_width() != w); - ERR_CONTINUE(img->get_height() != h); - set_layer_data(img, i); - } -} - -Dictionary TextureLayered::_get_data() const { - Dictionary d; - d["width"] = width; - d["height"] = height; - d["depth"] = depth; - d["flags"] = flags; - d["format"] = format; - - Array layers; - for (int i = 0; i < depth; i++) { - layers.push_back(get_layer_data(i)); - } - d["layers"] = layers; - return d; +bool ImageTextureLayered::has_mipmaps() const { + return mipmaps; } -void TextureLayered::create(uint32_t p_width, uint32_t p_height, uint32_t p_depth, Image::Format p_format, uint32_t p_flags) { - VS::get_singleton()->texture_allocate(texture, p_width, p_height, p_depth, p_format, is_3d ? VS::TEXTURE_TYPE_3D : VS::TEXTURE_TYPE_2D_ARRAY, p_flags); +ImageTextureLayered::LayeredType ImageTextureLayered::get_layered_type() const { + return layered_type; +} - width = p_width; - height = p_height; - depth = p_depth; - format = p_format; - flags = p_flags; +Error ImageTextureLayered::_create_from_images(const Array &p_images) { + Vector<Ref<Image>> images; + for (int i = 0; i < p_images.size(); i++) { + Ref<Image> img = p_images[i]; + ERR_FAIL_COND_V(img.is_null(), ERR_INVALID_PARAMETER); + images.push_back(img); + } + + return create_from_images(images); } -void TextureLayered::set_layer_data(const Ref<Image> &p_image, int p_layer) { - ERR_FAIL_COND(!texture.is_valid()); - ERR_FAIL_COND(!p_image.is_valid()); - VS::get_singleton()->texture_set_data(texture, p_image, p_layer); +Array ImageTextureLayered::_get_images() const { + Array images; + for (int i = 0; i < layers; i++) { + images.push_back(get_layer_data(i)); + } + return images; } -Ref<Image> TextureLayered::get_layer_data(int p_layer) const { +Error ImageTextureLayered::create_from_images(Vector<Ref<Image>> p_images) { + int new_layers = p_images.size(); + ERR_FAIL_COND_V(new_layers == 0, ERR_INVALID_PARAMETER); + if (layered_type == LAYERED_TYPE_CUBEMAP) { + ERR_FAIL_COND_V_MSG(new_layers != 6, ERR_INVALID_PARAMETER, + "Cubemaps require exactly 6 layers"); + } else if (layered_type == LAYERED_TYPE_CUBEMAP_ARRAY) { + ERR_FAIL_COND_V_MSG((new_layers % 6) != 0, ERR_INVALID_PARAMETER, + "Cubemap array layers must be a multiple of 6"); + } + + ERR_FAIL_COND_V(p_images[0].is_null() || p_images[0]->empty(), ERR_INVALID_PARAMETER); + + Image::Format new_format = p_images[0]->get_format(); + int new_width = p_images[0]->get_width(); + int new_height = p_images[0]->get_height(); + bool new_mipmaps = p_images[0]->has_mipmaps(); + + for (int i = 1; i < p_images.size(); i++) { + ERR_FAIL_COND_V_MSG(p_images[i]->get_format() != new_format, ERR_INVALID_PARAMETER, + "All images must share the same format"); + ERR_FAIL_COND_V_MSG(p_images[i]->get_width() != new_width || p_images[i]->get_height() != new_height, ERR_INVALID_PARAMETER, + "All images must share the same dimensions"); + ERR_FAIL_COND_V_MSG(p_images[i]->has_mipmaps() != new_mipmaps, ERR_INVALID_PARAMETER, + "All images must share the usage of mipmaps"); + } + + if (texture.is_valid()) { + RID new_texture = RS::get_singleton()->texture_2d_layered_create(p_images, RS::TextureLayeredType(layered_type)); + ERR_FAIL_COND_V(!new_texture.is_valid(), ERR_CANT_CREATE); + RS::get_singleton()->texture_replace(texture, new_texture); + } else { + texture = RS::get_singleton()->texture_2d_layered_create(p_images, RS::TextureLayeredType(layered_type)); + ERR_FAIL_COND_V(!texture.is_valid(), ERR_CANT_CREATE); + } + + format = new_format; + width = new_width; + height = new_height; + layers = new_layers; + mipmaps = new_mipmaps; + return OK; +} - ERR_FAIL_COND_V(!texture.is_valid(), Ref<Image>()); - return VS::get_singleton()->texture_get_data(texture, p_layer); +void ImageTextureLayered::update_layer(const Ref<Image> &p_image, int p_layer) { + ERR_FAIL_COND(texture.is_valid()); + ERR_FAIL_COND(p_image.is_null()); + ERR_FAIL_COND(p_image->get_format() != format); + ERR_FAIL_COND(p_image->get_width() != width || p_image->get_height() != height); + ERR_FAIL_INDEX(p_layer, layers); + ERR_FAIL_COND(p_image->has_mipmaps() != mipmaps); + RS::get_singleton()->texture_2d_update(texture, p_image, p_layer); } -void TextureLayered::set_data_partial(const Ref<Image> &p_image, int p_x_ofs, int p_y_ofs, int p_z, int p_mipmap) { - ERR_FAIL_COND(!texture.is_valid()); - ERR_FAIL_COND(!p_image.is_valid()); - VS::get_singleton()->texture_set_data_partial(texture, p_image, 0, 0, p_image->get_width(), p_image->get_height(), p_x_ofs, p_y_ofs, p_mipmap, p_z); +Ref<Image> ImageTextureLayered::get_layer_data(int p_layer) const { + ERR_FAIL_INDEX_V(p_layer, layers, Ref<Image>()); + return RS::get_singleton()->texture_2d_layer_get(texture, p_layer); } -RID TextureLayered::get_rid() const { +RID ImageTextureLayered::get_rid() const { + if (texture.is_null()) { + texture = RS::get_singleton()->texture_2d_layered_placeholder_create(RS::TextureLayeredType(layered_type)); + } return texture; } -void TextureLayered::set_path(const String &p_path, bool p_take_over) { +void ImageTextureLayered::set_path(const String &p_path, bool p_take_over) { if (texture.is_valid()) { - VS::get_singleton()->texture_set_path(texture, p_path); + RS::get_singleton()->texture_set_path(texture, p_path); } Resource::set_path(p_path, p_take_over); } -void TextureLayered::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_flags", "flags"), &TextureLayered::set_flags); - ClassDB::bind_method(D_METHOD("get_flags"), &TextureLayered::get_flags); - - ClassDB::bind_method(D_METHOD("get_format"), &TextureLayered::get_format); - - ClassDB::bind_method(D_METHOD("get_width"), &TextureLayered::get_width); - ClassDB::bind_method(D_METHOD("get_height"), &TextureLayered::get_height); - ClassDB::bind_method(D_METHOD("get_depth"), &TextureLayered::get_depth); - - ClassDB::bind_method(D_METHOD("create", "width", "height", "depth", "format", "flags"), &TextureLayered::create, DEFVAL(FLAGS_DEFAULT)); - ClassDB::bind_method(D_METHOD("set_layer_data", "image", "layer"), &TextureLayered::set_layer_data); - ClassDB::bind_method(D_METHOD("get_layer_data", "layer"), &TextureLayered::get_layer_data); - ClassDB::bind_method(D_METHOD("set_data_partial", "image", "x_offset", "y_offset", "layer", "mipmap"), &TextureLayered::set_data_partial, DEFVAL(0)); - - ClassDB::bind_method(D_METHOD("_set_data", "data"), &TextureLayered::_set_data); - ClassDB::bind_method(D_METHOD("_get_data"), &TextureLayered::_get_data); +void ImageTextureLayered::_bind_methods() { + ClassDB::bind_method(D_METHOD("create_from_images", "images"), &ImageTextureLayered::_create_from_images); + ClassDB::bind_method(D_METHOD("update_layer", "image", "layer"), &ImageTextureLayered::update_layer); - ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Mipmaps,Repeat,Filter"), "set_flags", "get_flags"); - ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_data", "_get_data"); + ClassDB::bind_method(D_METHOD("_get_images"), &ImageTextureLayered::_get_images); - BIND_ENUM_CONSTANT(FLAG_MIPMAPS); - BIND_ENUM_CONSTANT(FLAG_REPEAT); - BIND_ENUM_CONSTANT(FLAG_FILTER); - BIND_ENUM_CONSTANT(FLAGS_DEFAULT); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_images", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_INTERNAL), "create_from_images", "_get_images"); } -TextureLayered::TextureLayered(bool p_3d) { - is_3d = p_3d; +ImageTextureLayered::ImageTextureLayered(LayeredType p_layered_type) { + layered_type = p_layered_type; format = Image::FORMAT_MAX; - flags = FLAGS_DEFAULT; width = 0; height = 0; - depth = 0; - - texture = VS::get_singleton()->texture_create(); + layers = 0; } -TextureLayered::~TextureLayered() { +ImageTextureLayered::~ImageTextureLayered() { if (texture.is_valid()) { - VS::get_singleton()->free(texture); + RS::get_singleton()->free(texture); } } -RES ResourceFormatLoaderTextureLayered::load(const String &p_path, const String &p_original_path, Error *r_error) { +/////////////////////////////////////////// - if (r_error) { - *r_error = ERR_CANT_OPEN; +void StreamTextureLayered::set_path(const String &p_path, bool p_take_over) { + if (texture.is_valid()) { + RenderingServer::get_singleton()->texture_set_path(texture, p_path); } - Ref<TextureLayered> lt; - Ref<Texture3D> tex3d; - Ref<TextureArray> texarr; + Resource::set_path(p_path, p_take_over); +} - if (p_path.ends_with("tex3d")) { - tex3d.instance(); - lt = tex3d; - } else if (p_path.ends_with("texarr")) { - texarr.instance(); - lt = texarr; - } else { - ERR_FAIL_V_MSG(RES(), "Unrecognized layered texture extension."); - } +Image::Format StreamTextureLayered::get_format() const { + return format; +} - FileAccess *f = FileAccess::open(p_path, FileAccess::READ); - ERR_FAIL_COND_V_MSG(!f, RES(), "Cannot open file '" + p_path + "'."); +Error StreamTextureLayered::_load_data(const String &p_path, Vector<Ref<Image>> &images, int &mipmap_limit, int p_size_limit) { + ERR_FAIL_COND_V(images.size() != 0, ERR_INVALID_PARAMETER); - uint8_t header[5] = { 0, 0, 0, 0, 0 }; + FileAccessRef f = FileAccess::open(p_path, FileAccess::READ); + ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); + + uint8_t header[4]; f->get_buffer(header, 4); + if (header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != 'L') { + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture layered file is corrupt (Bad header)."); + } - if (header[0] == 'G' && header[1] == 'D' && header[2] == '3' && header[3] == 'T') { - if (tex3d.is_null()) { - f->close(); - memdelete(f); - ERR_FAIL_COND_V(tex3d.is_null(), RES()) - } - } else if (header[0] == 'G' && header[1] == 'D' && header[2] == 'A' && header[3] == 'T') { - if (texarr.is_null()) { - f->close(); - memdelete(f); - ERR_FAIL_COND_V(texarr.is_null(), RES()) - } - } else { + uint32_t version = f->get_32(); - f->close(); - memdelete(f); - ERR_FAIL_V_MSG(RES(), "Unrecognized layered texture file format '" + String((const char *)header) + "'."); + if (version > FORMAT_VERSION) { + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new."); } - int tw = f->get_32(); - int th = f->get_32(); - int td = f->get_32(); - int flags = f->get_32(); //texture flags! - Image::Format format = Image::Format(f->get_32()); - uint32_t compression = f->get_32(); // 0 - lossless (PNG), 1 - vram, 2 - uncompressed + uint32_t layer_count = f->get_32(); //layer count + uint32_t type = f->get_32(); //layer count + ERR_FAIL_COND_V(type != layered_type, ERR_INVALID_DATA); - lt->create(tw, th, td, format, flags); + uint32_t df = f->get_32(); //data format + mipmap_limit = int(f->get_32()); + //reserved + f->get_32(); + f->get_32(); + f->get_32(); - for (int layer = 0; layer < td; layer++) { + if (!(df & FORMAT_BIT_STREAM)) { + p_size_limit = 0; + } - Ref<Image> image; - image.instance(); + images.resize(layer_count); - if (compression == COMPRESSION_LOSSLESS) { - //look for a PNG file inside + for (uint32_t i = 0; i < layer_count; i++) { + Ref<Image> image = StreamTexture2D::load_image_from_file(f, p_size_limit); + ERR_FAIL_COND_V(image.is_null() || image->empty(), ERR_CANT_OPEN); + images.write[i] = image; + } - int mipmaps = f->get_32(); - Vector<Ref<Image> > mipmap_images; + return OK; +} - for (int i = 0; i < mipmaps; i++) { - uint32_t size = f->get_32(); +Error StreamTextureLayered::load(const String &p_path) { + Vector<Ref<Image>> images; - PoolVector<uint8_t> pv; - pv.resize(size); - { - PoolVector<uint8_t>::Write w = pv.write(); - f->get_buffer(w.ptr(), size); - } + int mipmap_limit; - Ref<Image> img = Image::lossless_unpacker(pv); + Error err = _load_data(p_path, images, mipmap_limit); + if (err) { + return err; + } - if (img.is_null() || img->empty() || format != img->get_format()) { - if (r_error) { - *r_error = ERR_FILE_CORRUPT; - } - f->close(); - memdelete(f); - ERR_FAIL_V(RES()); - } + if (texture.is_valid()) { + RID new_texture = RS::get_singleton()->texture_2d_layered_create(images, RS::TextureLayeredType(layered_type)); + RS::get_singleton()->texture_replace(texture, new_texture); + } else { + texture = RS::get_singleton()->texture_2d_layered_create(images, RS::TextureLayeredType(layered_type)); + } - mipmap_images.push_back(img); - } + w = images[0]->get_width(); + h = images[0]->get_height(); + mipmaps = images[0]->has_mipmaps(); + format = images[0]->get_format(); + layers = images.size(); - if (mipmap_images.size() == 1) { + path_to_file = p_path; - image = mipmap_images[0]; + if (get_path() == String()) { + //temporarily set path if no path set for resource, helps find errors + RenderingServer::get_singleton()->texture_set_path(texture, p_path); + } - } else { - int total_size = Image::get_image_data_size(tw, th, format, true); - PoolVector<uint8_t> img_data; - img_data.resize(total_size); - - { - PoolVector<uint8_t>::Write w = img_data.write(); - - int ofs = 0; - for (int i = 0; i < mipmap_images.size(); i++) { - - PoolVector<uint8_t> id = mipmap_images[i]->get_data(); - int len = id.size(); - PoolVector<uint8_t>::Read r = id.read(); - copymem(&w[ofs], r.ptr(), len); - ofs += len; - } - } + _change_notify(); + emit_changed(); + return OK; +} - image->create(tw, th, true, format, img_data); - if (image->empty()) { - if (r_error) { - *r_error = ERR_FILE_CORRUPT; - } - f->close(); - memdelete(f); - ERR_FAIL_V(RES()); - } - } +String StreamTextureLayered::get_load_path() const { + return path_to_file; +} - } else { +int StreamTextureLayered::get_width() const { + return w; +} - //look for regular format - bool mipmaps = (flags & Texture::FLAG_MIPMAPS); - int total_size = Image::get_image_data_size(tw, th, format, mipmaps); +int StreamTextureLayered::get_height() const { + return h; +} - PoolVector<uint8_t> img_data; - img_data.resize(total_size); +int StreamTextureLayered::get_layers() const { + return layers; +} - { - PoolVector<uint8_t>::Write w = img_data.write(); - int bytes = f->get_buffer(w.ptr(), total_size); - if (bytes != total_size) { - if (r_error) { - *r_error = ERR_FILE_CORRUPT; - } - f->close(); - memdelete(f); - ERR_FAIL_V(RES()); - } - } +bool StreamTextureLayered::has_mipmaps() const { + return mipmaps; +} - image->create(tw, th, mipmaps, format, img_data); - } +TextureLayered::LayeredType StreamTextureLayered::get_layered_type() const { + return layered_type; +} + +RID StreamTextureLayered::get_rid() const { + if (!texture.is_valid()) { + texture = RS::get_singleton()->texture_2d_layered_placeholder_create(RS::TextureLayeredType(layered_type)); + } + return texture; +} + +Ref<Image> StreamTextureLayered::get_layer_data(int p_layer) const { + if (texture.is_valid()) { + return RS::get_singleton()->texture_2d_layer_get(texture, p_layer); + } else { + return Ref<Image>(); + } +} + +void StreamTextureLayered::reload_from_file() { + String path = get_path(); + if (!path.is_resource_file()) { + return; + } - lt->set_layer_data(image, layer); + path = ResourceLoader::path_remap(path); //remap for translation + path = ResourceLoader::import_remap(path); //remap for import + if (!path.is_resource_file()) { + return; } - if (r_error) - *r_error = OK; + load(path); +} - return lt; +void StreamTextureLayered::_validate_property(PropertyInfo &property) const { } -void ResourceFormatLoaderTextureLayered::get_recognized_extensions(List<String> *p_extensions) const { +void StreamTextureLayered::_bind_methods() { + ClassDB::bind_method(D_METHOD("load", "path"), &StreamTextureLayered::load); + ClassDB::bind_method(D_METHOD("get_load_path"), &StreamTextureLayered::get_load_path); - p_extensions->push_back("tex3d"); - p_extensions->push_back("texarr"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.stex"), "load", "get_load_path"); } -bool ResourceFormatLoaderTextureLayered::handles_type(const String &p_type) const { - return p_type == "Texture3D" || p_type == "TextureArray"; + +StreamTextureLayered::StreamTextureLayered(LayeredType p_type) { + layered_type = p_type; + format = Image::FORMAT_MAX; + w = 0; + h = 0; + layers = 0; + mipmaps = false; } -String ResourceFormatLoaderTextureLayered::get_resource_type(const String &p_path) const { - if (p_path.get_extension().to_lower() == "tex3d") - return "Texture3D"; - if (p_path.get_extension().to_lower() == "texarr") - return "TextureArray"; +StreamTextureLayered::~StreamTextureLayered() { + if (texture.is_valid()) { + RS::get_singleton()->free(texture); + } +} + +///////////////////////////////////////////////// + +RES ResourceFormatLoaderStreamTextureLayered::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { + Ref<StreamTextureLayered> st; + if (p_path.get_extension().to_lower() == "stexarray") { + Ref<StreamTexture2DArray> s; + s.instance(); + st = s; + } else if (p_path.get_extension().to_lower() == "scube") { + Ref<StreamCubemap> s; + s.instance(); + st = s; + } else if (p_path.get_extension().to_lower() == "scubearray") { + Ref<StreamCubemapArray> s; + s.instance(); + st = s; + } else { + if (r_error) { + *r_error = ERR_FILE_UNRECOGNIZED; + } + return RES(); + } + Error err = st->load(p_path); + if (r_error) { + *r_error = err; + } + if (err != OK) { + return RES(); + } + + return st; +} + +void ResourceFormatLoaderStreamTextureLayered::get_recognized_extensions(List<String> *p_extensions) const { + p_extensions->push_back("stexarray"); + p_extensions->push_back("scube"); + p_extensions->push_back("scubearray"); +} + +bool ResourceFormatLoaderStreamTextureLayered::handles_type(const String &p_type) const { + return p_type == "StreamTexture2DArray" || p_type == "StreamCubemap" || p_type == "StreamCubemapArray"; +} + +String ResourceFormatLoaderStreamTextureLayered::get_resource_type(const String &p_path) const { + if (p_path.get_extension().to_lower() == "stexarray") { + return "StreamTexture2DArray"; + } + if (p_path.get_extension().to_lower() == "scube") { + return "StreamCubemap"; + } + if (p_path.get_extension().to_lower() == "scubearray") { + return "StreamCubemapArray"; + } return ""; } +/////////////////////////////// + void CameraTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_camera_feed_id", "feed_id"), &CameraTexture::set_camera_feed_id); ClassDB::bind_method(D_METHOD("get_camera_feed_id"), &CameraTexture::get_camera_feed_id); diff --git a/scene/resources/texture.h b/scene/resources/texture.h index fa698d387b..eebbf4f233 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -33,6 +33,7 @@ #include "core/io/resource_loader.h" #include "core/math/rect2.h" +#include "core/os/file_access.h" #include "core/os/mutex.h" #include "core/os/rw_lock.h" #include "core/os/thread_safe.h" @@ -40,137 +41,107 @@ #include "scene/resources/curve.h" #include "scene/resources/gradient.h" #include "servers/camera_server.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" class Texture : public Resource { - GDCLASS(Texture, Resource); - OBJ_SAVE_TYPE(Texture); // Saves derived classes with common type so they can be interchanged. + +public: + Texture() {} +}; + +class Texture2D : public Texture { + GDCLASS(Texture2D, Texture); + OBJ_SAVE_TYPE(Texture2D); // Saves derived classes with common type so they can be interchanged. protected: static void _bind_methods(); public: - enum Flags { - FLAG_MIPMAPS = VisualServer::TEXTURE_FLAG_MIPMAPS, - FLAG_REPEAT = VisualServer::TEXTURE_FLAG_REPEAT, - FLAG_FILTER = VisualServer::TEXTURE_FLAG_FILTER, - FLAG_ANISOTROPIC_FILTER = VisualServer::TEXTURE_FLAG_ANISOTROPIC_FILTER, - FLAG_CONVERT_TO_LINEAR = VisualServer::TEXTURE_FLAG_CONVERT_TO_LINEAR, - FLAG_VIDEO_SURFACE = VisualServer::TEXTURE_FLAG_USED_FOR_STREAMING, - FLAGS_DEFAULT = FLAG_MIPMAPS | FLAG_REPEAT | FLAG_FILTER, - FLAG_MIRRORED_REPEAT = VisualServer::TEXTURE_FLAG_MIRRORED_REPEAT - }; - virtual int get_width() const = 0; virtual int get_height() const = 0; virtual Size2 get_size() const; - virtual RID get_rid() const = 0; virtual bool is_pixel_opaque(int p_x, int p_y) const; virtual bool has_alpha() const = 0; - virtual void set_flags(uint32_t p_flags) = 0; - virtual uint32_t get_flags() const = 0; - - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const; virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const; virtual Ref<Image> get_data() const { return Ref<Image>(); } - Texture(); + Texture2D(); }; -VARIANT_ENUM_CAST(Texture::Flags); - class BitMap; -class ImageTexture : public Texture { - - GDCLASS(ImageTexture, Texture); +class ImageTexture : public Texture2D { + GDCLASS(ImageTexture, Texture2D); RES_BASE_EXTENSION("tex"); -public: - enum Storage { - STORAGE_RAW, - STORAGE_COMPRESS_LOSSY, - STORAGE_COMPRESS_LOSSLESS - }; - -private: - RID texture; + mutable RID texture; Image::Format format; - uint32_t flags; + bool mipmaps; int w, h; - Storage storage; Size2 size_override; - float lossy_storage_quality; mutable Ref<BitMap> alpha_cache; bool image_stored; protected: - virtual void reload_from_file(); + virtual void reload_from_file() override; 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; void _reload_hook(const RID &p_hook); - virtual void _resource_path_changed(); + virtual void _resource_path_changed() override; static void _bind_methods(); - void _set_data(Dictionary p_data); - public: - void create(int p_width, int p_height, Image::Format p_format, uint32_t p_flags = FLAGS_DEFAULT); - void create_from_image(const Ref<Image> &p_image, uint32_t p_flags = FLAGS_DEFAULT); + void create_from_image(const Ref<Image> &p_image); - void set_flags(uint32_t p_flags); - uint32_t get_flags() const; Image::Format get_format() const; -#ifndef DISABLE_DEPRECATED - Error load(const String &p_path); -#endif - void set_data(const Ref<Image> &p_image); - Ref<Image> get_data() const; - int get_width() const; - int get_height() const; + void update(const Ref<Image> &p_image, bool p_immediate = false); + Ref<Image> get_data() const override; - virtual RID get_rid() const; + int get_width() const override; + int get_height() const override; - bool has_alpha() const; - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const; - void set_storage(Storage p_storage); - Storage get_storage() const; + virtual RID get_rid() const override; - bool is_pixel_opaque(int p_x, int p_y) const; + bool has_alpha() const override; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const override; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const override; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const override; - void set_lossy_storage_quality(float p_lossy_storage_quality); - float get_lossy_storage_quality() const; + bool is_pixel_opaque(int p_x, int p_y) const override; void set_size_override(const Size2 &p_size); - virtual void set_path(const String &p_path, bool p_take_over = false); + virtual void set_path(const String &p_path, bool p_take_over = false) override; ImageTexture(); ~ImageTexture(); }; -class StreamTexture : public Texture { - - GDCLASS(StreamTexture, Texture); +class StreamTexture2D : public Texture2D { + GDCLASS(StreamTexture2D, Texture2D); public: enum DataFormat { DATA_FORMAT_IMAGE, DATA_FORMAT_LOSSLESS, - DATA_FORMAT_LOSSY + DATA_FORMAT_LOSSY, + DATA_FORMAT_BASIS_UNIVERSAL, + }; + + enum { + FORMAT_VERSION = 1 }; enum FormatBits { @@ -180,78 +151,76 @@ public: FORMAT_BIT_STREAM = 1 << 22, FORMAT_BIT_HAS_MIPMAPS = 1 << 23, FORMAT_BIT_DETECT_3D = 1 << 24, - FORMAT_BIT_DETECT_SRGB = 1 << 25, + //FORMAT_BIT_DETECT_SRGB = 1 << 25, FORMAT_BIT_DETECT_NORMAL = 1 << 26, + FORMAT_BIT_DETECT_ROUGNESS = 1 << 27, }; private: - Error _load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, int &flags, Ref<Image> &image, int p_size_limit = 0); + Error _load_data(const String &p_path, int &tw, int &th, int &tw_custom, int &th_custom, Ref<Image> &image, bool &r_request_3d, bool &r_request_normal, bool &r_request_roughness, int &mipmap_limit, int p_size_limit = 0); String path_to_file; - RID texture; + mutable RID texture; Image::Format format; - uint32_t flags; int w, h; mutable Ref<BitMap> alpha_cache; - virtual void reload_from_file(); + virtual void reload_from_file() override; static void _requested_3d(void *p_ud); - static void _requested_srgb(void *p_ud); + static void _requested_roughness(void *p_ud, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel); static void _requested_normal(void *p_ud); protected: static void _bind_methods(); - void _validate_property(PropertyInfo &property) const; + void _validate_property(PropertyInfo &property) const override; public: - typedef void (*TextureFormatRequestCallback)(const Ref<StreamTexture> &); + static Ref<Image> load_image_from_file(FileAccess *p_file, int p_size_limit); + + typedef void (*TextureFormatRequestCallback)(const Ref<StreamTexture2D> &); + typedef void (*TextureFormatRoughnessRequestCallback)(const Ref<StreamTexture2D> &, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel); static TextureFormatRequestCallback request_3d_callback; - static TextureFormatRequestCallback request_srgb_callback; + static TextureFormatRoughnessRequestCallback request_roughness_callback; static TextureFormatRequestCallback request_normal_callback; - uint32_t get_flags() const; Image::Format get_format() const; Error load(const String &p_path); String get_load_path() const; - int get_width() const; - int get_height() const; - virtual RID get_rid() const; + int get_width() const override; + int get_height() const override; + virtual RID get_rid() const override; - virtual void set_path(const String &p_path, bool p_take_over); + virtual void set_path(const String &p_path, bool p_take_over) override; - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const override; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const override; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const override; - virtual bool has_alpha() const; - virtual void set_flags(uint32_t p_flags); - bool is_pixel_opaque(int p_x, int p_y) const; + virtual bool has_alpha() const override; + bool is_pixel_opaque(int p_x, int p_y) const override; - virtual Ref<Image> get_data() const; + virtual Ref<Image> get_data() const override; - StreamTexture(); - ~StreamTexture(); + StreamTexture2D(); + ~StreamTexture2D(); }; -class ResourceFormatLoaderStreamTexture : public ResourceFormatLoader { +class ResourceFormatLoaderStreamTexture2D : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; }; -VARIANT_ENUM_CAST(ImageTexture::Storage); - -class AtlasTexture : public Texture { - - GDCLASS(AtlasTexture, Texture); +class AtlasTexture : public Texture2D { + GDCLASS(AtlasTexture, Texture2D); RES_BASE_EXTENSION("atlastex"); protected: - Ref<Texture> atlas; + Ref<Texture2D> atlas; Rect2 region; Rect2 margin; bool filter_clip; @@ -259,17 +228,14 @@ protected: static void _bind_methods(); public: - virtual int get_width() const; - virtual int get_height() const; - virtual RID get_rid() const; + virtual int get_width() const override; + virtual int get_height() const override; + virtual RID get_rid() const override; - virtual bool has_alpha() const; + virtual bool has_alpha() const override; - virtual void set_flags(uint32_t p_flags); - virtual uint32_t get_flags() const; - - void set_atlas(const Ref<Texture> &p_atlas); - Ref<Texture> get_atlas() const; + void set_atlas(const Ref<Texture2D> &p_atlas); + Ref<Texture2D> get_atlas() const; void set_region(const Rect2 &p_region); Rect2 get_region() const; @@ -280,24 +246,23 @@ public: void set_filter_clip(const bool p_enable); bool has_filter_clip() const; - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const; - virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const override; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const override; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const override; + virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const override; - bool is_pixel_opaque(int p_x, int p_y) const; + bool is_pixel_opaque(int p_x, int p_y) const override; AtlasTexture(); }; class Mesh; -class MeshTexture : public Texture { - - GDCLASS(MeshTexture, Texture); +class MeshTexture : public Texture2D { + GDCLASS(MeshTexture, Texture2D); RES_BASE_EXTENSION("meshtex"); - Ref<Texture> base_texture; + Ref<Texture2D> base_texture; Ref<Mesh> mesh; Size2i size; @@ -305,14 +270,11 @@ protected: static void _bind_methods(); public: - virtual int get_width() const; - virtual int get_height() const; - virtual RID get_rid() const; + virtual int get_width() const override; + virtual int get_height() const override; + virtual RID get_rid() const override; - virtual bool has_alpha() const; - - virtual void set_flags(uint32_t p_flags); - virtual uint32_t get_flags() const; + virtual bool has_alpha() const override; void set_mesh(const Ref<Mesh> &p_mesh); Ref<Mesh> get_mesh() const; @@ -320,29 +282,27 @@ public: void set_image_size(const Size2 &p_size); Size2 get_image_size() const; - void set_base_texture(const Ref<Texture> &p_texture); - Ref<Texture> get_base_texture() const; + void set_base_texture(const Ref<Texture2D> &p_texture); + Ref<Texture2D> get_base_texture() const; - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const; - virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const override; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const override; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const override; + virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const override; - bool is_pixel_opaque(int p_x, int p_y) const; + bool is_pixel_opaque(int p_x, int p_y) const override; MeshTexture(); }; -class LargeTexture : public Texture { - - GDCLASS(LargeTexture, Texture); +class LargeTexture : public Texture2D { + GDCLASS(LargeTexture, Texture2D); RES_BASE_EXTENSION("largetex"); protected: struct Piece { - Point2 offset; - Ref<Texture> texture; + Ref<Texture2D> texture; }; Vector<Piece> pieces; @@ -353,208 +313,330 @@ protected: static void _bind_methods(); public: - virtual int get_width() const; - virtual int get_height() const; - virtual RID get_rid() const; + virtual int get_width() const override; + virtual int get_height() const override; + virtual RID get_rid() const override; - virtual bool has_alpha() const; + virtual bool has_alpha() const override; - virtual void set_flags(uint32_t p_flags); - virtual uint32_t get_flags() const; - - int add_piece(const Point2 &p_offset, const Ref<Texture> &p_texture); + int add_piece(const Point2 &p_offset, const Ref<Texture2D> &p_texture); void set_piece_offset(int p_idx, const Point2 &p_offset); - void set_piece_texture(int p_idx, const Ref<Texture> &p_texture); + void set_piece_texture(int p_idx, const Ref<Texture2D> &p_texture); void set_size(const Size2 &p_size); void clear(); int get_piece_count() const; Vector2 get_piece_offset(int p_idx) const; - Ref<Texture> get_piece_texture(int p_idx) const; + Ref<Texture2D> get_piece_texture(int p_idx) const; Ref<Image> to_image() const; - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>()) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture> &p_normal_map = Ref<Texture>(), bool p_clip_uv = true) const; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const override; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const override; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref<Texture2D> &p_normal_map = Ref<Texture2D>(), const Ref<Texture2D> &p_specular_map = Ref<Texture2D>(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const override; - bool is_pixel_opaque(int p_x, int p_y) const; + bool is_pixel_opaque(int p_x, int p_y) const override; LargeTexture(); }; -class CubeMap : public Resource { +class TextureLayered : public Texture { + GDCLASS(TextureLayered, Texture); - GDCLASS(CubeMap, Resource); - RES_BASE_EXTENSION("cubemap"); +protected: + static void _bind_methods(); public: - enum Storage { - STORAGE_RAW, - STORAGE_COMPRESS_LOSSY, - STORAGE_COMPRESS_LOSSLESS + enum LayeredType { + LAYERED_TYPE_2D_ARRAY, + LAYERED_TYPE_CUBEMAP, + LAYERED_TYPE_CUBEMAP_ARRAY }; - enum Side { + virtual Image::Format get_format() const = 0; + virtual LayeredType get_layered_type() const = 0; + virtual int get_width() const = 0; + virtual int get_height() const = 0; + virtual int get_layers() const = 0; + virtual bool has_mipmaps() const = 0; + virtual Ref<Image> get_layer_data(int p_layer) const = 0; +}; - SIDE_LEFT, - SIDE_RIGHT, - SIDE_BOTTOM, - SIDE_TOP, - SIDE_FRONT, - SIDE_BACK - }; +VARIANT_ENUM_CAST(TextureLayered::LayeredType) - enum Flags { - FLAG_MIPMAPS = VisualServer::TEXTURE_FLAG_MIPMAPS, - FLAG_REPEAT = VisualServer::TEXTURE_FLAG_REPEAT, - FLAG_FILTER = VisualServer::TEXTURE_FLAG_FILTER, - FLAGS_DEFAULT = FLAG_MIPMAPS | FLAG_REPEAT | FLAG_FILTER, - }; +class ImageTextureLayered : public TextureLayered { + GDCLASS(ImageTextureLayered, TextureLayered); -private: - bool valid[6]; - RID cubemap; + LayeredType layered_type; + + mutable RID texture; Image::Format format; - uint32_t flags; - int w, h; - Storage storage; - Size2 size_override; - float lossy_storage_quality; - _FORCE_INLINE_ bool _is_valid() const { - for (int i = 0; i < 6; i++) { - if (valid[i]) return true; - } - return false; - } + int width; + int height; + int layers; + bool mipmaps; -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; + Error _create_from_images(const Array &p_images); + + Array _get_images() const; +protected: static void _bind_methods(); public: - void set_flags(uint32_t p_flags); - uint32_t get_flags() const; - void set_side(Side p_side, const Ref<Image> &p_image); - Ref<Image> get_side(Side p_side) const; - - Image::Format get_format() const; - int get_width() const; - int get_height() const; + virtual Image::Format get_format() const override; + virtual int get_width() const override; + virtual int get_height() const override; + virtual int get_layers() const override; + virtual bool has_mipmaps() const override; + virtual LayeredType get_layered_type() const override; + + Error create_from_images(Vector<Ref<Image>> p_images); + void update_layer(const Ref<Image> &p_image, int p_layer); + virtual Ref<Image> get_layer_data(int p_layer) const override; + + virtual RID get_rid() const override; + virtual void set_path(const String &p_path, bool p_take_over = false) override; + + ImageTextureLayered(LayeredType p_layered_type); + ~ImageTextureLayered(); +}; - virtual RID get_rid() const; +class Texture2DArray : public ImageTextureLayered { + GDCLASS(Texture2DArray, ImageTextureLayered) +public: + Texture2DArray() : + ImageTextureLayered(LAYERED_TYPE_2D_ARRAY) {} +}; - void set_storage(Storage p_storage); - Storage get_storage() const; +class Cubemap : public ImageTextureLayered { + GDCLASS(Cubemap, ImageTextureLayered); - void set_lossy_storage_quality(float p_lossy_storage_quality); - float get_lossy_storage_quality() const; +public: + Cubemap() : + ImageTextureLayered(LAYERED_TYPE_CUBEMAP) {} +}; - virtual void set_path(const String &p_path, bool p_take_over = false); +class CubemapArray : public ImageTextureLayered { + GDCLASS(CubemapArray, ImageTextureLayered); - CubeMap(); - ~CubeMap(); +public: + CubemapArray() : + ImageTextureLayered(LAYERED_TYPE_CUBEMAP_ARRAY) {} }; -VARIANT_ENUM_CAST(CubeMap::Flags) -VARIANT_ENUM_CAST(CubeMap::Side) -VARIANT_ENUM_CAST(CubeMap::Storage) +class StreamTextureLayered : public TextureLayered { + GDCLASS(StreamTextureLayered, TextureLayered); -class TextureLayered : public Resource { +public: + enum DataFormat { + DATA_FORMAT_IMAGE, + DATA_FORMAT_LOSSLESS, + DATA_FORMAT_LOSSY, + DATA_FORMAT_BASIS_UNIVERSAL, + }; - GDCLASS(TextureLayered, Resource); + enum { + FORMAT_VERSION = 1 + }; -public: - enum Flags { - FLAG_MIPMAPS = VisualServer::TEXTURE_FLAG_MIPMAPS, - FLAG_REPEAT = VisualServer::TEXTURE_FLAG_REPEAT, - FLAG_FILTER = VisualServer::TEXTURE_FLAG_FILTER, - FLAG_CONVERT_TO_LINEAR = VisualServer::TEXTURE_FLAG_CONVERT_TO_LINEAR, - FLAGS_DEFAULT = FLAG_FILTER, + enum FormatBits { + FORMAT_MASK_IMAGE_FORMAT = (1 << 20) - 1, + FORMAT_BIT_LOSSLESS = 1 << 20, + FORMAT_BIT_LOSSY = 1 << 21, + FORMAT_BIT_STREAM = 1 << 22, + FORMAT_BIT_HAS_MIPMAPS = 1 << 23, }; private: - bool is_3d; - RID texture; + Error _load_data(const String &p_path, Vector<Ref<Image>> &images, int &mipmap_limit, int p_size_limit = 0); + String path_to_file; + mutable RID texture; Image::Format format; - uint32_t flags; - - int width; - int height; - int depth; + int w, h, layers; + bool mipmaps; + LayeredType layered_type; - void _set_data(const Dictionary &p_data); - Dictionary _get_data() const; + virtual void reload_from_file() override; protected: static void _bind_methods(); + void _validate_property(PropertyInfo &property) const override; public: - void set_flags(uint32_t p_flags); - uint32_t get_flags() const; + Image::Format get_format() const override; + Error load(const String &p_path); + String get_load_path() const; + virtual LayeredType get_layered_type() const override; - Image::Format get_format() const; - uint32_t get_width() const; - uint32_t get_height() const; - uint32_t get_depth() const; + int get_width() const override; + int get_height() const override; + int get_layers() const override; + virtual bool has_mipmaps() const override; + virtual RID get_rid() const override; - void create(uint32_t p_width, uint32_t p_height, uint32_t p_depth, Image::Format p_format, uint32_t p_flags = FLAGS_DEFAULT); - void set_layer_data(const Ref<Image> &p_image, int p_layer); - Ref<Image> get_layer_data(int p_layer) const; - void set_data_partial(const Ref<Image> &p_image, int p_x_ofs, int p_y_ofs, int p_z, int p_mipmap = 0); + virtual void set_path(const String &p_path, bool p_take_over) override; - virtual RID get_rid() const; - virtual void set_path(const String &p_path, bool p_take_over = false); + virtual Ref<Image> get_layer_data(int p_layer) const override; - TextureLayered(bool p_3d = false); - ~TextureLayered(); + StreamTextureLayered(LayeredType p_layered_type); + ~StreamTextureLayered(); }; -VARIANT_ENUM_CAST(TextureLayered::Flags) +class StreamTexture2DArray : public StreamTextureLayered { + GDCLASS(StreamTexture2DArray, StreamTextureLayered) +public: + StreamTexture2DArray() : + StreamTextureLayered(LAYERED_TYPE_2D_ARRAY) {} +}; + +class StreamCubemap : public StreamTextureLayered { + GDCLASS(StreamCubemap, StreamTextureLayered); + +public: + StreamCubemap() : + StreamTextureLayered(LAYERED_TYPE_CUBEMAP) {} +}; -class Texture3D : public TextureLayered { +class StreamCubemapArray : public StreamTextureLayered { + GDCLASS(StreamCubemapArray, StreamTextureLayered); - GDCLASS(Texture3D, TextureLayered); +public: + StreamCubemapArray() : + StreamTextureLayered(LAYERED_TYPE_CUBEMAP_ARRAY) {} +}; +class ResourceFormatLoaderStreamTextureLayered : public ResourceFormatLoader { public: - Texture3D() : - TextureLayered(true) {} + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual bool handles_type(const String &p_type) const; + virtual String get_resource_type(const String &p_path) const; }; -class TextureArray : public TextureLayered { +class Texture3D : public Texture { + GDCLASS(Texture3D, Texture); - GDCLASS(TextureArray, TextureLayered); +protected: + static void _bind_methods(); + + TypedArray<Image> _get_data() const; public: - TextureArray() : - TextureLayered(false) {} + virtual Image::Format get_format() const = 0; + virtual int get_width() const = 0; + virtual int get_height() const = 0; + virtual int get_depth() const = 0; + virtual bool has_mipmaps() const = 0; + virtual Vector<Ref<Image>> get_data() const = 0; }; -class ResourceFormatLoaderTextureLayered : public ResourceFormatLoader { +class ImageTexture3D : public Texture3D { + GDCLASS(ImageTexture3D, Texture3D); + + mutable RID texture; + + Image::Format format = Image::FORMAT_MAX; + int width = 1; + int height = 1; + int depth = 1; + bool mipmaps = false; + +protected: + static void _bind_methods(); + + Error _create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const TypedArray<Image> &p_data); + void _update(const TypedArray<Image> &p_data); + public: - enum Compression { - COMPRESSION_LOSSLESS, - COMPRESSION_VRAM, - COMPRESSION_UNCOMPRESSED + virtual Image::Format get_format() const override; + virtual int get_width() const override; + virtual int get_height() const override; + virtual int get_depth() const override; + virtual bool has_mipmaps() const override; + + Error create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data); + void update(const Vector<Ref<Image>> &p_data); + virtual Vector<Ref<Image>> get_data() const override; + + virtual RID get_rid() const override; + virtual void set_path(const String &p_path, bool p_take_over = false) override; + + ImageTexture3D(); + ~ImageTexture3D(); +}; + +class StreamTexture3D : public Texture3D { + GDCLASS(StreamTexture3D, Texture3D); + +public: + enum DataFormat { + DATA_FORMAT_IMAGE, + DATA_FORMAT_LOSSLESS, + DATA_FORMAT_LOSSY, + DATA_FORMAT_BASIS_UNIVERSAL, + }; + + enum { + FORMAT_VERSION = 1 + }; + + enum FormatBits { + FORMAT_MASK_IMAGE_FORMAT = (1 << 20) - 1, + FORMAT_BIT_LOSSLESS = 1 << 20, + FORMAT_BIT_LOSSY = 1 << 21, + FORMAT_BIT_STREAM = 1 << 22, + FORMAT_BIT_HAS_MIPMAPS = 1 << 23, }; - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); +private: + Error _load_data(const String &p_path, Vector<Ref<Image>> &r_data, Image::Format &r_format, int &r_width, int &r_height, int &r_depth, bool &r_mipmaps); + String path_to_file; + mutable RID texture; + Image::Format format; + int w, h, d; + bool mipmaps; + + virtual void reload_from_file() override; + +protected: + static void _bind_methods(); + void _validate_property(PropertyInfo &property) const override; + +public: + Image::Format get_format() const override; + Error load(const String &p_path); + String get_load_path() const; + + int get_width() const override; + int get_height() const override; + int get_depth() const override; + virtual bool has_mipmaps() const override; + virtual RID get_rid() const override; + + virtual void set_path(const String &p_path, bool p_take_over) override; + + virtual Vector<Ref<Image>> get_data() const override; + + StreamTexture3D(); + ~StreamTexture3D(); +}; + +class ResourceFormatLoaderStreamTexture3D : public ResourceFormatLoader { +public: + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; }; -class CurveTexture : public Texture { - - GDCLASS(CurveTexture, Texture); +class CurveTexture : public Texture2D { + GDCLASS(CurveTexture, Texture2D); RES_BASE_EXTENSION("curvetex") private: - RID _texture; + mutable RID _texture; Ref<Curve> _curve; int _width; @@ -565,20 +647,17 @@ protected: public: void set_width(int p_width); - int get_width() const; + int get_width() const override; void ensure_default_setup(float p_min = 0, float p_max = 1); void set_curve(Ref<Curve> p_curve); Ref<Curve> get_curve() const; - virtual RID get_rid() const; + virtual RID get_rid() const override; - virtual int get_height() const { return 1; } - virtual bool has_alpha() const { return false; } - - virtual void set_flags(uint32_t p_flags) {} - virtual uint32_t get_flags() const { return FLAG_FILTER; } + virtual int get_height() const override { return 1; } + virtual bool has_alpha() const override { return false; } CurveTexture(); ~CurveTexture(); @@ -597,12 +676,11 @@ public: */ //VARIANT_ENUM_CAST( Texture::CubeMapSide ); -class GradientTexture : public Texture { - GDCLASS(GradientTexture, Texture); +class GradientTexture : public Texture2D { + GDCLASS(GradientTexture, Texture2D); public: struct Point { - float offset; Color color; bool operator<(const Point &p_ponit) const { @@ -627,64 +705,60 @@ public: Ref<Gradient> get_gradient() const; void set_width(int p_width); - int get_width() const; - - virtual RID get_rid() const { return texture; } - virtual int get_height() const { return 1; } - virtual bool has_alpha() const { return true; } + int get_width() const override; - virtual void set_flags(uint32_t p_flags) {} - virtual uint32_t get_flags() const { return FLAG_FILTER; } + virtual RID get_rid() const override { return texture; } + virtual int get_height() const override { return 1; } + virtual bool has_alpha() const override { return true; } - virtual Ref<Image> get_data() const; + virtual Ref<Image> get_data() const override; GradientTexture(); virtual ~GradientTexture(); }; -class ProxyTexture : public Texture { - GDCLASS(ProxyTexture, Texture); +class ProxyTexture : public Texture2D { + GDCLASS(ProxyTexture, Texture2D); private: - RID proxy; - Ref<Texture> base; + mutable RID proxy_ph; + mutable RID proxy; + Ref<Texture2D> base; protected: static void _bind_methods(); public: - void set_base(const Ref<Texture> &p_texture); - Ref<Texture> get_base() const; + void set_base(const Ref<Texture2D> &p_texture); + Ref<Texture2D> get_base() const; - virtual int get_width() const; - virtual int get_height() const; - virtual RID get_rid() const; + virtual int get_width() const override; + virtual int get_height() const override; + virtual RID get_rid() const override; - virtual bool has_alpha() const; - - virtual void set_flags(uint32_t p_flags); - virtual uint32_t get_flags() const; + virtual bool has_alpha() const override; ProxyTexture(); ~ProxyTexture(); }; -class AnimatedTexture : public Texture { - GDCLASS(AnimatedTexture, Texture); +class AnimatedTexture : public Texture2D { + GDCLASS(AnimatedTexture, Texture2D); //use readers writers lock for this, since its far more times read than written to RWLock *rw_lock; -private: +public: enum { MAX_FRAMES = 256 }; +private: + RID proxy_ph; RID proxy; struct Frame { - - Ref<Texture> texture; + Ref<Texture2D> texture; float delay_sec; Frame() { @@ -695,7 +769,8 @@ private: Frame frames[MAX_FRAMES]; int frame_count; int current_frame; - + bool pause; + bool oneshot; float fps; float time; @@ -706,14 +781,23 @@ private: protected: static void _bind_methods(); - void _validate_property(PropertyInfo &property) const; + void _validate_property(PropertyInfo &property) const override; public: void set_frames(int p_frames); int get_frames() const; - void set_frame_texture(int p_frame, const Ref<Texture> &p_texture); - Ref<Texture> get_frame_texture(int p_frame) const; + void set_current_frame(int p_frame); + int get_current_frame() const; + + void set_pause(bool p_pause); + bool get_pause() const; + + void set_oneshot(bool p_oneshot); + bool get_oneshot() const; + + void set_frame_texture(int p_frame, const Ref<Texture2D> &p_texture); + Ref<Texture2D> get_frame_texture(int p_frame) const; void set_frame_delay(int p_frame, float p_delay_sec); float get_frame_delay(int p_frame) const; @@ -721,25 +805,22 @@ public: void set_fps(float p_fps); float get_fps() const; - virtual int get_width() const; - virtual int get_height() const; - virtual RID get_rid() const; - - virtual bool has_alpha() const; + virtual int get_width() const override; + virtual int get_height() const override; + virtual RID get_rid() const override; - virtual void set_flags(uint32_t p_flags); - virtual uint32_t get_flags() const; + virtual bool has_alpha() const override; - virtual Ref<Image> get_data() const; + virtual Ref<Image> get_data() const override; - bool is_pixel_opaque(int p_x, int p_y) const; + bool is_pixel_opaque(int p_x, int p_y) const override; AnimatedTexture(); ~AnimatedTexture(); }; -class CameraTexture : public Texture { - GDCLASS(CameraTexture, Texture); +class CameraTexture : public Texture2D { + GDCLASS(CameraTexture, Texture2D); private: int camera_feed_id; @@ -749,15 +830,15 @@ protected: static void _bind_methods(); public: - virtual int get_width() const; - virtual int get_height() const; - virtual RID get_rid() const; - virtual bool has_alpha() const; + virtual int get_width() const override; + virtual int get_height() const override; + virtual RID get_rid() const override; + virtual bool has_alpha() const override; virtual void set_flags(uint32_t p_flags); virtual uint32_t get_flags() const; - virtual Ref<Image> get_data() const; + virtual Ref<Image> get_data() const override; void set_camera_feed_id(int p_new_id); int get_camera_feed_id() const; diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index 1f2fa1d60b..6a85d357ff 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -33,116 +33,108 @@ #include "core/print_string.h" void Theme::_emit_theme_changed() { - emit_changed(); } -PoolVector<String> Theme::_get_icon_list(const String &p_type) const { - - PoolVector<String> ilret; +Vector<String> Theme::_get_icon_list(const String &p_type) const { + Vector<String> ilret; List<StringName> il; get_icon_list(p_type, &il); ilret.resize(il.size()); int i = 0; - PoolVector<String>::Write w = ilret.write(); + String *w = ilret.ptrw(); for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { w[i] = E->get(); } return ilret; } -PoolVector<String> Theme::_get_stylebox_list(const String &p_type) const { - - PoolVector<String> ilret; +Vector<String> Theme::_get_stylebox_list(const String &p_type) const { + Vector<String> ilret; List<StringName> il; get_stylebox_list(p_type, &il); ilret.resize(il.size()); int i = 0; - PoolVector<String>::Write w = ilret.write(); + String *w = ilret.ptrw(); for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { w[i] = E->get(); } return ilret; } -PoolVector<String> Theme::_get_stylebox_types(void) const { - - PoolVector<String> ilret; +Vector<String> Theme::_get_stylebox_types() const { + Vector<String> ilret; List<StringName> il; get_stylebox_types(&il); ilret.resize(il.size()); int i = 0; - PoolVector<String>::Write w = ilret.write(); + String *w = ilret.ptrw(); for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { w[i] = E->get(); } return ilret; } -PoolVector<String> Theme::_get_font_list(const String &p_type) const { - - PoolVector<String> ilret; +Vector<String> Theme::_get_font_list(const String &p_type) const { + Vector<String> ilret; List<StringName> il; get_font_list(p_type, &il); ilret.resize(il.size()); int i = 0; - PoolVector<String>::Write w = ilret.write(); + String *w = ilret.ptrw(); for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { w[i] = E->get(); } return ilret; } -PoolVector<String> Theme::_get_color_list(const String &p_type) const { - - PoolVector<String> ilret; +Vector<String> Theme::_get_color_list(const String &p_type) const { + Vector<String> ilret; List<StringName> il; get_color_list(p_type, &il); ilret.resize(il.size()); int i = 0; - PoolVector<String>::Write w = ilret.write(); + String *w = ilret.ptrw(); for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { w[i] = E->get(); } return ilret; } -PoolVector<String> Theme::_get_constant_list(const String &p_type) const { - - PoolVector<String> ilret; +Vector<String> Theme::_get_constant_list(const String &p_type) const { + Vector<String> ilret; List<StringName> il; get_constant_list(p_type, &il); ilret.resize(il.size()); int i = 0; - PoolVector<String>::Write w = ilret.write(); + String *w = ilret.ptrw(); for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { w[i] = E->get(); } return ilret; } -PoolVector<String> Theme::_get_type_list(const String &p_type) const { - - PoolVector<String> ilret; +Vector<String> Theme::_get_type_list(const String &p_type) const { + Vector<String> ilret; List<StringName> il; get_type_list(&il); ilret.resize(il.size()); int i = 0; - PoolVector<String>::Write w = ilret.write(); + String *w = ilret.ptrw(); for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { w[i] = E->get(); } @@ -150,32 +142,26 @@ PoolVector<String> Theme::_get_type_list(const String &p_type) const { } bool Theme::_set(const StringName &p_name, const Variant &p_value) { - String sname = p_name; if (sname.find("/") != -1) { - String type = sname.get_slicec('/', 1); String node_type = sname.get_slicec('/', 0); String name = sname.get_slicec('/', 2); if (type == "icons") { - set_icon(name, node_type, p_value); } else if (type == "styles") { - set_stylebox(name, node_type, p_value); } else if (type == "fonts") { - set_font(name, node_type, p_value); } else if (type == "colors") { - set_color(name, node_type, p_value); } else if (type == "constants") { - set_constant(name, node_type, p_value); - } else + } else { return false; + } return true; } @@ -184,41 +170,38 @@ bool Theme::_set(const StringName &p_name, const Variant &p_value) { } bool Theme::_get(const StringName &p_name, Variant &r_ret) const { - String sname = p_name; if (sname.find("/") != -1) { - String type = sname.get_slicec('/', 1); String node_type = sname.get_slicec('/', 0); String name = sname.get_slicec('/', 2); if (type == "icons") { - - if (!has_icon(name, node_type)) - r_ret = Ref<Texture>(); - else + if (!has_icon(name, node_type)) { + r_ret = Ref<Texture2D>(); + } else { r_ret = get_icon(name, node_type); + } } else if (type == "styles") { - - if (!has_stylebox(name, node_type)) + if (!has_stylebox(name, node_type)) { r_ret = Ref<StyleBox>(); - else + } else { r_ret = get_stylebox(name, node_type); + } } else if (type == "fonts") { - - if (!has_font(name, node_type)) + if (!has_font(name, node_type)) { r_ret = Ref<Font>(); - else + } else { r_ret = get_font(name, node_type); + } } else if (type == "colors") { - r_ret = get_color(name, node_type); } else if (type == "constants") { - r_ret = get_constant(name, node_type); - } else + } else { return false; + } return true; } @@ -227,65 +210,54 @@ bool Theme::_get(const StringName &p_name, Variant &r_ret) const { } void Theme::_get_property_list(List<PropertyInfo> *p_list) const { - List<PropertyInfo> list; - const StringName *key = NULL; + const StringName *key = nullptr; while ((key = icon_map.next(key))) { - - const StringName *key2 = NULL; + const StringName *key2 = nullptr; while ((key2 = icon_map[*key].next(key2))) { - - list.push_back(PropertyInfo(Variant::OBJECT, String() + *key + "/icons/" + *key2, PROPERTY_HINT_RESOURCE_TYPE, "Texture", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL)); + list.push_back(PropertyInfo(Variant::OBJECT, String() + *key + "/icons/" + *key2, PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL)); } } - key = NULL; + key = nullptr; while ((key = style_map.next(key))) { - - const StringName *key2 = NULL; + const StringName *key2 = nullptr; while ((key2 = style_map[*key].next(key2))) { - list.push_back(PropertyInfo(Variant::OBJECT, String() + *key + "/styles/" + *key2, PROPERTY_HINT_RESOURCE_TYPE, "StyleBox", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL)); } } - key = NULL; + key = nullptr; while ((key = font_map.next(key))) { - - const StringName *key2 = NULL; + const StringName *key2 = nullptr; while ((key2 = font_map[*key].next(key2))) { - list.push_back(PropertyInfo(Variant::OBJECT, String() + *key + "/fonts/" + *key2, PROPERTY_HINT_RESOURCE_TYPE, "Font", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_STORE_IF_NULL)); } } - key = NULL; + key = nullptr; while ((key = color_map.next(key))) { - - const StringName *key2 = NULL; + const StringName *key2 = nullptr; while ((key2 = color_map[*key].next(key2))) { - list.push_back(PropertyInfo(Variant::COLOR, String() + *key + "/colors/" + *key2)); } } - key = NULL; + key = nullptr; while ((key = constant_map.next(key))) { - - const StringName *key2 = NULL; + const StringName *key2 = nullptr; while ((key2 = constant_map[*key].next(key2))) { - list.push_back(PropertyInfo(Variant::INT, String() + *key + "/constants/" + *key2)); } } @@ -297,18 +269,18 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const { } void Theme::set_default_theme_font(const Ref<Font> &p_default_font) { - - if (default_theme_font == p_default_font) + if (default_theme_font == p_default_font) { return; + } if (default_theme_font.is_valid()) { - default_theme_font->disconnect("changed", this, "_emit_theme_changed"); + default_theme_font->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } default_theme_font = p_default_font; if (default_theme_font.is_valid()) { - default_theme_font->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED); + default_theme_font->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED); } _change_notify(); @@ -316,63 +288,56 @@ void Theme::set_default_theme_font(const Ref<Font> &p_default_font) { } Ref<Font> Theme::get_default_theme_font() const { - return default_theme_font; } Ref<Theme> Theme::project_default_theme; Ref<Theme> Theme::default_theme; -Ref<Texture> Theme::default_icon; +Ref<Texture2D> Theme::default_icon; Ref<StyleBox> Theme::default_style; Ref<Font> Theme::default_font; Ref<Theme> Theme::get_default() { - return default_theme; } void Theme::set_default(const Ref<Theme> &p_default) { - default_theme = p_default; } Ref<Theme> Theme::get_project_default() { - return project_default_theme; } void Theme::set_project_default(const Ref<Theme> &p_project_default) { - project_default_theme = p_project_default; } -void Theme::set_default_icon(const Ref<Texture> &p_icon) { - +void Theme::set_default_icon(const Ref<Texture2D> &p_icon) { default_icon = p_icon; } -void Theme::set_default_style(const Ref<StyleBox> &p_style) { +void Theme::set_default_style(const Ref<StyleBox> &p_style) { default_style = p_style; } -void Theme::set_default_font(const Ref<Font> &p_font) { +void Theme::set_default_font(const Ref<Font> &p_font) { default_font = p_font; } -void Theme::set_icon(const StringName &p_name, const StringName &p_type, const Ref<Texture> &p_icon) { - +void Theme::set_icon(const StringName &p_name, const StringName &p_type, const Ref<Texture2D> &p_icon) { //ERR_FAIL_COND(p_icon.is_null()); bool new_value = !icon_map.has(p_type) || !icon_map[p_type].has(p_name); if (icon_map[p_type].has(p_name) && icon_map[p_type][p_name].is_valid()) { - icon_map[p_type][p_name]->disconnect("changed", this, "_emit_theme_changed"); + icon_map[p_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } icon_map[p_type][p_name] = p_icon; if (p_icon.is_valid()) { - icon_map[p_type][p_name]->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED); + icon_map[p_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED); } if (new_value) { @@ -380,10 +345,9 @@ void Theme::set_icon(const StringName &p_name, const StringName &p_type, const R emit_changed(); } } -Ref<Texture> Theme::get_icon(const StringName &p_name, const StringName &p_type) const { +Ref<Texture2D> Theme::get_icon(const StringName &p_name, const StringName &p_type) const { if (icon_map.has(p_type) && icon_map[p_type].has(p_name) && icon_map[p_type][p_name].is_valid()) { - return icon_map[p_type][p_name]; } else { return default_icon; @@ -391,17 +355,15 @@ Ref<Texture> Theme::get_icon(const StringName &p_name, const StringName &p_type) } bool Theme::has_icon(const StringName &p_name, const StringName &p_type) const { - return (icon_map.has(p_type) && icon_map[p_type].has(p_name) && icon_map[p_type][p_name].is_valid()); } void Theme::clear_icon(const StringName &p_name, const StringName &p_type) { - ERR_FAIL_COND(!icon_map.has(p_type)); ERR_FAIL_COND(!icon_map[p_type].has(p_name)); if (icon_map[p_type][p_name].is_valid()) { - icon_map[p_type][p_name]->disconnect("changed", this, "_emit_theme_changed"); + icon_map[p_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } icon_map[p_type].erase(p_name); @@ -411,16 +373,15 @@ void Theme::clear_icon(const StringName &p_name, const StringName &p_type) { } void Theme::get_icon_list(StringName p_type, List<StringName> *p_list) const { - ERR_FAIL_NULL(p_list); - if (!icon_map.has(p_type)) + if (!icon_map.has(p_type)) { return; + } - const StringName *key = NULL; + const StringName *key = nullptr; while ((key = icon_map[p_type].next(key))) { - p_list->push_back(*key); } } @@ -440,7 +401,7 @@ Ref<Shader> Theme::get_shader(const StringName &p_name, const StringName &p_type if (shader_map.has(p_type) && shader_map[p_type].has(p_name) && shader_map[p_type][p_name].is_valid()) { return shader_map[p_type][p_name]; } else { - return NULL; + return nullptr; } } @@ -458,45 +419,42 @@ void Theme::clear_shader(const StringName &p_name, const StringName &p_type) { } void Theme::get_shader_list(const StringName &p_type, List<StringName> *p_list) const { - ERR_FAIL_NULL(p_list); - if (!shader_map.has(p_type)) + if (!shader_map.has(p_type)) { return; + } - const StringName *key = NULL; + const StringName *key = nullptr; while ((key = shader_map[p_type].next(key))) { - p_list->push_back(*key); } } void Theme::set_stylebox(const StringName &p_name, const StringName &p_type, const Ref<StyleBox> &p_style) { - //ERR_FAIL_COND(p_style.is_null()); bool new_value = !style_map.has(p_type) || !style_map[p_type].has(p_name); if (style_map[p_type].has(p_name) && style_map[p_type][p_name].is_valid()) { - style_map[p_type][p_name]->disconnect("changed", this, "_emit_theme_changed"); + style_map[p_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } style_map[p_type][p_name] = p_style; if (p_style.is_valid()) { - style_map[p_type][p_name]->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED); + style_map[p_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED); } - if (new_value) + if (new_value) { _change_notify(); + } emit_changed(); } Ref<StyleBox> Theme::get_stylebox(const StringName &p_name, const StringName &p_type) const { - if (style_map.has(p_type) && style_map[p_type].has(p_name) && style_map[p_type][p_name].is_valid()) { - return style_map[p_type][p_name]; } else { return default_style; @@ -504,17 +462,15 @@ Ref<StyleBox> Theme::get_stylebox(const StringName &p_name, const StringName &p_ } bool Theme::has_stylebox(const StringName &p_name, const StringName &p_type) const { - return (style_map.has(p_type) && style_map[p_type].has(p_name) && style_map[p_type][p_name].is_valid()); } void Theme::clear_stylebox(const StringName &p_name, const StringName &p_type) { - ERR_FAIL_COND(!style_map.has(p_type)); ERR_FAIL_COND(!style_map[p_type].has(p_name)); if (style_map[p_type][p_name].is_valid()) { - style_map[p_type][p_name]->disconnect("changed", this, "_emit_theme_changed"); + style_map[p_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } style_map[p_type].erase(p_name); @@ -524,16 +480,15 @@ void Theme::clear_stylebox(const StringName &p_name, const StringName &p_type) { } void Theme::get_stylebox_list(StringName p_type, List<StringName> *p_list) const { - ERR_FAIL_NULL(p_list); - if (!style_map.has(p_type)) + if (!style_map.has(p_type)) { return; + } - const StringName *key = NULL; + const StringName *key = nullptr; while ((key = style_map[p_type].next(key))) { - p_list->push_back(*key); } } @@ -541,26 +496,25 @@ void Theme::get_stylebox_list(StringName p_type, List<StringName> *p_list) const void Theme::get_stylebox_types(List<StringName> *p_list) const { ERR_FAIL_NULL(p_list); - const StringName *key = NULL; + const StringName *key = nullptr; while ((key = style_map.next(key))) { p_list->push_back(*key); } } void Theme::set_font(const StringName &p_name, const StringName &p_type, const Ref<Font> &p_font) { - //ERR_FAIL_COND(p_font.is_null()); bool new_value = !font_map.has(p_type) || !font_map[p_type].has(p_name); if (font_map[p_type][p_name].is_valid()) { - font_map[p_type][p_name]->disconnect("changed", this, "_emit_theme_changed"); + font_map[p_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } font_map[p_type][p_name] = p_font; if (p_font.is_valid()) { - font_map[p_type][p_name]->connect("changed", this, "_emit_theme_changed", varray(), CONNECT_REFERENCE_COUNTED); + font_map[p_type][p_name]->connect("changed", callable_mp(this, &Theme::_emit_theme_changed), varray(), CONNECT_REFERENCE_COUNTED); } if (new_value) { @@ -568,28 +522,27 @@ void Theme::set_font(const StringName &p_name, const StringName &p_type, const R emit_changed(); } } -Ref<Font> Theme::get_font(const StringName &p_name, const StringName &p_type) const { - if (font_map.has(p_type) && font_map[p_type].has(p_name) && font_map[p_type][p_name].is_valid()) +Ref<Font> Theme::get_font(const StringName &p_name, const StringName &p_type) const { + if (font_map.has(p_type) && font_map[p_type].has(p_name) && font_map[p_type][p_name].is_valid()) { return font_map[p_type][p_name]; - else if (default_theme_font.is_valid()) + } else if (default_theme_font.is_valid()) { return default_theme_font; - else + } else { return default_font; + } } bool Theme::has_font(const StringName &p_name, const StringName &p_type) const { - return (font_map.has(p_type) && font_map[p_type].has(p_name) && font_map[p_type][p_name].is_valid()); } void Theme::clear_font(const StringName &p_name, const StringName &p_type) { - ERR_FAIL_COND(!font_map.has(p_type)); ERR_FAIL_COND(!font_map[p_type].has(p_name)); if (font_map[p_type][p_name].is_valid()) { - font_map[p_type][p_name]->disconnect("changed", this, "_emit_theme_changed"); + font_map[p_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } font_map[p_type].erase(p_name); @@ -598,22 +551,20 @@ void Theme::clear_font(const StringName &p_name, const StringName &p_type) { } void Theme::get_font_list(StringName p_type, List<StringName> *p_list) const { - ERR_FAIL_NULL(p_list); - if (!font_map.has(p_type)) + if (!font_map.has(p_type)) { return; + } - const StringName *key = NULL; + const StringName *key = nullptr; while ((key = font_map[p_type].next(key))) { - p_list->push_back(*key); } } void Theme::set_color(const StringName &p_name, const StringName &p_type, const Color &p_color) { - bool new_value = !color_map.has(p_type) || !color_map[p_type].has(p_name); color_map[p_type][p_name] = p_color; @@ -625,20 +576,18 @@ void Theme::set_color(const StringName &p_name, const StringName &p_type, const } Color Theme::get_color(const StringName &p_name, const StringName &p_type) const { - - if (color_map.has(p_type) && color_map[p_type].has(p_name)) + if (color_map.has(p_type) && color_map[p_type].has(p_name)) { return color_map[p_type][p_name]; - else + } else { return Color(); + } } bool Theme::has_color(const StringName &p_name, const StringName &p_type) const { - return (color_map.has(p_type) && color_map[p_type].has(p_name)); } void Theme::clear_color(const StringName &p_name, const StringName &p_type) { - ERR_FAIL_COND(!color_map.has(p_type)); ERR_FAIL_COND(!color_map[p_type].has(p_name)); @@ -648,22 +597,20 @@ void Theme::clear_color(const StringName &p_name, const StringName &p_type) { } void Theme::get_color_list(StringName p_type, List<StringName> *p_list) const { - ERR_FAIL_NULL(p_list); - if (!color_map.has(p_type)) + if (!color_map.has(p_type)) { return; + } - const StringName *key = NULL; + const StringName *key = nullptr; while ((key = color_map[p_type].next(key))) { - p_list->push_back(*key); } } void Theme::set_constant(const StringName &p_name, const StringName &p_type, int p_constant) { - bool new_value = !constant_map.has(p_type) || !constant_map[p_type].has(p_name); constant_map[p_type][p_name] = p_constant; @@ -674,21 +621,18 @@ void Theme::set_constant(const StringName &p_name, const StringName &p_type, int } int Theme::get_constant(const StringName &p_name, const StringName &p_type) const { - - if (constant_map.has(p_type) && constant_map[p_type].has(p_name)) + if (constant_map.has(p_type) && constant_map[p_type].has(p_name)) { return constant_map[p_type][p_name]; - else { + } else { return 0; } } bool Theme::has_constant(const StringName &p_name, const StringName &p_type) const { - return (constant_map.has(p_type) && constant_map[p_type].has(p_name)); } void Theme::clear_constant(const StringName &p_name, const StringName &p_type) { - ERR_FAIL_COND(!constant_map.has(p_type)); ERR_FAIL_COND(!constant_map[p_type].has(p_name)); @@ -698,57 +642,55 @@ void Theme::clear_constant(const StringName &p_name, const StringName &p_type) { } void Theme::get_constant_list(StringName p_type, List<StringName> *p_list) const { - ERR_FAIL_NULL(p_list); - if (!constant_map.has(p_type)) + if (!constant_map.has(p_type)) { return; + } - const StringName *key = NULL; + const StringName *key = nullptr; while ((key = constant_map[p_type].next(key))) { - p_list->push_back(*key); } } void Theme::clear() { - //these need disconnecting { - const StringName *K = NULL; + const StringName *K = nullptr; while ((K = icon_map.next(K))) { - const StringName *L = NULL; + const StringName *L = nullptr; while ((L = icon_map[*K].next(L))) { - Ref<Texture> icon = icon_map[*K][*L]; + Ref<Texture2D> icon = icon_map[*K][*L]; if (icon.is_valid()) { - icon->disconnect("changed", this, "_emit_theme_changed"); + icon->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } } } } { - const StringName *K = NULL; + const StringName *K = nullptr; while ((K = style_map.next(K))) { - const StringName *L = NULL; + const StringName *L = nullptr; while ((L = style_map[*K].next(L))) { Ref<StyleBox> style = style_map[*K][*L]; if (style.is_valid()) { - style->disconnect("changed", this, "_emit_theme_changed"); + style->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } } } } { - const StringName *K = NULL; + const StringName *K = nullptr; while ((K = font_map.next(K))) { - const StringName *L = NULL; + const StringName *L = nullptr; while ((L = font_map[*K].next(L))) { Ref<Font> font = font_map[*K][*L]; if (font.is_valid()) { - font->disconnect("changed", this, "_emit_theme_changed"); + font->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); } } } @@ -766,13 +708,11 @@ void Theme::clear() { } void Theme::copy_default_theme() { - Ref<Theme> default_theme2 = get_default(); copy_theme(default_theme2); } void Theme::copy_theme(const Ref<Theme> &p_other) { - if (p_other.is_null()) { clear(); @@ -781,9 +721,9 @@ void Theme::copy_theme(const Ref<Theme> &p_other) { //these need reconnecting, so add normally { - const StringName *K = NULL; + const StringName *K = nullptr; while ((K = p_other->icon_map.next(K))) { - const StringName *L = NULL; + const StringName *L = nullptr; while ((L = p_other->icon_map[*K].next(L))) { set_icon(*L, *K, p_other->icon_map[*K][*L]); } @@ -791,9 +731,9 @@ void Theme::copy_theme(const Ref<Theme> &p_other) { } { - const StringName *K = NULL; + const StringName *K = nullptr; while ((K = p_other->style_map.next(K))) { - const StringName *L = NULL; + const StringName *L = nullptr; while ((L = p_other->style_map[*K].next(L))) { set_stylebox(*L, *K, p_other->style_map[*K][*L]); } @@ -801,9 +741,9 @@ void Theme::copy_theme(const Ref<Theme> &p_other) { } { - const StringName *K = NULL; + const StringName *K = nullptr; while ((K = p_other->font_map.next(K))) { - const StringName *L = NULL; + const StringName *L = nullptr; while ((L = p_other->font_map[*K].next(L))) { set_font(*L, *K, p_other->font_map[*K][*L]); } @@ -821,53 +761,45 @@ void Theme::copy_theme(const Ref<Theme> &p_other) { } void Theme::get_type_list(List<StringName> *p_list) const { - ERR_FAIL_NULL(p_list); Set<StringName> types; - const StringName *key = NULL; + const StringName *key = nullptr; while ((key = icon_map.next(key))) { - types.insert(*key); } - key = NULL; + key = nullptr; while ((key = style_map.next(key))) { - types.insert(*key); } - key = NULL; + key = nullptr; while ((key = font_map.next(key))) { - types.insert(*key); } - key = NULL; + key = nullptr; while ((key = color_map.next(key))) { - types.insert(*key); } - key = NULL; + key = nullptr; while ((key = constant_map.next(key))) { - types.insert(*key); } for (Set<StringName>::Element *E = types.front(); E; E = E->next()) { - p_list->push_back(E->get()); } } void Theme::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_icon", "name", "type", "texture"), &Theme::set_icon); ClassDB::bind_method(D_METHOD("get_icon", "name", "type"), &Theme::get_icon); ClassDB::bind_method(D_METHOD("has_icon", "name", "type"), &Theme::has_icon); @@ -906,8 +838,6 @@ void Theme::_bind_methods() { ClassDB::bind_method(D_METHOD("get_type_list", "type"), &Theme::_get_type_list); - ClassDB::bind_method(D_METHOD("_emit_theme_changed"), &Theme::_emit_theme_changed); - ClassDB::bind_method("copy_default_theme", &Theme::copy_default_theme); ClassDB::bind_method(D_METHOD("copy_theme", "other"), &Theme::copy_theme); diff --git a/scene/resources/theme.h b/scene/resources/theme.h index 4bb614b24e..3c72ddd8a2 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -39,26 +39,25 @@ #include "scene/resources/texture.h" class Theme : public Resource { - GDCLASS(Theme, Resource); RES_BASE_EXTENSION("theme"); void _emit_theme_changed(); - HashMap<StringName, HashMap<StringName, Ref<Texture> > > icon_map; - HashMap<StringName, HashMap<StringName, Ref<StyleBox> > > style_map; - HashMap<StringName, HashMap<StringName, Ref<Font> > > font_map; - HashMap<StringName, HashMap<StringName, Ref<Shader> > > shader_map; - HashMap<StringName, HashMap<StringName, Color> > color_map; - HashMap<StringName, HashMap<StringName, int> > constant_map; - - PoolVector<String> _get_icon_list(const String &p_type) const; - PoolVector<String> _get_stylebox_list(const String &p_type) const; - PoolVector<String> _get_stylebox_types(void) const; - PoolVector<String> _get_font_list(const String &p_type) const; - PoolVector<String> _get_color_list(const String &p_type) const; - PoolVector<String> _get_constant_list(const String &p_type) const; - PoolVector<String> _get_type_list(const String &p_type) const; + HashMap<StringName, HashMap<StringName, Ref<Texture2D>>> icon_map; + HashMap<StringName, HashMap<StringName, Ref<StyleBox>>> style_map; + HashMap<StringName, HashMap<StringName, Ref<Font>>> font_map; + HashMap<StringName, HashMap<StringName, Ref<Shader>>> shader_map; + HashMap<StringName, HashMap<StringName, Color>> color_map; + HashMap<StringName, HashMap<StringName, int>> constant_map; + + Vector<String> _get_icon_list(const String &p_type) const; + Vector<String> _get_stylebox_list(const String &p_type) const; + Vector<String> _get_stylebox_types() const; + Vector<String> _get_font_list(const String &p_type) const; + Vector<String> _get_color_list(const String &p_type) const; + Vector<String> _get_constant_list(const String &p_type) const; + Vector<String> _get_type_list(const String &p_type) const; protected: bool _set(const StringName &p_name, const Variant &p_value); @@ -67,7 +66,7 @@ protected: static Ref<Theme> project_default_theme; static Ref<Theme> default_theme; - static Ref<Texture> default_icon; + static Ref<Texture2D> default_icon; static Ref<StyleBox> default_style; static Ref<Font> default_font; @@ -82,15 +81,15 @@ public: static Ref<Theme> get_project_default(); static void set_project_default(const Ref<Theme> &p_project_default); - static void set_default_icon(const Ref<Texture> &p_icon); + static void set_default_icon(const Ref<Texture2D> &p_icon); static void set_default_style(const Ref<StyleBox> &p_style); static void set_default_font(const Ref<Font> &p_font); void set_default_theme_font(const Ref<Font> &p_default_font); Ref<Font> get_default_theme_font() const; - void set_icon(const StringName &p_name, const StringName &p_type, const Ref<Texture> &p_icon); - Ref<Texture> get_icon(const StringName &p_name, const StringName &p_type) const; + void set_icon(const StringName &p_name, const StringName &p_type, const Ref<Texture2D> &p_icon); + Ref<Texture2D> get_icon(const StringName &p_name, const StringName &p_type) const; bool has_icon(const StringName &p_name, const StringName &p_type) const; void clear_icon(const StringName &p_name, const StringName &p_type); void get_icon_list(StringName p_type, List<StringName> *p_list) const; diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 555e90ed3c..84b067d1e2 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -29,54 +29,58 @@ /*************************************************************************/ #include "tile_set.h" + #include "core/array.h" #include "core/engine.h" +#include "core/math/geometry_2d.h" bool TileSet::_set(const StringName &p_name, const Variant &p_value) { - String n = p_name; int slash = n.find("/"); - if (slash == -1) + if (slash == -1) { return false; - int id = String::to_int(n.c_str(), slash); + } + int id = String::to_int(n.get_data(), slash); - if (!tile_map.has(id)) + if (!tile_map.has(id)) { create_tile(id); + } String what = n.substr(slash + 1, n.length()); - if (what == "name") + if (what == "name") { tile_set_name(id, p_value); - else if (what == "texture") + } else if (what == "texture") { tile_set_texture(id, p_value); - else if (what == "normal_map") + } else if (what == "normal_map") { tile_set_normal_map(id, p_value); - else if (what == "tex_offset") + } else if (what == "tex_offset") { tile_set_texture_offset(id, p_value); - else if (what == "material") + } else if (what == "material") { tile_set_material(id, p_value); - else if (what == "modulate") + } else if (what == "modulate") { tile_set_modulate(id, p_value); - else if (what == "region") + } else if (what == "region") { tile_set_region(id, p_value); - else if (what == "tile_mode") + } else if (what == "tile_mode") { tile_set_tile_mode(id, (TileMode)((int)p_value)); - else if (what == "is_autotile") { + } else if (what == "is_autotile") { // backward compatibility for Godot 3.0.x // autotile used to be a bool, it's now an enum bool is_autotile = p_value; - if (is_autotile) + if (is_autotile) { tile_set_tile_mode(id, AUTO_TILE); + } } else if (what.left(9) == "autotile/") { what = what.right(9); - if (what == "bitmask_mode") + if (what == "bitmask_mode") { autotile_set_bitmask_mode(id, (BitmaskMode)((int)p_value)); - else if (what == "icon_coordinate") + } else if (what == "icon_coordinate") { autotile_set_icon_coordinate(id, p_value); - else if (what == "tile_size") + } else if (what == "tile_size") { autotile_set_size(id, p_value); - else if (what == "spacing") + } else if (what == "spacing") { autotile_set_spacing(id, p_value); - else if (what == "bitmask_flags") { + } else if (what == "bitmask_flags") { tile_map[id].autotile_data.flags.clear(); if (p_value.is_array()) { Array p = p_value; @@ -147,7 +151,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { p.pop_front(); } } - } else if (what == "shape") + } else if (what == "shape") { if (tile_get_shape_count(id) > 0) { for (int i = 0; i < tile_get_shape_count(id); i++) { tile_set_shape(id, i, p_value); @@ -155,7 +159,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { } else { tile_set_shape(id, 0, p_value); } - else if (what == "shape_offset") + } else if (what == "shape_offset") { if (tile_get_shape_count(id) > 0) { for (int i = 0; i < tile_get_shape_count(id); i++) { tile_set_shape_offset(id, i, p_value); @@ -163,7 +167,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { } else { tile_set_shape_offset(id, 0, p_value); } - else if (what == "shape_transform") + } else if (what == "shape_transform") { if (tile_get_shape_count(id) > 0) { for (int i = 0; i < tile_get_shape_count(id); i++) { tile_set_shape_transform(id, i, p_value); @@ -171,7 +175,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { } else { tile_set_shape_transform(id, 0, p_value); } - else if (what == "shape_one_way") + } else if (what == "shape_one_way") { if (tile_get_shape_count(id) > 0) { for (int i = 0; i < tile_get_shape_count(id); i++) { tile_set_shape_one_way(id, i, p_value); @@ -179,7 +183,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { } else { tile_set_shape_one_way(id, 0, p_value); } - else if (what == "shape_one_way_margin") + } else if (what == "shape_one_way_margin") { if (tile_get_shape_count(id) > 0) { for (int i = 0; i < tile_get_shape_count(id); i++) { tile_set_shape_one_way_margin(id, i, p_value); @@ -187,63 +191,64 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { } else { tile_set_shape_one_way_margin(id, 0, p_value); } - else if (what == "shapes") + } else if (what == "shapes") { _tile_set_shapes(id, p_value); - else if (what == "occluder") + } else if (what == "occluder") { tile_set_light_occluder(id, p_value); - else if (what == "occluder_offset") + } else if (what == "occluder_offset") { tile_set_occluder_offset(id, p_value); - else if (what == "navigation") + } else if (what == "navigation") { tile_set_navigation_polygon(id, p_value); - else if (what == "navigation_offset") + } else if (what == "navigation_offset") { tile_set_navigation_polygon_offset(id, p_value); - else if (what == "z_index") + } else if (what == "z_index") { tile_set_z_index(id, p_value); - else + } else { return false; + } return true; } bool TileSet::_get(const StringName &p_name, Variant &r_ret) const { - String n = p_name; int slash = n.find("/"); - if (slash == -1) + if (slash == -1) { return false; - int id = String::to_int(n.c_str(), slash); + } + int id = String::to_int(n.get_data(), slash); ERR_FAIL_COND_V(!tile_map.has(id), false); String what = n.substr(slash + 1, n.length()); - if (what == "name") + if (what == "name") { r_ret = tile_get_name(id); - else if (what == "texture") + } else if (what == "texture") { r_ret = tile_get_texture(id); - else if (what == "normal_map") + } else if (what == "normal_map") { r_ret = tile_get_normal_map(id); - else if (what == "tex_offset") + } else if (what == "tex_offset") { r_ret = tile_get_texture_offset(id); - else if (what == "material") + } else if (what == "material") { r_ret = tile_get_material(id); - else if (what == "modulate") + } else if (what == "modulate") { r_ret = tile_get_modulate(id); - else if (what == "region") + } else if (what == "region") { r_ret = tile_get_region(id); - else if (what == "tile_mode") + } else if (what == "tile_mode") { r_ret = tile_get_tile_mode(id); - else if (what.left(9) == "autotile/") { + } else if (what.left(9) == "autotile/") { what = what.right(9); - if (what == "bitmask_mode") + if (what == "bitmask_mode") { r_ret = autotile_get_bitmask_mode(id); - else if (what == "icon_coordinate") + } else if (what == "icon_coordinate") { r_ret = autotile_get_icon_coordinate(id); - else if (what == "tile_size") + } else if (what == "tile_size") { r_ret = autotile_get_size(id); - else if (what == "spacing") + } else if (what == "spacing") { r_ret = autotile_get_spacing(id); - else if (what == "bitmask_flags") { + } else if (what == "bitmask_flags") { Array p; for (Map<Vector2, uint32_t>::Element *E = tile_map[id].autotile_data.flags.front(); E; E = E->next()) { p.push_back(E->key()); @@ -252,14 +257,14 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const { r_ret = p; } else if (what == "occluder_map") { Array p; - for (Map<Vector2, Ref<OccluderPolygon2D> >::Element *E = tile_map[id].autotile_data.occluder_map.front(); E; E = E->next()) { + for (Map<Vector2, Ref<OccluderPolygon2D>>::Element *E = tile_map[id].autotile_data.occluder_map.front(); E; E = E->next()) { p.push_back(E->key()); p.push_back(E->value()); } r_ret = p; } else if (what == "navpoly_map") { Array p; - for (Map<Vector2, Ref<NavigationPolygon> >::Element *E = tile_map[id].autotile_data.navpoly_map.front(); E; E = E->next()) { + for (Map<Vector2, Ref<NavigationPolygon>>::Element *E = tile_map[id].autotile_data.navpoly_map.front(); E; E = E->next()) { p.push_back(E->key()); p.push_back(E->value()); } @@ -291,48 +296,47 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const { } r_ret = p; } - } else if (what == "shape") + } else if (what == "shape") { r_ret = tile_get_shape(id, 0); - else if (what == "shape_offset") + } else if (what == "shape_offset") { r_ret = tile_get_shape_offset(id, 0); - else if (what == "shape_transform") + } else if (what == "shape_transform") { r_ret = tile_get_shape_transform(id, 0); - else if (what == "shape_one_way") + } else if (what == "shape_one_way") { r_ret = tile_get_shape_one_way(id, 0); - else if (what == "shape_one_way_margin") + } else if (what == "shape_one_way_margin") { r_ret = tile_get_shape_one_way_margin(id, 0); - else if (what == "shapes") + } else if (what == "shapes") { r_ret = _tile_get_shapes(id); - else if (what == "occluder") + } else if (what == "occluder") { r_ret = tile_get_light_occluder(id); - else if (what == "occluder_offset") + } else if (what == "occluder_offset") { r_ret = tile_get_occluder_offset(id); - else if (what == "navigation") + } else if (what == "navigation") { r_ret = tile_get_navigation_polygon(id); - else if (what == "navigation_offset") + } else if (what == "navigation_offset") { r_ret = tile_get_navigation_polygon_offset(id); - else if (what == "z_index") + } else if (what == "z_index") { r_ret = tile_get_z_index(id); - else + } else { return false; + } return true; } void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { - for (Map<int, TileData>::Element *E = tile_map.front(); E; E = E->next()) { - int id = E->key(); String pre = itos(id) + "/"; - p_list->push_back(PropertyInfo(Variant::STRING, pre + "name")); - p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture")); - p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "tex_offset")); - p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial")); - p_list->push_back(PropertyInfo(Variant::COLOR, pre + "modulate")); - p_list->push_back(PropertyInfo(Variant::RECT2, pre + "region")); - p_list->push_back(PropertyInfo(Variant::INT, pre + "tile_mode", PROPERTY_HINT_ENUM, "SINGLE_TILE,AUTO_TILE,ATLAS_TILE")); + p_list->push_back(PropertyInfo(Variant::STRING, pre + "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "normal_map", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "tex_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::COLOR, pre + "modulate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::RECT2, pre + "region", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::INT, pre + "tile_mode", PROPERTY_HINT_ENUM, "SINGLE_TILE,AUTO_TILE,ATLAS_TILE", PROPERTY_USAGE_NOEDITOR)); if (tile_get_tile_mode(id) == AUTO_TILE) { p_list->push_back(PropertyInfo(Variant::INT, pre + "autotile/bitmask_mode", PROPERTY_HINT_ENUM, "2X2,3X3 (minimal),3X3", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/bitmask_flags", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); @@ -352,17 +356,17 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/priority_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "autotile/z_index_map", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); } - p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "occluder_offset")); - p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "occluder", PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "navigation_offset")); - p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "navigation", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::BOOL, pre + "shape_one_way", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::REAL, pre + "shape_one_way_margin", PROPERTY_HINT_RANGE, "0,128,0.01", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "occluder_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "occluder", PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "navigation_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "navigation", PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "shape_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL, pre + "shape_one_way", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::FLOAT, pre + "shape_one_way_margin", PROPERTY_HINT_RANGE, "0,128,0.01", PROPERTY_USAGE_NOEDITOR)); p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "shapes", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::INT, pre + "z_index", PROPERTY_HINT_RANGE, itos(VS::CANVAS_ITEM_Z_MIN) + "," + itos(VS::CANVAS_ITEM_Z_MAX) + ",1")); + p_list->push_back(PropertyInfo(Variant::INT, pre + "z_index", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1", PROPERTY_USAGE_NOEDITOR)); } } @@ -382,53 +386,45 @@ void TileSet::autotile_set_bitmask_mode(int p_id, BitmaskMode p_mode) { } TileSet::BitmaskMode TileSet::autotile_get_bitmask_mode(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), BITMASK_2X2); return tile_map[p_id].autotile_data.bitmask_mode; } -void TileSet::tile_set_texture(int p_id, const Ref<Texture> &p_texture) { - +void TileSet::tile_set_texture(int p_id, const Ref<Texture2D> &p_texture) { ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].texture = p_texture; emit_changed(); _change_notify("texture"); } -Ref<Texture> TileSet::tile_get_texture(int p_id) const { - - ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<Texture>()); +Ref<Texture2D> TileSet::tile_get_texture(int p_id) const { + ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<Texture2D>()); return tile_map[p_id].texture; } -void TileSet::tile_set_normal_map(int p_id, const Ref<Texture> &p_normal_map) { - +void TileSet::tile_set_normal_map(int p_id, const Ref<Texture2D> &p_normal_map) { ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].normal_map = p_normal_map; emit_changed(); } -Ref<Texture> TileSet::tile_get_normal_map(int p_id) const { - - ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<Texture>()); +Ref<Texture2D> TileSet::tile_get_normal_map(int p_id) const { + ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<Texture2D>()); return tile_map[p_id].normal_map; } void TileSet::tile_set_material(int p_id, const Ref<ShaderMaterial> &p_material) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].material = p_material; emit_changed(); } Ref<ShaderMaterial> TileSet::tile_get_material(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<ShaderMaterial>()); return tile_map[p_id].material; } void TileSet::tile_set_modulate(int p_id, const Color &p_modulate) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].modulate = p_modulate; emit_changed(); @@ -436,26 +432,22 @@ void TileSet::tile_set_modulate(int p_id, const Color &p_modulate) { } Color TileSet::tile_get_modulate(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Color(1, 1, 1)); return tile_map[p_id].modulate; } void TileSet::tile_set_texture_offset(int p_id, const Vector2 &p_offset) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].offset = p_offset; emit_changed(); } Vector2 TileSet::tile_get_texture_offset(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Vector2()); return tile_map[p_id].offset; } void TileSet::tile_set_region(int p_id, const Rect2 &p_region) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].region = p_region; emit_changed(); @@ -463,7 +455,6 @@ void TileSet::tile_set_region(int p_id, const Rect2 &p_region) { } Rect2 TileSet::tile_get_region(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Rect2()); return tile_map[p_id].region; } @@ -476,26 +467,22 @@ void TileSet::tile_set_tile_mode(int p_id, TileMode p_tile_mode) { } TileSet::TileMode TileSet::tile_get_tile_mode(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), SINGLE_TILE); return tile_map[p_id].tile_mode; } void TileSet::autotile_set_icon_coordinate(int p_id, Vector2 coord) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].autotile_data.icon_coord = coord; emit_changed(); } Vector2 TileSet::autotile_get_icon_coordinate(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Vector2()); return tile_map[p_id].autotile_data.icon_coord; } void TileSet::autotile_set_spacing(int p_id, int p_spacing) { - ERR_FAIL_COND(!tile_map.has(p_id)); ERR_FAIL_COND(p_spacing < 0); tile_map[p_id].autotile_data.spacing = p_spacing; @@ -503,39 +490,33 @@ void TileSet::autotile_set_spacing(int p_id, int p_spacing) { } int TileSet::autotile_get_spacing(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), 0); return tile_map[p_id].autotile_data.spacing; } void TileSet::autotile_set_size(int p_id, Size2 p_size) { - ERR_FAIL_COND(!tile_map.has(p_id)); ERR_FAIL_COND(p_size.x <= 0 || p_size.y <= 0); tile_map[p_id].autotile_data.size = p_size; } Size2 TileSet::autotile_get_size(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Size2()); return tile_map[p_id].autotile_data.size; } void TileSet::autotile_clear_bitmask_map(int p_id) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].autotile_data.flags.clear(); } void TileSet::autotile_set_subtile_priority(int p_id, const Vector2 &p_coord, int p_priority) { - ERR_FAIL_COND(!tile_map.has(p_id)); ERR_FAIL_COND(p_priority <= 0); tile_map[p_id].autotile_data.priority_map[p_coord] = p_priority; } int TileSet::autotile_get_subtile_priority(int p_id, const Vector2 &p_coord) { - ERR_FAIL_COND_V(!tile_map.has(p_id), 1); if (tile_map[p_id].autotile_data.priority_map.has(p_coord)) { return tile_map[p_id].autotile_data.priority_map[p_coord]; @@ -545,21 +526,18 @@ int TileSet::autotile_get_subtile_priority(int p_id, const Vector2 &p_coord) { } const Map<Vector2, int> &TileSet::autotile_get_priority_map(int p_id) const { - static Map<Vector2, int> dummy; ERR_FAIL_COND_V(!tile_map.has(p_id), dummy); return tile_map[p_id].autotile_data.priority_map; } void TileSet::autotile_set_z_index(int p_id, const Vector2 &p_coord, int p_z_index) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].autotile_data.z_index_map[p_coord] = p_z_index; emit_changed(); } int TileSet::autotile_get_z_index(int p_id, const Vector2 &p_coord) { - ERR_FAIL_COND_V(!tile_map.has(p_id), 1); if (tile_map[p_id].autotile_data.z_index_map.has(p_coord)) { return tile_map[p_id].autotile_data.z_index_map[p_coord]; @@ -569,25 +547,23 @@ int TileSet::autotile_get_z_index(int p_id, const Vector2 &p_coord) { } const Map<Vector2, int> &TileSet::autotile_get_z_index_map(int p_id) const { - static Map<Vector2, int> dummy; ERR_FAIL_COND_V(!tile_map.has(p_id), dummy); return tile_map[p_id].autotile_data.z_index_map; } void TileSet::autotile_set_bitmask(int p_id, Vector2 p_coord, uint32_t p_flag) { - ERR_FAIL_COND(!tile_map.has(p_id)); if (p_flag == 0) { - if (tile_map[p_id].autotile_data.flags.has(p_coord)) + if (tile_map[p_id].autotile_data.flags.has(p_coord)) { tile_map[p_id].autotile_data.flags.erase(p_coord); + } } else { tile_map[p_id].autotile_data.flags[p_coord] = p_flag; } } uint32_t TileSet::autotile_get_bitmask(int p_id, Vector2 p_coord) { - ERR_FAIL_COND_V(!tile_map.has(p_id), 0); if (!tile_map[p_id].autotile_data.flags.has(p_coord)) { return 0; @@ -596,7 +572,6 @@ uint32_t TileSet::autotile_get_bitmask(int p_id, Vector2 p_coord) { } const Map<Vector2, uint32_t> &TileSet::autotile_get_bitmask_map(int p_id) { - static Map<Vector2, uint32_t> dummy; static Map<Vector2, uint32_t> dummy_atlas; ERR_FAIL_COND_V(!tile_map.has(p_id), dummy); @@ -611,16 +586,16 @@ const Map<Vector2, uint32_t> &TileSet::autotile_get_bitmask_map(int p_id) { } } return dummy_atlas; - } else + } else { return tile_map[p_id].autotile_data.flags; + } } Vector2 TileSet::autotile_get_subtile_for_bitmask(int p_id, uint16_t p_bitmask, const Node *p_tilemap_node, const Vector2 &p_tile_location) { - ERR_FAIL_COND_V(!tile_map.has(p_id), Vector2()); //First try to forward selection to script if (p_tilemap_node->get_class_name() == "TileMap") { - if (get_script_instance() != NULL) { + if (get_script_instance() != nullptr) { if (get_script_instance()->has_method("_forward_subtile_selection")) { Variant ret = get_script_instance()->call("_forward_subtile_selection", p_id, p_bitmask, p_tilemap_node, p_tile_location); if (ret.get_type() == Variant::VECTOR2) { @@ -678,10 +653,9 @@ Vector2 TileSet::autotile_get_subtile_for_bitmask(int p_id, uint16_t p_bitmask, } Vector2 TileSet::atlastile_get_subtile_by_priority(int p_id, const Node *p_tilemap_node, const Vector2 &p_tile_location) { - ERR_FAIL_COND_V(!tile_map.has(p_id), Vector2()); //First try to forward selection to script - if (get_script_instance() != NULL) { + if (get_script_instance() != nullptr) { if (get_script_instance()->has_method("_forward_atlas_subtile_selection")) { Variant ret = get_script_instance()->call("_forward_atlas_subtile_selection", p_id, p_tilemap_node, p_tile_location); if (ret.get_type() == Variant::VECTOR2) { @@ -708,7 +682,6 @@ Vector2 TileSet::atlastile_get_subtile_by_priority(int p_id, const Node *p_tilem } void TileSet::tile_set_name(int p_id, const String &p_name) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].name = p_name; emit_changed(); @@ -716,19 +689,16 @@ void TileSet::tile_set_name(int p_id, const String &p_name) { } String TileSet::tile_get_name(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), String()); return tile_map[p_id].name; } void TileSet::tile_clear_shapes(int p_id) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].shapes_data.clear(); } void TileSet::tile_add_shape(int p_id, const Ref<Shape2D> &p_shape, const Transform2D &p_transform, bool p_one_way, const Vector2 &p_autotile_coord) { - ERR_FAIL_COND(!tile_map.has(p_id)); ShapeData new_data = ShapeData(); @@ -741,52 +711,51 @@ void TileSet::tile_add_shape(int p_id, const Ref<Shape2D> &p_shape, const Transf } int TileSet::tile_get_shape_count(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), 0); return tile_map[p_id].shapes_data.size(); } void TileSet::tile_set_shape(int p_id, int p_shape_id, const Ref<Shape2D> &p_shape) { - ERR_FAIL_COND(!tile_map.has(p_id)); ERR_FAIL_COND(p_shape_id < 0); - if (p_shape_id >= tile_map[p_id].shapes_data.size()) + if (p_shape_id >= tile_map[p_id].shapes_data.size()) { tile_map[p_id].shapes_data.resize(p_shape_id + 1); + } tile_map[p_id].shapes_data.write[p_shape_id].shape = p_shape; _decompose_convex_shape(p_shape); emit_changed(); } Ref<Shape2D> TileSet::tile_get_shape(int p_id, int p_shape_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<Shape2D>()); ERR_FAIL_COND_V(p_shape_id < 0, Ref<Shape2D>()); - if (p_shape_id < tile_map[p_id].shapes_data.size()) + if (p_shape_id < tile_map[p_id].shapes_data.size()) { return tile_map[p_id].shapes_data[p_shape_id].shape; + } return Ref<Shape2D>(); } void TileSet::tile_set_shape_transform(int p_id, int p_shape_id, const Transform2D &p_offset) { - ERR_FAIL_COND(!tile_map.has(p_id)); ERR_FAIL_COND(p_shape_id < 0); - if (p_shape_id >= tile_map[p_id].shapes_data.size()) + if (p_shape_id >= tile_map[p_id].shapes_data.size()) { tile_map[p_id].shapes_data.resize(p_shape_id + 1); + } tile_map[p_id].shapes_data.write[p_shape_id].shape_transform = p_offset; emit_changed(); } Transform2D TileSet::tile_get_shape_transform(int p_id, int p_shape_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Transform2D()); ERR_FAIL_COND_V(p_shape_id < 0, Transform2D()); - if (p_shape_id < tile_map[p_id].shapes_data.size()) + if (p_shape_id < tile_map[p_id].shapes_data.size()) { return tile_map[p_id].shapes_data[p_shape_id].shape_transform; + } return Transform2D(); } @@ -802,57 +771,55 @@ Vector2 TileSet::tile_get_shape_offset(int p_id, int p_shape_id) const { } void TileSet::tile_set_shape_one_way(int p_id, int p_shape_id, const bool p_one_way) { - ERR_FAIL_COND(!tile_map.has(p_id)); ERR_FAIL_COND(p_shape_id < 0); - if (p_shape_id >= tile_map[p_id].shapes_data.size()) + if (p_shape_id >= tile_map[p_id].shapes_data.size()) { tile_map[p_id].shapes_data.resize(p_shape_id + 1); + } tile_map[p_id].shapes_data.write[p_shape_id].one_way_collision = p_one_way; emit_changed(); } bool TileSet::tile_get_shape_one_way(int p_id, int p_shape_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), false); ERR_FAIL_COND_V(p_shape_id < 0, false); - if (p_shape_id < tile_map[p_id].shapes_data.size()) + if (p_shape_id < tile_map[p_id].shapes_data.size()) { return tile_map[p_id].shapes_data[p_shape_id].one_way_collision; + } return false; } void TileSet::tile_set_shape_one_way_margin(int p_id, int p_shape_id, float p_margin) { - ERR_FAIL_COND(!tile_map.has(p_id)); ERR_FAIL_COND(p_shape_id < 0); - if (p_shape_id >= tile_map[p_id].shapes_data.size()) + if (p_shape_id >= tile_map[p_id].shapes_data.size()) { tile_map[p_id].shapes_data.resize(p_shape_id + 1); + } tile_map[p_id].shapes_data.write[p_shape_id].one_way_collision_margin = p_margin; emit_changed(); } float TileSet::tile_get_shape_one_way_margin(int p_id, int p_shape_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), 0); ERR_FAIL_COND_V(p_shape_id < 0, 0); - if (p_shape_id < tile_map[p_id].shapes_data.size()) + if (p_shape_id < tile_map[p_id].shapes_data.size()) { return tile_map[p_id].shapes_data[p_shape_id].one_way_collision_margin; + } return 0; } void TileSet::tile_set_light_occluder(int p_id, const Ref<OccluderPolygon2D> &p_light_occluder) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].occluder = p_light_occluder; } Ref<OccluderPolygon2D> TileSet::tile_get_light_occluder(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<OccluderPolygon2D>()); return tile_map[p_id].occluder; } @@ -869,7 +836,6 @@ void TileSet::autotile_set_light_occluder(int p_id, const Ref<OccluderPolygon2D> } Ref<OccluderPolygon2D> TileSet::autotile_get_light_occluder(int p_id, const Vector2 &p_coord) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<OccluderPolygon2D>()); if (!tile_map[p_id].autotile_data.occluder_map.has(p_coord)) { @@ -880,38 +846,32 @@ Ref<OccluderPolygon2D> TileSet::autotile_get_light_occluder(int p_id, const Vect } void TileSet::tile_set_navigation_polygon_offset(int p_id, const Vector2 &p_offset) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].navigation_polygon_offset = p_offset; } Vector2 TileSet::tile_get_navigation_polygon_offset(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Vector2()); return tile_map[p_id].navigation_polygon_offset; } void TileSet::tile_set_navigation_polygon(int p_id, const Ref<NavigationPolygon> &p_navigation_polygon) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].navigation_polygon = p_navigation_polygon; } Ref<NavigationPolygon> TileSet::tile_get_navigation_polygon(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<NavigationPolygon>()); return tile_map[p_id].navigation_polygon; } -const Map<Vector2, Ref<OccluderPolygon2D> > &TileSet::autotile_get_light_oclusion_map(int p_id) const { - - static Map<Vector2, Ref<OccluderPolygon2D> > dummy; +const Map<Vector2, Ref<OccluderPolygon2D>> &TileSet::autotile_get_light_oclusion_map(int p_id) const { + static Map<Vector2, Ref<OccluderPolygon2D>> dummy; ERR_FAIL_COND_V(!tile_map.has(p_id), dummy); return tile_map[p_id].autotile_data.occluder_map; } void TileSet::autotile_set_navigation_polygon(int p_id, const Ref<NavigationPolygon> &p_navigation_polygon, const Vector2 &p_coord) { - ERR_FAIL_COND(!tile_map.has(p_id)); if (p_navigation_polygon.is_null()) { if (tile_map[p_id].autotile_data.navpoly_map.has(p_coord)) { @@ -923,7 +883,6 @@ void TileSet::autotile_set_navigation_polygon(int p_id, const Ref<NavigationPoly } Ref<NavigationPolygon> TileSet::autotile_get_navigation_polygon(int p_id, const Vector2 &p_coord) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<NavigationPolygon>()); if (!tile_map[p_id].autotile_data.navpoly_map.has(p_coord)) { return Ref<NavigationPolygon>(); @@ -932,27 +891,23 @@ Ref<NavigationPolygon> TileSet::autotile_get_navigation_polygon(int p_id, const } } -const Map<Vector2, Ref<NavigationPolygon> > &TileSet::autotile_get_navigation_map(int p_id) const { - - static Map<Vector2, Ref<NavigationPolygon> > dummy; +const Map<Vector2, Ref<NavigationPolygon>> &TileSet::autotile_get_navigation_map(int p_id) const { + static Map<Vector2, Ref<NavigationPolygon>> dummy; ERR_FAIL_COND_V(!tile_map.has(p_id), dummy); return tile_map[p_id].autotile_data.navpoly_map; } void TileSet::tile_set_occluder_offset(int p_id, const Vector2 &p_offset) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].occluder_offset = p_offset; } Vector2 TileSet::tile_get_occluder_offset(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Vector2()); return tile_map[p_id].occluder_offset; } void TileSet::tile_set_shapes(int p_id, const Vector<ShapeData> &p_shapes) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].shapes_data = p_shapes; for (int i = 0; i < p_shapes.size(); i++) { @@ -962,27 +917,23 @@ void TileSet::tile_set_shapes(int p_id, const Vector<ShapeData> &p_shapes) { } Vector<TileSet::ShapeData> TileSet::tile_get_shapes(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Vector<ShapeData>()); return tile_map[p_id].shapes_data; } int TileSet::tile_get_z_index(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), 0); return tile_map[p_id].z_index; } void TileSet::tile_set_z_index(int p_id, int p_z_index) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].z_index = p_z_index; emit_changed(); } void TileSet::_tile_set_shapes(int p_id, const Array &p_shapes) { - ERR_FAIL_COND(!tile_map.has(p_id)); Vector<ShapeData> shapes_data; Transform2D default_transform = tile_get_shape_transform(p_id, 0); @@ -993,7 +944,9 @@ void TileSet::_tile_set_shapes(int p_id, const Array &p_shapes) { if (p_shapes[i].get_type() == Variant::OBJECT) { Ref<Shape2D> shape = p_shapes[i]; - if (shape.is_null()) continue; + if (shape.is_null()) { + continue; + } s.shape = shape; s.shape_transform = default_transform; @@ -1005,30 +958,35 @@ void TileSet::_tile_set_shapes(int p_id, const Array &p_shapes) { if (d.has("shape") && d["shape"].get_type() == Variant::OBJECT) { s.shape = d["shape"]; _decompose_convex_shape(s.shape); - } else + } else { continue; + } - if (d.has("shape_transform") && d["shape_transform"].get_type() == Variant::TRANSFORM2D) + if (d.has("shape_transform") && d["shape_transform"].get_type() == Variant::TRANSFORM2D) { s.shape_transform = d["shape_transform"]; - else if (d.has("shape_offset") && d["shape_offset"].get_type() == Variant::VECTOR2) + } else if (d.has("shape_offset") && d["shape_offset"].get_type() == Variant::VECTOR2) { s.shape_transform = Transform2D(0, (Vector2)d["shape_offset"]); - else + } else { s.shape_transform = default_transform; + } - if (d.has("one_way") && d["one_way"].get_type() == Variant::BOOL) + if (d.has("one_way") && d["one_way"].get_type() == Variant::BOOL) { s.one_way_collision = d["one_way"]; - else + } else { s.one_way_collision = default_one_way; + } - if (d.has("one_way_margin") && d["one_way_margin"].is_num()) + if (d.has("one_way_margin") && d["one_way_margin"].is_num()) { s.one_way_collision_margin = d["one_way_margin"]; - else + } else { s.one_way_collision_margin = 1.0; + } - if (d.has("autotile_coord") && d["autotile_coord"].get_type() == Variant::VECTOR2) + if (d.has("autotile_coord") && d["autotile_coord"].get_type() == Variant::VECTOR2) { s.autotile_coord = d["autotile_coord"]; - else + } else { s.autotile_coord = default_autotile_coord; + } } else { ERR_CONTINUE_MSG(true, "Expected an array of objects or dictionaries for tile_set_shapes."); @@ -1042,7 +1000,6 @@ void TileSet::_tile_set_shapes(int p_id, const Array &p_shapes) { } Array TileSet::_tile_get_shapes(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Array()); Array arr; @@ -1061,7 +1018,6 @@ Array TileSet::_tile_get_shapes(int p_id) const { } Array TileSet::_get_tiles_ids() const { - Array arr; for (Map<int, TileData>::Element *E = tile_map.front(); E; E = E->next()) { @@ -1072,12 +1028,14 @@ Array TileSet::_get_tiles_ids() const { } void TileSet::_decompose_convex_shape(Ref<Shape2D> p_shape) { - if (Engine::get_singleton()->is_editor_hint()) + if (Engine::get_singleton()->is_editor_hint()) { return; + } Ref<ConvexPolygonShape2D> convex = p_shape; - if (!convex.is_valid()) + if (!convex.is_valid()) { return; - Vector<Vector<Vector2> > decomp = Geometry::decompose_polygon_in_convex(convex->get_points()); + } + Vector<Vector<Vector2>> decomp = Geometry2D::decompose_polygon_in_convex(convex->get_points()); if (decomp.size() > 1) { Array sub_shapes; for (int i = 0; i < decomp.size(); i++) { @@ -1092,23 +1050,19 @@ void TileSet::_decompose_convex_shape(Ref<Shape2D> p_shape) { } void TileSet::get_tile_list(List<int> *p_tiles) const { - for (Map<int, TileData>::Element *E = tile_map.front(); E; E = E->next()) { - p_tiles->push_back(E->key()); } } bool TileSet::has_tile(int p_id) const { - return tile_map.has(p_id); } bool TileSet::is_tile_bound(int p_drawn_id, int p_neighbor_id) { - if (p_drawn_id == p_neighbor_id) { return true; - } else if (get_script_instance() != NULL) { + } else if (get_script_instance() != nullptr) { if (get_script_instance()->has_method("_is_tile_bound")) { Variant ret = get_script_instance()->call("_is_tile_bound", p_drawn_id, p_neighbor_id); if (ret.get_type() == Variant::BOOL) { @@ -1120,7 +1074,6 @@ bool TileSet::is_tile_bound(int p_drawn_id, int p_neighbor_id) { } void TileSet::remove_tile(int p_id) { - ERR_FAIL_COND(!tile_map.has(p_id)); tile_map.erase(p_id); _change_notify(""); @@ -1128,32 +1081,29 @@ void TileSet::remove_tile(int p_id) { } int TileSet::get_last_unused_tile_id() const { - - if (tile_map.size()) + if (tile_map.size()) { return tile_map.back()->key() + 1; - else + } else { return 0; + } } int TileSet::find_tile_by_name(const String &p_name) const { - for (Map<int, TileData>::Element *E = tile_map.front(); E; E = E->next()) { - - if (p_name == E->get().name) + if (p_name == E->get().name) { return E->key(); + } } return -1; } void TileSet::clear() { - tile_map.clear(); _change_notify(""); emit_changed(); } void TileSet::_bind_methods() { - ClassDB::bind_method(D_METHOD("create_tile", "id"), &TileSet::create_tile); ClassDB::bind_method(D_METHOD("autotile_clear_bitmask_map", "id"), &TileSet::autotile_clear_bitmask_map); ClassDB::bind_method(D_METHOD("autotile_set_icon_coordinate", "id", "coord"), &TileSet::autotile_set_icon_coordinate); diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index eab40ce467..78f34e46ce 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -34,13 +34,12 @@ #include "core/array.h" #include "core/resource.h" #include "scene/2d/light_occluder_2d.h" -#include "scene/2d/navigation_polygon.h" +#include "scene/2d/navigation_region_2d.h" #include "scene/resources/convex_polygon_shape_2d.h" #include "scene/resources/shape_2d.h" #include "scene/resources/texture.h" class TileSet : public Resource { - GDCLASS(TileSet, Resource); public: @@ -48,13 +47,10 @@ public: Ref<Shape2D> shape; Transform2D shape_transform; Vector2 autotile_coord; - bool one_way_collision; - float one_way_collision_margin; + bool one_way_collision = false; + float one_way_collision_margin = 1.0; - ShapeData() { - one_way_collision = false; - one_way_collision_margin = 1.0; - } + ShapeData() {} }; enum BitmaskMode { @@ -92,30 +88,25 @@ public: }; struct AutotileData { - BitmaskMode bitmask_mode; - Size2 size; - int spacing; - Vector2 icon_coord; + BitmaskMode bitmask_mode = BITMASK_2X2; + // Default size to prevent invalid value + Size2 size = Size2(64, 64); + Vector2 icon_coord = Vector2(0, 0); + int spacing = 0; Map<Vector2, uint32_t> flags; - Map<Vector2, Ref<OccluderPolygon2D> > occluder_map; - Map<Vector2, Ref<NavigationPolygon> > navpoly_map; + Map<Vector2, Ref<OccluderPolygon2D>> occluder_map; + Map<Vector2, Ref<NavigationPolygon>> navpoly_map; Map<Vector2, int> priority_map; Map<Vector2, int> z_index_map; - // Default size to prevent invalid value - explicit AutotileData() : - bitmask_mode(BITMASK_2X2), - size(64, 64), - spacing(0), - icon_coord(0, 0) {} + explicit AutotileData() {} }; private: struct TileData { - String name; - Ref<Texture> texture; - Ref<Texture> normal_map; + Ref<Texture2D> texture; + Ref<Texture2D> normal_map; Vector2 offset; Rect2i region; Vector<ShapeData> shapes_data; @@ -124,16 +115,13 @@ private: Vector2 navigation_polygon_offset; Ref<NavigationPolygon> navigation_polygon; Ref<ShaderMaterial> material; - TileMode tile_mode; - Color modulate; + TileMode tile_mode = SINGLE_TILE; + // Default modulate for back-compat + Color modulate = Color(1, 1, 1); AutotileData autotile_data; - int z_index; + int z_index = 0; - // Default modulate for back-compat - explicit TileData() : - tile_mode(SINGLE_TILE), - modulate(1, 1, 1), - z_index(0) {} + explicit TileData() {} }; Map<int, TileData> tile_map; @@ -158,11 +146,11 @@ public: void tile_set_name(int p_id, const String &p_name); String tile_get_name(int p_id) const; - void tile_set_texture(int p_id, const Ref<Texture> &p_texture); - Ref<Texture> tile_get_texture(int p_id) const; + void tile_set_texture(int p_id, const Ref<Texture2D> &p_texture); + Ref<Texture2D> tile_get_texture(int p_id) const; - void tile_set_normal_map(int p_id, const Ref<Texture> &p_normal_map); - Ref<Texture> tile_get_normal_map(int p_id) const; + void tile_set_normal_map(int p_id, const Ref<Texture2D> &p_normal_map); + Ref<Texture2D> tile_get_normal_map(int p_id) const; void tile_set_texture_offset(int p_id, const Vector2 &p_offset); Vector2 tile_get_texture_offset(int p_id) const; @@ -194,8 +182,8 @@ public: void autotile_set_bitmask(int p_id, Vector2 p_coord, uint32_t p_flag); uint32_t autotile_get_bitmask(int p_id, Vector2 p_coord); const Map<Vector2, uint32_t> &autotile_get_bitmask_map(int p_id); - Vector2 autotile_get_subtile_for_bitmask(int p_id, uint16_t p_bitmask, const Node *p_tilemap_node = NULL, const Vector2 &p_tile_location = Vector2()); - Vector2 atlastile_get_subtile_by_priority(int p_id, const Node *p_tilemap_node = NULL, const Vector2 &p_tile_location = Vector2()); + Vector2 autotile_get_subtile_for_bitmask(int p_id, uint16_t p_bitmask, const Node *p_tilemap_node = nullptr, const Vector2 &p_tile_location = Vector2()); + Vector2 atlastile_get_subtile_by_priority(int p_id, const Node *p_tilemap_node = nullptr, const Vector2 &p_tile_location = Vector2()); void tile_set_shape(int p_id, int p_shape_id, const Ref<Shape2D> &p_shape); Ref<Shape2D> tile_get_shape(int p_id, int p_shape_id) const; @@ -233,7 +221,7 @@ public: void autotile_set_light_occluder(int p_id, const Ref<OccluderPolygon2D> &p_light_occluder, const Vector2 &p_coord); Ref<OccluderPolygon2D> autotile_get_light_occluder(int p_id, const Vector2 &p_coord) const; - const Map<Vector2, Ref<OccluderPolygon2D> > &autotile_get_light_oclusion_map(int p_id) const; + const Map<Vector2, Ref<OccluderPolygon2D>> &autotile_get_light_oclusion_map(int p_id) const; void tile_set_navigation_polygon_offset(int p_id, const Vector2 &p_offset); Vector2 tile_get_navigation_polygon_offset(int p_id) const; @@ -243,7 +231,7 @@ public: void autotile_set_navigation_polygon(int p_id, const Ref<NavigationPolygon> &p_navigation_polygon, const Vector2 &p_coord); Ref<NavigationPolygon> autotile_get_navigation_polygon(int p_id, const Vector2 &p_coord) const; - const Map<Vector2, Ref<NavigationPolygon> > &autotile_get_navigation_map(int p_id) const; + const Map<Vector2, Ref<NavigationPolygon>> &autotile_get_navigation_map(int p_id) const; void tile_set_z_index(int p_id, int p_z_index); int tile_get_z_index(int p_id) const; diff --git a/scene/resources/video_stream.h b/scene/resources/video_stream.h index 444bb698ae..379ba53a34 100644 --- a/scene/resources/video_stream.h +++ b/scene/resources/video_stream.h @@ -34,7 +34,6 @@ #include "scene/resources/texture.h" class VideoStreamPlayback : public Resource { - GDCLASS(VideoStreamPlayback, Resource); public: @@ -58,7 +57,8 @@ public: virtual void set_audio_track(int p_idx) = 0; - virtual Ref<Texture> get_texture() const = 0; + virtual Ref<Texture2D> get_texture() const = 0; + virtual void update(float p_delta) = 0; virtual void set_mix_callback(AudioMixCallback p_callback, void *p_userdata) = 0; @@ -67,7 +67,6 @@ public: }; class VideoStream : public Resource { - GDCLASS(VideoStream, Resource); OBJ_SAVE_TYPE(VideoStream); // Saves derived classes with common type so they can be interchanged. diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index b3a72ea7b6..b8d2003e68 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -31,19 +31,18 @@ #include "visual_shader.h" #include "core/vmap.h" -#include "servers/visual/shader_types.h" +#include "servers/rendering/shader_types.h" +#include "visual_shader_nodes.h" bool VisualShaderNode::is_simple_decl() const { return simple_decl; } void VisualShaderNode::set_output_port_for_preview(int p_index) { - port_preview = p_index; } int VisualShaderNode::get_output_port_for_preview() const { - return port_preview; } @@ -64,9 +63,56 @@ bool VisualShaderNode::is_port_separator(int p_index) const { return false; } +bool VisualShaderNode::is_output_port_connected(int p_port) const { + if (connected_output_ports.has(p_port)) { + return connected_output_ports[p_port]; + } + return false; +} + +void VisualShaderNode::set_output_port_connected(int p_port, bool p_connected) { + if (p_connected) { + connected_output_ports[p_port] = true; + ++connected_output_count; + } else { + --connected_output_count; + if (connected_output_count == 0) { + connected_output_ports[p_port] = false; + } + } +} + +bool VisualShaderNode::is_input_port_connected(int p_port) const { + if (connected_input_ports.has(p_port)) { + return connected_input_ports[p_port]; + } + return false; +} + +void VisualShaderNode::set_input_port_connected(int p_port, bool p_connected) { + connected_input_ports[p_port] = p_connected; +} + +bool VisualShaderNode::is_generate_input_var(int p_port) const { + return true; +} + +bool VisualShaderNode::is_code_generated() const { + return true; +} + +bool VisualShaderNode::is_show_prop_names() const { + return false; +} + +bool VisualShaderNode::is_use_prop_slots() const { + return false; +} + Vector<VisualShader::DefaultTextureParam> VisualShaderNode::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { return Vector<VisualShader::DefaultTextureParam>(); } + String VisualShaderNode::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { return String(); } @@ -84,7 +130,6 @@ Vector<StringName> VisualShaderNode::get_editable_properties() const { } Array VisualShaderNode::get_default_input_values() const { - Array ret; for (Map<int, Variant>::Element *E = default_input_values.front(); E; E = E->next()) { ret.push_back(E->key()); @@ -92,8 +137,8 @@ Array VisualShaderNode::get_default_input_values() const { } return ret; } -void VisualShaderNode::set_default_input_values(const Array &p_values) { +void VisualShaderNode::set_default_input_values(const Array &p_values) { if (p_values.size() % 2 == 0) { for (int i = 0; i < p_values.size(); i += 2) { default_input_values[p_values[i + 0]] = p_values[i + 1]; @@ -112,7 +157,6 @@ String VisualShaderNode::get_input_port_default_hint(int p_port) const { } void VisualShaderNode::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_output_port_for_preview", "port"), &VisualShaderNode::set_output_port_for_preview); ClassDB::bind_method(D_METHOD("get_output_port_for_preview"), &VisualShaderNode::get_output_port_for_preview); @@ -127,6 +171,7 @@ void VisualShaderNode::_bind_methods() { ADD_SIGNAL(MethodInfo("editor_refresh_request")); BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR); + BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR_INT); BIND_ENUM_CONSTANT(PORT_TYPE_VECTOR); BIND_ENUM_CONSTANT(PORT_TYPE_BOOLEAN); BIND_ENUM_CONSTANT(PORT_TYPE_TRANSFORM); @@ -135,8 +180,6 @@ void VisualShaderNode::_bind_methods() { } VisualShaderNode::VisualShaderNode() { - port_preview = -1; - simple_decl = true; } ///////////////////////////////////////////////////////// @@ -223,7 +266,6 @@ String VisualShaderNodeCustom::get_output_port_name(int p_port) const { } String VisualShaderNodeCustom::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 { - ERR_FAIL_COND_V(!get_script_instance(), ""); ERR_FAIL_COND_V(!get_script_instance()->has_method("_get_code"), ""); Array input_vars; @@ -262,20 +304,19 @@ String VisualShaderNodeCustom::generate_global_per_node(Shader::Mode p_mode, Vis } void VisualShaderNodeCustom::_bind_methods() { - BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_name")); BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_description")); BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_category")); - BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_subcategory")); BIND_VMETHOD(MethodInfo(Variant::INT, "_get_return_icon_type")); BIND_VMETHOD(MethodInfo(Variant::INT, "_get_input_port_count")); BIND_VMETHOD(MethodInfo(Variant::INT, "_get_input_port_type", PropertyInfo(Variant::INT, "port"))); - BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_input_port_name", PropertyInfo(Variant::INT, "port"))); + BIND_VMETHOD(MethodInfo(Variant::STRING_NAME, "_get_input_port_name", PropertyInfo(Variant::INT, "port"))); BIND_VMETHOD(MethodInfo(Variant::INT, "_get_output_port_count")); BIND_VMETHOD(MethodInfo(Variant::INT, "_get_output_port_type", PropertyInfo(Variant::INT, "port"))); - BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_output_port_name", PropertyInfo(Variant::INT, "port"))); + BIND_VMETHOD(MethodInfo(Variant::STRING_NAME, "_get_output_port_name", PropertyInfo(Variant::INT, "port"))); BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_code", PropertyInfo(Variant::ARRAY, "input_vars"), PropertyInfo(Variant::ARRAY, "output_vars"), PropertyInfo(Variant::INT, "mode"), PropertyInfo(Variant::INT, "type"))); BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_global_code", PropertyInfo(Variant::INT, "mode"))); + BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_highend")); } VisualShaderNodeCustom::VisualShaderNodeCustom() { @@ -284,6 +325,57 @@ VisualShaderNodeCustom::VisualShaderNodeCustom() { ///////////////////////////////////////////////////////// +void VisualShader::set_shader_type(Type p_type) { + current_type = p_type; +} + +VisualShader::Type VisualShader::get_shader_type() const { + return current_type; +} + +void VisualShader::set_version(const String &p_version) { + version = p_version; +} + +String VisualShader::get_version() const { + return version; +} + +void VisualShader::update_version(const String &p_new_version) { + if (version == "") { + for (int i = 0; i < TYPE_MAX; i++) { + for (Map<int, Node>::Element *E = graph[i].nodes.front(); E; E = E->next()) { + Ref<VisualShaderNodeExpression> expression = Object::cast_to<VisualShaderNodeExpression>(E->get().node.ptr()); + if (expression.is_valid()) { + for (int j = 0; j < expression->get_input_port_count(); j++) { + int type = expression->get_input_port_type(j); + if (type > 0) { // + PORT_TYPE_SCALAR_INT + type += 1; + } + expression->set_input_port_type(j, type); + } + for (int j = 0; j < expression->get_output_port_count(); j++) { + int type = expression->get_output_port_type(j); + if (type > 0) { // + PORT_TYPE_SCALAR_INT + type += 1; + } + expression->set_output_port_type(j, type); + } + } + Ref<VisualShaderNodeCompare> compare = Object::cast_to<VisualShaderNodeCompare>(E->get().node.ptr()); + if (compare.is_valid()) { + int ctype = int(compare->get_comparison_type()); + if (int(ctype) > 0) { // + PORT_TYPE_SCALAR_INT + ctype += 1; + } + compare->set_comparison_type(VisualShaderNodeCompare::ComparisonType(ctype)); + } + } + } + } + set_version(p_new_version); +} + void VisualShader::add_node(Type p_type, const Ref<VisualShaderNode> &p_node, const Vector2 &p_position, int p_id) { ERR_FAIL_COND(p_node.is_null()); ERR_FAIL_COND(p_id < 2); @@ -304,10 +396,10 @@ void VisualShader::add_node(Type p_type, const Ref<VisualShaderNode> &p_node, co if (input.is_valid()) { input->shader_mode = shader_mode; input->shader_type = p_type; - input->connect("input_type_changed", this, "_input_type_changed", varray(p_type, p_id)); + input->connect("input_type_changed", callable_mp(this, &VisualShader::_input_type_changed), varray(p_type, p_id)); } - n.node->connect("changed", this, "_queue_update"); + n.node->connect("changed", callable_mp(this, &VisualShader::_queue_update)); Ref<VisualShaderNodeCustom> custom = n.node; if (custom.is_valid()) { @@ -351,6 +443,7 @@ Vector<int> VisualShader::get_node_list(Type p_type) const { return ret; } + int VisualShader::get_valid_node_id(Type p_type) const { ERR_FAIL_INDEX_V(p_type, TYPE_MAX, NODE_ID_INVALID); const Graph *g = &graph[p_type]; @@ -359,8 +452,9 @@ int VisualShader::get_valid_node_id(Type p_type) const { int VisualShader::find_node_id(Type p_type, const Ref<VisualShaderNode> &p_node) const { for (const Map<int, Node>::Element *E = graph[p_type].nodes.front(); E; E = E->next()) { - if (E->get().node == p_node) + if (E->get().node == p_node) { return E->key(); + } } return NODE_ID_INVALID; @@ -374,10 +468,10 @@ void VisualShader::remove_node(Type p_type, int p_id) { Ref<VisualShaderNodeInput> input = g->nodes[p_id].node; if (input.is_valid()) { - input->disconnect("input_type_changed", this, "_input_type_changed"); + input->disconnect("input_type_changed", callable_mp(this, &VisualShader::_input_type_changed)); } - g->nodes[p_id].node->disconnect("changed", this, "_queue_update"); + g->nodes[p_id].node->disconnect("changed", callable_mp(this, &VisualShader::_queue_update)); g->nodes.erase(p_id); @@ -387,6 +481,7 @@ void VisualShader::remove_node(Type p_type, int p_id) { g->connections.erase(E); if (E->get().from_node == p_id) { g->nodes[E->get().to_node].prev_connected_nodes.erase(p_id); + g->nodes[E->get().to_node].node->set_input_port_connected(E->get().to_port, false); } } E = N; @@ -400,7 +495,6 @@ bool VisualShader::is_node_connection(Type p_type, int p_from_node, int p_from_p const Graph *g = &graph[p_type]; for (const List<Connection>::Element *E = g->connections.front(); E; E = E->next()) { - if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) { return true; } @@ -415,7 +509,6 @@ bool VisualShader::is_nodes_connected_relatively(const Graph *p_graph, int p_nod const VisualShader::Node &node = p_graph->nodes[p_node]; for (const List<int>::Element *E = node.prev_connected_nodes.front(); E; E = E->next()) { - if (E->get() == p_target) { return true; } @@ -429,24 +522,28 @@ bool VisualShader::is_nodes_connected_relatively(const Graph *p_graph, int p_nod } bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) const { - ERR_FAIL_INDEX_V(p_type, TYPE_MAX, false); const Graph *g = &graph[p_type]; - if (!g->nodes.has(p_from_node)) + if (!g->nodes.has(p_from_node)) { return false; + } - if (p_from_node == p_to_node) + if (p_from_node == p_to_node) { return false; + } - if (p_from_port < 0 || p_from_port >= g->nodes[p_from_node].node->get_output_port_count()) + if (p_from_port < 0 || p_from_port >= g->nodes[p_from_node].node->get_output_port_count()) { return false; + } - if (!g->nodes.has(p_to_node)) + if (!g->nodes.has(p_to_node)) { return false; + } - if (p_to_port < 0 || p_to_port >= g->nodes[p_to_node].node->get_input_port_count()) + if (p_to_port < 0 || p_to_port >= g->nodes[p_to_node].node->get_input_port_count()) { return false; + } VisualShaderNode::PortType from_port_type = g->nodes[p_from_node].node->get_output_port_type(p_from_port); VisualShaderNode::PortType to_port_type = g->nodes[p_to_node].node->get_input_port_type(p_to_port); @@ -456,20 +553,20 @@ bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_po } for (const List<Connection>::Element *E = g->connections.front(); E; E = E->next()) { - if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) { return false; } } - if (is_nodes_connected_relatively(g, p_from_node, p_to_node)) + if (is_nodes_connected_relatively(g, p_from_node, p_to_node)) { return false; + } return true; } bool VisualShader::is_port_types_compatible(int p_a, int p_b) const { - return MAX(0, p_a - 2) == (MAX(0, p_b - 2)); + return MAX(0, p_a - 3) == (MAX(0, p_b - 3)); } void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) { @@ -482,6 +579,8 @@ void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from c.to_port = p_to_port; g->connections.push_back(c); g->nodes[p_to_node].prev_connected_nodes.push_back(p_from_node); + g->nodes[p_from_node].node->set_output_port_connected(p_from_port, true); + g->nodes[p_to_node].node->set_input_port_connected(p_to_port, true); _queue_update(); } @@ -501,7 +600,6 @@ Error VisualShader::connect_nodes(Type p_type, int p_from_node, int p_from_port, ERR_FAIL_COND_V_MSG(!is_port_types_compatible(from_port_type, to_port_type), ERR_INVALID_PARAMETER, "Incompatible port types (scalar/vec/bool) with transform."); for (List<Connection>::Element *E = g->connections.front(); E; E = E->next()) { - if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) { ERR_FAIL_V(ERR_ALREADY_EXISTS); } @@ -514,6 +612,8 @@ Error VisualShader::connect_nodes(Type p_type, int p_from_node, int p_from_port, c.to_port = p_to_port; g->connections.push_back(c); g->nodes[p_to_node].prev_connected_nodes.push_back(p_from_node); + g->nodes[p_from_node].node->set_output_port_connected(p_from_port, true); + g->nodes[p_to_node].node->set_input_port_connected(p_to_port, true); _queue_update(); return OK; @@ -524,10 +624,11 @@ void VisualShader::disconnect_nodes(Type p_type, int p_from_node, int p_from_por Graph *g = &graph[p_type]; for (List<Connection>::Element *E = g->connections.front(); E; E = E->next()) { - if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) { g->connections.erase(E); g->nodes[p_to_node].prev_connected_nodes.erase(p_from_node); + g->nodes[p_from_node].node->set_output_port_connected(p_from_port, false); + g->nodes[p_to_node].node->set_input_port_connected(p_to_port, false); _queue_update(); return; } @@ -570,9 +671,7 @@ void VisualShader::set_mode(Mode p_mode) { flags.clear(); shader_mode = p_mode; for (int i = 0; i < TYPE_MAX; i++) { - for (Map<int, Node>::Element *E = graph[i].nodes.front(); E; E = E->next()) { - Ref<VisualShaderNodeInput> input = E->get().node; if (input.is_valid()) { input->shader_mode = shader_mode; @@ -585,7 +684,6 @@ void VisualShader::set_mode(Mode p_mode) { // clear connections since they are no longer valid for (List<Connection>::Element *E = graph[i].connections.front(); E;) { - bool keep = true; List<Connection>::Element *N = E->next(); @@ -639,7 +737,6 @@ bool VisualShader::is_text_shader() const { } String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port, Vector<DefaultTextureParam> &default_tex_params) const { - Ref<VisualShaderNode> node = get_node(p_type, p_node); ERR_FAIL_COND_V(!node.is_valid(), String()); ERR_FAIL_COND_V(p_port < 0 || p_port >= node->get_output_port_count(), String()); @@ -658,7 +755,6 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port for (Map<int, Node>::Element *E = graph[i].nodes.front(); E; E = E->next()) { Ref<VisualShaderNodeGlobalExpression> global_expression = Object::cast_to<VisualShaderNodeGlobalExpression>(E->get().node.ptr()); if (global_expression.is_valid()) { - String expr = ""; expr += "// " + global_expression->get_caption() + ":" + itos(index++) + "\n"; expr += global_expression->generate_global(get_mode(), Type(i), -1); @@ -697,9 +793,11 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port ERR_FAIL_COND_V(err != OK, String()); if (node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_SCALAR) { - code += "\tCOLOR.rgb = vec3( n_out" + itos(p_node) + "p" + itos(p_port) + " );\n"; + code += "\tCOLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + " );\n"; + } else if (node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_SCALAR_INT) { + code += "\tCOLOR.rgb = vec3(float(n_out" + itos(p_node) + "p" + itos(p_port) + "));\n"; } else if (node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_BOOLEAN) { - code += "\tCOLOR.rgb = vec3( n_out" + itos(p_node) + "p" + itos(p_port) + " ? 1.0 : 0.0 );\n"; + code += "\tCOLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + " ? 1.0 : 0.0);\n"; } else { code += "\tCOLOR.rgb = n_out" + itos(p_node) + "p" + itos(p_port) + ";\n"; } @@ -725,7 +823,6 @@ String VisualShader::validate_port_name(const String &p_name, const List<String> } if (name != String()) { - String valid_name; for (int i = 0; i < name.length(); i++) { @@ -766,13 +863,11 @@ String VisualShader::validate_port_name(const String &p_name, const List<String> } String VisualShader::validate_uniform_name(const String &p_name, const Ref<VisualShaderNodeUniform> &p_uniform) const { - String name = p_name; //validate name first while (name.length() && !IS_INITIAL_CHAR(name[0])) { name = name.substr(1, name.length() - 1); } if (name != String()) { - String valid_name; for (int i = 0; i < name.length(); i++) { @@ -793,7 +888,6 @@ String VisualShader::validate_uniform_name(const String &p_name, const Ref<Visua int attempt = 1; while (true) { - bool exists = false; for (int i = 0; i < TYPE_MAX; i++) { for (const Map<int, Node>::Element *E = graph[i].nodes.front(); E; E = E->next()) { @@ -834,16 +928,19 @@ VisualShader::RenderModeEnums VisualShader::render_mode_enums[] = { { Shader::MODE_SPATIAL, "diffuse" }, { Shader::MODE_SPATIAL, "specular" }, { Shader::MODE_CANVAS_ITEM, "blend" }, - { Shader::MODE_CANVAS_ITEM, NULL } + { Shader::MODE_CANVAS_ITEM, nullptr } }; static const char *type_string[VisualShader::TYPE_MAX] = { "vertex", "fragment", - "light" + "light", + "emit", + "process", + "end" }; -bool VisualShader::_set(const StringName &p_name, const Variant &p_value) { +bool VisualShader::_set(const StringName &p_name, const Variant &p_value) { String name = p_name; if (name == "mode") { set_mode(Shader::Mode(int(p_value))); @@ -880,7 +977,6 @@ bool VisualShader::_set(const StringName &p_name, const Variant &p_value) { String index = name.get_slicec('/', 2); if (index == "connections") { - Vector<int> conns = p_value; if (conns.size() % 4 == 0) { for (int i = 0; i < conns.size(); i += 4) { @@ -917,7 +1013,6 @@ bool VisualShader::_set(const StringName &p_name, const Variant &p_value) { } bool VisualShader::_get(const StringName &p_name, Variant &r_ret) const { - String name = p_name; if (name == "mode") { r_ret = get_mode(); @@ -946,7 +1041,6 @@ bool VisualShader::_get(const StringName &p_name, Variant &r_ret) const { String index = name.get_slicec('/', 2); if (index == "connections") { - Vector<int> conns; for (const List<Connection>::Element *E = graph[type].connections.front(); E; E = E->next()) { conns.push_back(E->get().from_node); @@ -984,18 +1078,17 @@ bool VisualShader::_get(const StringName &p_name, Variant &r_ret) const { } return false; } -void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const { +void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const { //mode - p_list->push_back(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Spatial,CanvasItem,Particles")); + p_list->push_back(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Node3D,CanvasItem,Particles,Sky")); //render modes Map<String, String> blend_mode_enums; Set<String> toggles; - for (int i = 0; i < ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader_mode)).size(); i++) { - - String mode = ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader_mode))[i]; + for (int i = 0; i < ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode)).size(); i++) { + String mode = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode))[i]; int idx = 0; bool in_enum = false; while (render_mode_enums[idx].string) { @@ -1019,7 +1112,6 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const { } for (Map<String, String>::Element *E = blend_mode_enums.front(); E; E = E->next()) { - p_list->push_back(PropertyInfo(Variant::INT, "modes/" + E->key(), PROPERTY_HINT_ENUM, E->get())); } @@ -1029,32 +1121,29 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const { for (int i = 0; i < TYPE_MAX; i++) { for (Map<int, Node>::Element *E = graph[i].nodes.front(); E; E = E->next()) { - String prop_name = "nodes/"; prop_name += type_string[i]; prop_name += "/" + itos(E->key()); if (E->key() != NODE_ID_OUTPUT) { - p_list->push_back(PropertyInfo(Variant::OBJECT, prop_name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "VisualShaderNode", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE)); } p_list->push_back(PropertyInfo(Variant::VECTOR2, prop_name + "/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - if (Object::cast_to<VisualShaderNodeGroupBase>(E->get().node.ptr()) != NULL) { + if (Object::cast_to<VisualShaderNodeGroupBase>(E->get().node.ptr()) != nullptr) { p_list->push_back(PropertyInfo(Variant::VECTOR2, prop_name + "/size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); p_list->push_back(PropertyInfo(Variant::STRING, prop_name + "/input_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); p_list->push_back(PropertyInfo(Variant::STRING, prop_name + "/output_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); } - if (Object::cast_to<VisualShaderNodeExpression>(E->get().node.ptr()) != NULL) { + if (Object::cast_to<VisualShaderNodeExpression>(E->get().node.ptr()) != nullptr) { p_list->push_back(PropertyInfo(Variant::STRING, prop_name + "/expression", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); } } - p_list->push_back(PropertyInfo(Variant::POOL_INT_ARRAY, "nodes/" + String(type_string[i]) + "/connections", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, "nodes/" + String(type_string[i]) + "/connections", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); } } Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBuilder &global_code_per_node, Map<Type, StringBuilder> &global_code_per_func, StringBuilder &code, Vector<VisualShader::DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const { - const Ref<VisualShaderNode> vsnode = graph[type].nodes[node].node; //check inputs recursively first @@ -1071,13 +1160,46 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui } Error err = _write_node(type, global_code, global_code_per_node, global_code_per_func, code, def_tex_params, input_connections, output_connections, from_node, processed, for_preview, r_classes); - if (err) + if (err) { return err; + } } } // then this node + Vector<VisualShader::DefaultTextureParam> params = vsnode->get_default_texture_parameters(type, node); + for (int i = 0; i < params.size(); i++) { + def_tex_params.push_back(params[i]); + } + + Ref<VisualShaderNodeInput> input = vsnode; + bool skip_global = input.is_valid() && for_preview; + + if (!skip_global) { + Ref<VisualShaderNodeUniform> uniform = vsnode; + if (!uniform.is_valid() || !uniform->is_global_code_generated()) { + global_code += vsnode->generate_global(get_mode(), type, node); + } + + String class_name = vsnode->get_class_name(); + if (class_name == "VisualShaderNodeCustom") { + class_name = vsnode->get_script_instance()->get_script()->get_path(); + } + if (!r_classes.has(class_name)) { + global_code_per_node += vsnode->generate_global_per_node(get_mode(), type, node); + for (int i = 0; i < TYPE_MAX; i++) { + global_code_per_func[Type(i)] += vsnode->generate_global_per_func(get_mode(), Type(i), node); + } + r_classes.insert(class_name); + } + } + + if (!vsnode->is_code_generated()) { // just generate globals and ignore locals + processed.insert(node); + return OK; + } + code += "// " + vsnode->get_caption() + ":" + itos(node) + "\n"; Vector<String> input_vars; @@ -1112,24 +1234,43 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui inputs[i] = src_var; } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR && out_type == VisualShaderNode::PORT_TYPE_VECTOR) { inputs[i] = "dot(" + src_var + ", vec3(0.333333, 0.333333, 0.333333))"; + } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR_INT && out_type == VisualShaderNode::PORT_TYPE_VECTOR) { + inputs[i] = "dot(float(" + src_var + "), vec3(0.333333, 0.333333, 0.333333))"; } else if (in_type == VisualShaderNode::PORT_TYPE_VECTOR && out_type == VisualShaderNode::PORT_TYPE_SCALAR) { inputs[i] = "vec3(" + src_var + ")"; + } else if (in_type == VisualShaderNode::PORT_TYPE_VECTOR && out_type == VisualShaderNode::PORT_TYPE_SCALAR_INT) { + inputs[i] = "vec3(float(" + src_var + "))"; } else if (in_type == VisualShaderNode::PORT_TYPE_BOOLEAN && out_type == VisualShaderNode::PORT_TYPE_VECTOR) { inputs[i] = "all(bvec3(" + src_var + "))"; } else if (in_type == VisualShaderNode::PORT_TYPE_BOOLEAN && out_type == VisualShaderNode::PORT_TYPE_SCALAR) { inputs[i] = src_var + " > 0.0 ? true : false"; + } else if (in_type == VisualShaderNode::PORT_TYPE_BOOLEAN && out_type == VisualShaderNode::PORT_TYPE_SCALAR_INT) { + inputs[i] = src_var + " > 0 ? true : false"; } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR && out_type == VisualShaderNode::PORT_TYPE_BOOLEAN) { inputs[i] = src_var + " ? 1.0 : 0.0"; + } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR_INT && out_type == VisualShaderNode::PORT_TYPE_BOOLEAN) { + inputs[i] = src_var + " ? 1 : 0"; } else if (in_type == VisualShaderNode::PORT_TYPE_VECTOR && out_type == VisualShaderNode::PORT_TYPE_BOOLEAN) { inputs[i] = "vec3(" + src_var + " ? 1.0 : 0.0)"; + } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR && out_type == VisualShaderNode::PORT_TYPE_SCALAR_INT) { + inputs[i] = "float(" + src_var + ")"; + } else if (in_type == VisualShaderNode::PORT_TYPE_SCALAR_INT && out_type == VisualShaderNode::PORT_TYPE_SCALAR) { + inputs[i] = "int(" + src_var + ")"; } } else { + if (!vsnode->is_generate_input_var(i)) { + continue; + } Variant defval = vsnode->get_input_port_default_value(i); - if (defval.get_type() == Variant::REAL || defval.get_type() == Variant::INT) { + if (defval.get_type() == Variant::FLOAT) { float val = defval; inputs[i] = "n_in" + itos(node) + "p" + itos(i); code += "\tfloat " + inputs[i] + " = " + vformat("%.5f", val) + ";\n"; + } else if (defval.get_type() == Variant::INT) { + int val = defval; + inputs[i] = "n_in" + itos(node) + "p" + itos(i); + code += "\tint " + inputs[i] + " = " + itos(val) + ";\n"; } else if (defval.get_type() == Variant::BOOL) { bool val = defval; inputs[i] = "n_in" + itos(node) + "p" + itos(i); @@ -1168,10 +1309,21 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui for (int i = 0; i < output_count; i++) { String var_name = "n_out" + itos(node) + "p" + itos(i); switch (vsnode->get_output_port_type(i)) { - case VisualShaderNode::PORT_TYPE_SCALAR: outputs[i] = "float " + var_name; break; - case VisualShaderNode::PORT_TYPE_VECTOR: outputs[i] = "vec3 " + var_name; break; - case VisualShaderNode::PORT_TYPE_BOOLEAN: outputs[i] = "bool " + var_name; break; - case VisualShaderNode::PORT_TYPE_TRANSFORM: outputs[i] = "mat4 " + var_name; break; + case VisualShaderNode::PORT_TYPE_SCALAR: + outputs[i] = "float " + var_name; + break; + case VisualShaderNode::PORT_TYPE_SCALAR_INT: + outputs[i] = "int " + var_name; + break; + case VisualShaderNode::PORT_TYPE_VECTOR: + outputs[i] = "vec3 " + var_name; + break; + case VisualShaderNode::PORT_TYPE_BOOLEAN: + outputs[i] = "bool " + var_name; + break; + case VisualShaderNode::PORT_TYPE_TRANSFORM: + outputs[i] = "mat4 " + var_name; + break; default: { } } @@ -1181,52 +1333,52 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui for (int i = 0; i < output_count; i++) { outputs[i] = "n_out" + itos(node) + "p" + itos(i); switch (vsnode->get_output_port_type(i)) { - case VisualShaderNode::PORT_TYPE_SCALAR: code += String() + "\tfloat " + outputs[i] + ";\n"; break; - case VisualShaderNode::PORT_TYPE_VECTOR: code += String() + "\tvec3 " + outputs[i] + ";\n"; break; - case VisualShaderNode::PORT_TYPE_BOOLEAN: code += String() + "\tbool " + outputs[i] + ";\n"; break; - case VisualShaderNode::PORT_TYPE_TRANSFORM: code += String() + "\tmat4 " + outputs[i] + ";\n"; break; + case VisualShaderNode::PORT_TYPE_SCALAR: + code += String() + "\tfloat " + outputs[i] + ";\n"; + break; + case VisualShaderNode::PORT_TYPE_SCALAR_INT: + code += String() + "\tint " + outputs[i] + ";\n"; + break; + case VisualShaderNode::PORT_TYPE_VECTOR: + code += String() + "\tvec3 " + outputs[i] + ";\n"; + break; + case VisualShaderNode::PORT_TYPE_BOOLEAN: + code += String() + "\tbool " + outputs[i] + ";\n"; + break; + case VisualShaderNode::PORT_TYPE_TRANSFORM: + code += String() + "\tmat4 " + outputs[i] + ";\n"; + break; default: { } } } } - Vector<VisualShader::DefaultTextureParam> params = vsnode->get_default_texture_parameters(type, node); - for (int i = 0; i < params.size(); i++) { - def_tex_params.push_back(params[i]); - } - - Ref<VisualShaderNodeInput> input = vsnode; - bool skip_global = input.is_valid() && for_preview; + code += vsnode->generate_code(get_mode(), type, node, inputs, outputs, for_preview); - if (!skip_global) { + code += "\n"; // + processed.insert(node); - global_code += vsnode->generate_global(get_mode(), type, node); + return OK; +} - String class_name = vsnode->get_class_name(); - if (class_name == "VisualShaderNodeCustom") { - class_name = vsnode->get_script_instance()->get_script()->get_language()->get_global_class_name(vsnode->get_script_instance()->get_script()->get_path()); - } - if (!r_classes.has(class_name)) { - global_code_per_node += vsnode->generate_global_per_node(get_mode(), type, node); - for (int i = 0; i < TYPE_MAX; i++) { - global_code_per_func[Type(i)] += vsnode->generate_global_per_func(get_mode(), Type(i), node); +bool VisualShader::has_func_name(RenderingServer::ShaderMode p_mode, const String &p_func_name) const { + if (!ShaderTypes::get_singleton()->get_functions(p_mode).has(p_func_name)) { + if (p_mode == RenderingServer::ShaderMode::SHADER_PARTICLES) { + if (p_func_name == "emit" || p_func_name == "process" || p_func_name == "end") { + return true; } - r_classes.insert(class_name); } + return false; } - code += vsnode->generate_code(get_mode(), type, node, inputs, outputs, for_preview); - - code += "\n"; // - processed.insert(node); - - return OK; + return true; } void VisualShader::_update_shader() const { - if (!dirty) + if (!dirty) { return; + } dirty = false; @@ -1236,8 +1388,8 @@ void VisualShader::_update_shader() const { StringBuilder code; Vector<VisualShader::DefaultTextureParam> default_tex_params; Set<StringName> classes; - List<int> insertion_pos; - static const char *shader_mode_str[Shader::MODE_MAX] = { "spatial", "canvas_item", "particles" }; + Map<int, int> insertion_pos; + static const char *shader_mode_str[Shader::MODE_MAX] = { "spatial", "canvas_item", "particles", "sky" }; global_code += String() + "shader_type " + shader_mode_str[shader_mode] + ";\n"; @@ -1246,16 +1398,22 @@ void VisualShader::_update_shader() const { { //fill render mode enums int idx = 0; + bool specular = false; while (render_mode_enums[idx].string) { - if (shader_mode == render_mode_enums[idx].mode) { - - if (modes.has(render_mode_enums[idx].string)) { - - int which = modes[render_mode_enums[idx].string]; + if (shader_mode == Shader::MODE_SPATIAL) { + if (String(render_mode_enums[idx].string) == "specular") { + specular = true; + } + } + if (modes.has(render_mode_enums[idx].string) || specular) { + int which = 0; + if (modes.has(render_mode_enums[idx].string)) { + which = modes[render_mode_enums[idx].string]; + } int count = 0; - for (int i = 0; i < ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader_mode)).size(); i++) { - String mode = ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader_mode))[i]; + for (int i = 0; i < ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode)).size(); i++) { + String mode = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode))[i]; if (mode.begins_with(render_mode_enums[idx].string)) { if (count == which) { if (render_mode != String()) { @@ -1273,9 +1431,8 @@ void VisualShader::_update_shader() const { } //fill render mode flags - for (int i = 0; i < ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader_mode)).size(); i++) { - - String mode = ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader_mode))[i]; + for (int i = 0; i < ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode)).size(); i++) { + String mode = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode))[i]; if (flags.has(mode)) { if (render_mode != String()) { render_mode += ", "; @@ -1286,18 +1443,23 @@ void VisualShader::_update_shader() const { } if (render_mode != String()) { - global_code += "render_mode " + render_mode + ";\n\n"; } - static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light" }; + static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light", "emit", "process", "end" }; String global_expressions; + Set<String> used_uniform_names; + List<VisualShaderNodeUniform *> uniforms; + for (int i = 0, index = 0; i < TYPE_MAX; i++) { + if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) { + continue; + } + for (Map<int, Node>::Element *E = graph[i].nodes.front(); E; E = E->next()) { Ref<VisualShaderNodeGlobalExpression> global_expression = Object::cast_to<VisualShaderNodeGlobalExpression>(E->get().node.ptr()); if (global_expression.is_valid()) { - String expr = ""; expr += "// " + global_expression->get_caption() + ":" + itos(index++) + "\n"; expr += global_expression->generate_global(get_mode(), Type(i), -1); @@ -1305,15 +1467,40 @@ void VisualShader::_update_shader() const { expr += "\n"; global_expressions += expr; } + Ref<VisualShaderNodeUniformRef> uniform_ref = Object::cast_to<VisualShaderNodeUniformRef>(E->get().node.ptr()); + if (uniform_ref.is_valid()) { + used_uniform_names.insert(uniform_ref->get_uniform_name()); + } + Ref<VisualShaderNodeUniform> uniform = Object::cast_to<VisualShaderNodeUniform>(E->get().node.ptr()); + if (uniform.is_valid()) { + uniforms.push_back(uniform.ptr()); + } } } + for (int i = 0; i < uniforms.size(); i++) { + VisualShaderNodeUniform *uniform = uniforms[i]; + if (used_uniform_names.has(uniform->get_uniform_name())) { + global_code += uniform->generate_global(get_mode(), Type(i), -1); + const_cast<VisualShaderNodeUniform *>(uniform)->set_global_code_generated(true); + } else { + const_cast<VisualShaderNodeUniform *>(uniform)->set_global_code_generated(false); + } + } + + Map<int, String> code_map; + for (int i = 0; i < TYPE_MAX; i++) { + if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) { + continue; + } //make it faster to go around through shader VMap<ConnectionKey, const List<Connection>::Element *> input_connections; VMap<ConnectionKey, const List<Connection>::Element *> output_connections; + StringBuilder func_code; + for (const List<Connection>::Element *E = graph[i].connections.front(); E; E = E->next()) { ConnectionKey from_key; from_key.node = E->get().from_node; @@ -1327,14 +1514,30 @@ void VisualShader::_update_shader() const { input_connections.insert(to_key, E); } - - code += "\nvoid " + String(func_name[i]) + "() {\n"; + if (shader_mode != Shader::MODE_PARTICLES) { + func_code += "\nvoid " + String(func_name[i]) + "() {\n"; + } + insertion_pos.insert(i, code.get_string_length() + func_code.get_string_length()); Set<int> processed; - Error err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false, classes); + Error err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, func_code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false, classes); ERR_FAIL_COND(err != OK); - insertion_pos.push_back(code.get_string_length()); + if (shader_mode == Shader::MODE_PARTICLES) { + code_map.insert(i, func_code); + } else { + func_code += "}\n"; + code += func_code; + } + } + + if (shader_mode == Shader::MODE_PARTICLES) { + code += "\nvoid compute() {\n"; + code += "\tif (RESTART) {\n"; + code += code_map[TYPE_EMIT]; + code += "\t} else {\n"; + code += code_map[TYPE_PROCESS]; + code += "\t}\n"; code += "}\n"; } @@ -1345,6 +1548,9 @@ void VisualShader::_update_shader() const { final_code += global_expressions; String tcode = code; for (int i = 0; i < TYPE_MAX; i++) { + if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) { + continue; + } tcode = tcode.insert(insertion_pos[i], global_code_per_func[Type(i)]); } final_code += tcode; @@ -1388,7 +1594,6 @@ void VisualShader::rebuild() { } void VisualShader::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_mode", "mode"), &VisualShader::set_mode); ClassDB::bind_method(D_METHOD("add_node", "type", "node", "position", "id"), &VisualShader::add_node); @@ -1403,7 +1608,7 @@ void VisualShader::_bind_methods() { ClassDB::bind_method(D_METHOD("remove_node", "type", "id"), &VisualShader::remove_node); ClassDB::bind_method(D_METHOD("is_node_connection", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::is_node_connection); - ClassDB::bind_method(D_METHOD("can_connect_nodes", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::is_node_connection); + ClassDB::bind_method(D_METHOD("can_connect_nodes", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::can_connect_nodes); ClassDB::bind_method(D_METHOD("connect_nodes", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::connect_nodes); ClassDB::bind_method(D_METHOD("disconnect_nodes", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::disconnect_nodes); @@ -1411,19 +1616,25 @@ void VisualShader::_bind_methods() { ClassDB::bind_method(D_METHOD("get_node_connections", "type"), &VisualShader::_get_node_connections); + ClassDB::bind_method(D_METHOD("set_version", "version"), &VisualShader::set_version); + ClassDB::bind_method(D_METHOD("get_version"), &VisualShader::get_version); + ClassDB::bind_method(D_METHOD("set_graph_offset", "offset"), &VisualShader::set_graph_offset); ClassDB::bind_method(D_METHOD("get_graph_offset"), &VisualShader::get_graph_offset); - ClassDB::bind_method(D_METHOD("_queue_update"), &VisualShader::_queue_update); ClassDB::bind_method(D_METHOD("_update_shader"), &VisualShader::_update_shader); - ClassDB::bind_method(D_METHOD("_input_type_changed"), &VisualShader::_input_type_changed); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_graph_offset", "get_graph_offset"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "version", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_version", "get_version"); + + ADD_PROPERTY_DEFAULT("code", ""); // Inherited from Shader, prevents showing default code as override in docs. BIND_ENUM_CONSTANT(TYPE_VERTEX); BIND_ENUM_CONSTANT(TYPE_FRAGMENT); BIND_ENUM_CONSTANT(TYPE_LIGHT); + BIND_ENUM_CONSTANT(TYPE_EMIT); + BIND_ENUM_CONSTANT(TYPE_PROCESS); + BIND_ENUM_CONSTANT(TYPE_END); BIND_ENUM_CONSTANT(TYPE_MAX); BIND_CONSTANT(NODE_ID_INVALID); @@ -1431,8 +1642,6 @@ void VisualShader::_bind_methods() { } VisualShader::VisualShader() { - shader_mode = Shader::MODE_SPATIAL; - for (int i = 0; i < TYPE_MAX; i++) { Ref<VisualShaderNodeOutput> output; output.instance(); @@ -1441,8 +1650,6 @@ VisualShader::VisualShader() { graph[i].nodes[NODE_ID_OUTPUT].node = output; graph[i].nodes[NODE_ID_OUTPUT].position = Vector2(400, 150); } - - dirty = true; } /////////////////////////////////////////////////////////// @@ -1554,32 +1761,94 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light_vec", "vec3(LIGHT_VEC, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_height", "LIGHT_HEIGHT" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light_color", "LIGHT_COLOR.rgb" }, - { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light_alpha", "LIGHT_COLOR.a" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_alpha", "LIGHT_COLOR.a" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light_uv", "vec3(LIGHT_UV, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "shadow_color", "SHADOW_COLOR.rgb" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "shadow_alpha", "SHADOW_COLOR.a" }, + { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "shadow_vec", "vec3(SHADOW_VEC, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "texture_pixel_size", "vec3(TEXTURE_PIXEL_SIZE, 1.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "point_coord", "vec3(POINT_COORD, 0.0)" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SAMPLER, "texture", "TEXTURE" }, - // Particles, Vertex - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, - - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "index", "float(INDEX)" }, - - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, - { Shader::MODE_MAX, VisualShader::TYPE_MAX, VisualShaderNode::PORT_TYPE_TRANSFORM, NULL, NULL }, + // Particles, Emit + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, + + // Particles, Process + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, + + // Particles, End + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, + + // Sky, Fragment + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_cubemap_pass", "AT_CUBEMAP_PASS" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_half_res_pass", "AT_HALF_RES_PASS" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_quarter_res_pass", "AT_QUARTER_RES_PASS" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "eyedir", "EYEDIR" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "half_res_color", "HALF_RES_COLOR.rgb" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "half_res_alpha", "HALF_RES_COLOR.a" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "light0_color", "LIGHT0_COLOR" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "light0_direction", "LIGHT0_DIRECTION" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "light0_enabled", "LIGHT0_ENABLED" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "light0_energy", "LIGHT0_ENERGY" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "light1_color", "LIGHT1_COLOR" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "light1_direction", "LIGHT1_DIRECTION" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "light1_enabled", "LIGHT1_ENABLED" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "light1_energy", "LIGHT1_ENERGY" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "light2_color", "LIGHT2_COLOR" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "light2_direction", "LIGHT2_DIRECTION" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "light2_enabled", "LIGHT2_ENABLED" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "light2_energy", "LIGHT2_ENERGY" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "light3_color", "LIGHT3_COLOR" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "light3_direction", "LIGHT3_DIRECTION" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "light3_enabled", "LIGHT3_ENABLED" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "light3_energy", "LIGHT3_ENERGY" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "position", "POSITION" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "quarter_res_color", "QUARTER_RES_COLOR.rgb" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "quarter_res_alpha", "QUARTER_RES_COLOR.a" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "radiance", "RADIANCE" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "screen_uv", "vec3(SCREEN_UV, 0.0)" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "sky_coords", "vec3(SKY_COORDS, 0.0)" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, + + { Shader::MODE_MAX, VisualShader::TYPE_MAX, VisualShaderNode::PORT_TYPE_TRANSFORM, nullptr, nullptr }, }; const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = { @@ -1628,30 +1897,29 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = { { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "vec3(0.0, 0.0, 1.0)" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, - { Shader::MODE_MAX, VisualShader::TYPE_MAX, VisualShaderNode::PORT_TYPE_TRANSFORM, NULL, NULL }, + { Shader::MODE_MAX, VisualShader::TYPE_MAX, VisualShaderNode::PORT_TYPE_TRANSFORM, nullptr, nullptr }, }; int VisualShaderNodeInput::get_input_port_count() const { - return 0; } -VisualShaderNodeInput::PortType VisualShaderNodeInput::get_input_port_type(int p_port) const { +VisualShaderNodeInput::PortType VisualShaderNodeInput::get_input_port_type(int p_port) const { return PORT_TYPE_SCALAR; } -String VisualShaderNodeInput::get_input_port_name(int p_port) const { +String VisualShaderNodeInput::get_input_port_name(int p_port) const { return ""; } int VisualShaderNodeInput::get_output_port_count() const { - return 1; } -VisualShaderNodeInput::PortType VisualShaderNodeInput::get_output_port_type(int p_port) const { +VisualShaderNodeInput::PortType VisualShaderNodeInput::get_output_port_type(int p_port) const { return get_input_type_by_name(input_name); } + String VisualShaderNodeInput::get_output_port_name(int p_port) const { return ""; } @@ -1661,7 +1929,6 @@ String VisualShaderNodeInput::get_caption() const { } String VisualShaderNodeInput::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 { - if (get_output_port_type(0) == PORT_TYPE_SAMPLER) { return ""; } @@ -1683,17 +1950,20 @@ String VisualShaderNodeInput::generate_code(Shader::Mode p_mode, VisualShader::T switch (get_output_port_type(0)) { case PORT_TYPE_SCALAR: { code = "\t" + p_output_vars[0] + " = 0.0;\n"; - } break; //default (none found) is scalar + } break; + case PORT_TYPE_SCALAR_INT: { + code = "\t" + p_output_vars[0] + " = 0;\n"; + } break; case PORT_TYPE_VECTOR: { code = "\t" + p_output_vars[0] + " = vec3(0.0);\n"; - } break; //default (none found) is scalar + } break; case PORT_TYPE_TRANSFORM: { code = "\t" + p_output_vars[0] + " = mat4( vec4(1.0,0.0,0.0,0.0), vec4(0.0,1.0,0.0,0.0), vec4(0.0,0.0,1.0,0.0), vec4(0.0,0.0,0.0,1.0) );\n"; - } break; //default (none found) is scalar + } break; case PORT_TYPE_BOOLEAN: { code = "\t" + p_output_vars[0] + " = false;\n"; } break; - default: + default: //default (none found) is scalar break; } } @@ -1735,7 +2005,6 @@ String VisualShaderNodeInput::get_input_name() const { } String VisualShaderNodeInput::get_input_real_name() const { - int idx = 0; while (ports[idx].mode != Shader::MODE_MAX) { @@ -1749,7 +2018,6 @@ String VisualShaderNodeInput::get_input_real_name() const { } VisualShaderNodeInput::PortType VisualShaderNodeInput::get_input_type_by_name(String p_name) const { - int idx = 0; while (ports[idx].mode != Shader::MODE_MAX) { @@ -1811,7 +2079,6 @@ String VisualShaderNodeInput::get_input_index_name(int p_index) const { } void VisualShaderNodeInput::_validate_property(PropertyInfo &property) const { - if (property.name == "input_name") { String port_list; @@ -1841,19 +2108,227 @@ Vector<StringName> VisualShaderNodeInput::get_editable_properties() const { } void VisualShaderNodeInput::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_input_name", "name"), &VisualShaderNodeInput::set_input_name); ClassDB::bind_method(D_METHOD("get_input_name"), &VisualShaderNodeInput::get_input_name); ClassDB::bind_method(D_METHOD("get_input_real_name"), &VisualShaderNodeInput::get_input_real_name); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "input_name", PROPERTY_HINT_ENUM, ""), "set_input_name", "get_input_name"); + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "input_name", PROPERTY_HINT_ENUM, ""), "set_input_name", "get_input_name"); ADD_SIGNAL(MethodInfo("input_type_changed")); } + VisualShaderNodeInput::VisualShaderNodeInput() { - input_name = "[None]"; - // changed when set - shader_type = VisualShader::TYPE_MAX; - shader_mode = Shader::MODE_MAX; +} + +////////////// UniformRef + +List<VisualShaderNodeUniformRef::Uniform> uniforms; + +void VisualShaderNodeUniformRef::add_uniform(const String &p_name, UniformType p_type) { + uniforms.push_back({ p_name, p_type }); +} + +void VisualShaderNodeUniformRef::clear_uniforms() { + uniforms.clear(); +} + +bool VisualShaderNodeUniformRef::has_uniform(const String &p_name) { + for (List<VisualShaderNodeUniformRef::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { + if (E->get().name == p_name) { + return true; + } + } + return false; +} + +String VisualShaderNodeUniformRef::get_caption() const { + return "UniformRef"; +} + +int VisualShaderNodeUniformRef::get_input_port_count() const { + return 0; +} + +VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_input_port_type(int p_port) const { + return PortType::PORT_TYPE_SCALAR; +} + +String VisualShaderNodeUniformRef::get_input_port_name(int p_port) const { + return ""; +} + +int VisualShaderNodeUniformRef::get_output_port_count() const { + switch (uniform_type) { + case UniformType::UNIFORM_TYPE_FLOAT: + return 1; + case UniformType::UNIFORM_TYPE_INT: + return 1; + case UniformType::UNIFORM_TYPE_BOOLEAN: + return 1; + case UniformType::UNIFORM_TYPE_VECTOR: + return 1; + case UniformType::UNIFORM_TYPE_TRANSFORM: + return 1; + case UniformType::UNIFORM_TYPE_COLOR: + return 2; + case UniformType::UNIFORM_TYPE_SAMPLER: + return 1; + default: + break; + } + return 1; +} + +VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_output_port_type(int p_port) const { + switch (uniform_type) { + case UniformType::UNIFORM_TYPE_FLOAT: + return PortType::PORT_TYPE_SCALAR; + case UniformType::UNIFORM_TYPE_INT: + return PortType::PORT_TYPE_SCALAR_INT; + case UniformType::UNIFORM_TYPE_BOOLEAN: + return PortType::PORT_TYPE_BOOLEAN; + case UniformType::UNIFORM_TYPE_VECTOR: + return PortType::PORT_TYPE_VECTOR; + case UniformType::UNIFORM_TYPE_TRANSFORM: + return PortType::PORT_TYPE_TRANSFORM; + case UniformType::UNIFORM_TYPE_COLOR: + if (p_port == 0) { + return PortType::PORT_TYPE_VECTOR; + } else if (p_port == 1) { + return PORT_TYPE_SCALAR; + } + break; + case UniformType::UNIFORM_TYPE_SAMPLER: + return PortType::PORT_TYPE_SAMPLER; + default: + break; + } + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeUniformRef::get_output_port_name(int p_port) const { + switch (uniform_type) { + case UniformType::UNIFORM_TYPE_FLOAT: + return ""; + case UniformType::UNIFORM_TYPE_INT: + return ""; + case UniformType::UNIFORM_TYPE_BOOLEAN: + return ""; + case UniformType::UNIFORM_TYPE_VECTOR: + return ""; + case UniformType::UNIFORM_TYPE_TRANSFORM: + return ""; + case UniformType::UNIFORM_TYPE_COLOR: + if (p_port == 0) { + return "rgb"; + } else if (p_port == 1) { + return "alpha"; + } + break; + case UniformType::UNIFORM_TYPE_SAMPLER: + return ""; + break; + default: + break; + } + return ""; +} + +void VisualShaderNodeUniformRef::set_uniform_name(const String &p_name) { + uniform_name = p_name; + if (uniform_name != "[None]") { + uniform_type = get_uniform_type_by_name(uniform_name); + } else { + uniform_type = UniformType::UNIFORM_TYPE_FLOAT; + } + emit_changed(); +} + +String VisualShaderNodeUniformRef::get_uniform_name() const { + return uniform_name; +} + +int VisualShaderNodeUniformRef::get_uniforms_count() const { + return uniforms.size(); +} + +String VisualShaderNodeUniformRef::get_uniform_name_by_index(int p_idx) const { + if (p_idx >= 0 && p_idx < uniforms.size()) { + return uniforms[p_idx].name; + } + return ""; +} + +VisualShaderNodeUniformRef::UniformType VisualShaderNodeUniformRef::get_uniform_type_by_name(const String &p_name) const { + for (int i = 0; i < uniforms.size(); i++) { + if (uniforms[i].name == p_name) { + return uniforms[i].type; + } + } + return UniformType::UNIFORM_TYPE_FLOAT; +} + +VisualShaderNodeUniformRef::UniformType VisualShaderNodeUniformRef::get_uniform_type_by_index(int p_idx) const { + if (p_idx >= 0 && p_idx < uniforms.size()) { + return uniforms[p_idx].type; + } + return UniformType::UNIFORM_TYPE_FLOAT; +} + +String VisualShaderNodeUniformRef::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 { + switch (uniform_type) { + case UniformType::UNIFORM_TYPE_FLOAT: + if (uniform_name == "[None]") { + return "\t" + p_output_vars[0] + " = 0.0;\n"; + } + return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; + case UniformType::UNIFORM_TYPE_INT: + return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; + case UniformType::UNIFORM_TYPE_BOOLEAN: + return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; + case UniformType::UNIFORM_TYPE_VECTOR: + return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; + case UniformType::UNIFORM_TYPE_TRANSFORM: + return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; + case UniformType::UNIFORM_TYPE_COLOR: { + String code = "\t" + p_output_vars[0] + " = " + get_uniform_name() + ".rgb;\n"; + code += "\t" + p_output_vars[1] + " = " + get_uniform_name() + ".a;\n"; + return code; + } break; + case UniformType::UNIFORM_TYPE_SAMPLER: + break; + default: + break; + } + return ""; +} + +void VisualShaderNodeUniformRef::_set_uniform_type(int p_uniform_type) { + uniform_type = (UniformType)p_uniform_type; +} + +int VisualShaderNodeUniformRef::_get_uniform_type() const { + return (int)uniform_type; +} + +void VisualShaderNodeUniformRef::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_uniform_name", "name"), &VisualShaderNodeUniformRef::set_uniform_name); + ClassDB::bind_method(D_METHOD("get_uniform_name"), &VisualShaderNodeUniformRef::get_uniform_name); + + ClassDB::bind_method(D_METHOD("_set_uniform_type", "type"), &VisualShaderNodeUniformRef::_set_uniform_type); + ClassDB::bind_method(D_METHOD("_get_uniform_type"), &VisualShaderNodeUniformRef::_get_uniform_type); + + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "uniform_name", PROPERTY_HINT_ENUM, ""), "set_uniform_name", "get_uniform_name"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "uniform_type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_uniform_type", "_get_uniform_type"); +} + +Vector<StringName> VisualShaderNodeUniformRef::get_editable_properties() const { + Vector<StringName> props; + props.push_back("uniform_name"); + props.push_back("uniform_type"); + return props; +} + +VisualShaderNodeUniformRef::VisualShaderNodeUniformRef() { } //////////////////////////////////////////// @@ -1912,18 +2387,38 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { // Canvas Item, Light { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light", "LIGHT.rgb" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_alpha", "LIGHT.a" }, - // Particles, Vertex - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, - { Shader::MODE_MAX, VisualShader::TYPE_MAX, VisualShaderNode::PORT_TYPE_TRANSFORM, NULL, NULL }, + // Particles, Emit + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" }, + // Particles, Process + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" }, + // Particles, End + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" }, + // Sky, Fragment + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR" }, + { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "ALPHA" }, + + { Shader::MODE_MAX, VisualShader::TYPE_MAX, VisualShaderNode::PORT_TYPE_TRANSFORM, nullptr, nullptr }, }; int VisualShaderNodeOutput::get_input_port_count() const { - int idx = 0; int count = 0; @@ -1938,7 +2433,6 @@ int VisualShaderNodeOutput::get_input_port_count() const { } VisualShaderNodeOutput::PortType VisualShaderNodeOutput::get_input_port_type(int p_port) const { - int idx = 0; int count = 0; @@ -1956,7 +2450,6 @@ VisualShaderNodeOutput::PortType VisualShaderNodeOutput::get_input_port_type(int } String VisualShaderNodeOutput::get_input_port_name(int p_port) const { - int idx = 0; int count = 0; @@ -1978,18 +2471,18 @@ Variant VisualShaderNodeOutput::get_input_port_default_value(int p_port) const { } int VisualShaderNodeOutput::get_output_port_count() const { - return 0; } + VisualShaderNodeOutput::PortType VisualShaderNodeOutput::get_output_port_type(int p_port) const { return PORT_TYPE_SCALAR; } + String VisualShaderNodeOutput::get_output_port_name(int p_port) const { return String(); } bool VisualShaderNodeOutput::is_port_separator(int p_index) const { - if (shader_mode == Shader::MODE_SPATIAL && shader_type == VisualShader::TYPE_FRAGMENT) { String name = get_input_port_name(p_index); return (name == "Normal" || name == "Rim" || name == "Alpha Scissor"); @@ -2002,14 +2495,12 @@ String VisualShaderNodeOutput::get_caption() const { } String VisualShaderNodeOutput::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 { - int idx = 0; int count = 0; String code; while (ports[idx].mode != Shader::MODE_MAX) { if (ports[idx].mode == shader_mode && ports[idx].shader_type == shader_type) { - if (p_input_vars[count] != String()) { String s = ports[idx].string; if (s.find(":") != -1) { @@ -2041,12 +2532,69 @@ String VisualShaderNodeUniform::get_uniform_name() const { return uniform_name; } -void VisualShaderNodeUniform::_bind_methods() { +void VisualShaderNodeUniform::set_qualifier(VisualShaderNodeUniform::Qualifier p_qual) { + qualifier = p_qual; + emit_changed(); +} +VisualShaderNodeUniform::Qualifier VisualShaderNodeUniform::get_qualifier() const { + return qualifier; +} + +void VisualShaderNodeUniform::set_global_code_generated(bool p_enabled) { + global_code_generated = p_enabled; +} + +bool VisualShaderNodeUniform::is_global_code_generated() const { + return global_code_generated; +} + +void VisualShaderNodeUniform::_bind_methods() { ClassDB::bind_method(D_METHOD("set_uniform_name", "name"), &VisualShaderNodeUniform::set_uniform_name); ClassDB::bind_method(D_METHOD("get_uniform_name"), &VisualShaderNodeUniform::get_uniform_name); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "uniform_name"), "set_uniform_name", "get_uniform_name"); + ClassDB::bind_method(D_METHOD("set_qualifier", "qualifier"), &VisualShaderNodeUniform::set_qualifier); + ClassDB::bind_method(D_METHOD("get_qualifier"), &VisualShaderNodeUniform::get_qualifier); + + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "uniform_name"), "set_uniform_name", "get_uniform_name"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "qualifier", PROPERTY_HINT_ENUM, "None,Global,Instance"), "set_qualifier", "get_qualifier"); + + BIND_ENUM_CONSTANT(QUAL_NONE); + BIND_ENUM_CONSTANT(QUAL_GLOBAL); + BIND_ENUM_CONSTANT(QUAL_INSTANCE); +} + +String VisualShaderNodeUniform::_get_qual_str() const { + if (is_qualifier_supported(qualifier)) { + switch (qualifier) { + case QUAL_NONE: + break; + case QUAL_GLOBAL: + return "global "; + case QUAL_INSTANCE: + return "instance "; + } + } + return String(); +} + +String VisualShaderNodeUniform::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const { + List<String> keyword_list; + ShaderLanguage::get_keyword_list(&keyword_list); + if (keyword_list.find(uniform_name)) { + return TTR("Uniform name cannot be equal to a shader keyword. Choose another name."); + } + if (!is_qualifier_supported(qualifier)) { + return "This uniform type does not support that qualifier."; + } + + return String(); +} + +Vector<StringName> VisualShaderNodeUniform::get_editable_properties() const { + Vector<StringName> props; + props.push_back("qualifier"); + return props; } VisualShaderNodeUniform::VisualShaderNodeUniform() { @@ -2067,9 +2615,9 @@ Vector2 VisualShaderNodeGroupBase::get_size() const { } void VisualShaderNodeGroupBase::set_inputs(const String &p_inputs) { - - if (inputs == p_inputs) + if (inputs == p_inputs) { return; + } clear_input_ports(); @@ -2080,7 +2628,6 @@ void VisualShaderNodeGroupBase::set_inputs(const String &p_inputs) { int input_port_count = input_strings.size(); for (int i = 0; i < input_port_count; i++) { - Vector<String> arr = input_strings[i].split(","); ERR_FAIL_COND(arr.size() != 3); @@ -2100,9 +2647,9 @@ String VisualShaderNodeGroupBase::get_inputs() const { } void VisualShaderNodeGroupBase::set_outputs(const String &p_outputs) { - - if (outputs == p_outputs) + if (outputs == p_outputs) { return; + } clear_output_ports(); @@ -2113,7 +2660,6 @@ void VisualShaderNodeGroupBase::set_outputs(const String &p_outputs) { int output_port_count = output_strings.size(); for (int i = 0; i < output_port_count; i++) { - Vector<String> arr = output_strings[i].split(","); ERR_FAIL_COND(arr.size() != 3); @@ -2150,7 +2696,6 @@ bool VisualShaderNodeGroupBase::is_valid_port_name(const String &p_name) const { } void VisualShaderNodeGroupBase::add_input_port(int p_id, int p_type, const String &p_name) { - String str = itos(p_id) + "," + itos(p_type) + "," + p_name + ";"; Vector<String> inputs_strings = inputs.split(";", false); int index = 0; @@ -2184,10 +2729,10 @@ void VisualShaderNodeGroupBase::add_input_port(int p_id, int p_type, const Strin } _apply_port_changes(); + emit_changed(); } void VisualShaderNodeGroupBase::remove_input_port(int p_id) { - ERR_FAIL_COND(!has_input_port(p_id)); Vector<String> inputs_strings = inputs.split(";", false); @@ -2209,6 +2754,7 @@ void VisualShaderNodeGroupBase::remove_input_port(int p_id) { } _apply_port_changes(); + emit_changed(); } int VisualShaderNodeGroupBase::get_input_port_count() const { @@ -2220,7 +2766,6 @@ bool VisualShaderNodeGroupBase::has_input_port(int p_id) const { } void VisualShaderNodeGroupBase::add_output_port(int p_id, int p_type, const String &p_name) { - String str = itos(p_id) + "," + itos(p_type) + "," + p_name + ";"; Vector<String> outputs_strings = outputs.split(";", false); int index = 0; @@ -2254,10 +2799,10 @@ void VisualShaderNodeGroupBase::add_output_port(int p_id, int p_type, const Stri } _apply_port_changes(); + emit_changed(); } void VisualShaderNodeGroupBase::remove_output_port(int p_id) { - ERR_FAIL_COND(!has_output_port(p_id)); Vector<String> outputs_strings = outputs.split(";", false); @@ -2279,6 +2824,7 @@ void VisualShaderNodeGroupBase::remove_output_port(int p_id) { } _apply_port_changes(); + emit_changed(); } int VisualShaderNodeGroupBase::get_output_port_count() const { @@ -2298,12 +2844,12 @@ void VisualShaderNodeGroupBase::clear_output_ports() { } void VisualShaderNodeGroupBase::set_input_port_type(int p_id, int p_type) { - ERR_FAIL_COND(!has_input_port(p_id)); ERR_FAIL_COND(p_type < 0 || p_type >= PORT_TYPE_MAX); - if (input_ports[p_id].type == p_type) + if (input_ports[p_id].type == p_type) { return; + } Vector<String> inputs_strings = inputs.split(";", false); int count = 0; @@ -2325,6 +2871,7 @@ void VisualShaderNodeGroupBase::set_input_port_type(int p_id, int p_type) { inputs = inputs.insert(index, itos(p_type)); _apply_port_changes(); + emit_changed(); } VisualShaderNodeGroupBase::PortType VisualShaderNodeGroupBase::get_input_port_type(int p_id) const { @@ -2333,12 +2880,12 @@ VisualShaderNodeGroupBase::PortType VisualShaderNodeGroupBase::get_input_port_ty } void VisualShaderNodeGroupBase::set_input_port_name(int p_id, const String &p_name) { - ERR_FAIL_COND(!has_input_port(p_id)); ERR_FAIL_COND(!is_valid_port_name(p_name)); - if (input_ports[p_id].name == p_name) + if (input_ports[p_id].name == p_name) { return; + } Vector<String> inputs_strings = inputs.split(";", false); int count = 0; @@ -2360,6 +2907,7 @@ void VisualShaderNodeGroupBase::set_input_port_name(int p_id, const String &p_na inputs = inputs.insert(index, p_name); _apply_port_changes(); + emit_changed(); } String VisualShaderNodeGroupBase::get_input_port_name(int p_id) const { @@ -2368,12 +2916,12 @@ String VisualShaderNodeGroupBase::get_input_port_name(int p_id) const { } void VisualShaderNodeGroupBase::set_output_port_type(int p_id, int p_type) { - ERR_FAIL_COND(!has_output_port(p_id)); ERR_FAIL_COND(p_type < 0 || p_type >= PORT_TYPE_MAX); - if (output_ports[p_id].type == p_type) + if (output_ports[p_id].type == p_type) { return; + } Vector<String> output_strings = outputs.split(";", false); int count = 0; @@ -2395,6 +2943,7 @@ void VisualShaderNodeGroupBase::set_output_port_type(int p_id, int p_type) { outputs = outputs.insert(index, itos(p_type)); _apply_port_changes(); + emit_changed(); } VisualShaderNodeGroupBase::PortType VisualShaderNodeGroupBase::get_output_port_type(int p_id) const { @@ -2403,12 +2952,12 @@ VisualShaderNodeGroupBase::PortType VisualShaderNodeGroupBase::get_output_port_t } void VisualShaderNodeGroupBase::set_output_port_name(int p_id, const String &p_name) { - ERR_FAIL_COND(!has_output_port(p_id)); ERR_FAIL_COND(!is_valid_port_name(p_name)); - if (output_ports[p_id].name == p_name) + if (output_ports[p_id].name == p_name) { return; + } Vector<String> output_strings = outputs.split(";", false); int count = 0; @@ -2430,6 +2979,7 @@ void VisualShaderNodeGroupBase::set_output_port_name(int p_id, const String &p_n outputs = outputs.insert(index, p_name); _apply_port_changes(); + emit_changed(); } String VisualShaderNodeGroupBase::get_output_port_name(int p_id) const { @@ -2450,12 +3000,11 @@ void VisualShaderNodeGroupBase::set_control(Control *p_control, int p_index) { } Control *VisualShaderNodeGroupBase::get_control(int p_index) { - ERR_FAIL_COND_V(!controls.has(p_index), NULL); + ERR_FAIL_COND_V(!controls.has(p_index), nullptr); return controls[p_index]; } void VisualShaderNodeGroupBase::_apply_port_changes() { - Vector<String> inputs_strings = inputs.split(";", false); Vector<String> outputs_strings = outputs.split(";", false); @@ -2491,7 +3040,6 @@ bool VisualShaderNodeGroupBase::is_editable() const { } void VisualShaderNodeGroupBase::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_size", "size"), &VisualShaderNodeGroupBase::set_size); ClassDB::bind_method(D_METHOD("get_size"), &VisualShaderNodeGroupBase::get_size); @@ -2531,10 +3079,6 @@ String VisualShaderNodeGroupBase::generate_code(Shader::Mode p_mode, VisualShade } VisualShaderNodeGroupBase::VisualShaderNodeGroupBase() { - size = Size2(0, 0); - inputs = ""; - outputs = ""; - editable = false; simple_decl = false; } @@ -2546,6 +3090,7 @@ String VisualShaderNodeExpression::get_caption() const { void VisualShaderNodeExpression::set_expression(const String &p_expression) { expression = p_expression; + emit_changed(); } String VisualShaderNodeExpression::get_expression() const { @@ -2553,7 +3098,6 @@ String VisualShaderNodeExpression::get_expression() const { } String VisualShaderNodeExpression::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 _expression = expression; _expression = _expression.insert(0, "\n"); @@ -2625,6 +3169,9 @@ String VisualShaderNodeExpression::generate_code(Shader::Mode p_mode, VisualShad case PORT_TYPE_SCALAR: tk = "0.0"; break; + case PORT_TYPE_SCALAR_INT: + tk = "0"; + break; case PORT_TYPE_VECTOR: tk = "vec3(0.0, 0.0, 0.0)"; break; @@ -2650,7 +3197,6 @@ String VisualShaderNodeExpression::generate_code(Shader::Mode p_mode, VisualShad } void VisualShaderNodeExpression::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_expression", "expression"), &VisualShaderNodeExpression::set_expression); ClassDB::bind_method(D_METHOD("get_expression"), &VisualShaderNodeExpression::get_expression); @@ -2658,7 +3204,6 @@ void VisualShaderNodeExpression::_bind_methods() { } VisualShaderNodeExpression::VisualShaderNodeExpression() { - expression = ""; set_editable(true); } diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index f35318e090..e7d74b6c17 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -41,11 +41,18 @@ class VisualShaderNode; class VisualShader : public Shader { GDCLASS(VisualShader, Shader); + friend class VisualShaderNodeVersionChecker; + + String version = ""; + public: enum Type { TYPE_VERTEX, TYPE_FRAGMENT, TYPE_LIGHT, + TYPE_EMIT, + TYPE_PROCESS, + TYPE_END, TYPE_MAX }; @@ -58,10 +65,12 @@ public: struct DefaultTextureParam { StringName name; - Ref<Texture> param; + Ref<Texture2D> param; }; private: + Type current_type; + struct Node { Ref<VisualShaderNode> node; Vector2 position; @@ -73,7 +82,7 @@ private: List<Connection> connections; } graph[TYPE_MAX]; - Shader::Mode shader_mode; + Shader::Mode shader_mode = Shader::MODE_SPATIAL; mutable String previous_code; Array _get_node_connections(Type p_type) const; @@ -90,11 +99,10 @@ private: static RenderModeEnums render_mode_enums[]; - volatile mutable bool dirty; + volatile mutable bool dirty = true; void _queue_update(); union ConnectionKey { - struct { uint64_t node : 32; uint64_t port : 32; @@ -108,16 +116,26 @@ private: Error _write_node(Type p_type, StringBuilder &global_code, StringBuilder &global_code_per_node, Map<Type, StringBuilder> &global_code_per_func, StringBuilder &code, Vector<DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const; void _input_type_changed(Type p_type, int p_id); + bool has_func_name(RenderingServer::ShaderMode p_mode, const String &p_func_name) const; protected: - virtual void _update_shader() const; + virtual void _update_shader() const override; static void _bind_methods(); 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; +public: // internal methods + void set_shader_type(Type p_type); + Type get_shader_type() const; + public: + void set_version(const String &p_version); + String get_version() const; + + void update_version(const String &p_new_version); + enum { NODE_ID_INVALID = -1, NODE_ID_OUTPUT = 0, @@ -148,9 +166,9 @@ public: void get_node_connections(Type p_type, List<Connection> *r_connections) const; void set_mode(Mode p_mode); - virtual Mode get_mode() const; + virtual Mode get_mode() const override; - virtual bool is_text_shader() const; + virtual bool is_text_shader() const override; void set_graph_offset(const Vector2 &p_offset); Vector2 get_graph_offset() const; @@ -171,17 +189,21 @@ VARIANT_ENUM_CAST(VisualShader::Type) class VisualShaderNode : public Resource { GDCLASS(VisualShaderNode, Resource); - int port_preview; + int port_preview = -1; Map<int, Variant> default_input_values; + Map<int, bool> connected_input_ports; + Map<int, bool> connected_output_ports; + int connected_output_count = 0; protected: - bool simple_decl; + bool simple_decl = true; static void _bind_methods(); public: enum PortType { PORT_TYPE_SCALAR, + PORT_TYPE_SCALAR_INT, PORT_TYPE_VECTOR, PORT_TYPE_BOOLEAN, PORT_TYPE_TRANSFORM, @@ -213,6 +235,16 @@ public: virtual bool is_port_separator(int p_index) const; + bool is_output_port_connected(int p_port) const; + void set_output_port_connected(int p_port, bool p_connected); + bool is_input_port_connected(int p_port) const; + void set_input_port_connected(int p_port, bool p_connected); + virtual bool is_generate_input_var(int p_port) const; + + virtual bool is_code_generated() const; + virtual bool is_show_prop_names() const; + virtual bool is_use_prop_slots() const; + virtual Vector<StringName> get_editable_properties() const; virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const; @@ -242,19 +274,19 @@ class VisualShaderNodeCustom : public VisualShaderNode { friend class VisualShaderEditor; protected: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; protected: - 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; - virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; + 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; + virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; static void _bind_methods(); @@ -269,8 +301,8 @@ class VisualShaderNodeInput : public VisualShaderNode { GDCLASS(VisualShaderNodeInput, VisualShaderNode); friend class VisualShader; - VisualShader::Type shader_type; - Shader::Mode shader_mode; + VisualShader::Type shader_type = VisualShader::TYPE_MAX; + Shader::Mode shader_mode = Shader::MODE_MAX; struct Port { Shader::Mode mode; @@ -283,24 +315,24 @@ class VisualShaderNodeInput : public VisualShaderNode { static const Port ports[]; static const Port preview_ports[]; - String input_name; + String input_name = "[None]"; protected: static void _bind_methods(); - void _validate_property(PropertyInfo &property) const; + void _validate_property(PropertyInfo &property) const override; public: - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; - virtual String get_caption() const; + virtual String get_caption() 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; + 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; void set_input_name(String p_name); String get_input_name() const; @@ -312,7 +344,7 @@ public: PortType get_input_type_by_name(String p_name) const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeInput(); }; @@ -338,20 +370,20 @@ public: static const Port ports[]; public: - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; Variant get_input_port_default_value(int p_port) const; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; - virtual bool is_port_separator(int p_index) const; + virtual bool is_port_separator(int p_index) const override; - virtual String get_caption() const; + virtual String get_caption() 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; + 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; VisualShaderNodeOutput(); }; @@ -359,19 +391,102 @@ public: class VisualShaderNodeUniform : public VisualShaderNode { GDCLASS(VisualShaderNodeUniform, VisualShaderNode); +public: + enum Qualifier { + QUAL_NONE, + QUAL_GLOBAL, + QUAL_INSTANCE, + }; + private: - String uniform_name; + String uniform_name = ""; + Qualifier qualifier = QUAL_NONE; + bool global_code_generated = false; protected: static void _bind_methods(); + String _get_qual_str() const; public: void set_uniform_name(const String &p_name); String get_uniform_name() const; + void set_qualifier(Qualifier p_qual); + Qualifier get_qualifier() const; + + void set_global_code_generated(bool p_enabled); + bool is_global_code_generated() const; + + virtual bool is_qualifier_supported(Qualifier p_qual) const = 0; + + virtual Vector<StringName> get_editable_properties() const override; + virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override; + VisualShaderNodeUniform(); }; +VARIANT_ENUM_CAST(VisualShaderNodeUniform::Qualifier) + +class VisualShaderNodeUniformRef : public VisualShaderNode { + GDCLASS(VisualShaderNodeUniformRef, VisualShaderNode); + +public: + enum UniformType { + UNIFORM_TYPE_FLOAT, + UNIFORM_TYPE_INT, + UNIFORM_TYPE_BOOLEAN, + UNIFORM_TYPE_VECTOR, + UNIFORM_TYPE_TRANSFORM, + UNIFORM_TYPE_COLOR, + UNIFORM_TYPE_SAMPLER, + }; + + struct Uniform { + String name; + UniformType type; + }; + +private: + String uniform_name = "[None]"; + UniformType uniform_type = UniformType::UNIFORM_TYPE_FLOAT; + +protected: + static void _bind_methods(); + +public: + static void add_uniform(const String &p_name, UniformType p_type); + static void clear_uniforms(); + static bool has_uniform(const String &p_name); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; + + void set_uniform_name(const String &p_name); + String get_uniform_name() const; + + void _set_uniform_type(int p_uniform_type); + int _get_uniform_type() const; + + int get_uniforms_count() const; + String get_uniform_name_by_index(int p_idx) const; + UniformType get_uniform_type_by_name(const String &p_name) const; + UniformType get_uniform_type_by_index(int p_idx) const; + + virtual Vector<StringName> get_editable_properties() 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; + + VisualShaderNodeUniformRef(); +}; + class VisualShaderNodeGroupBase : public VisualShaderNode { GDCLASS(VisualShaderNodeGroupBase, VisualShaderNode); @@ -379,10 +494,10 @@ private: void _apply_port_changes(); protected: - Vector2 size; - String inputs; - String outputs; - bool editable; + Vector2 size = Size2(0, 0); + String inputs = ""; + String outputs = ""; + bool editable = false; struct Port { PortType type; @@ -397,7 +512,7 @@ protected: static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; void set_size(const Vector2 &p_size); Vector2 get_size() const; @@ -412,25 +527,25 @@ public: void add_input_port(int p_id, int p_type, const String &p_name); void remove_input_port(int p_id); - virtual int get_input_port_count() const; + virtual int get_input_port_count() const override; bool has_input_port(int p_id) const; void clear_input_ports(); void add_output_port(int p_id, int p_type, const String &p_name); void remove_output_port(int p_id); - virtual int get_output_port_count() const; + virtual int get_output_port_count() const override; bool has_output_port(int p_id) const; void clear_output_ports(); void set_input_port_type(int p_id, int p_type); - virtual PortType get_input_port_type(int p_id) const; + virtual PortType get_input_port_type(int p_id) const override; void set_input_port_name(int p_id, const String &p_name); - virtual String get_input_port_name(int p_id) const; + virtual String get_input_port_name(int p_id) const override; void set_output_port_type(int p_id, int p_type); - virtual PortType get_output_port_type(int p_id) const; + virtual PortType get_output_port_type(int p_id) const override; void set_output_port_name(int p_id, const String &p_name); - virtual String get_output_port_name(int p_id) const; + virtual String get_output_port_name(int p_id) const override; int get_free_input_port_id() const; int get_free_output_port_id() const; @@ -441,7 +556,7 @@ public: void set_editable(bool p_enabled); bool is_editable() const; - 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; + 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; VisualShaderNodeGroupBase(); }; @@ -450,17 +565,17 @@ class VisualShaderNodeExpression : public VisualShaderNodeGroupBase { GDCLASS(VisualShaderNodeExpression, VisualShaderNodeGroupBase); protected: - String expression; + String expression = ""; static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; void set_expression(const String &p_expression); String get_expression() const; - 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; + 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; VisualShaderNodeExpression(); }; @@ -469,9 +584,9 @@ class VisualShaderNodeGlobalExpression : public VisualShaderNodeExpression { GDCLASS(VisualShaderNodeGlobalExpression, VisualShaderNodeExpression); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; + virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; VisualShaderNodeGlobalExpression(); }; diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index daf770e92a..cffe0bb5cd 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -30,67 +30,122 @@ #include "visual_shader_nodes.h" -////////////// Scalar +////////////// Scalar(Float) -String VisualShaderNodeScalarConstant::get_caption() const { - return "Scalar"; +String VisualShaderNodeFloatConstant::get_caption() const { + return "ScalarFloat"; } -int VisualShaderNodeScalarConstant::get_input_port_count() const { +int VisualShaderNodeFloatConstant::get_input_port_count() const { return 0; } -VisualShaderNodeScalarConstant::PortType VisualShaderNodeScalarConstant::get_input_port_type(int p_port) const { +VisualShaderNodeFloatConstant::PortType VisualShaderNodeFloatConstant::get_input_port_type(int p_port) const { return PORT_TYPE_SCALAR; } -String VisualShaderNodeScalarConstant::get_input_port_name(int p_port) const { +String VisualShaderNodeFloatConstant::get_input_port_name(int p_port) const { return String(); } -int VisualShaderNodeScalarConstant::get_output_port_count() const { +int VisualShaderNodeFloatConstant::get_output_port_count() const { return 1; } -VisualShaderNodeScalarConstant::PortType VisualShaderNodeScalarConstant::get_output_port_type(int p_port) const { +VisualShaderNodeFloatConstant::PortType VisualShaderNodeFloatConstant::get_output_port_type(int p_port) const { return PORT_TYPE_SCALAR; } -String VisualShaderNodeScalarConstant::get_output_port_name(int p_port) const { +String VisualShaderNodeFloatConstant::get_output_port_name(int p_port) const { return ""; //no output port means the editor will be used as port } -String VisualShaderNodeScalarConstant::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 VisualShaderNodeFloatConstant::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 { return "\t" + p_output_vars[0] + " = " + vformat("%.6f", constant) + ";\n"; } -void VisualShaderNodeScalarConstant::set_constant(float p_value) { - +void VisualShaderNodeFloatConstant::set_constant(float p_value) { constant = p_value; emit_changed(); } -float VisualShaderNodeScalarConstant::get_constant() const { - +float VisualShaderNodeFloatConstant::get_constant() const { return constant; } -Vector<StringName> VisualShaderNodeScalarConstant::get_editable_properties() const { +Vector<StringName> VisualShaderNodeFloatConstant::get_editable_properties() const { Vector<StringName> props; props.push_back("constant"); return props; } -void VisualShaderNodeScalarConstant::_bind_methods() { +void VisualShaderNodeFloatConstant::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_constant", "value"), &VisualShaderNodeFloatConstant::set_constant); + ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeFloatConstant::get_constant); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant"), "set_constant", "get_constant"); +} + +VisualShaderNodeFloatConstant::VisualShaderNodeFloatConstant() { +} + +////////////// Scalar(Int) + +String VisualShaderNodeIntConstant::get_caption() const { + return "ScalarInt"; +} + +int VisualShaderNodeIntConstant::get_input_port_count() const { + return 0; +} + +VisualShaderNodeIntConstant::PortType VisualShaderNodeIntConstant::get_input_port_type(int p_port) const { + return PORT_TYPE_SCALAR_INT; +} + +String VisualShaderNodeIntConstant::get_input_port_name(int p_port) const { + return String(); +} + +int VisualShaderNodeIntConstant::get_output_port_count() const { + return 1; +} - ClassDB::bind_method(D_METHOD("set_constant", "value"), &VisualShaderNodeScalarConstant::set_constant); - ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeScalarConstant::get_constant); +VisualShaderNodeIntConstant::PortType VisualShaderNodeIntConstant::get_output_port_type(int p_port) const { + return PORT_TYPE_SCALAR_INT; +} - ADD_PROPERTY(PropertyInfo(Variant::REAL, "constant"), "set_constant", "get_constant"); +String VisualShaderNodeIntConstant::get_output_port_name(int p_port) const { + return ""; //no output port means the editor will be used as port } -VisualShaderNodeScalarConstant::VisualShaderNodeScalarConstant() { - constant = 0; +String VisualShaderNodeIntConstant::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 { + return "\t" + p_output_vars[0] + " = " + itos(constant) + ";\n"; +} + +void VisualShaderNodeIntConstant::set_constant(int p_value) { + constant = p_value; + emit_changed(); +} + +int VisualShaderNodeIntConstant::get_constant() const { + return constant; +} + +Vector<StringName> VisualShaderNodeIntConstant::get_editable_properties() const { + Vector<StringName> props; + props.push_back("constant"); + return props; +} + +void VisualShaderNodeIntConstant::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_constant", "value"), &VisualShaderNodeIntConstant::set_constant); + ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeIntConstant::get_constant); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "constant"), "set_constant", "get_constant"); +} + +VisualShaderNodeIntConstant::VisualShaderNodeIntConstant() { } ////////////// Boolean @@ -143,7 +198,6 @@ Vector<StringName> VisualShaderNodeBooleanConstant::get_editable_properties() co } void VisualShaderNodeBooleanConstant::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_constant", "value"), &VisualShaderNodeBooleanConstant::set_constant); ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeBooleanConstant::get_constant); @@ -151,7 +205,6 @@ void VisualShaderNodeBooleanConstant::_bind_methods() { } VisualShaderNodeBooleanConstant::VisualShaderNodeBooleanConstant() { - constant = false; } ////////////// Color @@ -185,7 +238,6 @@ String VisualShaderNodeColorConstant::get_output_port_name(int p_port) const { } String VisualShaderNodeColorConstant::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; code += "\t" + p_output_vars[0] + " = " + vformat("vec3(%.6f, %.6f, %.6f)", constant.r, constant.g, constant.b) + ";\n"; code += "\t" + p_output_vars[1] + " = " + vformat("%.6f", constant.a) + ";\n"; @@ -194,13 +246,11 @@ String VisualShaderNodeColorConstant::generate_code(Shader::Mode p_mode, VisualS } void VisualShaderNodeColorConstant::set_constant(Color p_value) { - constant = p_value; emit_changed(); } Color VisualShaderNodeColorConstant::get_constant() const { - return constant; } @@ -211,7 +261,6 @@ Vector<StringName> VisualShaderNodeColorConstant::get_editable_properties() cons } void VisualShaderNodeColorConstant::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_constant", "value"), &VisualShaderNodeColorConstant::set_constant); ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeColorConstant::get_constant); @@ -219,7 +268,6 @@ void VisualShaderNodeColorConstant::_bind_methods() { } VisualShaderNodeColorConstant::VisualShaderNodeColorConstant() { - constant = Color(1, 1, 1, 1); } ////////////// Vector @@ -257,13 +305,11 @@ String VisualShaderNodeVec3Constant::generate_code(Shader::Mode p_mode, VisualSh } void VisualShaderNodeVec3Constant::set_constant(Vector3 p_value) { - constant = p_value; emit_changed(); } Vector3 VisualShaderNodeVec3Constant::get_constant() const { - return constant; } @@ -274,7 +320,6 @@ Vector<StringName> VisualShaderNodeVec3Constant::get_editable_properties() const } void VisualShaderNodeVec3Constant::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_constant", "value"), &VisualShaderNodeVec3Constant::set_constant); ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeVec3Constant::get_constant); @@ -327,13 +372,11 @@ String VisualShaderNodeTransformConstant::generate_code(Shader::Mode p_mode, Vis } void VisualShaderNodeTransformConstant::set_constant(Transform p_value) { - constant = p_value; emit_changed(); } Transform VisualShaderNodeTransformConstant::get_constant() const { - return constant; } @@ -344,7 +387,6 @@ Vector<StringName> VisualShaderNodeTransformConstant::get_editable_properties() } void VisualShaderNodeTransformConstant::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_constant", "value"), &VisualShaderNodeTransformConstant::set_constant); ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeTransformConstant::get_constant); @@ -357,7 +399,7 @@ VisualShaderNodeTransformConstant::VisualShaderNodeTransformConstant() { ////////////// Texture String VisualShaderNodeTexture::get_caption() const { - return "Texture"; + return "Texture2D"; } int VisualShaderNodeTexture::get_input_port_count() const { @@ -365,7 +407,6 @@ int VisualShaderNodeTexture::get_input_port_count() const { } VisualShaderNodeTexture::PortType VisualShaderNodeTexture::get_input_port_type(int p_port) const { - switch (p_port) { case 0: return PORT_TYPE_VECTOR; @@ -379,7 +420,6 @@ VisualShaderNodeTexture::PortType VisualShaderNodeTexture::get_input_port_type(i } String VisualShaderNodeTexture::get_input_port_name(int p_port) const { - switch (p_port) { case 0: return "uv"; @@ -397,14 +437,16 @@ int VisualShaderNodeTexture::get_output_port_count() const { } VisualShaderNodeTexture::PortType VisualShaderNodeTexture::get_output_port_type(int p_port) const { - if (p_port == 0 && source == SOURCE_DEPTH) + if (p_port == 0 && source == SOURCE_DEPTH) { return PORT_TYPE_SCALAR; + } return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR; } String VisualShaderNodeTexture::get_output_port_name(int p_port) const { - if (p_port == 0 && source == SOURCE_DEPTH) + if (p_port == 0 && source == SOURCE_DEPTH) { return "depth"; + } return p_port == 0 ? "rgb" : "alpha"; } @@ -416,7 +458,6 @@ String VisualShaderNodeTexture::get_input_port_default_hint(int p_port) const { } static String make_unique_id(VisualShader::Type p_type, int p_id, const String &p_name) { - static const char *typepf[VisualShader::TYPE_MAX] = { "vtx", "frg", "lgt" }; return p_name + "_" + String(typepf[p_type]) + "_" + itos(p_id); } @@ -431,14 +472,17 @@ Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture::get_default_t } String VisualShaderNodeTexture::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - if (source == SOURCE_TEXTURE) { - String u = "uniform sampler2D " + make_unique_id(p_type, p_id, "tex"); switch (texture_type) { - case TYPE_DATA: break; - case TYPE_COLOR: u += " : hint_albedo"; break; - case TYPE_NORMALMAP: u += " : hint_normal"; break; + case TYPE_DATA: + break; + case TYPE_COLOR: + u += " : hint_albedo"; + break; + case TYPE_NORMALMAP: + u += " : hint_normal"; + break; } return u + ";\n"; } @@ -447,7 +491,6 @@ String VisualShaderNodeTexture::generate_global(Shader::Mode p_mode, VisualShade } String VisualShaderNodeTexture::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 { - if (source == SOURCE_TEXTURE) { String id = make_unique_id(p_type, p_id, "tex"); String code; @@ -502,7 +545,6 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: } if (source == SOURCE_SCREEN && (p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) { - String code = "\t{\n"; if (p_input_vars[0] == String() || p_for_preview) { // Use UV by default. @@ -526,7 +568,6 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: } if (source == SOURCE_2D_TEXTURE && p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) { - String code = "\t{\n"; if (p_input_vars[0] == String()) { // Use UV by default. @@ -550,7 +591,6 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: } if (source == SOURCE_2D_NORMAL && p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) { - String code = "\t{\n"; if (p_input_vars[0] == String()) { // Use UV by default. @@ -584,7 +624,6 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader: } if (source == SOURCE_DEPTH && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) { - String code = "\t{\n"; if (p_input_vars[0] == String()) { // Use UV by default. @@ -649,14 +688,12 @@ VisualShaderNodeTexture::Source VisualShaderNodeTexture::get_source() const { return source; } -void VisualShaderNodeTexture::set_texture(Ref<Texture> p_value) { - +void VisualShaderNodeTexture::set_texture(Ref<Texture2D> p_value) { texture = p_value; emit_changed(); } -Ref<Texture> VisualShaderNodeTexture::get_texture() const { - +Ref<Texture2D> VisualShaderNodeTexture::get_texture() const { return texture; } @@ -680,7 +717,6 @@ Vector<StringName> VisualShaderNodeTexture::get_editable_properties() const { } String VisualShaderNodeTexture::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const { - if (source == SOURCE_TEXTURE) { return String(); // all good } @@ -690,22 +726,18 @@ String VisualShaderNodeTexture::get_warning(Shader::Mode p_mode, VisualShader::T } if (source == SOURCE_SCREEN && (p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) { - return String(); // all good } if (source == SOURCE_2D_TEXTURE && p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) { - return String(); // all good } if (source == SOURCE_2D_NORMAL && p_mode == Shader::MODE_CANVAS_ITEM) { - return String(); // all good } if (source == SOURCE_DEPTH && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) { - if (get_output_port_for_preview() == 0) { // DEPTH_TEXTURE is not supported in preview(canvas_item) shader return TTR("Invalid source for preview."); } @@ -716,7 +748,6 @@ String VisualShaderNodeTexture::get_warning(Shader::Mode p_mode, VisualShader::T } void VisualShaderNodeTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_source", "value"), &VisualShaderNodeTexture::set_source); ClassDB::bind_method(D_METHOD("get_source"), &VisualShaderNodeTexture::get_source); @@ -727,7 +758,7 @@ void VisualShaderNodeTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("get_texture_type"), &VisualShaderNodeTexture::get_texture_type); ADD_PROPERTY(PropertyInfo(Variant::INT, "source", PROPERTY_HINT_ENUM, "Texture,Screen,Texture2D,NormalMap2D,Depth,SamplerPort"), "set_source", "get_source"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture"); ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normalmap"), "set_texture_type", "get_texture_type"); BIND_ENUM_CONSTANT(SOURCE_TEXTURE); @@ -742,21 +773,253 @@ void VisualShaderNodeTexture::_bind_methods() { } VisualShaderNodeTexture::VisualShaderNodeTexture() { - texture_type = TYPE_DATA; - source = SOURCE_TEXTURE; } -////////////// CubeMap +////////////// Sample3D + +int VisualShaderNodeSample3D::get_input_port_count() const { + return 3; +} + +VisualShaderNodeSample3D::PortType VisualShaderNodeSample3D::get_input_port_type(int p_port) const { + switch (p_port) { + case 0: + return PORT_TYPE_VECTOR; + case 1: + return PORT_TYPE_SCALAR; + case 2: + return PORT_TYPE_SAMPLER; + default: + return PORT_TYPE_SCALAR; + } +} + +String VisualShaderNodeSample3D::get_input_port_name(int p_port) const { + switch (p_port) { + case 0: + return "uvw"; + case 1: + return "lod"; + default: + return ""; + } +} + +int VisualShaderNodeSample3D::get_output_port_count() const { + return 2; +} + +VisualShaderNodeSample3D::PortType VisualShaderNodeSample3D::get_output_port_type(int p_port) const { + return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR; +} + +String VisualShaderNodeSample3D::get_output_port_name(int p_port) const { + return p_port == 0 ? "rgb" : "alpha"; +} + +String VisualShaderNodeSample3D::get_input_port_default_hint(int p_port) const { + if (p_port == 0) { + return "vec3(UV.xy, 0.0)"; + } + return ""; +} + +String VisualShaderNodeSample3D::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 (source == SOURCE_TEXTURE || source == SOURCE_PORT) { + String id; + code += "\t{\n"; + if (source == SOURCE_TEXTURE) { + id = make_unique_id(p_type, p_id, "tex3d"); + } else { + id = p_input_vars[2]; + } + if (id != String()) { + if (p_input_vars[0] == String()) { // Use UV by default. + if (p_input_vars[1] == String()) { + code += "\t\tvec4 " + id + "_tex_read = texture(" + id + ", vec3(UV.xy, 0.0));\n"; + } else { + code += "\t\tvec4 " + id + "_tex_read = textureLod(" + id + ", vec3(UV.xy, 0.0), " + p_input_vars[1] + ");\n"; + } + } else if (p_input_vars[1] == String()) { + //no lod + code += "\t\tvec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ");\n"; + } else { + code += "\t\tvec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + } + } else { + code += "\t\tvec4 " + id + "_tex_read = vec4(0.0);\n"; + } + + code += "\t\t" + p_output_vars[0] + " = " + id + "_tex_read.rgb;\n"; + code += "\t\t" + p_output_vars[1] + " = " + id + "_tex_read.a;\n"; + code += "\t}\n"; + return code; + } + code += "\t" + p_output_vars[0] + " = vec3(0.0);\n"; + code += "\t" + p_output_vars[1] + " = 1.0;\n"; + return code; +} + +void VisualShaderNodeSample3D::set_source(Source p_source) { + source = p_source; + emit_changed(); + emit_signal("editor_refresh_request"); +} + +VisualShaderNodeSample3D::Source VisualShaderNodeSample3D::get_source() const { + return source; +} + +void VisualShaderNodeSample3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_source", "value"), &VisualShaderNodeSample3D::set_source); + ClassDB::bind_method(D_METHOD("get_source"), &VisualShaderNodeSample3D::get_source); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "source", PROPERTY_HINT_ENUM, "Texture,SamplerPort"), "set_source", "get_source"); + + BIND_ENUM_CONSTANT(SOURCE_TEXTURE); + BIND_ENUM_CONSTANT(SOURCE_PORT); +} + +String VisualShaderNodeSample3D::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const { + if (source == SOURCE_TEXTURE) { + return String(); // all good + } + if (source == SOURCE_PORT) { + return String(); // all good + } + return TTR("Invalid source for shader."); +} + +VisualShaderNodeSample3D::VisualShaderNodeSample3D() { + simple_decl = false; +} + +////////////// Texture2DArray + +String VisualShaderNodeTexture2DArray::get_caption() const { + return "Texture2DArray"; +} + +String VisualShaderNodeTexture2DArray::get_input_port_name(int p_port) const { + if (p_port == 2) { + return "sampler2DArray"; + } + return VisualShaderNodeSample3D::get_input_port_name(p_port); +} + +Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture2DArray::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "tex3d"); + dtp.param = texture; + Vector<VisualShader::DefaultTextureParam> ret; + ret.push_back(dtp); + return ret; +} + +String VisualShaderNodeTexture2DArray::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + if (source == SOURCE_TEXTURE) { + return "uniform sampler2DArray " + make_unique_id(p_type, p_id, "tex3d") + ";\n"; + } + return String(); +} + +void VisualShaderNodeTexture2DArray::set_texture_array(Ref<Texture2DArray> p_value) { + texture = p_value; + emit_changed(); +} + +Ref<Texture2DArray> VisualShaderNodeTexture2DArray::get_texture_array() const { + return texture; +} + +Vector<StringName> VisualShaderNodeTexture2DArray::get_editable_properties() const { + Vector<StringName> props; + props.push_back("source"); + if (source == SOURCE_TEXTURE) { + props.push_back("texture_array"); + } + return props; +} + +void VisualShaderNodeTexture2DArray::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_texture_array", "value"), &VisualShaderNodeTexture2DArray::set_texture_array); + ClassDB::bind_method(D_METHOD("get_texture_array"), &VisualShaderNodeTexture2DArray::get_texture_array); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_array", PROPERTY_HINT_RESOURCE_TYPE, "Texture2DArray"), "set_texture_array", "get_texture_array"); +} + +VisualShaderNodeTexture2DArray::VisualShaderNodeTexture2DArray() { +} + +////////////// Texture3D + +String VisualShaderNodeTexture3D::get_caption() const { + return "Texture3D"; +} + +String VisualShaderNodeTexture3D::get_input_port_name(int p_port) const { + if (p_port == 2) { + return "sampler3D"; + } + return VisualShaderNodeSample3D::get_input_port_name(p_port); +} + +Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture3D::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "tex3d"); + dtp.param = texture; + Vector<VisualShader::DefaultTextureParam> ret; + ret.push_back(dtp); + return ret; +} + +String VisualShaderNodeTexture3D::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + if (source == SOURCE_TEXTURE) { + return "uniform sampler3D " + make_unique_id(p_type, p_id, "tex3d") + ";\n"; + } + return String(); +} + +void VisualShaderNodeTexture3D::set_texture(Ref<Texture3D> p_value) { + texture = p_value; + emit_changed(); +} + +Ref<Texture3D> VisualShaderNodeTexture3D::get_texture() const { + return texture; +} + +Vector<StringName> VisualShaderNodeTexture3D::get_editable_properties() const { + Vector<StringName> props; + props.push_back("source"); + if (source == SOURCE_TEXTURE) { + props.push_back("texture"); + } + return props; +} + +void VisualShaderNodeTexture3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_texture", "value"), &VisualShaderNodeTexture3D::set_texture); + ClassDB::bind_method(D_METHOD("get_texture"), &VisualShaderNodeTexture3D::get_texture); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_texture", "get_texture"); +} + +VisualShaderNodeTexture3D::VisualShaderNodeTexture3D() { +} + +////////////// Cubemap -String VisualShaderNodeCubeMap::get_caption() const { - return "CubeMap"; +String VisualShaderNodeCubemap::get_caption() const { + return "Cubemap"; } -int VisualShaderNodeCubeMap::get_input_port_count() const { +int VisualShaderNodeCubemap::get_input_port_count() const { return 3; } -VisualShaderNodeCubeMap::PortType VisualShaderNodeCubeMap::get_input_port_type(int p_port) const { +VisualShaderNodeCubemap::PortType VisualShaderNodeCubemap::get_input_port_type(int p_port) const { switch (p_port) { case 0: return PORT_TYPE_VECTOR; @@ -769,7 +1032,7 @@ VisualShaderNodeCubeMap::PortType VisualShaderNodeCubeMap::get_input_port_type(i } } -String VisualShaderNodeCubeMap::get_input_port_name(int p_port) const { +String VisualShaderNodeCubemap::get_input_port_name(int p_port) const { switch (p_port) { case 0: return "uv"; @@ -782,19 +1045,19 @@ String VisualShaderNodeCubeMap::get_input_port_name(int p_port) const { } } -int VisualShaderNodeCubeMap::get_output_port_count() const { +int VisualShaderNodeCubemap::get_output_port_count() const { return 2; } -VisualShaderNodeCubeMap::PortType VisualShaderNodeCubeMap::get_output_port_type(int p_port) const { +VisualShaderNodeCubemap::PortType VisualShaderNodeCubemap::get_output_port_type(int p_port) const { return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR; } -String VisualShaderNodeCubeMap::get_output_port_name(int p_port) const { +String VisualShaderNodeCubemap::get_output_port_name(int p_port) const { return p_port == 0 ? "rgb" : "alpha"; } -Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCubeMap::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { +Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCubemap::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { VisualShader::DefaultTextureParam dtp; dtp.name = make_unique_id(p_type, p_id, "cube"); dtp.param = cube_map; @@ -803,22 +1066,25 @@ Vector<VisualShader::DefaultTextureParam> VisualShaderNodeCubeMap::get_default_t return ret; } -String VisualShaderNodeCubeMap::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - +String VisualShaderNodeCubemap::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { if (source == SOURCE_TEXTURE) { String u = "uniform samplerCube " + make_unique_id(p_type, p_id, "cube"); switch (texture_type) { - case TYPE_DATA: break; - case TYPE_COLOR: u += " : hint_albedo"; break; - case TYPE_NORMALMAP: u += " : hint_normal"; break; + case TYPE_DATA: + break; + case TYPE_COLOR: + u += " : hint_albedo"; + break; + case TYPE_NORMALMAP: + u += " : hint_normal"; + break; } return u + ";\n"; } return String(); } -String VisualShaderNodeCubeMap::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 VisualShaderNodeCubemap::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; String id; if (source == SOURCE_TEXTURE) { @@ -860,44 +1126,42 @@ String VisualShaderNodeCubeMap::generate_code(Shader::Mode p_mode, VisualShader: return code; } -String VisualShaderNodeCubeMap::get_input_port_default_hint(int p_port) const { +String VisualShaderNodeCubemap::get_input_port_default_hint(int p_port) const { if (p_port == 0) { return "vec3(UV, 0.0)"; } return ""; } -void VisualShaderNodeCubeMap::set_source(Source p_source) { +void VisualShaderNodeCubemap::set_source(Source p_source) { source = p_source; emit_changed(); emit_signal("editor_refresh_request"); } -VisualShaderNodeCubeMap::Source VisualShaderNodeCubeMap::get_source() const { +VisualShaderNodeCubemap::Source VisualShaderNodeCubemap::get_source() const { return source; } -void VisualShaderNodeCubeMap::set_cube_map(Ref<CubeMap> p_value) { - +void VisualShaderNodeCubemap::set_cube_map(Ref<Cubemap> p_value) { cube_map = p_value; emit_changed(); } -Ref<CubeMap> VisualShaderNodeCubeMap::get_cube_map() const { - +Ref<Cubemap> VisualShaderNodeCubemap::get_cube_map() const { return cube_map; } -void VisualShaderNodeCubeMap::set_texture_type(TextureType p_type) { +void VisualShaderNodeCubemap::set_texture_type(TextureType p_type) { texture_type = p_type; emit_changed(); } -VisualShaderNodeCubeMap::TextureType VisualShaderNodeCubeMap::get_texture_type() const { +VisualShaderNodeCubemap::TextureType VisualShaderNodeCubemap::get_texture_type() const { return texture_type; } -Vector<StringName> VisualShaderNodeCubeMap::get_editable_properties() const { +Vector<StringName> VisualShaderNodeCubemap::get_editable_properties() const { Vector<StringName> props; props.push_back("source"); if (source == SOURCE_TEXTURE) { @@ -907,19 +1171,18 @@ Vector<StringName> VisualShaderNodeCubeMap::get_editable_properties() const { return props; } -void VisualShaderNodeCubeMap::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_source", "value"), &VisualShaderNodeCubeMap::set_source); - ClassDB::bind_method(D_METHOD("get_source"), &VisualShaderNodeCubeMap::get_source); +void VisualShaderNodeCubemap::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_source", "value"), &VisualShaderNodeCubemap::set_source); + ClassDB::bind_method(D_METHOD("get_source"), &VisualShaderNodeCubemap::get_source); - ClassDB::bind_method(D_METHOD("set_cube_map", "value"), &VisualShaderNodeCubeMap::set_cube_map); - ClassDB::bind_method(D_METHOD("get_cube_map"), &VisualShaderNodeCubeMap::get_cube_map); + ClassDB::bind_method(D_METHOD("set_cube_map", "value"), &VisualShaderNodeCubemap::set_cube_map); + ClassDB::bind_method(D_METHOD("get_cube_map"), &VisualShaderNodeCubemap::get_cube_map); - ClassDB::bind_method(D_METHOD("set_texture_type", "value"), &VisualShaderNodeCubeMap::set_texture_type); - ClassDB::bind_method(D_METHOD("get_texture_type"), &VisualShaderNodeCubeMap::get_texture_type); + ClassDB::bind_method(D_METHOD("set_texture_type", "value"), &VisualShaderNodeCubemap::set_texture_type); + ClassDB::bind_method(D_METHOD("get_texture_type"), &VisualShaderNodeCubemap::get_texture_type); ADD_PROPERTY(PropertyInfo(Variant::INT, "source", PROPERTY_HINT_ENUM, "Texture,SamplerPort"), "set_source", "get_source"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "cube_map", PROPERTY_HINT_RESOURCE_TYPE, "CubeMap"), "set_cube_map", "get_cube_map"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "cube_map", PROPERTY_HINT_RESOURCE_TYPE, "Cubemap"), "set_cube_map", "get_cube_map"); ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normalmap"), "set_texture_type", "get_texture_type"); BIND_ENUM_CONSTANT(SOURCE_TEXTURE); @@ -930,83 +1193,96 @@ void VisualShaderNodeCubeMap::_bind_methods() { BIND_ENUM_CONSTANT(TYPE_NORMALMAP); } -VisualShaderNodeCubeMap::VisualShaderNodeCubeMap() { - texture_type = TYPE_DATA; - source = SOURCE_TEXTURE; +VisualShaderNodeCubemap::VisualShaderNodeCubemap() { simple_decl = false; } -////////////// Scalar Op +////////////// Float Op -String VisualShaderNodeScalarOp::get_caption() const { - return "ScalarOp"; +String VisualShaderNodeFloatOp::get_caption() const { + return "FloatOp"; } -int VisualShaderNodeScalarOp::get_input_port_count() const { +int VisualShaderNodeFloatOp::get_input_port_count() const { return 2; } -VisualShaderNodeScalarOp::PortType VisualShaderNodeScalarOp::get_input_port_type(int p_port) const { +VisualShaderNodeFloatOp::PortType VisualShaderNodeFloatOp::get_input_port_type(int p_port) const { return PORT_TYPE_SCALAR; } -String VisualShaderNodeScalarOp::get_input_port_name(int p_port) const { +String VisualShaderNodeFloatOp::get_input_port_name(int p_port) const { return p_port == 0 ? "a" : "b"; } -int VisualShaderNodeScalarOp::get_output_port_count() const { +int VisualShaderNodeFloatOp::get_output_port_count() const { return 1; } -VisualShaderNodeScalarOp::PortType VisualShaderNodeScalarOp::get_output_port_type(int p_port) const { +VisualShaderNodeFloatOp::PortType VisualShaderNodeFloatOp::get_output_port_type(int p_port) const { return PORT_TYPE_SCALAR; } -String VisualShaderNodeScalarOp::get_output_port_name(int p_port) const { +String VisualShaderNodeFloatOp::get_output_port_name(int p_port) const { return "op"; //no output port means the editor will be used as port } -String VisualShaderNodeScalarOp::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 VisualShaderNodeFloatOp::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 = "\t" + p_output_vars[0] + " = "; switch (op) { - - case OP_ADD: code += p_input_vars[0] + " + " + p_input_vars[1] + ";\n"; break; - case OP_SUB: code += p_input_vars[0] + " - " + p_input_vars[1] + ";\n"; break; - case OP_MUL: code += p_input_vars[0] + " * " + p_input_vars[1] + ";\n"; break; - case OP_DIV: code += p_input_vars[0] + " / " + p_input_vars[1] + ";\n"; break; - case OP_MOD: code += "mod(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_POW: code += "pow(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_MAX: code += "max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_MIN: code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_ATAN2: code += "atan(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_STEP: code += "step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_ADD: + code += p_input_vars[0] + " + " + p_input_vars[1] + ";\n"; + break; + case OP_SUB: + code += p_input_vars[0] + " - " + p_input_vars[1] + ";\n"; + break; + case OP_MUL: + code += p_input_vars[0] + " * " + p_input_vars[1] + ";\n"; + break; + case OP_DIV: + code += p_input_vars[0] + " / " + p_input_vars[1] + ";\n"; + break; + case OP_MOD: + code += "mod(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_POW: + code += "pow(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_MAX: + code += "max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_MIN: + code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_ATAN2: + code += "atan(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_STEP: + code += "step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; } return code; } -void VisualShaderNodeScalarOp::set_operator(Operator p_op) { - +void VisualShaderNodeFloatOp::set_operator(Operator p_op) { op = p_op; emit_changed(); } -VisualShaderNodeScalarOp::Operator VisualShaderNodeScalarOp::get_operator() const { - +VisualShaderNodeFloatOp::Operator VisualShaderNodeFloatOp::get_operator() const { return op; } -Vector<StringName> VisualShaderNodeScalarOp::get_editable_properties() const { +Vector<StringName> VisualShaderNodeFloatOp::get_editable_properties() const { Vector<StringName> props; props.push_back("operator"); return props; } -void VisualShaderNodeScalarOp::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeScalarOp::set_operator); - ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeScalarOp::get_operator); +void VisualShaderNodeFloatOp::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeFloatOp::set_operator); + ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeFloatOp::get_operator); ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Sub,Multiply,Divide,Remainder,Power,Max,Min,Atan2,Step"), "set_operator", "get_operator"); @@ -1022,12 +1298,105 @@ void VisualShaderNodeScalarOp::_bind_methods() { BIND_ENUM_CONSTANT(OP_STEP); } -VisualShaderNodeScalarOp::VisualShaderNodeScalarOp() { - op = OP_ADD; +VisualShaderNodeFloatOp::VisualShaderNodeFloatOp() { set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); } +////////////// Integer Op + +String VisualShaderNodeIntOp::get_caption() const { + return "IntOp"; +} + +int VisualShaderNodeIntOp::get_input_port_count() const { + return 2; +} + +VisualShaderNodeIntOp::PortType VisualShaderNodeIntOp::get_input_port_type(int p_port) const { + return PORT_TYPE_SCALAR_INT; +} + +String VisualShaderNodeIntOp::get_input_port_name(int p_port) const { + return p_port == 0 ? "a" : "b"; +} + +int VisualShaderNodeIntOp::get_output_port_count() const { + return 1; +} + +VisualShaderNodeIntOp::PortType VisualShaderNodeIntOp::get_output_port_type(int p_port) const { + return PORT_TYPE_SCALAR_INT; +} + +String VisualShaderNodeIntOp::get_output_port_name(int p_port) const { + return "op"; //no output port means the editor will be used as port +} + +String VisualShaderNodeIntOp::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 = "\t" + p_output_vars[0] + " = "; + switch (op) { + case OP_ADD: + code += p_input_vars[0] + " + " + p_input_vars[1] + ";\n"; + break; + case OP_SUB: + code += p_input_vars[0] + " - " + p_input_vars[1] + ";\n"; + break; + case OP_MUL: + code += p_input_vars[0] + " * " + p_input_vars[1] + ";\n"; + break; + case OP_DIV: + code += p_input_vars[0] + " / " + p_input_vars[1] + ";\n"; + break; + case OP_MOD: + code += p_input_vars[0] + " % " + p_input_vars[1] + ";\n"; + break; + case OP_MAX: + code += "max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_MIN: + code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + } + + return code; +} + +void VisualShaderNodeIntOp::set_operator(Operator p_op) { + op = p_op; + emit_changed(); +} + +VisualShaderNodeIntOp::Operator VisualShaderNodeIntOp::get_operator() const { + return op; +} + +Vector<StringName> VisualShaderNodeIntOp::get_editable_properties() const { + Vector<StringName> props; + props.push_back("operator"); + return props; +} + +void VisualShaderNodeIntOp::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeIntOp::set_operator); + ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeIntOp::get_operator); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Sub,Multiply,Divide,Remainder,Max,Min"), "set_operator", "get_operator"); + + BIND_ENUM_CONSTANT(OP_ADD); + BIND_ENUM_CONSTANT(OP_SUB); + BIND_ENUM_CONSTANT(OP_MUL); + BIND_ENUM_CONSTANT(OP_DIV); + BIND_ENUM_CONSTANT(OP_MOD); + BIND_ENUM_CONSTANT(OP_MAX); + BIND_ENUM_CONSTANT(OP_MIN); +} + +VisualShaderNodeIntOp::VisualShaderNodeIntOp() { + set_input_port_default_value(0, 0); + set_input_port_default_value(1, 0); +} + ////////////// Vector Op String VisualShaderNodeVectorOp::get_caption() const { @@ -1059,35 +1428,55 @@ String VisualShaderNodeVectorOp::get_output_port_name(int p_port) const { } String VisualShaderNodeVectorOp::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 = "\t" + p_output_vars[0] + " = "; switch (op) { - - case OP_ADD: code += p_input_vars[0] + " + " + p_input_vars[1] + ";\n"; break; - case OP_SUB: code += p_input_vars[0] + " - " + p_input_vars[1] + ";\n"; break; - case OP_MUL: code += p_input_vars[0] + " * " + p_input_vars[1] + ";\n"; break; - case OP_DIV: code += p_input_vars[0] + " / " + p_input_vars[1] + ";\n"; break; - case OP_MOD: code += "mod(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_POW: code += "pow(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_MAX: code += "max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_MIN: code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_CROSS: code += "cross(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_ATAN2: code += "atan(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_REFLECT: code += "reflect(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; - case OP_STEP: code += "step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; break; + case OP_ADD: + code += p_input_vars[0] + " + " + p_input_vars[1] + ";\n"; + break; + case OP_SUB: + code += p_input_vars[0] + " - " + p_input_vars[1] + ";\n"; + break; + case OP_MUL: + code += p_input_vars[0] + " * " + p_input_vars[1] + ";\n"; + break; + case OP_DIV: + code += p_input_vars[0] + " / " + p_input_vars[1] + ";\n"; + break; + case OP_MOD: + code += "mod(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_POW: + code += "pow(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_MAX: + code += "max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_MIN: + code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_CROSS: + code += "cross(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_ATAN2: + code += "atan(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_REFLECT: + code += "reflect(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; + case OP_STEP: + code += "step(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + break; } return code; } void VisualShaderNodeVectorOp::set_operator(Operator p_op) { - op = p_op; emit_changed(); } VisualShaderNodeVectorOp::Operator VisualShaderNodeVectorOp::get_operator() const { - return op; } @@ -1098,7 +1487,6 @@ Vector<StringName> VisualShaderNodeVectorOp::get_editable_properties() const { } void VisualShaderNodeVectorOp::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeVectorOp::set_operator); ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeVectorOp::get_operator); @@ -1119,7 +1507,6 @@ void VisualShaderNodeVectorOp::_bind_methods() { } VisualShaderNodeVectorOp::VisualShaderNodeVectorOp() { - op = OP_ADD; set_input_port_default_value(0, Vector3()); set_input_port_default_value(1, Vector3()); } @@ -1155,29 +1542,23 @@ String VisualShaderNodeColorOp::get_output_port_name(int p_port) const { } String VisualShaderNodeColorOp::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; static const char *axisn[3] = { "x", "y", "z" }; switch (op) { case OP_SCREEN: { - code += "\t" + p_output_vars[0] + " = vec3(1.0) - (vec3(1.0) - " + p_input_vars[0] + ") * (vec3(1.0) - " + p_input_vars[1] + ");\n"; } break; case OP_DIFFERENCE: { - code += "\t" + p_output_vars[0] + " = abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ");\n"; } break; case OP_DARKEN: { - code += "\t" + p_output_vars[0] + " = min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } break; case OP_LIGHTEN: { - code += "\t" + p_output_vars[0] + " = max(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } break; case OP_OVERLAY: { - for (int i = 0; i < 3; i++) { code += "\t{\n"; code += "\t\tfloat base = " + p_input_vars[0] + "." + axisn[i] + ";\n"; @@ -1192,16 +1573,13 @@ String VisualShaderNodeColorOp::generate_code(Shader::Mode p_mode, VisualShader: } break; case OP_DODGE: { - code += "\t" + p_output_vars[0] + " = (" + p_input_vars[0] + ") / (vec3(1.0) - " + p_input_vars[1] + ");\n"; } break; case OP_BURN: { - code += "\t" + p_output_vars[0] + " = vec3(1.0) - (vec3(1.0) - " + p_input_vars[0] + ") / (" + p_input_vars[1] + ");\n"; } break; case OP_SOFT_LIGHT: { - for (int i = 0; i < 3; i++) { code += "\t{\n"; code += "\t\tfloat base = " + p_input_vars[0] + "." + axisn[i] + ";\n"; @@ -1216,7 +1594,6 @@ String VisualShaderNodeColorOp::generate_code(Shader::Mode p_mode, VisualShader: } break; case OP_HARD_LIGHT: { - for (int i = 0; i < 3; i++) { code += "\t{\n"; code += "\t\tfloat base = " + p_input_vars[0] + "." + axisn[i] + ";\n"; @@ -1236,7 +1613,6 @@ String VisualShaderNodeColorOp::generate_code(Shader::Mode p_mode, VisualShader: } void VisualShaderNodeColorOp::set_operator(Operator p_op) { - op = p_op; switch (op) { case OP_SCREEN: @@ -1271,7 +1647,6 @@ void VisualShaderNodeColorOp::set_operator(Operator p_op) { } VisualShaderNodeColorOp::Operator VisualShaderNodeColorOp::get_operator() const { - return op; } @@ -1282,7 +1657,6 @@ Vector<StringName> VisualShaderNodeColorOp::get_editable_properties() const { } void VisualShaderNodeColorOp::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeColorOp::set_operator); ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeColorOp::get_operator); @@ -1300,7 +1674,6 @@ void VisualShaderNodeColorOp::_bind_methods() { } VisualShaderNodeColorOp::VisualShaderNodeColorOp() { - op = OP_SCREEN; set_input_port_default_value(0, Vector3()); set_input_port_default_value(1, Vector3()); } @@ -1336,7 +1709,6 @@ String VisualShaderNodeTransformMult::get_output_port_name(int p_port) const { } String VisualShaderNodeTransformMult::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 { - if (op == OP_AxB) { return "\t" + p_output_vars[0] + " = " + p_input_vars[0] + " * " + p_input_vars[1] + ";\n"; } else if (op == OP_BxA) { @@ -1349,13 +1721,11 @@ String VisualShaderNodeTransformMult::generate_code(Shader::Mode p_mode, VisualS } void VisualShaderNodeTransformMult::set_operator(Operator p_op) { - op = p_op; emit_changed(); } VisualShaderNodeTransformMult::Operator VisualShaderNodeTransformMult::get_operator() const { - return op; } @@ -1366,7 +1736,6 @@ Vector<StringName> VisualShaderNodeTransformMult::get_editable_properties() cons } void VisualShaderNodeTransformMult::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeTransformMult::set_operator); ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeTransformMult::get_operator); @@ -1379,7 +1748,6 @@ void VisualShaderNodeTransformMult::_bind_methods() { } VisualShaderNodeTransformMult::VisualShaderNodeTransformMult() { - op = OP_AxB; set_input_port_default_value(0, Transform()); set_input_port_default_value(1, Transform()); } @@ -1427,13 +1795,11 @@ String VisualShaderNodeTransformVecMult::generate_code(Shader::Mode p_mode, Visu } void VisualShaderNodeTransformVecMult::set_operator(Operator p_op) { - op = p_op; emit_changed(); } VisualShaderNodeTransformVecMult::Operator VisualShaderNodeTransformVecMult::get_operator() const { - return op; } @@ -1444,7 +1810,6 @@ Vector<StringName> VisualShaderNodeTransformVecMult::get_editable_properties() c } void VisualShaderNodeTransformVecMult::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeTransformVecMult::set_operator); ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeTransformVecMult::get_operator); @@ -1457,43 +1822,41 @@ void VisualShaderNodeTransformVecMult::_bind_methods() { } VisualShaderNodeTransformVecMult::VisualShaderNodeTransformVecMult() { - op = OP_AxB; set_input_port_default_value(0, Transform()); set_input_port_default_value(1, Vector3()); } -////////////// Scalar Func +////////////// Float Func -String VisualShaderNodeScalarFunc::get_caption() const { - return "ScalarFunc"; +String VisualShaderNodeFloatFunc::get_caption() const { + return "FloatFunc"; } -int VisualShaderNodeScalarFunc::get_input_port_count() const { +int VisualShaderNodeFloatFunc::get_input_port_count() const { return 1; } -VisualShaderNodeScalarFunc::PortType VisualShaderNodeScalarFunc::get_input_port_type(int p_port) const { +VisualShaderNodeFloatFunc::PortType VisualShaderNodeFloatFunc::get_input_port_type(int p_port) const { return PORT_TYPE_SCALAR; } -String VisualShaderNodeScalarFunc::get_input_port_name(int p_port) const { +String VisualShaderNodeFloatFunc::get_input_port_name(int p_port) const { return ""; } -int VisualShaderNodeScalarFunc::get_output_port_count() const { +int VisualShaderNodeFloatFunc::get_output_port_count() const { return 1; } -VisualShaderNodeScalarFunc::PortType VisualShaderNodeScalarFunc::get_output_port_type(int p_port) const { +VisualShaderNodeFloatFunc::PortType VisualShaderNodeFloatFunc::get_output_port_type(int p_port) const { return PORT_TYPE_SCALAR; } -String VisualShaderNodeScalarFunc::get_output_port_name(int p_port) const { +String VisualShaderNodeFloatFunc::get_output_port_name(int p_port) const { return ""; //no output port means the editor will be used as port } -String VisualShaderNodeScalarFunc::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 VisualShaderNodeFloatFunc::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 { static const char *scalar_func_id[FUNC_ONEMINUS + 1] = { "sin($)", "cos($)", @@ -1532,27 +1895,24 @@ String VisualShaderNodeScalarFunc::generate_code(Shader::Mode p_mode, VisualShad return "\t" + p_output_vars[0] + " = " + String(scalar_func_id[func]).replace("$", p_input_vars[0]) + ";\n"; } -void VisualShaderNodeScalarFunc::set_function(Function p_func) { - +void VisualShaderNodeFloatFunc::set_function(Function p_func) { func = p_func; emit_changed(); } -VisualShaderNodeScalarFunc::Function VisualShaderNodeScalarFunc::get_function() const { - +VisualShaderNodeFloatFunc::Function VisualShaderNodeFloatFunc::get_function() const { return func; } -Vector<StringName> VisualShaderNodeScalarFunc::get_editable_properties() const { +Vector<StringName> VisualShaderNodeFloatFunc::get_editable_properties() const { Vector<StringName> props; props.push_back("function"); return props; } -void VisualShaderNodeScalarFunc::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeScalarFunc::set_function); - ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeScalarFunc::get_function); +void VisualShaderNodeFloatFunc::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeFloatFunc::set_function); + ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeFloatFunc::get_function); ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Sin,Cos,Tan,ASin,ACos,ATan,SinH,CosH,TanH,Log,Exp,Sqrt,Abs,Sign,Floor,Round,Ceil,Frac,Saturate,Negate,ACosH,ASinH,ATanH,Degrees,Exp2,InverseSqrt,Log2,Radians,Reciprocal,RoundEven,Trunc,OneMinus"), "set_function", "get_function"); @@ -1590,11 +1950,104 @@ void VisualShaderNodeScalarFunc::_bind_methods() { BIND_ENUM_CONSTANT(FUNC_ONEMINUS); } -VisualShaderNodeScalarFunc::VisualShaderNodeScalarFunc() { - func = FUNC_SIGN; +VisualShaderNodeFloatFunc::VisualShaderNodeFloatFunc() { set_input_port_default_value(0, 0.0); } +////////////// Int Func + +String VisualShaderNodeIntFunc::get_caption() const { + return "IntFunc"; +} + +int VisualShaderNodeIntFunc::get_input_port_count() const { + if (func == FUNC_CLAMP) { + return 3; + } + return 1; +} + +VisualShaderNodeIntFunc::PortType VisualShaderNodeIntFunc::get_input_port_type(int p_port) const { + return PORT_TYPE_SCALAR_INT; +} + +String VisualShaderNodeIntFunc::get_input_port_name(int p_port) const { + if (func == FUNC_CLAMP) { + if (p_port == 0) { + return ""; + } else if (p_port == 1) { + return "min"; + } else if (p_port == 2) { + return "max"; + } + } + return ""; +} + +int VisualShaderNodeIntFunc::get_output_port_count() const { + return 1; +} + +VisualShaderNodeIntFunc::PortType VisualShaderNodeIntFunc::get_output_port_type(int p_port) const { + return PORT_TYPE_SCALAR_INT; +} + +String VisualShaderNodeIntFunc::get_output_port_name(int p_port) const { + return ""; //no output port means the editor will be used as port +} + +String VisualShaderNodeIntFunc::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 { + if (func == FUNC_CLAMP) { + return "\t" + p_output_vars[0] + " = clamp(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; + } + + static const char *int_func_id[FUNC_SIGN + 1] = { + "abs($)", + "", + "-($)", + "sign($)" + }; + + return "\t" + p_output_vars[0] + " = " + String(int_func_id[func]).replace("$", p_input_vars[0]) + ";\n"; +} + +void VisualShaderNodeIntFunc::set_function(Function p_func) { + if (func != p_func) { + if (p_func == FUNC_CLAMP) { + set_input_port_default_value(1, 0); + set_input_port_default_value(2, 0); + } + } + func = p_func; + emit_changed(); +} + +VisualShaderNodeIntFunc::Function VisualShaderNodeIntFunc::get_function() const { + return func; +} + +Vector<StringName> VisualShaderNodeIntFunc::get_editable_properties() const { + Vector<StringName> props; + props.push_back("function"); + return props; +} + +void VisualShaderNodeIntFunc::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeIntFunc::set_function); + ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeIntFunc::get_function); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Abs,Clamp,Negate,Sign"), "set_function", "get_function"); + + BIND_ENUM_CONSTANT(FUNC_ABS); + BIND_ENUM_CONSTANT(FUNC_CLAMP); + BIND_ENUM_CONSTANT(FUNC_NEGATE); + BIND_ENUM_CONSTANT(FUNC_SIGN); +} + +VisualShaderNodeIntFunc::VisualShaderNodeIntFunc() { + set_input_port_default_value(0, 0); +} + ////////////// Vector Func String VisualShaderNodeVectorFunc::get_caption() const { @@ -1626,7 +2079,6 @@ String VisualShaderNodeVectorFunc::get_output_port_name(int p_port) const { } String VisualShaderNodeVectorFunc::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 { - static const char *vec_func_id[FUNC_ONEMINUS + 1] = { "normalize($)", "max(min($, vec3(1.0)), vec3(0.0))", @@ -1693,7 +2145,6 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad } void VisualShaderNodeVectorFunc::set_function(Function p_func) { - func = p_func; if (func == FUNC_RGB2HSV) { simple_decl = false; @@ -1706,7 +2157,6 @@ void VisualShaderNodeVectorFunc::set_function(Function p_func) { } VisualShaderNodeVectorFunc::Function VisualShaderNodeVectorFunc::get_function() const { - return func; } @@ -1717,7 +2167,6 @@ Vector<StringName> VisualShaderNodeVectorFunc::get_editable_properties() const { } void VisualShaderNodeVectorFunc::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeVectorFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeVectorFunc::get_function); @@ -1761,7 +2210,6 @@ void VisualShaderNodeVectorFunc::_bind_methods() { } VisualShaderNodeVectorFunc::VisualShaderNodeVectorFunc() { - func = FUNC_NORMALIZE; set_input_port_default_value(0, Vector3()); } @@ -1796,7 +2244,6 @@ String VisualShaderNodeColorFunc::get_output_port_name(int p_port) const { } String VisualShaderNodeColorFunc::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; switch (func) { @@ -1824,13 +2271,11 @@ String VisualShaderNodeColorFunc::generate_code(Shader::Mode p_mode, VisualShade } void VisualShaderNodeColorFunc::set_function(Function p_func) { - func = p_func; emit_changed(); } VisualShaderNodeColorFunc::Function VisualShaderNodeColorFunc::get_function() const { - return func; } @@ -1841,7 +2286,6 @@ Vector<StringName> VisualShaderNodeColorFunc::get_editable_properties() const { } void VisualShaderNodeColorFunc::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeColorFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeColorFunc::get_function); @@ -1852,9 +2296,8 @@ void VisualShaderNodeColorFunc::_bind_methods() { } VisualShaderNodeColorFunc::VisualShaderNodeColorFunc() { - func = FUNC_GRAYSCALE; - set_input_port_default_value(0, Vector3()); simple_decl = false; + set_input_port_default_value(0, Vector3()); } ////////////// Transform Func @@ -1888,7 +2331,6 @@ String VisualShaderNodeTransformFunc::get_output_port_name(int p_port) const { } String VisualShaderNodeTransformFunc::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 { - static const char *funcs[FUNC_TRANSPOSE + 1] = { "inverse($)", "transpose($)" @@ -1900,13 +2342,11 @@ String VisualShaderNodeTransformFunc::generate_code(Shader::Mode p_mode, VisualS } void VisualShaderNodeTransformFunc::set_function(Function p_func) { - func = p_func; emit_changed(); } VisualShaderNodeTransformFunc::Function VisualShaderNodeTransformFunc::get_function() const { - return func; } @@ -1917,7 +2357,6 @@ Vector<StringName> VisualShaderNodeTransformFunc::get_editable_properties() cons } void VisualShaderNodeTransformFunc::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeTransformFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeTransformFunc::get_function); @@ -1928,7 +2367,6 @@ void VisualShaderNodeTransformFunc::_bind_methods() { } VisualShaderNodeTransformFunc::VisualShaderNodeTransformFunc() { - func = FUNC_INVERSE; set_input_port_default_value(0, Transform()); } @@ -2078,7 +2516,6 @@ String VisualShaderNodeScalarDerivativeFunc::get_output_port_name(int p_port) co } String VisualShaderNodeScalarDerivativeFunc::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 { - static const char *funcs[FUNC_Y + 1] = { "fwidth($)", "dFdx($)", @@ -2091,13 +2528,11 @@ String VisualShaderNodeScalarDerivativeFunc::generate_code(Shader::Mode p_mode, } void VisualShaderNodeScalarDerivativeFunc::set_function(Function p_func) { - func = p_func; emit_changed(); } VisualShaderNodeScalarDerivativeFunc::Function VisualShaderNodeScalarDerivativeFunc::get_function() const { - return func; } @@ -2108,7 +2543,6 @@ Vector<StringName> VisualShaderNodeScalarDerivativeFunc::get_editable_properties } void VisualShaderNodeScalarDerivativeFunc::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeScalarDerivativeFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeScalarDerivativeFunc::get_function); @@ -2120,7 +2554,6 @@ void VisualShaderNodeScalarDerivativeFunc::_bind_methods() { } VisualShaderNodeScalarDerivativeFunc::VisualShaderNodeScalarDerivativeFunc() { - func = FUNC_SUM; set_input_port_default_value(0, 0.0); } @@ -2155,7 +2588,6 @@ String VisualShaderNodeVectorDerivativeFunc::get_output_port_name(int p_port) co } String VisualShaderNodeVectorDerivativeFunc::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 { - static const char *funcs[FUNC_Y + 1] = { "fwidth($)", "dFdx($)", @@ -2168,13 +2600,11 @@ String VisualShaderNodeVectorDerivativeFunc::generate_code(Shader::Mode p_mode, } void VisualShaderNodeVectorDerivativeFunc::set_function(Function p_func) { - func = p_func; emit_changed(); } VisualShaderNodeVectorDerivativeFunc::Function VisualShaderNodeVectorDerivativeFunc::get_function() const { - return func; } @@ -2185,7 +2615,6 @@ Vector<StringName> VisualShaderNodeVectorDerivativeFunc::get_editable_properties } void VisualShaderNodeVectorDerivativeFunc::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeVectorDerivativeFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeVectorDerivativeFunc::get_function); @@ -2197,7 +2626,6 @@ void VisualShaderNodeVectorDerivativeFunc::_bind_methods() { } VisualShaderNodeVectorDerivativeFunc::VisualShaderNodeVectorDerivativeFunc() { - func = FUNC_SUM; set_input_port_default_value(0, Vector3()); } @@ -2216,12 +2644,13 @@ VisualShaderNodeScalarClamp::PortType VisualShaderNodeScalarClamp::get_input_por } String VisualShaderNodeScalarClamp::get_input_port_name(int p_port) const { - if (p_port == 0) + if (p_port == 0) { return ""; - else if (p_port == 1) + } else if (p_port == 1) { return "min"; - else if (p_port == 2) + } else if (p_port == 2) { return "max"; + } return ""; } @@ -2262,12 +2691,13 @@ VisualShaderNodeVectorClamp::PortType VisualShaderNodeVectorClamp::get_input_por } String VisualShaderNodeVectorClamp::get_input_port_name(int p_port) const { - if (p_port == 0) + if (p_port == 0) { return ""; - else if (p_port == 1) + } else if (p_port == 1) { return "min"; - else if (p_port == 2) + } else if (p_port == 2) { return "max"; + } return ""; } @@ -2406,10 +2836,11 @@ VisualShaderNodeVectorScalarStep::PortType VisualShaderNodeVectorScalarStep::get } String VisualShaderNodeVectorScalarStep::get_input_port_name(int p_port) const { - if (p_port == 0) + if (p_port == 0) { return "edge"; - else if (p_port == 1) + } else if (p_port == 1) { return "x"; + } return ""; } @@ -2449,12 +2880,13 @@ VisualShaderNodeScalarSmoothStep::PortType VisualShaderNodeScalarSmoothStep::get } String VisualShaderNodeScalarSmoothStep::get_input_port_name(int p_port) const { - if (p_port == 0) + if (p_port == 0) { return "edge0"; - else if (p_port == 1) + } else if (p_port == 1) { return "edge1"; - else if (p_port == 2) + } else if (p_port == 2) { return "x"; + } return ""; } @@ -2495,12 +2927,13 @@ VisualShaderNodeVectorSmoothStep::PortType VisualShaderNodeVectorSmoothStep::get } String VisualShaderNodeVectorSmoothStep::get_input_port_name(int p_port) const { - if (p_port == 0) + if (p_port == 0) { return "edge0"; - else if (p_port == 1) + } else if (p_port == 1) { return "edge1"; - else if (p_port == 2) + } else if (p_port == 2) { return "x"; + } return ""; } @@ -2546,12 +2979,13 @@ VisualShaderNodeVectorScalarSmoothStep::PortType VisualShaderNodeVectorScalarSmo } String VisualShaderNodeVectorScalarSmoothStep::get_input_port_name(int p_port) const { - if (p_port == 0) + if (p_port == 0) { return "edge0"; - else if (p_port == 1) + } else if (p_port == 1) { return "edge1"; - else if (p_port == 2) + } else if (p_port == 2) { return "x"; + } return ""; } @@ -2632,7 +3066,6 @@ int VisualShaderNodeVectorRefract::get_input_port_count() const { } VisualShaderNodeVectorRefract::PortType VisualShaderNodeVectorRefract::get_input_port_type(int p_port) const { - if (p_port == 2) { return PORT_TYPE_SCALAR; } @@ -2776,8 +3209,9 @@ int VisualShaderNodeVectorScalarMix::get_input_port_count() const { } VisualShaderNodeVectorScalarMix::PortType VisualShaderNodeVectorScalarMix::get_input_port_type(int p_port) const { - if (p_port == 2) + if (p_port == 2) { return PORT_TYPE_SCALAR; + } return PORT_TYPE_VECTOR; } @@ -2854,7 +3288,6 @@ String VisualShaderNodeVectorCompose::generate_code(Shader::Mode p_mode, VisualS } VisualShaderNodeVectorCompose::VisualShaderNodeVectorCompose() { - set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); set_input_port_default_value(2, 0.0); @@ -2903,7 +3336,6 @@ String VisualShaderNodeTransformCompose::generate_code(Shader::Mode p_mode, Visu } VisualShaderNodeTransformCompose::VisualShaderNodeTransformCompose() { - set_input_port_default_value(0, Vector3()); set_input_port_default_value(1, Vector3()); set_input_port_default_value(2, Vector3()); @@ -3008,45 +3440,338 @@ VisualShaderNodeTransformDecompose::VisualShaderNodeTransformDecompose() { set_input_port_default_value(0, Transform()); } -////////////// Scalar Uniform +////////////// Float Uniform -String VisualShaderNodeScalarUniform::get_caption() const { - return "ScalarUniform"; +String VisualShaderNodeFloatUniform::get_caption() const { + return "FloatUniform"; } -int VisualShaderNodeScalarUniform::get_input_port_count() const { +int VisualShaderNodeFloatUniform::get_input_port_count() const { return 0; } -VisualShaderNodeScalarUniform::PortType VisualShaderNodeScalarUniform::get_input_port_type(int p_port) const { +VisualShaderNodeFloatUniform::PortType VisualShaderNodeFloatUniform::get_input_port_type(int p_port) const { return PORT_TYPE_SCALAR; } -String VisualShaderNodeScalarUniform::get_input_port_name(int p_port) const { +String VisualShaderNodeFloatUniform::get_input_port_name(int p_port) const { return String(); } -int VisualShaderNodeScalarUniform::get_output_port_count() const { +int VisualShaderNodeFloatUniform::get_output_port_count() const { return 1; } -VisualShaderNodeScalarUniform::PortType VisualShaderNodeScalarUniform::get_output_port_type(int p_port) const { +VisualShaderNodeFloatUniform::PortType VisualShaderNodeFloatUniform::get_output_port_type(int p_port) const { return PORT_TYPE_SCALAR; } -String VisualShaderNodeScalarUniform::get_output_port_name(int p_port) const { +String VisualShaderNodeFloatUniform::get_output_port_name(int p_port) const { + return ""; //no output port means the editor will be used as port +} + +String VisualShaderNodeFloatUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + String code = ""; + if (hint == HINT_RANGE) { + code += _get_qual_str() + "uniform float " + get_uniform_name() + " : hint_range(" + rtos(hint_range_min) + ", " + rtos(hint_range_max) + ")"; + } else if (hint == HINT_RANGE_STEP) { + code += _get_qual_str() + "uniform float " + get_uniform_name() + " : hint_range(" + rtos(hint_range_min) + ", " + rtos(hint_range_max) + ", " + rtos(hint_range_step) + ")"; + } else { + code += _get_qual_str() + "uniform float " + get_uniform_name(); + } + if (default_value_enabled) { + code += " = " + rtos(default_value); + } + code += ";\n"; + return code; +} + +String VisualShaderNodeFloatUniform::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 { + return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; +} + +bool VisualShaderNodeFloatUniform::is_show_prop_names() const { + return true; +} + +bool VisualShaderNodeFloatUniform::is_use_prop_slots() const { + return true; +} + +void VisualShaderNodeFloatUniform::set_hint(Hint p_hint) { + hint = p_hint; + emit_changed(); +} + +VisualShaderNodeFloatUniform::Hint VisualShaderNodeFloatUniform::get_hint() const { + return hint; +} + +void VisualShaderNodeFloatUniform::set_min(float p_value) { + hint_range_min = p_value; + emit_changed(); +} + +float VisualShaderNodeFloatUniform::get_min() const { + return hint_range_min; +} + +void VisualShaderNodeFloatUniform::set_max(float p_value) { + hint_range_max = p_value; + emit_changed(); +} + +float VisualShaderNodeFloatUniform::get_max() const { + return hint_range_max; +} + +void VisualShaderNodeFloatUniform::set_step(float p_value) { + hint_range_step = p_value; + emit_changed(); +} + +float VisualShaderNodeFloatUniform::get_step() const { + return hint_range_step; +} + +void VisualShaderNodeFloatUniform::set_default_value_enabled(bool p_enabled) { + default_value_enabled = p_enabled; + emit_changed(); +} + +bool VisualShaderNodeFloatUniform::is_default_value_enabled() const { + return default_value_enabled; +} + +void VisualShaderNodeFloatUniform::set_default_value(float p_value) { + default_value = p_value; + emit_changed(); +} + +float VisualShaderNodeFloatUniform::get_default_value() const { + return default_value; +} + +void VisualShaderNodeFloatUniform::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_hint", "hint"), &VisualShaderNodeFloatUniform::set_hint); + ClassDB::bind_method(D_METHOD("get_hint"), &VisualShaderNodeFloatUniform::get_hint); + + ClassDB::bind_method(D_METHOD("set_min", "value"), &VisualShaderNodeFloatUniform::set_min); + ClassDB::bind_method(D_METHOD("get_min"), &VisualShaderNodeFloatUniform::get_min); + + ClassDB::bind_method(D_METHOD("set_max", "value"), &VisualShaderNodeFloatUniform::set_max); + ClassDB::bind_method(D_METHOD("get_max"), &VisualShaderNodeFloatUniform::get_max); + + ClassDB::bind_method(D_METHOD("set_step", "value"), &VisualShaderNodeFloatUniform::set_step); + ClassDB::bind_method(D_METHOD("get_step"), &VisualShaderNodeFloatUniform::get_step); + + ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeFloatUniform::set_default_value_enabled); + ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeFloatUniform::is_default_value_enabled); + + ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeFloatUniform::set_default_value); + ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeFloatUniform::get_default_value); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range+Step"), "set_hint", "get_hint"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "min"), "set_min", "get_min"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max"), "set_max", "get_max"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step"), "set_step", "get_step"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "default_value"), "set_default_value", "get_default_value"); + + BIND_ENUM_CONSTANT(HINT_NONE); + BIND_ENUM_CONSTANT(HINT_RANGE); + BIND_ENUM_CONSTANT(HINT_RANGE_STEP); +} + +bool VisualShaderNodeFloatUniform::is_qualifier_supported(Qualifier p_qual) const { + return true; // all qualifiers are supported +} + +Vector<StringName> VisualShaderNodeFloatUniform::get_editable_properties() const { + Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); + props.push_back("hint"); + if (hint == HINT_RANGE || hint == HINT_RANGE_STEP) { + props.push_back("min"); + props.push_back("max"); + } + if (hint == HINT_RANGE_STEP) { + props.push_back("step"); + } + props.push_back("default_value_enabled"); + if (default_value_enabled) { + props.push_back("default_value"); + } + return props; +} + +VisualShaderNodeFloatUniform::VisualShaderNodeFloatUniform() { +} + +////////////// Integer Uniform + +String VisualShaderNodeIntUniform::get_caption() const { + return "IntUniform"; +} + +int VisualShaderNodeIntUniform::get_input_port_count() const { + return 0; +} + +VisualShaderNodeIntUniform::PortType VisualShaderNodeIntUniform::get_input_port_type(int p_port) const { + return PORT_TYPE_SCALAR_INT; +} + +String VisualShaderNodeIntUniform::get_input_port_name(int p_port) const { + return String(); +} + +int VisualShaderNodeIntUniform::get_output_port_count() const { + return 1; +} + +VisualShaderNodeIntUniform::PortType VisualShaderNodeIntUniform::get_output_port_type(int p_port) const { + return PORT_TYPE_SCALAR_INT; +} + +String VisualShaderNodeIntUniform::get_output_port_name(int p_port) const { return ""; //no output port means the editor will be used as port } -String VisualShaderNodeScalarUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - return "uniform float " + get_uniform_name() + ";\n"; +String VisualShaderNodeIntUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + String code = ""; + if (hint == HINT_RANGE) { + code += _get_qual_str() + "uniform int " + get_uniform_name() + " : hint_range(" + itos(hint_range_min) + ", " + itos(hint_range_max) + ")"; + } else if (hint == HINT_RANGE_STEP) { + code += _get_qual_str() + "uniform int " + get_uniform_name() + " : hint_range(" + itos(hint_range_min) + ", " + itos(hint_range_max) + ", " + itos(hint_range_step) + ")"; + } else { + code += _get_qual_str() + "uniform int " + get_uniform_name(); + } + if (default_value_enabled) { + code += " = " + itos(default_value); + } + code += ";\n"; + return code; } -String VisualShaderNodeScalarUniform::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 VisualShaderNodeIntUniform::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 { return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; } -VisualShaderNodeScalarUniform::VisualShaderNodeScalarUniform() { +bool VisualShaderNodeIntUniform::is_show_prop_names() const { + return true; +} + +bool VisualShaderNodeIntUniform::is_use_prop_slots() const { + return true; +} + +void VisualShaderNodeIntUniform::set_hint(Hint p_hint) { + hint = p_hint; + emit_changed(); +} + +VisualShaderNodeIntUniform::Hint VisualShaderNodeIntUniform::get_hint() const { + return hint; +} + +void VisualShaderNodeIntUniform::set_min(int p_value) { + hint_range_min = p_value; + emit_changed(); +} + +int VisualShaderNodeIntUniform::get_min() const { + return hint_range_min; +} + +void VisualShaderNodeIntUniform::set_max(int p_value) { + hint_range_max = p_value; + emit_changed(); +} + +int VisualShaderNodeIntUniform::get_max() const { + return hint_range_max; +} + +void VisualShaderNodeIntUniform::set_step(int p_value) { + hint_range_step = p_value; + emit_changed(); +} + +int VisualShaderNodeIntUniform::get_step() const { + return hint_range_step; +} + +void VisualShaderNodeIntUniform::set_default_value_enabled(bool p_enabled) { + default_value_enabled = p_enabled; + emit_changed(); +} + +bool VisualShaderNodeIntUniform::is_default_value_enabled() const { + return default_value_enabled; +} + +void VisualShaderNodeIntUniform::set_default_value(int p_value) { + default_value = p_value; + emit_changed(); +} + +int VisualShaderNodeIntUniform::get_default_value() const { + return default_value; +} + +void VisualShaderNodeIntUniform::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_hint", "hint"), &VisualShaderNodeIntUniform::set_hint); + ClassDB::bind_method(D_METHOD("get_hint"), &VisualShaderNodeIntUniform::get_hint); + + ClassDB::bind_method(D_METHOD("set_min", "value"), &VisualShaderNodeIntUniform::set_min); + ClassDB::bind_method(D_METHOD("get_min"), &VisualShaderNodeIntUniform::get_min); + + ClassDB::bind_method(D_METHOD("set_max", "value"), &VisualShaderNodeIntUniform::set_max); + ClassDB::bind_method(D_METHOD("get_max"), &VisualShaderNodeIntUniform::get_max); + + ClassDB::bind_method(D_METHOD("set_step", "value"), &VisualShaderNodeIntUniform::set_step); + ClassDB::bind_method(D_METHOD("get_step"), &VisualShaderNodeIntUniform::get_step); + + ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeIntUniform::set_default_value_enabled); + ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeIntUniform::is_default_value_enabled); + + ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeIntUniform::set_default_value); + ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeIntUniform::get_default_value); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range+Step"), "set_hint", "get_hint"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "min"), "set_min", "get_min"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max"), "set_max", "get_max"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "step"), "set_step", "get_step"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "default_value"), "set_default_value", "get_default_value"); + + BIND_ENUM_CONSTANT(HINT_NONE); + BIND_ENUM_CONSTANT(HINT_RANGE); + BIND_ENUM_CONSTANT(HINT_RANGE_STEP); +} + +bool VisualShaderNodeIntUniform::is_qualifier_supported(Qualifier p_qual) const { + return true; // all qualifiers are supported +} + +Vector<StringName> VisualShaderNodeIntUniform::get_editable_properties() const { + Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); + props.push_back("hint"); + if (hint == HINT_RANGE || hint == HINT_RANGE_STEP) { + props.push_back("min"); + props.push_back("max"); + } + if (hint == HINT_RANGE_STEP) { + props.push_back("step"); + } + props.push_back("default_value_enabled"); + if (default_value_enabled) { + props.push_back("default_value"); + } + return props; +} + +VisualShaderNodeIntUniform::VisualShaderNodeIntUniform() { } ////////////// Boolean Uniform @@ -3079,14 +3804,73 @@ String VisualShaderNodeBooleanUniform::get_output_port_name(int p_port) const { return ""; //no output port means the editor will be used as port } +void VisualShaderNodeBooleanUniform::set_default_value_enabled(bool p_enabled) { + default_value_enabled = p_enabled; + emit_changed(); +} + +bool VisualShaderNodeBooleanUniform::is_default_value_enabled() const { + return default_value_enabled; +} + +void VisualShaderNodeBooleanUniform::set_default_value(bool p_value) { + default_value = p_value; + emit_changed(); +} + +bool VisualShaderNodeBooleanUniform::get_default_value() const { + return default_value; +} + String VisualShaderNodeBooleanUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - return "uniform bool " + get_uniform_name() + ";\n"; + String code = _get_qual_str() + "uniform bool " + get_uniform_name(); + if (default_value_enabled) { + if (default_value) { + code += " = true"; + } else { + code += " = false"; + } + } + code += ";\n"; + return code; } String VisualShaderNodeBooleanUniform::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 { return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; } +bool VisualShaderNodeBooleanUniform::is_show_prop_names() const { + return true; +} + +bool VisualShaderNodeBooleanUniform::is_use_prop_slots() const { + return true; +} + +void VisualShaderNodeBooleanUniform::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeBooleanUniform::set_default_value_enabled); + ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeBooleanUniform::is_default_value_enabled); + + ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeBooleanUniform::set_default_value); + ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeBooleanUniform::get_default_value); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value"), "set_default_value", "get_default_value"); +} + +bool VisualShaderNodeBooleanUniform::is_qualifier_supported(Qualifier p_qual) const { + return true; // all qualifiers are supported +} + +Vector<StringName> VisualShaderNodeBooleanUniform::get_editable_properties() const { + Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); + props.push_back("default_value_enabled"); + if (default_value_enabled) { + props.push_back("default_value"); + } + return props; +} + VisualShaderNodeBooleanUniform::VisualShaderNodeBooleanUniform() { } @@ -3120,9 +3904,31 @@ String VisualShaderNodeColorUniform::get_output_port_name(int p_port) const { return p_port == 0 ? "color" : "alpha"; //no output port means the editor will be used as port } -String VisualShaderNodeColorUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { +void VisualShaderNodeColorUniform::set_default_value_enabled(bool p_enabled) { + default_value_enabled = p_enabled; + emit_changed(); +} + +bool VisualShaderNodeColorUniform::is_default_value_enabled() const { + return default_value_enabled; +} - return "uniform vec4 " + get_uniform_name() + " : hint_color;\n"; +void VisualShaderNodeColorUniform::set_default_value(const Color &p_value) { + default_value = p_value; + emit_changed(); +} + +Color VisualShaderNodeColorUniform::get_default_value() const { + return default_value; +} + +String VisualShaderNodeColorUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + String code = _get_qual_str() + "uniform vec4 " + get_uniform_name() + " : hint_color"; + if (default_value_enabled) { + code += vformat(" = vec4(%.6f, %.6f, %.6f, %.6f)", default_value.r, default_value.g, default_value.b, default_value.a); + } + code += ";\n"; + return code; } String VisualShaderNodeColorUniform::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 { @@ -3131,6 +3937,34 @@ String VisualShaderNodeColorUniform::generate_code(Shader::Mode p_mode, VisualSh return code; } +bool VisualShaderNodeColorUniform::is_show_prop_names() const { + return true; +} + +void VisualShaderNodeColorUniform::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeColorUniform::set_default_value_enabled); + ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeColorUniform::is_default_value_enabled); + + ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeColorUniform::set_default_value); + ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeColorUniform::get_default_value); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "default_value"), "set_default_value", "get_default_value"); +} + +bool VisualShaderNodeColorUniform::is_qualifier_supported(Qualifier p_qual) const { + return true; // all qualifiers are supported +} + +Vector<StringName> VisualShaderNodeColorUniform::get_editable_properties() const { + Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); + props.push_back("default_value_enabled"); + if (default_value_enabled) { + props.push_back("default_value"); + } + return props; +} + VisualShaderNodeColorUniform::VisualShaderNodeColorUniform() { } @@ -3164,14 +3998,69 @@ String VisualShaderNodeVec3Uniform::get_output_port_name(int p_port) const { return ""; //no output port means the editor will be used as port } +void VisualShaderNodeVec3Uniform::set_default_value_enabled(bool p_enabled) { + default_value_enabled = p_enabled; + emit_changed(); +} + +bool VisualShaderNodeVec3Uniform::is_default_value_enabled() const { + return default_value_enabled; +} + +void VisualShaderNodeVec3Uniform::set_default_value(const Vector3 &p_value) { + default_value = p_value; + emit_changed(); +} + +Vector3 VisualShaderNodeVec3Uniform::get_default_value() const { + return default_value; +} + String VisualShaderNodeVec3Uniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - return "uniform vec3 " + get_uniform_name() + ";\n"; + String code = _get_qual_str() + "uniform vec3 " + get_uniform_name(); + if (default_value_enabled) { + code += vformat(" = vec3(%.6f, %.6f, %.6f)", default_value.x, default_value.y, default_value.z); + } + code += ";\n"; + return code; } String VisualShaderNodeVec3Uniform::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 { return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; } +void VisualShaderNodeVec3Uniform::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeVec3Uniform::set_default_value_enabled); + ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeVec3Uniform::is_default_value_enabled); + + ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeVec3Uniform::set_default_value); + ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeVec3Uniform::get_default_value); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "default_value"), "set_default_value", "get_default_value"); +} + +bool VisualShaderNodeVec3Uniform::is_show_prop_names() const { + return true; +} + +bool VisualShaderNodeVec3Uniform::is_use_prop_slots() const { + return true; +} + +bool VisualShaderNodeVec3Uniform::is_qualifier_supported(Qualifier p_qual) const { + return true; // all qualifiers are supported +} + +Vector<StringName> VisualShaderNodeVec3Uniform::get_editable_properties() const { + Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); + props.push_back("default_value_enabled"); + if (default_value_enabled) { + props.push_back("default_value"); + } + return props; +} + VisualShaderNodeVec3Uniform::VisualShaderNodeVec3Uniform() { } @@ -3205,14 +4094,73 @@ String VisualShaderNodeTransformUniform::get_output_port_name(int p_port) const return ""; //no output port means the editor will be used as port } +void VisualShaderNodeTransformUniform::set_default_value_enabled(bool p_enabled) { + default_value_enabled = p_enabled; + emit_changed(); +} + +bool VisualShaderNodeTransformUniform::is_default_value_enabled() const { + return default_value_enabled; +} + +void VisualShaderNodeTransformUniform::set_default_value(const Transform &p_value) { + default_value = p_value; + emit_changed(); +} + +Transform VisualShaderNodeTransformUniform::get_default_value() const { + return default_value; +} + String VisualShaderNodeTransformUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - return "uniform mat4 " + get_uniform_name() + ";\n"; + String code = _get_qual_str() + "uniform mat4 " + get_uniform_name(); + if (default_value_enabled) { + Vector3 row0 = default_value.basis.get_row(0); + Vector3 row1 = default_value.basis.get_row(1); + Vector3 row2 = default_value.basis.get_row(2); + Vector3 origin = default_value.origin; + code += " = mat4(" + vformat("vec4(%.6f, %.6f, %.6f, 0.0)", row0.x, row0.y, row0.z) + vformat(", vec4(%.6f, %.6f, %.6f, 0.0)", row1.x, row1.y, row1.z) + vformat(", vec4(%.6f, %.6f, %.6f, 0.0)", row2.x, row2.y, row2.z) + vformat(", vec4(%.6f, %.6f, %.6f, 1.0)", origin.x, origin.y, origin.z) + ")"; + } + code += ";\n"; + return code; } String VisualShaderNodeTransformUniform::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 { return "\t" + p_output_vars[0] + " = " + get_uniform_name() + ";\n"; } +void VisualShaderNodeTransformUniform::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeTransformUniform::set_default_value_enabled); + ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeTransformUniform::is_default_value_enabled); + + ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeTransformUniform::set_default_value); + ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeTransformUniform::get_default_value); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "default_value"), "set_default_value", "get_default_value"); +} + +bool VisualShaderNodeTransformUniform::is_show_prop_names() const { + return true; +} + +bool VisualShaderNodeTransformUniform::is_use_prop_slots() const { + return true; +} + +bool VisualShaderNodeTransformUniform::is_qualifier_supported(Qualifier p_qual) const { + return true; // all qualifiers are supported +} + +Vector<StringName> VisualShaderNodeTransformUniform::get_editable_properties() const { + Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); + props.push_back("default_value_enabled"); + if (default_value_enabled) { + props.push_back("default_value"); + } + return props; +} + VisualShaderNodeTransformUniform::VisualShaderNodeTransformUniform() { } @@ -3239,7 +4187,6 @@ int VisualShaderNodeTextureUniform::get_output_port_count() const { } VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_output_port_type(int p_port) const { - switch (p_port) { case 0: return PORT_TYPE_VECTOR; @@ -3253,7 +4200,6 @@ VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_out } String VisualShaderNodeTextureUniform::get_output_port_name(int p_port) const { - switch (p_port) { case 0: return "rgb"; @@ -3267,30 +4213,39 @@ String VisualShaderNodeTextureUniform::get_output_port_name(int p_port) const { } String VisualShaderNodeTextureUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - String code = "uniform sampler2D " + get_uniform_name(); + String code = _get_qual_str() + "uniform sampler2D " + get_uniform_name(); switch (texture_type) { case TYPE_DATA: - if (color_default == COLOR_DEFAULT_BLACK) + if (color_default == COLOR_DEFAULT_BLACK) { code += " : hint_black;\n"; - else + } else { code += ";\n"; + } break; case TYPE_COLOR: - if (color_default == COLOR_DEFAULT_BLACK) + if (color_default == COLOR_DEFAULT_BLACK) { code += " : hint_black_albedo;\n"; - else + } else { code += " : hint_albedo;\n"; + } + break; + case TYPE_NORMALMAP: + code += " : hint_normal;\n"; + break; + case TYPE_ANISO: + code += " : hint_aniso;\n"; break; - case TYPE_NORMALMAP: code += " : hint_normal;\n"; break; - case TYPE_ANISO: code += " : hint_aniso;\n"; break; } return code; } -String VisualShaderNodeTextureUniform::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 { +bool VisualShaderNodeTextureUniform::is_code_generated() const { + return is_output_port_connected(0) || is_output_port_connected(1); // rgb or alpha +} +String VisualShaderNodeTextureUniform::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 id = get_uniform_name(); String code = "\t{\n"; if (p_input_vars[0] == String()) { // Use UV by default. @@ -3313,7 +4268,6 @@ String VisualShaderNodeTextureUniform::generate_code(Shader::Mode p_mode, Visual } void VisualShaderNodeTextureUniform::set_texture_type(TextureType p_type) { - texture_type = p_type; emit_changed(); } @@ -3332,7 +4286,7 @@ VisualShaderNodeTextureUniform::ColorDefault VisualShaderNodeTextureUniform::get } Vector<StringName> VisualShaderNodeTextureUniform::get_editable_properties() const { - Vector<StringName> props; + Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties(); props.push_back("texture_type"); props.push_back("color_default"); return props; @@ -3364,9 +4318,19 @@ String VisualShaderNodeTextureUniform::get_input_port_default_hint(int p_port) c return ""; } +bool VisualShaderNodeTextureUniform::is_qualifier_supported(Qualifier p_qual) const { + switch (p_qual) { + case Qualifier::QUAL_NONE: + return true; + case Qualifier::QUAL_GLOBAL: + return true; + case Qualifier::QUAL_INSTANCE: + return false; + } + return false; +} + VisualShaderNodeTextureUniform::VisualShaderNodeTextureUniform() { - texture_type = TYPE_DATA; - color_default = COLOR_DEFAULT_WHITE; simple_decl = false; } @@ -3399,7 +4363,6 @@ String VisualShaderNodeTextureUniformTriplanar::get_input_port_name(int p_port) } String VisualShaderNodeTextureUniformTriplanar::generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - String code; code += "// TRIPLANAR FUNCTION GLOBAL CODE\n"; @@ -3422,11 +4385,9 @@ String VisualShaderNodeTextureUniformTriplanar::generate_global_per_node(Shader: } String VisualShaderNodeTextureUniformTriplanar::generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - String code; if (p_type == VisualShader::TYPE_VERTEX) { - code += "\t// TRIPLANAR FUNCTION VERTEX CODE\n"; code += "\t\ttriplanar_power_normal = pow(abs(NORMAL), vec3(triplanar_sharpness));\n"; code += "\t\ttriplanar_power_normal /= dot(triplanar_power_normal, vec3(1.0));\n"; @@ -3438,18 +4399,17 @@ String VisualShaderNodeTextureUniformTriplanar::generate_global_per_func(Shader: } String VisualShaderNodeTextureUniformTriplanar::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 id = get_uniform_name(); String code = "\t{\n"; if (p_input_vars[0] == String() && p_input_vars[1] == String()) { - code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", triplanar_power_normal, triplanar_pos );\n"; + code += "\t\tvec4 n_tex_read = triplanar_texture(" + id + ", triplanar_power_normal, triplanar_pos);\n"; } else if (p_input_vars[0] != String() && p_input_vars[1] == String()) { - code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", " + p_input_vars[0] + ", triplanar_pos );\n"; + code += "\t\tvec4 n_tex_read = triplanar_texture(" + id + ", " + p_input_vars[0] + ", triplanar_pos);\n"; } else if (p_input_vars[0] == String() && p_input_vars[1] != String()) { - code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", triplanar_power_normal," + p_input_vars[1] + " );\n"; + code += "\t\tvec4 n_tex_read = triplanar_texture(" + id + ", triplanar_power_normal, " + p_input_vars[1] + ");\n"; } else { - code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + " );\n"; + code += "\t\tvec4 n_tex_read = triplanar_texture(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } code += "\t\t" + p_output_vars[0] + " = n_tex_read.rgb;\n"; @@ -3471,42 +4431,110 @@ String VisualShaderNodeTextureUniformTriplanar::get_input_port_default_hint(int VisualShaderNodeTextureUniformTriplanar::VisualShaderNodeTextureUniformTriplanar() { } -////////////// CubeMap Uniform +////////////// Texture2DArray Uniform -String VisualShaderNodeCubeMapUniform::get_caption() const { - return "CubeMapUniform"; +String VisualShaderNodeTexture2DArrayUniform::get_caption() const { + return "Texture2DArrayUniform"; } -int VisualShaderNodeCubeMapUniform::get_output_port_count() const { +int VisualShaderNodeTexture2DArrayUniform::get_output_port_count() const { return 1; } -VisualShaderNodeCubeMapUniform::PortType VisualShaderNodeCubeMapUniform::get_output_port_type(int p_port) const { +VisualShaderNodeTexture2DArrayUniform::PortType VisualShaderNodeTexture2DArrayUniform::get_output_port_type(int p_port) const { return PORT_TYPE_SAMPLER; } -String VisualShaderNodeCubeMapUniform::get_output_port_name(int p_port) const { - return "samplerCube"; +String VisualShaderNodeTexture2DArrayUniform::get_output_port_name(int p_port) const { + return "sampler2DArray"; +} + +int VisualShaderNodeTexture2DArrayUniform::get_input_port_count() const { + return 0; +} + +VisualShaderNodeTexture2DArrayUniform::PortType VisualShaderNodeTexture2DArrayUniform::get_input_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeTexture2DArrayUniform::get_input_port_name(int p_port) const { + return ""; +} + +String VisualShaderNodeTexture2DArrayUniform::get_input_port_default_hint(int p_port) const { + return ""; +} + +String VisualShaderNodeTexture2DArrayUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + String code = _get_qual_str() + "uniform sampler2DArray " + get_uniform_name(); + + switch (texture_type) { + case TYPE_DATA: + if (color_default == COLOR_DEFAULT_BLACK) + code += " : hint_black;\n"; + else + code += ";\n"; + break; + case TYPE_COLOR: + if (color_default == COLOR_DEFAULT_BLACK) + code += " : hint_black_albedo;\n"; + else + code += " : hint_albedo;\n"; + break; + case TYPE_NORMALMAP: + code += " : hint_normal;\n"; + break; + case TYPE_ANISO: + code += " : hint_aniso;\n"; + break; + } + + return code; +} + +String VisualShaderNodeTexture2DArrayUniform::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 { + return String(); +} + +VisualShaderNodeTexture2DArrayUniform::VisualShaderNodeTexture2DArrayUniform() { +} + +////////////// Texture3D Uniform + +String VisualShaderNodeTexture3DUniform::get_caption() const { + return "Texture3DUniform"; +} + +int VisualShaderNodeTexture3DUniform::get_output_port_count() const { + return 1; +} + +VisualShaderNodeTexture3DUniform::PortType VisualShaderNodeTexture3DUniform::get_output_port_type(int p_port) const { + return PORT_TYPE_SAMPLER; } -int VisualShaderNodeCubeMapUniform::get_input_port_count() const { +String VisualShaderNodeTexture3DUniform::get_output_port_name(int p_port) const { + return "sampler3D"; +} + +int VisualShaderNodeTexture3DUniform::get_input_port_count() const { return 0; } -VisualShaderNodeCubeMapUniform::PortType VisualShaderNodeCubeMapUniform::get_input_port_type(int p_port) const { +VisualShaderNodeTexture3DUniform::PortType VisualShaderNodeTexture3DUniform::get_input_port_type(int p_port) const { return PORT_TYPE_SCALAR; } -String VisualShaderNodeCubeMapUniform::get_input_port_name(int p_port) const { +String VisualShaderNodeTexture3DUniform::get_input_port_name(int p_port) const { return ""; } -String VisualShaderNodeCubeMapUniform::get_input_port_default_hint(int p_port) const { +String VisualShaderNodeTexture3DUniform::get_input_port_default_hint(int p_port) const { return ""; } -String VisualShaderNodeCubeMapUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { - String code = "uniform samplerCube " + get_uniform_name(); +String VisualShaderNodeTexture3DUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + String code = _get_qual_str() + "uniform sampler3D " + get_uniform_name(); switch (texture_type) { case TYPE_DATA: @@ -3521,18 +4549,92 @@ String VisualShaderNodeCubeMapUniform::generate_global(Shader::Mode p_mode, Visu else code += " : hint_albedo;\n"; break; - case TYPE_NORMALMAP: code += " : hint_normal;\n"; break; - case TYPE_ANISO: code += " : hint_aniso;\n"; break; + case TYPE_NORMALMAP: + code += " : hint_normal;\n"; + break; + case TYPE_ANISO: + code += " : hint_aniso;\n"; + break; + } + + return code; +} + +String VisualShaderNodeTexture3DUniform::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 { + return String(); +} + +VisualShaderNodeTexture3DUniform::VisualShaderNodeTexture3DUniform() { +} + +////////////// Cubemap Uniform + +String VisualShaderNodeCubemapUniform::get_caption() const { + return "CubemapUniform"; +} + +int VisualShaderNodeCubemapUniform::get_output_port_count() const { + return 1; +} + +VisualShaderNodeCubemapUniform::PortType VisualShaderNodeCubemapUniform::get_output_port_type(int p_port) const { + return PORT_TYPE_SAMPLER; +} + +String VisualShaderNodeCubemapUniform::get_output_port_name(int p_port) const { + return "samplerCube"; +} + +int VisualShaderNodeCubemapUniform::get_input_port_count() const { + return 0; +} + +VisualShaderNodeCubemapUniform::PortType VisualShaderNodeCubemapUniform::get_input_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeCubemapUniform::get_input_port_name(int p_port) const { + return ""; +} + +String VisualShaderNodeCubemapUniform::get_input_port_default_hint(int p_port) const { + return ""; +} + +String VisualShaderNodeCubemapUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + String code = _get_qual_str() + "uniform samplerCube " + get_uniform_name(); + + switch (texture_type) { + case TYPE_DATA: + if (color_default == COLOR_DEFAULT_BLACK) { + code += " : hint_black;\n"; + } else { + code += ";\n"; + } + break; + case TYPE_COLOR: + if (color_default == COLOR_DEFAULT_BLACK) { + code += " : hint_black_albedo;\n"; + } else { + code += " : hint_albedo;\n"; + } + break; + case TYPE_NORMALMAP: + code += " : hint_normal;\n"; + break; + case TYPE_ANISO: + code += " : hint_aniso;\n"; + break; } return code; } -String VisualShaderNodeCubeMapUniform::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 VisualShaderNodeCubemapUniform::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 { return String(); } -VisualShaderNodeCubeMapUniform::VisualShaderNodeCubeMapUniform() { +VisualShaderNodeCubemapUniform::VisualShaderNodeCubemapUniform() { } ////////////// If @@ -3584,7 +4686,6 @@ String VisualShaderNodeIf::get_output_port_name(int p_port) const { } String VisualShaderNodeIf::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; code += "\tif(abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ")\n"; // abs(a - b) < tolerance eg. a == b code += "\t{\n"; @@ -3602,13 +4703,13 @@ String VisualShaderNodeIf::generate_code(Shader::Mode p_mode, VisualShader::Type } VisualShaderNodeIf::VisualShaderNodeIf() { + simple_decl = false; set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); set_input_port_default_value(2, CMP_EPSILON); set_input_port_default_value(3, Vector3(0.0, 0.0, 0.0)); set_input_port_default_value(4, Vector3(0.0, 0.0, 0.0)); set_input_port_default_value(5, Vector3(0.0, 0.0, 0.0)); - simple_decl = false; } ////////////// Switch @@ -3654,7 +4755,6 @@ String VisualShaderNodeSwitch::get_output_port_name(int p_port) const { } String VisualShaderNodeSwitch::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; code += "\tif(" + p_input_vars[0] + ")\n"; code += "\t{\n"; @@ -3668,10 +4768,10 @@ String VisualShaderNodeSwitch::generate_code(Shader::Mode p_mode, VisualShader:: } VisualShaderNodeSwitch::VisualShaderNodeSwitch() { + simple_decl = false; set_input_port_default_value(0, false); set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0)); set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); - simple_decl = false; } ////////////// Switch(scalar) @@ -3749,8 +4849,14 @@ String VisualShaderNodeFresnel::get_output_port_name(int p_port) const { return "result"; } -String VisualShaderNodeFresnel::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 { +bool VisualShaderNodeFresnel::is_generate_input_var(int p_port) const { + if (p_port == 2) { + return false; + } + return true; +} +String VisualShaderNodeFresnel::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 normal; String view; if (p_input_vars[0] == String()) { @@ -3764,7 +4870,15 @@ String VisualShaderNodeFresnel::generate_code(Shader::Mode p_mode, VisualShader: view = p_input_vars[1]; } - return "\t" + p_output_vars[0] + " = " + p_input_vars[2] + " ? (pow(clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ")) : (pow(1.0 - clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + "));\n"; + if (is_input_port_connected(2)) { + return "\t" + p_output_vars[0] + " = " + p_input_vars[2] + " ? (pow(clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ")) : (pow(1.0 - clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + "));\n"; + } else { + if (get_input_port_default_value(2)) { + return "\t" + p_output_vars[0] + " = pow(clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ");\n"; + } else { + return "\t" + p_output_vars[0] + " = pow(1.0 - clamp(dot(" + normal + ", " + view + "), 0.0, 1.0), " + p_input_vars[3] + ");\n"; + } + } } String VisualShaderNodeFresnel::get_input_port_default_hint(int p_port) const { @@ -3784,42 +4898,34 @@ VisualShaderNodeFresnel::VisualShaderNodeFresnel() { ////////////// Is String VisualShaderNodeIs::get_caption() const { - return "Is"; } int VisualShaderNodeIs::get_input_port_count() const { - return 1; } VisualShaderNodeIs::PortType VisualShaderNodeIs::get_input_port_type(int p_port) const { - return PORT_TYPE_SCALAR; } String VisualShaderNodeIs::get_input_port_name(int p_port) const { - return ""; } int VisualShaderNodeIs::get_output_port_count() const { - return 1; } VisualShaderNodeIs::PortType VisualShaderNodeIs::get_output_port_type(int p_port) const { - return PORT_TYPE_BOOLEAN; } String VisualShaderNodeIs::get_output_port_name(int p_port) const { - return ""; } String VisualShaderNodeIs::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 { - static const char *funcs[FUNC_IS_NAN + 1] = { "isinf($)", "isnan($)" @@ -3831,25 +4937,21 @@ String VisualShaderNodeIs::generate_code(Shader::Mode p_mode, VisualShader::Type } void VisualShaderNodeIs::set_function(Function p_func) { - func = p_func; emit_changed(); } VisualShaderNodeIs::Function VisualShaderNodeIs::get_function() const { - return func; } Vector<StringName> VisualShaderNodeIs::get_editable_properties() const { - Vector<StringName> props; props.push_back("function"); return props; } void VisualShaderNodeIs::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeIs::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeIs::get_function); @@ -3860,20 +4962,16 @@ void VisualShaderNodeIs::_bind_methods() { } VisualShaderNodeIs::VisualShaderNodeIs() { - - func = FUNC_IS_INF; set_input_port_default_value(0, 0.0); } ////////////// Compare String VisualShaderNodeCompare::get_caption() const { - return "Compare"; } int VisualShaderNodeCompare::get_input_port_count() const { - if (ctype == CTYPE_SCALAR && (func == FUNC_EQUAL || func == FUNC_NOT_EQUAL)) { return 3; } @@ -3881,12 +4979,14 @@ int VisualShaderNodeCompare::get_input_port_count() const { } VisualShaderNodeCompare::PortType VisualShaderNodeCompare::get_input_port_type(int p_port) const { - - if (p_port == 2) + if (p_port == 2) { return PORT_TYPE_SCALAR; + } switch (ctype) { case CTYPE_SCALAR: return PORT_TYPE_SCALAR; + case CTYPE_SCALAR_INT: + return PORT_TYPE_SCALAR_INT; case CTYPE_VECTOR: return PORT_TYPE_VECTOR; case CTYPE_BOOLEAN: @@ -3898,12 +4998,13 @@ VisualShaderNodeCompare::PortType VisualShaderNodeCompare::get_input_port_type(i } String VisualShaderNodeCompare::get_input_port_name(int p_port) const { - if (p_port == 0) + if (p_port == 0) { return "a"; - else if (p_port == 1) + } else if (p_port == 1) { return "b"; - else if (p_port == 2) + } else if (p_port == 2) { return "tolerance"; + } return ""; } @@ -3916,13 +5017,13 @@ VisualShaderNodeCompare::PortType VisualShaderNodeCompare::get_output_port_type( } String VisualShaderNodeCompare::get_output_port_name(int p_port) const { - if (p_port == 0) + if (p_port == 0) { return "result"; + } return ""; } String VisualShaderNodeCompare::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const { - if (ctype == CTYPE_BOOLEAN || ctype == CTYPE_TRANSFORM) { if (func > FUNC_NOT_EQUAL) { return TTR("Invalid comparison function for that type."); @@ -3933,7 +5034,6 @@ String VisualShaderNodeCompare::get_warning(Shader::Mode p_mode, VisualShader::T } String VisualShaderNodeCompare::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 { - static const char *ops[FUNC_LESS_THAN_EQUAL + 1] = { "==", "!=", @@ -3965,10 +5065,14 @@ String VisualShaderNodeCompare::generate_code(Shader::Mode p_mode, VisualShader: } else if (func == FUNC_NOT_EQUAL) { code += "\t" + p_output_vars[0] + " = !(abs(" + p_input_vars[0] + " - " + p_input_vars[1] + ") < " + p_input_vars[2] + ");"; } else { - code += "\t" + p_output_vars[0] + " = " + (p_input_vars[0] + "$" + p_input_vars[1]).replace("$", ops[func]) + ";\n"; + code += "\t" + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n"; } break; + case CTYPE_SCALAR_INT: + code += "\t" + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n"; + break; + case CTYPE_VECTOR: code += "\t{\n"; code += "\t\tbvec3 _bv = " + String(funcs[func]).replace("$", p_input_vars[0] + ", " + p_input_vars[1]) + ";\n"; @@ -3977,14 +5081,16 @@ String VisualShaderNodeCompare::generate_code(Shader::Mode p_mode, VisualShader: break; case CTYPE_BOOLEAN: - if (func > FUNC_NOT_EQUAL) + if (func > FUNC_NOT_EQUAL) { return "\t" + p_output_vars[0] + " = false;\n"; + } code += "\t" + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n"; break; case CTYPE_TRANSFORM: - if (func > FUNC_NOT_EQUAL) + if (func > FUNC_NOT_EQUAL) { return "\t" + p_output_vars[0] + " = false;\n"; + } code += "\t" + p_output_vars[0] + " = " + (p_input_vars[0] + " $ " + p_input_vars[1]).replace("$", ops[func]) + ";\n"; break; @@ -3995,7 +5101,6 @@ String VisualShaderNodeCompare::generate_code(Shader::Mode p_mode, VisualShader: } void VisualShaderNodeCompare::set_comparison_type(ComparisonType p_type) { - ctype = p_type; switch (ctype) { @@ -4004,6 +5109,11 @@ void VisualShaderNodeCompare::set_comparison_type(ComparisonType p_type) { set_input_port_default_value(1, 0.0); simple_decl = true; break; + case CTYPE_SCALAR_INT: + set_input_port_default_value(0, 0); + set_input_port_default_value(1, 0); + simple_decl = true; + break; case CTYPE_VECTOR: set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); @@ -4024,29 +5134,24 @@ void VisualShaderNodeCompare::set_comparison_type(ComparisonType p_type) { } VisualShaderNodeCompare::ComparisonType VisualShaderNodeCompare::get_comparison_type() const { - return ctype; } void VisualShaderNodeCompare::set_function(Function p_func) { - func = p_func; emit_changed(); } VisualShaderNodeCompare::Function VisualShaderNodeCompare::get_function() const { - return func; } void VisualShaderNodeCompare::set_condition(Condition p_cond) { - condition = p_cond; emit_changed(); } VisualShaderNodeCompare::Condition VisualShaderNodeCompare::get_condition() const { - return condition; } @@ -4054,13 +5159,13 @@ Vector<StringName> VisualShaderNodeCompare::get_editable_properties() const { Vector<StringName> props; props.push_back("type"); props.push_back("function"); - if (ctype == CTYPE_VECTOR) + if (ctype == CTYPE_VECTOR) { props.push_back("condition"); + } return props; } void VisualShaderNodeCompare::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_comparison_type", "type"), &VisualShaderNodeCompare::set_comparison_type); ClassDB::bind_method(D_METHOD("get_comparison_type"), &VisualShaderNodeCompare::get_comparison_type); @@ -4070,11 +5175,12 @@ void VisualShaderNodeCompare::_bind_methods() { ClassDB::bind_method(D_METHOD("set_condition", "condition"), &VisualShaderNodeCompare::set_condition); ClassDB::bind_method(D_METHOD("get_condition"), &VisualShaderNodeCompare::get_condition); - ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, "Scalar,Vector,Boolean,Transform"), "set_comparison_type", "get_comparison_type"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, "Float,Int,Vector,Boolean,Transform"), "set_comparison_type", "get_comparison_type"); ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "a == b,a != b,a > b,a >= b,a < b,a <= b"), "set_function", "get_function"); ADD_PROPERTY(PropertyInfo(Variant::INT, "condition", PROPERTY_HINT_ENUM, "All,Any"), "set_condition", "get_condition"); BIND_ENUM_CONSTANT(CTYPE_SCALAR); + BIND_ENUM_CONSTANT(CTYPE_SCALAR_INT); BIND_ENUM_CONSTANT(CTYPE_VECTOR); BIND_ENUM_CONSTANT(CTYPE_BOOLEAN); BIND_ENUM_CONSTANT(CTYPE_TRANSFORM); @@ -4091,10 +5197,99 @@ void VisualShaderNodeCompare::_bind_methods() { } VisualShaderNodeCompare::VisualShaderNodeCompare() { - ctype = CTYPE_SCALAR; - func = FUNC_EQUAL; - condition = COND_ALL; set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); set_input_port_default_value(2, CMP_EPSILON); } + +////////////// Fma + +String VisualShaderNodeMultiplyAdd::get_caption() const { + return "MultiplyAdd"; +} + +int VisualShaderNodeMultiplyAdd::get_input_port_count() const { + return 3; +} + +VisualShaderNodeMultiplyAdd::PortType VisualShaderNodeMultiplyAdd::get_input_port_type(int p_port) const { + if (type == TYPE_SCALAR) { + return PORT_TYPE_SCALAR; + } + return PORT_TYPE_VECTOR; +} + +String VisualShaderNodeMultiplyAdd::get_input_port_name(int p_port) const { + if (p_port == 0) { + return "a"; + } else if (p_port == 1) { + return "b(*)"; + } else if (p_port == 2) { + return "c(+)"; + } + return ""; +} + +int VisualShaderNodeMultiplyAdd::get_output_port_count() const { + return 1; +} + +VisualShaderNodeMultiplyAdd::PortType VisualShaderNodeMultiplyAdd::get_output_port_type(int p_port) const { + if (type == TYPE_SCALAR) { + return PORT_TYPE_SCALAR; + } else { + return PORT_TYPE_VECTOR; + } +} + +String VisualShaderNodeMultiplyAdd::get_output_port_name(int p_port) const { + return ""; +} + +String VisualShaderNodeMultiplyAdd::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 { + return "\t" + p_output_vars[0] + " = fma(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n"; +} + +void VisualShaderNodeMultiplyAdd::set_type(Type p_type) { + ERR_FAIL_INDEX((int)p_type, TYPE_MAX); + if (p_type != type) { + if (p_type == TYPE_SCALAR) { + set_input_port_default_value(0, 0.0); + set_input_port_default_value(1, 0.0); + set_input_port_default_value(2, 0.0); + } else { + set_input_port_default_value(0, Vector3(0.0, 0.0, 0.0)); + set_input_port_default_value(1, Vector3(0.0, 0.0, 0.0)); + set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); + } + } + type = p_type; + emit_changed(); +} + +VisualShaderNodeMultiplyAdd::Type VisualShaderNodeMultiplyAdd::get_type() const { + return type; +} + +Vector<StringName> VisualShaderNodeMultiplyAdd::get_editable_properties() const { + Vector<StringName> props; + props.push_back("type"); + return props; +} + +void VisualShaderNodeMultiplyAdd::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_type", "type"), &VisualShaderNodeMultiplyAdd::set_type); + ClassDB::bind_method(D_METHOD("get_type"), &VisualShaderNodeMultiplyAdd::get_type); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, "Scalar,Vector"), "set_type", "get_type"); + + BIND_ENUM_CONSTANT(TYPE_SCALAR); + BIND_ENUM_CONSTANT(TYPE_VECTOR); + BIND_ENUM_CONSTANT(TYPE_MAX); +} + +VisualShaderNodeMultiplyAdd::VisualShaderNodeMultiplyAdd() { + set_input_port_default_value(0, 0.0); + set_input_port_default_value(1, 0.0); + set_input_port_default_value(2, 0.0); +} diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index cca37273d9..1c986d1ef4 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -37,60 +37,90 @@ /// CONSTANTS /////////////////////////////////////// -class VisualShaderNodeScalarConstant : public VisualShaderNode { - GDCLASS(VisualShaderNodeScalarConstant, VisualShaderNode); - float constant; +class VisualShaderNodeFloatConstant : public VisualShaderNode { + GDCLASS(VisualShaderNodeFloatConstant, VisualShaderNode); + float constant = 0.0f; protected: static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_constant(float p_value); float get_constant() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; - VisualShaderNodeScalarConstant(); + VisualShaderNodeFloatConstant(); +}; + +/////////////////////////////////////// + +class VisualShaderNodeIntConstant : public VisualShaderNode { + GDCLASS(VisualShaderNodeIntConstant, VisualShaderNode); + int constant = 0; + +protected: + static void _bind_methods(); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + + void set_constant(int p_value); + int get_constant() const; + + virtual Vector<StringName> get_editable_properties() const override; + + VisualShaderNodeIntConstant(); }; /////////////////////////////////////// class VisualShaderNodeBooleanConstant : public VisualShaderNode { GDCLASS(VisualShaderNodeBooleanConstant, VisualShaderNode); - bool constant; + bool constant = false; protected: static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_constant(bool p_value); bool get_constant() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeBooleanConstant(); }; @@ -99,28 +129,28 @@ public: class VisualShaderNodeColorConstant : public VisualShaderNode { GDCLASS(VisualShaderNodeColorConstant, VisualShaderNode); - Color constant; + Color constant = Color(1, 1, 1, 1); protected: static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_constant(Color p_value); Color get_constant() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeColorConstant(); }; @@ -135,22 +165,22 @@ protected: static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_constant(Vector3 p_value); Vector3 get_constant() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeVec3Constant(); }; @@ -165,22 +195,22 @@ protected: static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_constant(Transform p_value); Transform get_constant() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeTransformConstant(); }; @@ -191,7 +221,7 @@ public: class VisualShaderNodeTexture : public VisualShaderNode { GDCLASS(VisualShaderNodeTexture, VisualShaderNode); - Ref<Texture> texture; + Ref<Texture2D> texture; public: enum Source { @@ -206,45 +236,45 @@ public: enum TextureType { TYPE_DATA, TYPE_COLOR, - TYPE_NORMALMAP + TYPE_NORMALMAP, }; private: - Source source; - TextureType texture_type; + Source source = SOURCE_TEXTURE; + TextureType texture_type = TYPE_DATA; protected: static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const; + virtual String get_input_port_default_hint(int p_port) const override; - virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const; - virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; - 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_source(Source p_source); Source get_source() const; - void set_texture(Ref<Texture> p_value); - Ref<Texture> get_texture() const; + void set_texture(Ref<Texture2D> p_value); + Ref<Texture2D> get_texture() const; void set_texture_type(TextureType p_type); TextureType get_texture_type() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; - virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const; + virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override; VisualShaderNodeTexture(); }; @@ -254,9 +284,91 @@ VARIANT_ENUM_CAST(VisualShaderNodeTexture::Source) /////////////////////////////////////// -class VisualShaderNodeCubeMap : public VisualShaderNode { - GDCLASS(VisualShaderNodeCubeMap, VisualShaderNode); - Ref<CubeMap> cube_map; +class VisualShaderNodeSample3D : public VisualShaderNode { + GDCLASS(VisualShaderNodeSample3D, VisualShaderNode); + +public: + enum Source { + SOURCE_TEXTURE, + SOURCE_PORT, + }; + +protected: + Source source = SOURCE_TEXTURE; + + static void _bind_methods(); + +public: + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + virtual String get_input_port_default_hint(int p_port) const override; + + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + + void set_source(Source p_source); + Source get_source() const; + + virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override; + + VisualShaderNodeSample3D(); +}; + +VARIANT_ENUM_CAST(VisualShaderNodeSample3D::Source) + +class VisualShaderNodeTexture2DArray : public VisualShaderNodeSample3D { + GDCLASS(VisualShaderNodeTexture2DArray, VisualShaderNodeSample3D); + Ref<Texture2DArray> texture; + +protected: + static void _bind_methods(); + +public: + virtual String get_caption() const override; + + virtual String get_input_port_name(int p_port) const override; + + virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override; + virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; + + void set_texture_array(Ref<Texture2DArray> p_value); + Ref<Texture2DArray> get_texture_array() const; + + virtual Vector<StringName> get_editable_properties() const override; + + VisualShaderNodeTexture2DArray(); +}; + +class VisualShaderNodeTexture3D : public VisualShaderNodeSample3D { + GDCLASS(VisualShaderNodeTexture3D, VisualShaderNodeSample3D); + Ref<Texture3D> texture; + +protected: + static void _bind_methods(); + +public: + virtual String get_caption() const override; + + virtual String get_input_port_name(int p_port) const override; + + virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override; + virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; + + void set_texture(Ref<Texture3D> p_value); + Ref<Texture3D> get_texture() const; + + virtual Vector<StringName> get_editable_properties() const override; + + VisualShaderNodeTexture3D(); +}; + +class VisualShaderNodeCubemap : public VisualShaderNode { + GDCLASS(VisualShaderNodeCubemap, VisualShaderNode); + Ref<Cubemap> cube_map; public: enum Source { @@ -271,51 +383,51 @@ public: }; private: - Source source; - TextureType texture_type; + Source source = SOURCE_TEXTURE; + TextureType texture_type = TYPE_DATA; protected: static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; - virtual String get_input_port_default_hint(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + virtual String get_input_port_default_hint(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; - virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const; - virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; - 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_source(Source p_source); Source get_source() const; - void set_cube_map(Ref<CubeMap> p_value); - Ref<CubeMap> get_cube_map() const; + void set_cube_map(Ref<Cubemap> p_value); + Ref<Cubemap> get_cube_map() const; void set_texture_type(TextureType p_type); TextureType get_texture_type() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; - VisualShaderNodeCubeMap(); + VisualShaderNodeCubemap(); }; -VARIANT_ENUM_CAST(VisualShaderNodeCubeMap::TextureType) -VARIANT_ENUM_CAST(VisualShaderNodeCubeMap::Source) +VARIANT_ENUM_CAST(VisualShaderNodeCubemap::TextureType) +VARIANT_ENUM_CAST(VisualShaderNodeCubemap::Source) /////////////////////////////////////// /// OPS /////////////////////////////////////// -class VisualShaderNodeScalarOp : public VisualShaderNode { - GDCLASS(VisualShaderNodeScalarOp, VisualShaderNode); +class VisualShaderNodeFloatOp : public VisualShaderNode { + GDCLASS(VisualShaderNodeFloatOp, VisualShaderNode); public: enum Operator { @@ -332,32 +444,74 @@ public: }; protected: - Operator op; + Operator op = OP_ADD; static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_operator(Operator p_op); Operator get_operator() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; - VisualShaderNodeScalarOp(); + VisualShaderNodeFloatOp(); }; -VARIANT_ENUM_CAST(VisualShaderNodeScalarOp::Operator) +VARIANT_ENUM_CAST(VisualShaderNodeFloatOp::Operator) + +class VisualShaderNodeIntOp : public VisualShaderNode { + GDCLASS(VisualShaderNodeIntOp, VisualShaderNode); + +public: + enum Operator { + OP_ADD, + OP_SUB, + OP_MUL, + OP_DIV, + OP_MOD, + OP_MAX, + OP_MIN, + }; + +protected: + Operator op = OP_ADD; + + static void _bind_methods(); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + + void set_operator(Operator p_op); + Operator get_operator() const; + + virtual Vector<StringName> get_editable_properties() const override; + + VisualShaderNodeIntOp(); +}; + +VARIANT_ENUM_CAST(VisualShaderNodeIntOp::Operator) class VisualShaderNodeVectorOp : public VisualShaderNode { GDCLASS(VisualShaderNodeVectorOp, VisualShaderNode); @@ -379,27 +533,27 @@ public: }; protected: - Operator op; + Operator op = OP_ADD; static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_operator(Operator p_op); Operator get_operator() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeVectorOp(); }; @@ -425,27 +579,27 @@ public: }; protected: - Operator op; + Operator op = OP_SCREEN; static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_operator(Operator p_op); Operator get_operator() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeColorOp(); }; @@ -468,27 +622,27 @@ public: }; protected: - Operator op; + Operator op = OP_AxB; static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_operator(Operator p_op); Operator get_operator() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeTransformMult(); }; @@ -511,27 +665,27 @@ public: }; protected: - Operator op; + Operator op = OP_AxB; static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_operator(Operator p_op); Operator get_operator() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeTransformVecMult(); }; @@ -539,11 +693,11 @@ public: VARIANT_ENUM_CAST(VisualShaderNodeTransformVecMult::Operator) /////////////////////////////////////// -/// SCALAR FUNC +/// FLOAT FUNC /////////////////////////////////////// -class VisualShaderNodeScalarFunc : public VisualShaderNode { - GDCLASS(VisualShaderNodeScalarFunc, VisualShaderNode); +class VisualShaderNodeFloatFunc : public VisualShaderNode { + GDCLASS(VisualShaderNodeFloatFunc, VisualShaderNode); public: enum Function { @@ -582,32 +736,75 @@ public: }; protected: - Function func; + Function func = FUNC_SIGN; static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_function(Function p_func); Function get_function() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; - VisualShaderNodeScalarFunc(); + VisualShaderNodeFloatFunc(); }; -VARIANT_ENUM_CAST(VisualShaderNodeScalarFunc::Function) +VARIANT_ENUM_CAST(VisualShaderNodeFloatFunc::Function) + +/////////////////////////////////////// +/// INT FUNC +/////////////////////////////////////// + +class VisualShaderNodeIntFunc : public VisualShaderNode { + GDCLASS(VisualShaderNodeIntFunc, VisualShaderNode); + +public: + enum Function { + FUNC_ABS, + FUNC_CLAMP, + FUNC_NEGATE, + FUNC_SIGN, + }; + +protected: + Function func = FUNC_SIGN; + + static void _bind_methods(); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + + void set_function(Function p_func); + Function get_function() const; + + virtual Vector<StringName> get_editable_properties() const override; + + VisualShaderNodeIntFunc(); +}; + +VARIANT_ENUM_CAST(VisualShaderNodeIntFunc::Function) /////////////////////////////////////// /// VECTOR FUNC @@ -656,27 +853,27 @@ public: }; protected: - Function func; + Function func = FUNC_NORMALIZE; static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_function(Function p_func); Function get_function() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeVectorFunc(); }; @@ -697,27 +894,27 @@ public: }; protected: - Function func; + Function func = FUNC_GRAYSCALE; static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_function(Function p_func); Function get_function() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeColorFunc(); }; @@ -738,27 +935,27 @@ public: }; protected: - Function func; + Function func = FUNC_INVERSE; static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_function(Function p_func); Function get_function() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeTransformFunc(); }; @@ -773,17 +970,17 @@ class VisualShaderNodeDotProduct : public VisualShaderNode { GDCLASS(VisualShaderNodeDotProduct, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeDotProduct(); }; @@ -796,17 +993,17 @@ class VisualShaderNodeVectorLen : public VisualShaderNode { GDCLASS(VisualShaderNodeVectorLen, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeVectorLen(); }; @@ -819,17 +1016,17 @@ class VisualShaderNodeDeterminant : public VisualShaderNode { GDCLASS(VisualShaderNodeDeterminant, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeDeterminant(); }; @@ -842,17 +1039,17 @@ class VisualShaderNodeScalarClamp : public VisualShaderNode { GDCLASS(VisualShaderNodeScalarClamp, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeScalarClamp(); }; @@ -863,17 +1060,17 @@ class VisualShaderNodeVectorClamp : public VisualShaderNode { GDCLASS(VisualShaderNodeVectorClamp, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeVectorClamp(); }; @@ -893,27 +1090,27 @@ public: }; protected: - Function func; + Function func = FUNC_SUM; static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_function(Function p_func); Function get_function() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeScalarDerivativeFunc(); }; @@ -933,27 +1130,27 @@ public: }; protected: - Function func; + Function func = FUNC_SUM; static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_function(Function p_func); Function get_function() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeVectorDerivativeFunc(); }; @@ -968,17 +1165,17 @@ class VisualShaderNodeFaceForward : public VisualShaderNode { GDCLASS(VisualShaderNodeFaceForward, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeFaceForward(); }; @@ -991,17 +1188,17 @@ class VisualShaderNodeOuterProduct : public VisualShaderNode { GDCLASS(VisualShaderNodeOuterProduct, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeOuterProduct(); }; @@ -1014,17 +1211,17 @@ class VisualShaderNodeVectorScalarStep : public VisualShaderNode { GDCLASS(VisualShaderNodeVectorScalarStep, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeVectorScalarStep(); }; @@ -1037,17 +1234,17 @@ class VisualShaderNodeScalarSmoothStep : public VisualShaderNode { GDCLASS(VisualShaderNodeScalarSmoothStep, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeScalarSmoothStep(); }; @@ -1058,17 +1255,17 @@ class VisualShaderNodeVectorSmoothStep : public VisualShaderNode { GDCLASS(VisualShaderNodeVectorSmoothStep, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeVectorSmoothStep(); }; @@ -1079,17 +1276,17 @@ class VisualShaderNodeVectorScalarSmoothStep : public VisualShaderNode { GDCLASS(VisualShaderNodeVectorScalarSmoothStep, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeVectorScalarSmoothStep(); }; @@ -1102,17 +1299,17 @@ class VisualShaderNodeVectorDistance : public VisualShaderNode { GDCLASS(VisualShaderNodeVectorDistance, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeVectorDistance(); }; @@ -1125,17 +1322,17 @@ class VisualShaderNodeVectorRefract : public VisualShaderNode { GDCLASS(VisualShaderNodeVectorRefract, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeVectorRefract(); }; @@ -1148,17 +1345,17 @@ class VisualShaderNodeScalarInterp : public VisualShaderNode { GDCLASS(VisualShaderNodeScalarInterp, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeScalarInterp(); }; @@ -1169,17 +1366,17 @@ class VisualShaderNodeVectorInterp : public VisualShaderNode { GDCLASS(VisualShaderNodeVectorInterp, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeVectorInterp(); }; @@ -1190,17 +1387,17 @@ class VisualShaderNodeVectorScalarMix : public VisualShaderNode { GDCLASS(VisualShaderNodeVectorScalarMix, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeVectorScalarMix(); }; @@ -1213,17 +1410,17 @@ class VisualShaderNodeVectorCompose : public VisualShaderNode { GDCLASS(VisualShaderNodeVectorCompose, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeVectorCompose(); }; @@ -1234,17 +1431,17 @@ class VisualShaderNodeTransformCompose : public VisualShaderNode { GDCLASS(VisualShaderNodeTransformCompose, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeTransformCompose(); }; @@ -1257,17 +1454,17 @@ class VisualShaderNodeVectorDecompose : public VisualShaderNode { GDCLASS(VisualShaderNodeVectorDecompose, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeVectorDecompose(); }; @@ -1278,17 +1475,17 @@ class VisualShaderNodeTransformDecompose : public VisualShaderNode { GDCLASS(VisualShaderNodeTransformDecompose, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeTransformDecompose(); }; @@ -1297,44 +1494,174 @@ public: /// UNIFORMS /////////////////////////////////////// -class VisualShaderNodeScalarUniform : public VisualShaderNodeUniform { - GDCLASS(VisualShaderNodeScalarUniform, VisualShaderNodeUniform); +class VisualShaderNodeFloatUniform : public VisualShaderNodeUniform { + GDCLASS(VisualShaderNodeFloatUniform, VisualShaderNodeUniform); public: - virtual String get_caption() const; + enum Hint { + HINT_NONE, + HINT_RANGE, + HINT_RANGE_STEP, + }; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; +private: + Hint hint = HINT_NONE; + float hint_range_min = 0.0f; + float hint_range_max = 1.0f; + float hint_range_step = 0.1f; + bool default_value_enabled = false; + float default_value = 0.0f; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; +protected: + static void _bind_methods(); - virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; - 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + + virtual bool is_show_prop_names() const override; + virtual bool is_use_prop_slots() const override; + + void set_hint(Hint p_hint); + Hint get_hint() const; + + void set_min(float p_value); + float get_min() const; + + void set_max(float p_value); + float get_max() const; - VisualShaderNodeScalarUniform(); + void set_step(float p_value); + float get_step() const; + + void set_default_value_enabled(bool p_enabled); + bool is_default_value_enabled() const; + + void set_default_value(float p_value); + float get_default_value() const; + + bool is_qualifier_supported(Qualifier p_qual) const override; + + virtual Vector<StringName> get_editable_properties() const override; + + VisualShaderNodeFloatUniform(); }; +VARIANT_ENUM_CAST(VisualShaderNodeFloatUniform::Hint) + +class VisualShaderNodeIntUniform : public VisualShaderNodeUniform { + GDCLASS(VisualShaderNodeIntUniform, VisualShaderNodeUniform); + +public: + enum Hint { + HINT_NONE, + HINT_RANGE, + HINT_RANGE_STEP, + }; + +private: + Hint hint = HINT_NONE; + int hint_range_min = 0; + int hint_range_max = 100; + int hint_range_step = 1; + bool default_value_enabled = false; + int default_value = 0; + +protected: + static void _bind_methods(); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + + virtual bool is_show_prop_names() const override; + virtual bool is_use_prop_slots() const override; + + void set_hint(Hint p_hint); + Hint get_hint() const; + + void set_min(int p_value); + int get_min() const; + + void set_max(int p_value); + int get_max() const; + + void set_step(int p_value); + int get_step() const; + + void set_default_value_enabled(bool p_enabled); + bool is_default_value_enabled() const; + + void set_default_value(int p_value); + int get_default_value() const; + + bool is_qualifier_supported(Qualifier p_qual) const override; + + virtual Vector<StringName> get_editable_properties() const override; + + VisualShaderNodeIntUniform(); +}; + +VARIANT_ENUM_CAST(VisualShaderNodeIntUniform::Hint) + /////////////////////////////////////// class VisualShaderNodeBooleanUniform : public VisualShaderNodeUniform { GDCLASS(VisualShaderNodeBooleanUniform, VisualShaderNodeUniform); +private: + bool default_value_enabled = false; + bool default_value = false; + +protected: + static void _bind_methods(); + public: - virtual String get_caption() const; + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty - virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; - 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual bool is_show_prop_names() const override; + virtual bool is_use_prop_slots() const override; + + void set_default_value_enabled(bool p_enabled); + bool is_default_value_enabled() const; + + void set_default_value(bool p_value); + bool get_default_value() const; + + bool is_qualifier_supported(Qualifier p_qual) const override; + + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeBooleanUniform(); }; @@ -1344,19 +1671,38 @@ public: class VisualShaderNodeColorUniform : public VisualShaderNodeUniform { GDCLASS(VisualShaderNodeColorUniform, VisualShaderNodeUniform); +private: + bool default_value_enabled = false; + Color default_value = Color(1.0, 1.0, 1.0, 1.0); + +protected: + static void _bind_methods(); + public: - virtual String get_caption() const; + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual bool is_show_prop_names() const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + void set_default_value_enabled(bool p_enabled); + bool is_default_value_enabled() const; - virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; - 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + void set_default_value(const Color &p_value); + Color get_default_value() const; + + bool is_qualifier_supported(Qualifier p_qual) const override; + + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeColorUniform(); }; @@ -1366,19 +1712,39 @@ public: class VisualShaderNodeVec3Uniform : public VisualShaderNodeUniform { GDCLASS(VisualShaderNodeVec3Uniform, VisualShaderNodeUniform); +private: + bool default_value_enabled = false; + Vector3 default_value; + +protected: + static void _bind_methods(); + public: - virtual String get_caption() const; + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + + virtual bool is_show_prop_names() const override; + virtual bool is_use_prop_slots() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + void set_default_value_enabled(bool p_enabled); + bool is_default_value_enabled() const; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + void set_default_value(const Vector3 &p_value); + Vector3 get_default_value() const; - virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; - 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + bool is_qualifier_supported(Qualifier p_qual) const override; + + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeVec3Uniform(); }; @@ -1388,19 +1754,39 @@ public: class VisualShaderNodeTransformUniform : public VisualShaderNodeUniform { GDCLASS(VisualShaderNodeTransformUniform, VisualShaderNodeUniform); +private: + bool default_value_enabled = false; + Transform default_value = Transform(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0); + +protected: + static void _bind_methods(); + public: - virtual String get_caption() const; + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty - virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; - 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual bool is_show_prop_names() const override; + virtual bool is_use_prop_slots() const override; + + void set_default_value_enabled(bool p_enabled); + bool is_default_value_enabled() const; + + void set_default_value(const Transform &p_value); + Transform get_default_value() const; + + bool is_qualifier_supported(Qualifier p_qual) const override; + + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeTransformUniform(); }; @@ -1424,28 +1810,30 @@ public: }; protected: - TextureType texture_type; - ColorDefault color_default; + TextureType texture_type = TYPE_DATA; + ColorDefault color_default = COLOR_DEFAULT_WHITE; protected: static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; - virtual String get_input_port_default_hint(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + virtual String get_input_port_default_hint(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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; - 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty - Vector<StringName> get_editable_properties() const; + virtual bool is_code_generated() const override; + + Vector<StringName> get_editable_properties() const override; void set_texture_type(TextureType p_type); TextureType get_texture_type() const; @@ -1453,6 +1841,8 @@ public: void set_color_default(ColorDefault p_default); ColorDefault get_color_default() const; + bool is_qualifier_supported(Qualifier p_qual) const override; + VisualShaderNodeTextureUniform(); }; @@ -1465,42 +1855,88 @@ class VisualShaderNodeTextureUniformTriplanar : public VisualShaderNodeTextureUn GDCLASS(VisualShaderNodeTextureUniformTriplanar, VisualShaderNodeTextureUniform); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const; + virtual String get_input_port_default_hint(int p_port) const override; - virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; - virtual String generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; - 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; + virtual String generate_global_per_func(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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty VisualShaderNodeTextureUniformTriplanar(); }; /////////////////////////////////////// -class VisualShaderNodeCubeMapUniform : public VisualShaderNodeTextureUniform { - GDCLASS(VisualShaderNodeCubeMapUniform, VisualShaderNodeTextureUniform); +class VisualShaderNodeTexture2DArrayUniform : public VisualShaderNodeTextureUniform { + GDCLASS(VisualShaderNodeTexture2DArrayUniform, VisualShaderNodeTextureUniform); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; + + virtual String get_input_port_default_hint(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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + + VisualShaderNodeTexture2DArrayUniform(); +}; + +/////////////////////////////////////// + +class VisualShaderNodeTexture3DUniform : public VisualShaderNodeTextureUniform { + GDCLASS(VisualShaderNodeTexture3DUniform, VisualShaderNodeTextureUniform); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const; - virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; - 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + virtual String get_input_port_default_hint(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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty - VisualShaderNodeCubeMapUniform(); + VisualShaderNodeTexture3DUniform(); +}; + +/////////////////////////////////////// + +class VisualShaderNodeCubemapUniform : public VisualShaderNodeTextureUniform { + GDCLASS(VisualShaderNodeCubemapUniform, VisualShaderNodeTextureUniform); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; + + virtual String get_input_port_default_hint(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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + + VisualShaderNodeCubemapUniform(); }; /////////////////////////////////////// @@ -1511,17 +1947,17 @@ class VisualShaderNodeIf : public VisualShaderNode { GDCLASS(VisualShaderNodeIf, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; + 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; VisualShaderNodeIf(); }; @@ -1534,17 +1970,17 @@ class VisualShaderNodeSwitch : public VisualShaderNode { GDCLASS(VisualShaderNodeSwitch, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; + 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; VisualShaderNodeSwitch(); }; @@ -1553,10 +1989,10 @@ class VisualShaderNodeScalarSwitch : public VisualShaderNodeSwitch { GDCLASS(VisualShaderNodeScalarSwitch, VisualShaderNodeSwitch); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual PortType get_input_port_type(int p_port) const; - virtual PortType get_output_port_type(int p_port) const; + virtual PortType get_input_port_type(int p_port) const override; + virtual PortType get_output_port_type(int p_port) const override; VisualShaderNodeScalarSwitch(); }; @@ -1569,18 +2005,19 @@ class VisualShaderNodeFresnel : public VisualShaderNode { GDCLASS(VisualShaderNodeFresnel, VisualShaderNode); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const; - 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; + virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_generate_input_var(int p_port) 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; VisualShaderNodeFresnel(); }; @@ -1599,28 +2036,28 @@ public: }; protected: - Function func; + Function func = FUNC_IS_INF; protected: static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_function(Function p_func); Function get_function() const; - virtual Vector<StringName> get_editable_properties() const; + virtual Vector<StringName> get_editable_properties() const override; VisualShaderNodeIs(); }; @@ -1637,9 +2074,10 @@ class VisualShaderNodeCompare : public VisualShaderNode { public: enum ComparisonType { CTYPE_SCALAR, + CTYPE_SCALAR_INT, CTYPE_VECTOR, CTYPE_BOOLEAN, - CTYPE_TRANSFORM + CTYPE_TRANSFORM, }; enum Function { @@ -1657,25 +2095,25 @@ public: }; protected: - ComparisonType ctype; - Function func; - Condition condition; + ComparisonType ctype = CTYPE_SCALAR; + Function func = FUNC_EQUAL; + Condition condition = COND_ALL; protected: static void _bind_methods(); public: - virtual String get_caption() const; + virtual String get_caption() const override; - virtual int get_input_port_count() const; - virtual PortType get_input_port_type(int p_port) const; - virtual String get_input_port_name(int p_port) const; + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; - virtual int get_output_port_count() const; - virtual PortType get_output_port_type(int p_port) const; - virtual String get_output_port_name(int p_port) const; + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + 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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty void set_comparison_type(ComparisonType p_type); ComparisonType get_comparison_type() const; @@ -1686,8 +2124,8 @@ public: void set_condition(Condition p_cond); Condition get_condition() const; - virtual Vector<StringName> get_editable_properties() const; - virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const; + virtual Vector<StringName> get_editable_properties() const override; + virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override; VisualShaderNodeCompare(); }; @@ -1696,4 +2134,43 @@ VARIANT_ENUM_CAST(VisualShaderNodeCompare::ComparisonType) VARIANT_ENUM_CAST(VisualShaderNodeCompare::Function) VARIANT_ENUM_CAST(VisualShaderNodeCompare::Condition) +class VisualShaderNodeMultiplyAdd : public VisualShaderNode { + GDCLASS(VisualShaderNodeMultiplyAdd, VisualShaderNode); + +public: + enum Type { + TYPE_SCALAR, + TYPE_VECTOR, + TYPE_MAX, + }; + +protected: + Type type = TYPE_SCALAR; + +protected: + static void _bind_methods(); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + 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_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; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + + void set_type(Type p_type); + Type get_type() const; + + virtual Vector<StringName> get_editable_properties() const override; + + VisualShaderNodeMultiplyAdd(); +}; + +VARIANT_ENUM_CAST(VisualShaderNodeMultiplyAdd::Type) + #endif // VISUAL_SHADER_NODES_H diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index 5cc809d8e3..d2bc2bea31 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -33,14 +33,12 @@ #include "core/project_settings.h" #include "scene/2d/camera_2d.h" #include "scene/2d/visibility_notifier_2d.h" -#include "scene/main/viewport.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "scene/main/window.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" struct SpatialIndexer2D { - struct CellRef { - int ref; _FORCE_INLINE_ int inc() { @@ -58,7 +56,6 @@ struct SpatialIndexer2D { }; struct CellKey { - union { struct { int32_t x; @@ -74,7 +71,6 @@ struct SpatialIndexer2D { }; struct CellData { - Map<VisibilityNotifier2D *, CellRef> notifiers; }; @@ -84,7 +80,6 @@ struct SpatialIndexer2D { Map<VisibilityNotifier2D *, Rect2> notifiers; struct ViewportData { - Map<VisibilityNotifier2D *, uint64_t> notifiers; Rect2 rect; }; @@ -96,30 +91,25 @@ struct SpatialIndexer2D { uint64_t pass; void _notifier_update_cells(VisibilityNotifier2D *p_notifier, const Rect2 &p_rect, bool p_add) { - Point2i begin = p_rect.position; begin /= cell_size; Point2i end = p_rect.position + p_rect.size; end /= cell_size; for (int i = begin.x; i <= end.x; i++) { - for (int j = begin.y; j <= end.y; j++) { - CellKey ck; ck.x = i; ck.y = j; Map<CellKey, CellData>::Element *E = cells.find(ck); if (p_add) { - - if (!E) + if (!E) { E = cells.insert(ck, CellData()); + } E->get().notifiers[p_notifier].inc(); } else { - ERR_CONTINUE(!E); if (E->get().notifiers[p_notifier].dec() == 0) { - E->get().notifiers.erase(p_notifier); if (E->get().notifiers.empty()) { cells.erase(E); @@ -131,7 +121,6 @@ struct SpatialIndexer2D { } void _notifier_add(VisibilityNotifier2D *p_notifier, const Rect2 &p_rect) { - ERR_FAIL_COND(notifiers.has(p_notifier)); notifiers[p_notifier] = p_rect; _notifier_update_cells(p_notifier, p_rect, true); @@ -139,11 +128,11 @@ struct SpatialIndexer2D { } void _notifier_update(VisibilityNotifier2D *p_notifier, const Rect2 &p_rect) { - Map<VisibilityNotifier2D *, Rect2>::Element *E = notifiers.find(p_notifier); ERR_FAIL_COND(!E); - if (E->get() == p_rect) + if (E->get() == p_rect) { return; + } _notifier_update_cells(p_notifier, p_rect, true); _notifier_update_cells(p_notifier, E->get(), false); @@ -152,7 +141,6 @@ struct SpatialIndexer2D { } void _notifier_remove(VisibilityNotifier2D *p_notifier) { - Map<VisibilityNotifier2D *, Rect2>::Element *E = notifiers.find(p_notifier); ERR_FAIL_COND(!E); _notifier_update_cells(p_notifier, E->get(), false); @@ -160,7 +148,6 @@ struct SpatialIndexer2D { List<Viewport *> removed; for (Map<Viewport *, ViewportData>::Element *F = viewports.front(); F; F = F->next()) { - Map<VisibilityNotifier2D *, uint64_t>::Element *G = F->get().notifiers.find(p_notifier); if (G) { @@ -170,7 +157,6 @@ struct SpatialIndexer2D { } while (!removed.empty()) { - p_notifier->_exit_viewport(removed.front()->get()); removed.pop_front(); } @@ -179,7 +165,6 @@ struct SpatialIndexer2D { } void _add_viewport(Viewport *p_viewport, const Rect2 &p_rect) { - ERR_FAIL_COND(viewports.has(p_viewport)); ViewportData vd; vd.rect = p_rect; @@ -188,11 +173,11 @@ struct SpatialIndexer2D { } void _update_viewport(Viewport *p_viewport, const Rect2 &p_rect) { - Map<Viewport *, ViewportData>::Element *E = viewports.find(p_viewport); ERR_FAIL_COND(!E); - if (E->get().rect == p_rect) + if (E->get().rect == p_rect) { return; + } E->get().rect = p_rect; changed = true; } @@ -201,7 +186,6 @@ struct SpatialIndexer2D { ERR_FAIL_COND(!viewports.has(p_viewport)); List<VisibilityNotifier2D *> removed; for (Map<VisibilityNotifier2D *, uint64_t>::Element *E = viewports[p_viewport].notifiers.front(); E; E = E->next()) { - removed.push_back(E->key()); } @@ -214,12 +198,11 @@ struct SpatialIndexer2D { } void _update() { - - if (!changed) + if (!changed) { return; + } for (Map<Viewport *, ViewportData>::Element *E = viewports.front(); E; E = E->next()) { - Point2i begin = E->get().rect.position; begin /= cell_size; Point2i end = E->get().rect.position + E->get().rect.size; @@ -228,27 +211,25 @@ struct SpatialIndexer2D { List<VisibilityNotifier2D *> added; List<VisibilityNotifier2D *> removed; - int visible_cells = (end.x - begin.x) * (end.y - begin.y); + uint64_t visible_cells = (uint64_t)(end.x - begin.x) * (uint64_t)(end.y - begin.y); if (visible_cells > 10000) { - //well you zoomed out a lot, it's your problem. To avoid freezing in the for loops below, we'll manually check cell by cell for (Map<CellKey, CellData>::Element *F = cells.front(); F; F = F->next()) { - const CellKey &ck = F->key(); - if (ck.x < begin.x || ck.x > end.x) + if (ck.x < begin.x || ck.x > end.x) { continue; - if (ck.y < begin.y || ck.y > end.y) + } + if (ck.y < begin.y || ck.y > end.y) { continue; + } //notifiers in cell for (Map<VisibilityNotifier2D *, CellRef>::Element *G = F->get().notifiers.front(); G; G = G->next()) { - Map<VisibilityNotifier2D *, uint64_t>::Element *H = E->get().notifiers.find(G->key()); if (!H) { - H = E->get().notifiers.insert(G->key(), pass); added.push_back(G->key()); } else { @@ -258,12 +239,9 @@ struct SpatialIndexer2D { } } else { - //check cells in grid fashion for (int i = begin.x; i <= end.x; i++) { - for (int j = begin.y; j <= end.y; j++) { - CellKey ck; ck.x = i; ck.y = j; @@ -275,10 +253,8 @@ struct SpatialIndexer2D { //notifiers in cell for (Map<VisibilityNotifier2D *, CellRef>::Element *G = F->get().notifiers.front(); G; G = G->next()) { - Map<VisibilityNotifier2D *, uint64_t>::Element *H = E->get().notifiers.find(G->key()); if (!H) { - H = E->get().notifiers.insert(G->key(), pass); added.push_back(G->key()); } else { @@ -290,9 +266,9 @@ struct SpatialIndexer2D { } for (Map<VisibilityNotifier2D *, uint64_t>::Element *F = E->get().notifiers.front(); F; F = F->next()) { - - if (F->get() != pass) + if (F->get() != pass) { removed.push_back(F->key()); + } } while (!added.empty()) { @@ -311,64 +287,55 @@ struct SpatialIndexer2D { } SpatialIndexer2D() { - pass = 0; changed = false; - cell_size = 100; //should be configurable with GLOBAL_DEF("") i guess + cell_size = GLOBAL_DEF("world/2d/cell_size", 100); } }; void World2D::_register_viewport(Viewport *p_viewport, const Rect2 &p_rect) { - indexer->_add_viewport(p_viewport, p_rect); } void World2D::_update_viewport(Viewport *p_viewport, const Rect2 &p_rect) { - indexer->_update_viewport(p_viewport, p_rect); } -void World2D::_remove_viewport(Viewport *p_viewport) { +void World2D::_remove_viewport(Viewport *p_viewport) { indexer->_remove_viewport(p_viewport); } void World2D::_register_notifier(VisibilityNotifier2D *p_notifier, const Rect2 &p_rect) { - indexer->_notifier_add(p_notifier, p_rect); } -void World2D::_update_notifier(VisibilityNotifier2D *p_notifier, const Rect2 &p_rect) { +void World2D::_update_notifier(VisibilityNotifier2D *p_notifier, const Rect2 &p_rect) { indexer->_notifier_update(p_notifier, p_rect); } -void World2D::_remove_notifier(VisibilityNotifier2D *p_notifier) { +void World2D::_remove_notifier(VisibilityNotifier2D *p_notifier) { indexer->_notifier_remove(p_notifier); } void World2D::_update() { - indexer->_update(); } RID World2D::get_canvas() { - return canvas; } RID World2D::get_space() { - return space; } void World2D::get_viewport_list(List<Viewport *> *r_viewports) { - for (Map<Viewport *, SpatialIndexer2D::ViewportData>::Element *E = indexer->viewports.front(); E; E = E->next()) { r_viewports->push_back(E->key()); } } void World2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_canvas"), &World2D::get_canvas); ClassDB::bind_method(D_METHOD("get_space"), &World2D::get_space); @@ -376,33 +343,30 @@ void World2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::_RID, "canvas", PROPERTY_HINT_NONE, "", 0), "", "get_canvas"); ADD_PROPERTY(PropertyInfo(Variant::_RID, "space", PROPERTY_HINT_NONE, "", 0), "", "get_space"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "direct_space_state", PROPERTY_HINT_RESOURCE_TYPE, "Physics2DDirectSpaceState", 0), "", "get_direct_space_state"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "direct_space_state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectSpaceState2D", 0), "", "get_direct_space_state"); } -Physics2DDirectSpaceState *World2D::get_direct_space_state() { - - return Physics2DServer::get_singleton()->space_get_direct_state(space); +PhysicsDirectSpaceState2D *World2D::get_direct_space_state() { + return PhysicsServer2D::get_singleton()->space_get_direct_state(space); } World2D::World2D() { - - canvas = VisualServer::get_singleton()->canvas_create(); - space = Physics2DServer::get_singleton()->space_create(); + canvas = RenderingServer::get_singleton()->canvas_create(); + space = PhysicsServer2D::get_singleton()->space_create(); //set space2D to be more friendly with pixels than meters, by adjusting some constants - Physics2DServer::get_singleton()->space_set_active(space, true); - Physics2DServer::get_singleton()->area_set_param(space, Physics2DServer::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/2d/default_gravity", 98)); - Physics2DServer::get_singleton()->area_set_param(space, Physics2DServer::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/2d/default_gravity_vector", Vector2(0, 1))); - Physics2DServer::get_singleton()->area_set_param(space, Physics2DServer::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF("physics/2d/default_linear_damp", 0.1)); - ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_linear_damp", PropertyInfo(Variant::REAL, "physics/2d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater")); - Physics2DServer::get_singleton()->area_set_param(space, Physics2DServer::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/2d/default_angular_damp", 1.0)); - ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_angular_damp", PropertyInfo(Variant::REAL, "physics/2d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater")); + PhysicsServer2D::get_singleton()->space_set_active(space, true); + PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/2d/default_gravity", 98)); + PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/2d/default_gravity_vector", Vector2(0, 1))); + PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF("physics/2d/default_linear_damp", 0.1)); + ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_linear_damp", PropertyInfo(Variant::FLOAT, "physics/2d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater")); + PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/2d/default_angular_damp", 1.0)); + ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_angular_damp", PropertyInfo(Variant::FLOAT, "physics/2d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater")); indexer = memnew(SpatialIndexer2D); } World2D::~World2D() { - - VisualServer::get_singleton()->free(canvas); - Physics2DServer::get_singleton()->free(space); + RenderingServer::get_singleton()->free(canvas); + PhysicsServer2D::get_singleton()->free(space); memdelete(indexer); } diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h index d837ef58c2..c330719104 100644 --- a/scene/resources/world_2d.h +++ b/scene/resources/world_2d.h @@ -33,14 +33,13 @@ #include "core/project_settings.h" #include "core/resource.h" -#include "servers/physics_2d_server.h" +#include "servers/physics_server_2d.h" class VisibilityNotifier2D; class Viewport; struct SpatialIndexer2D; class World2D : public Resource { - GDCLASS(World2D, Resource); RID canvas; @@ -67,7 +66,7 @@ public: RID get_canvas(); RID get_space(); - Physics2DDirectSpaceState *get_direct_space_state(); + PhysicsDirectSpaceState2D *get_direct_space_state(); void get_viewport_list(List<Viewport *> *r_viewports); diff --git a/scene/resources/world.cpp b/scene/resources/world_3d.cpp index 1099852098..8100f150ef 100644 --- a/scene/resources/world.cpp +++ b/scene/resources/world_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* world.cpp */ +/* world_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,74 +28,68 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "world.h" +#include "world_3d.h" #include "core/math/camera_matrix.h" #include "core/math/octree.h" -#include "scene/3d/camera.h" -#include "scene/3d/visibility_notifier.h" +#include "scene/3d/camera_3d.h" +#include "scene/3d/visibility_notifier_3d.h" #include "scene/scene_string_names.h" struct SpatialIndexer { - - Octree<VisibilityNotifier> octree; + Octree<VisibilityNotifier3D> octree; struct NotifierData { - AABB aabb; OctreeElementID id; }; - Map<VisibilityNotifier *, NotifierData> notifiers; + Map<VisibilityNotifier3D *, NotifierData> notifiers; struct CameraData { - - Map<VisibilityNotifier *, uint64_t> notifiers; + Map<VisibilityNotifier3D *, uint64_t> notifiers; }; - Map<Camera *, CameraData> cameras; + Map<Camera3D *, CameraData> cameras; enum { VISIBILITY_CULL_MAX = 32768 }; - Vector<VisibilityNotifier *> cull; + Vector<VisibilityNotifier3D *> cull; bool changed; uint64_t pass; uint64_t last_frame; - void _notifier_add(VisibilityNotifier *p_notifier, const AABB &p_rect) { - + void _notifier_add(VisibilityNotifier3D *p_notifier, const AABB &p_rect) { ERR_FAIL_COND(notifiers.has(p_notifier)); notifiers[p_notifier].aabb = p_rect; notifiers[p_notifier].id = octree.create(p_notifier, p_rect); changed = true; } - void _notifier_update(VisibilityNotifier *p_notifier, const AABB &p_rect) { - - Map<VisibilityNotifier *, NotifierData>::Element *E = notifiers.find(p_notifier); + void _notifier_update(VisibilityNotifier3D *p_notifier, const AABB &p_rect) { + Map<VisibilityNotifier3D *, NotifierData>::Element *E = notifiers.find(p_notifier); ERR_FAIL_COND(!E); - if (E->get().aabb == p_rect) + if (E->get().aabb == p_rect) { return; + } E->get().aabb = p_rect; octree.move(E->get().id, E->get().aabb); changed = true; } - void _notifier_remove(VisibilityNotifier *p_notifier) { - - Map<VisibilityNotifier *, NotifierData>::Element *E = notifiers.find(p_notifier); + void _notifier_remove(VisibilityNotifier3D *p_notifier) { + Map<VisibilityNotifier3D *, NotifierData>::Element *E = notifiers.find(p_notifier); ERR_FAIL_COND(!E); octree.erase(E->get().id); notifiers.erase(p_notifier); - List<Camera *> removed; - for (Map<Camera *, CameraData>::Element *F = cameras.front(); F; F = F->next()) { - - Map<VisibilityNotifier *, uint64_t>::Element *G = F->get().notifiers.find(p_notifier); + List<Camera3D *> removed; + for (Map<Camera3D *, CameraData>::Element *F = cameras.front(); F; F = F->next()) { + Map<VisibilityNotifier3D *, uint64_t>::Element *G = F->get().notifiers.find(p_notifier); if (G) { F->get().notifiers.erase(G); @@ -104,7 +98,6 @@ struct SpatialIndexer { } while (!removed.empty()) { - p_notifier->_exit_camera(removed.front()->get()); removed.pop_front(); } @@ -112,26 +105,23 @@ struct SpatialIndexer { changed = true; } - void _add_camera(Camera *p_camera) { - + void _add_camera(Camera3D *p_camera) { ERR_FAIL_COND(cameras.has(p_camera)); CameraData vd; cameras[p_camera] = vd; changed = true; } - void _update_camera(Camera *p_camera) { - - Map<Camera *, CameraData>::Element *E = cameras.find(p_camera); + void _update_camera(Camera3D *p_camera) { + Map<Camera3D *, CameraData>::Element *E = cameras.find(p_camera); ERR_FAIL_COND(!E); changed = true; } - void _remove_camera(Camera *p_camera) { + void _remove_camera(Camera3D *p_camera) { ERR_FAIL_COND(!cameras.has(p_camera)); - List<VisibilityNotifier *> removed; - for (Map<VisibilityNotifier *, uint64_t>::Element *E = cameras[p_camera].notifiers.front(); E; E = E->next()) { - + List<VisibilityNotifier3D *> removed; + for (Map<VisibilityNotifier3D *, uint64_t>::Element *E = cameras[p_camera].notifiers.front(); E; E = E->next()) { removed.push_back(E->key()); } @@ -144,36 +134,34 @@ struct SpatialIndexer { } void _update(uint64_t p_frame) { - - if (p_frame == last_frame) + if (p_frame == last_frame) { return; + } last_frame = p_frame; - if (!changed) + if (!changed) { return; + } - for (Map<Camera *, CameraData>::Element *E = cameras.front(); E; E = E->next()) { - + for (Map<Camera3D *, CameraData>::Element *E = cameras.front(); E; E = E->next()) { pass++; - Camera *c = E->key(); + Camera3D *c = E->key(); Vector<Plane> planes = c->get_frustum(); int culled = octree.cull_convex(planes, cull.ptrw(), cull.size()); - VisibilityNotifier **ptr = cull.ptrw(); + VisibilityNotifier3D **ptr = cull.ptrw(); - List<VisibilityNotifier *> added; - List<VisibilityNotifier *> removed; + List<VisibilityNotifier3D *> added; + List<VisibilityNotifier3D *> removed; for (int i = 0; i < culled; i++) { - //notifiers in frustum - Map<VisibilityNotifier *, uint64_t>::Element *H = E->get().notifiers.find(ptr[i]); + Map<VisibilityNotifier3D *, uint64_t>::Element *H = E->get().notifiers.find(ptr[i]); if (!H) { - E->get().notifiers.insert(ptr[i], pass); added.push_back(ptr[i]); } else { @@ -181,10 +169,10 @@ struct SpatialIndexer { } } - for (Map<VisibilityNotifier *, uint64_t>::Element *F = E->get().notifiers.front(); F; F = F->next()) { - - if (F->get() != pass) + for (Map<VisibilityNotifier3D *, uint64_t>::Element *F = E->get().notifiers.front(); F; F = F->next()) { + if (F->get() != pass) { removed.push_back(F->key()); + } } while (!added.empty()) { @@ -202,7 +190,6 @@ struct SpatialIndexer { } SpatialIndexer() { - pass = 0; last_frame = 0; changed = false; @@ -210,153 +197,157 @@ struct SpatialIndexer { } }; -void World::_register_camera(Camera *p_camera) { - +void World3D::_register_camera(Camera3D *p_camera) { #ifndef _3D_DISABLED indexer->_add_camera(p_camera); #endif } -void World::_update_camera(Camera *p_camera) { - +void World3D::_update_camera(Camera3D *p_camera) { #ifndef _3D_DISABLED indexer->_update_camera(p_camera); #endif } -void World::_remove_camera(Camera *p_camera) { +void World3D::_remove_camera(Camera3D *p_camera) { #ifndef _3D_DISABLED indexer->_remove_camera(p_camera); #endif } -void World::_register_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect) { - +void World3D::_register_notifier(VisibilityNotifier3D *p_notifier, const AABB &p_rect) { #ifndef _3D_DISABLED indexer->_notifier_add(p_notifier, p_rect); #endif } -void World::_update_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect) { - +void World3D::_update_notifier(VisibilityNotifier3D *p_notifier, const AABB &p_rect) { #ifndef _3D_DISABLED indexer->_notifier_update(p_notifier, p_rect); #endif } -void World::_remove_notifier(VisibilityNotifier *p_notifier) { - +void World3D::_remove_notifier(VisibilityNotifier3D *p_notifier) { #ifndef _3D_DISABLED indexer->_notifier_remove(p_notifier); #endif } -void World::_update(uint64_t p_frame) { - +void World3D::_update(uint64_t p_frame) { #ifndef _3D_DISABLED indexer->_update(p_frame); #endif } -RID World::get_space() const { - +RID World3D::get_space() const { return space; } -RID World::get_scenario() const { +RID World3D::get_scenario() const { return scenario; } -void World::set_environment(const Ref<Environment> &p_environment) { +void World3D::set_environment(const Ref<Environment> &p_environment) { if (environment == p_environment) { return; } environment = p_environment; - if (environment.is_valid()) - VS::get_singleton()->scenario_set_environment(scenario, environment->get_rid()); - else - VS::get_singleton()->scenario_set_environment(scenario, RID()); + if (environment.is_valid()) { + RS::get_singleton()->scenario_set_environment(scenario, environment->get_rid()); + } else { + RS::get_singleton()->scenario_set_environment(scenario, RID()); + } emit_changed(); } -Ref<Environment> World::get_environment() const { - +Ref<Environment> World3D::get_environment() const { return environment; } -void World::set_fallback_environment(const Ref<Environment> &p_environment) { +void World3D::set_fallback_environment(const Ref<Environment> &p_environment) { if (fallback_environment == p_environment) { return; } fallback_environment = p_environment; - if (fallback_environment.is_valid()) - VS::get_singleton()->scenario_set_fallback_environment(scenario, p_environment->get_rid()); - else - VS::get_singleton()->scenario_set_fallback_environment(scenario, RID()); + if (fallback_environment.is_valid()) { + RS::get_singleton()->scenario_set_fallback_environment(scenario, p_environment->get_rid()); + } else { + RS::get_singleton()->scenario_set_fallback_environment(scenario, RID()); + } emit_changed(); } -Ref<Environment> World::get_fallback_environment() const { - +Ref<Environment> World3D::get_fallback_environment() const { return fallback_environment; } -PhysicsDirectSpaceState *World::get_direct_space_state() { +void World3D::set_camera_effects(const Ref<CameraEffects> &p_camera_effects) { + camera_effects = p_camera_effects; + if (camera_effects.is_valid()) { + RS::get_singleton()->scenario_set_camera_effects(scenario, camera_effects->get_rid()); + } else { + RS::get_singleton()->scenario_set_camera_effects(scenario, RID()); + } +} - return PhysicsServer::get_singleton()->space_get_direct_state(space); +Ref<CameraEffects> World3D::get_camera_effects() const { + return camera_effects; } -void World::get_camera_list(List<Camera *> *r_cameras) { +PhysicsDirectSpaceState3D *World3D::get_direct_space_state() { + return PhysicsServer3D::get_singleton()->space_get_direct_state(space); +} - for (Map<Camera *, SpatialIndexer::CameraData>::Element *E = indexer->cameras.front(); E; E = E->next()) { +void World3D::get_camera_list(List<Camera3D *> *r_cameras) { + for (Map<Camera3D *, SpatialIndexer::CameraData>::Element *E = indexer->cameras.front(); E; E = E->next()) { r_cameras->push_back(E->key()); } } -void World::_bind_methods() { - - ClassDB::bind_method(D_METHOD("get_space"), &World::get_space); - ClassDB::bind_method(D_METHOD("get_scenario"), &World::get_scenario); - ClassDB::bind_method(D_METHOD("set_environment", "env"), &World::set_environment); - ClassDB::bind_method(D_METHOD("get_environment"), &World::get_environment); - ClassDB::bind_method(D_METHOD("set_fallback_environment", "env"), &World::set_fallback_environment); - ClassDB::bind_method(D_METHOD("get_fallback_environment"), &World::get_fallback_environment); - ClassDB::bind_method(D_METHOD("get_direct_space_state"), &World::get_direct_space_state); +void World3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_space"), &World3D::get_space); + ClassDB::bind_method(D_METHOD("get_scenario"), &World3D::get_scenario); + ClassDB::bind_method(D_METHOD("set_environment", "env"), &World3D::set_environment); + ClassDB::bind_method(D_METHOD("get_environment"), &World3D::get_environment); + ClassDB::bind_method(D_METHOD("set_fallback_environment", "env"), &World3D::set_fallback_environment); + ClassDB::bind_method(D_METHOD("get_fallback_environment"), &World3D::get_fallback_environment); + ClassDB::bind_method(D_METHOD("set_camera_effects", "env"), &World3D::set_camera_effects); + ClassDB::bind_method(D_METHOD("get_camera_effects"), &World3D::get_camera_effects); + ClassDB::bind_method(D_METHOD("get_direct_space_state"), &World3D::get_direct_space_state); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "fallback_environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_fallback_environment", "get_fallback_environment"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_effects", PROPERTY_HINT_RESOURCE_TYPE, "CameraEffects"), "set_camera_effects", "get_camera_effects"); ADD_PROPERTY(PropertyInfo(Variant::_RID, "space", PROPERTY_HINT_NONE, "", 0), "", "get_space"); ADD_PROPERTY(PropertyInfo(Variant::_RID, "scenario", PROPERTY_HINT_NONE, "", 0), "", "get_scenario"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "direct_space_state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectSpaceState", 0), "", "get_direct_space_state"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "direct_space_state", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsDirectSpaceState3D", 0), "", "get_direct_space_state"); } -World::World() { +World3D::World3D() { + space = PhysicsServer3D::get_singleton()->space_create(); + scenario = RenderingServer::get_singleton()->scenario_create(); - space = PhysicsServer::get_singleton()->space_create(); - scenario = VisualServer::get_singleton()->scenario_create(); - - PhysicsServer::get_singleton()->space_set_active(space, true); - PhysicsServer::get_singleton()->area_set_param(space, PhysicsServer::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/3d/default_gravity", 9.8)); - PhysicsServer::get_singleton()->area_set_param(space, PhysicsServer::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/3d/default_gravity_vector", Vector3(0, -1, 0))); - PhysicsServer::get_singleton()->area_set_param(space, PhysicsServer::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF("physics/3d/default_linear_damp", 0.1)); - ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/default_linear_damp", PropertyInfo(Variant::REAL, "physics/3d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater")); - PhysicsServer::get_singleton()->area_set_param(space, PhysicsServer::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/3d/default_angular_damp", 0.1)); - ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/default_angular_damp", PropertyInfo(Variant::REAL, "physics/3d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater")); + PhysicsServer3D::get_singleton()->space_set_active(space, true); + PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/3d/default_gravity", 9.8)); + PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/3d/default_gravity_vector", Vector3(0, -1, 0))); + PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF("physics/3d/default_linear_damp", 0.1)); + ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/default_linear_damp", PropertyInfo(Variant::FLOAT, "physics/3d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater")); + PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/3d/default_angular_damp", 0.1)); + ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/default_angular_damp", PropertyInfo(Variant::FLOAT, "physics/3d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater")); #ifdef _3D_DISABLED - indexer = NULL; + indexer = nullptr; #else indexer = memnew(SpatialIndexer); #endif } -World::~World() { - - PhysicsServer::get_singleton()->free(space); - VisualServer::get_singleton()->free(scenario); +World3D::~World3D() { + PhysicsServer3D::get_singleton()->free(space); + RenderingServer::get_singleton()->free(scenario); #ifndef _3D_DISABLED memdelete(indexer); diff --git a/scene/resources/world.h b/scene/resources/world_3d.h index b6248b28c8..02a821637f 100644 --- a/scene/resources/world.h +++ b/scene/resources/world_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* world.h */ +/* world_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,21 +28,21 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef WORLD_H -#define WORLD_H +#ifndef WORLD_3D_H +#define WORLD_3D_H #include "core/resource.h" +#include "scene/resources/camera_effects.h" #include "scene/resources/environment.h" -#include "servers/physics_server.h" -#include "servers/visual_server.h" +#include "servers/physics_server_3d.h" +#include "servers/rendering_server.h" -class Camera; -class VisibilityNotifier; +class Camera3D; +class VisibilityNotifier3D; struct SpatialIndexer; -class World : public Resource { - GDCLASS(World, Resource); - RES_BASE_EXTENSION("world"); +class World3D : public Resource { + GDCLASS(World3D, Resource); private: RID space; @@ -50,20 +50,21 @@ private: SpatialIndexer *indexer; Ref<Environment> environment; Ref<Environment> fallback_environment; + Ref<CameraEffects> camera_effects; protected: static void _bind_methods(); - friend class Camera; - friend class VisibilityNotifier; + friend class Camera3D; + friend class VisibilityNotifier3D; - void _register_camera(Camera *p_camera); - void _update_camera(Camera *p_camera); - void _remove_camera(Camera *p_camera); + void _register_camera(Camera3D *p_camera); + void _update_camera(Camera3D *p_camera); + void _remove_camera(Camera3D *p_camera); - void _register_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect); - void _update_notifier(VisibilityNotifier *p_notifier, const AABB &p_rect); - void _remove_notifier(VisibilityNotifier *p_notifier); + void _register_notifier(VisibilityNotifier3D *p_notifier, const AABB &p_rect); + void _update_notifier(VisibilityNotifier3D *p_notifier, const AABB &p_rect); + void _remove_notifier(VisibilityNotifier3D *p_notifier); friend class Viewport; void _update(uint64_t p_frame); @@ -77,12 +78,15 @@ public: void set_fallback_environment(const Ref<Environment> &p_environment); Ref<Environment> get_fallback_environment() const; - void get_camera_list(List<Camera *> *r_cameras); + void set_camera_effects(const Ref<CameraEffects> &p_camera_effects); + Ref<CameraEffects> get_camera_effects() const; - PhysicsDirectSpaceState *get_direct_space_state(); + void get_camera_list(List<Camera3D *> *r_cameras); - World(); - ~World(); + PhysicsDirectSpaceState3D *get_direct_space_state(); + + World3D(); + ~World3D(); }; -#endif // WORLD_H +#endif // WORLD_3D_H diff --git a/scene/resources/plane_shape.cpp b/scene/resources/world_margin_shape_3d.cpp index ddc820233e..0936fcc657 100644 --- a/scene/resources/plane_shape.cpp +++ b/scene/resources/world_margin_shape_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* plane_shape.cpp */ +/* world_margin_shape_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,12 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "plane_shape.h" +#include "world_margin_shape_3d.h" -#include "servers/physics_server.h" - -Vector<Vector3> PlaneShape::get_debug_mesh_lines() { +#include "servers/physics_server_3d.h" +Vector<Vector3> WorldMarginShape3D::get_debug_mesh_lines() const { Plane p = get_plane(); Vector<Vector3> points; @@ -61,35 +60,30 @@ Vector<Vector3> PlaneShape::get_debug_mesh_lines() { return points; } -void PlaneShape::_update_shape() { - - PhysicsServer::get_singleton()->shape_set_data(get_shape(), plane); - Shape::_update_shape(); +void WorldMarginShape3D::_update_shape() { + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), plane); + Shape3D::_update_shape(); } -void PlaneShape::set_plane(Plane p_plane) { - +void WorldMarginShape3D::set_plane(Plane p_plane) { plane = p_plane; _update_shape(); notify_change_to_owners(); _change_notify("plane"); } -Plane PlaneShape::get_plane() const { - +Plane WorldMarginShape3D::get_plane() const { return plane; } -void PlaneShape::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_plane", "plane"), &PlaneShape::set_plane); - ClassDB::bind_method(D_METHOD("get_plane"), &PlaneShape::get_plane); +void WorldMarginShape3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_plane", "plane"), &WorldMarginShape3D::set_plane); + ClassDB::bind_method(D_METHOD("get_plane"), &WorldMarginShape3D::get_plane); ADD_PROPERTY(PropertyInfo(Variant::PLANE, "plane"), "set_plane", "get_plane"); } -PlaneShape::PlaneShape() : - Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_PLANE)) { - +WorldMarginShape3D::WorldMarginShape3D() : + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_PLANE)) { set_plane(Plane(0, 1, 0, 0)); } diff --git a/scene/resources/plane_shape.h b/scene/resources/world_margin_shape_3d.h index 8bea1268e5..8099592d80 100644 --- a/scene/resources/plane_shape.h +++ b/scene/resources/world_margin_shape_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* plane_shape.h */ +/* world_margin_shape_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,26 +28,29 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PLANE_SHAPE_H -#define PLANE_SHAPE_H +#ifndef WORLD_MARGIN_SHAPE_3D_H +#define WORLD_MARGIN_SHAPE_3D_H -#include "scene/resources/shape.h" +#include "scene/resources/shape_3d.h" -class PlaneShape : public Shape { - - GDCLASS(PlaneShape, Shape); +class WorldMarginShape3D : public Shape3D { + GDCLASS(WorldMarginShape3D, Shape3D); Plane plane; protected: static void _bind_methods(); - virtual void _update_shape(); + virtual void _update_shape() override; public: void set_plane(Plane p_plane); Plane get_plane() const; - virtual Vector<Vector3> get_debug_mesh_lines(); + virtual Vector<Vector3> get_debug_mesh_lines() const override; + virtual real_t get_enclosing_radius() const override { + // Should be infinite? + return 0; + } - PlaneShape(); + WorldMarginShape3D(); }; -#endif // PLANE_SHAPE_H +#endif // WORLD_MARGIN_SHAPE_H |