diff options
Diffstat (limited to 'scene/resources')
| -rw-r--r-- | scene/resources/2d/tile_set.cpp | 6 | ||||
| -rw-r--r-- | scene/resources/animation.cpp | 29 | ||||
| -rw-r--r-- | scene/resources/animation.h | 5 | ||||
| -rw-r--r-- | scene/resources/audio_stream_wav.cpp | 144 | ||||
| -rw-r--r-- | scene/resources/audio_stream_wav.h | 23 | ||||
| -rw-r--r-- | scene/resources/material.cpp | 11 | ||||
| -rw-r--r-- | scene/resources/material.h | 1 | ||||
| -rw-r--r-- | scene/resources/particle_process_material.cpp | 8 | ||||
| -rw-r--r-- | scene/resources/visual_shader.cpp | 4 | ||||
| -rw-r--r-- | scene/resources/visual_shader.h | 1 |
10 files changed, 190 insertions, 42 deletions
diff --git a/scene/resources/2d/tile_set.cpp b/scene/resources/2d/tile_set.cpp index 57cc4ad602..6649cb9b82 100644 --- a/scene/resources/2d/tile_set.cpp +++ b/scene/resources/2d/tile_set.cpp @@ -4650,7 +4650,7 @@ Ref<Texture2D> TileSetAtlasSource::get_texture() const { void TileSetAtlasSource::set_margins(Vector2i p_margins) { if (p_margins.x < 0 || p_margins.y < 0) { WARN_PRINT("Atlas source margins should be positive."); - margins = p_margins.max(Vector2i()); + margins = p_margins.maxi(0); } else { margins = p_margins; } @@ -4666,7 +4666,7 @@ Vector2i TileSetAtlasSource::get_margins() const { void TileSetAtlasSource::set_separation(Vector2i p_separation) { if (p_separation.x < 0 || p_separation.y < 0) { WARN_PRINT("Atlas source separation should be positive."); - separation = p_separation.max(Vector2i()); + separation = p_separation.maxi(0); } else { separation = p_separation; } @@ -4682,7 +4682,7 @@ Vector2i TileSetAtlasSource::get_separation() const { void TileSetAtlasSource::set_texture_region_size(Vector2i p_tile_size) { if (p_tile_size.x <= 0 || p_tile_size.y <= 0) { WARN_PRINT("Atlas source tile_size should be strictly positive."); - texture_region_size = p_tile_size.max(Vector2i(1, 1)); + texture_region_size = p_tile_size.maxi(1); } else { texture_region_size = p_tile_size; } diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index cd530f100e..8ffb629ba9 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -247,6 +247,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) { } vt->update_mode = UpdateMode(um); } + capture_included = capture_included || (vt->update_mode == UPDATE_CAPTURE); Vector<real_t> times = d["times"]; Array values = d["values"]; @@ -966,6 +967,28 @@ void Animation::remove_track(int p_track) { memdelete(t); tracks.remove_at(p_track); emit_changed(); + _check_capture_included(); +} + +void Animation::set_capture_included(bool p_capture_included) { + capture_included = p_capture_included; +} + +bool Animation::is_capture_included() const { + return capture_included; +} + +void Animation::_check_capture_included() { + capture_included = false; + for (int i = 0; i < tracks.size(); i++) { + if (tracks[i]->type == TYPE_VALUE) { + ValueTrack *vt = static_cast<ValueTrack *>(tracks[i]); + if (vt->update_mode == UPDATE_CAPTURE) { + capture_included = true; + break; + } + } + } } int Animation::get_track_count() const { @@ -2681,6 +2704,8 @@ void Animation::value_track_set_update_mode(int p_track, UpdateMode p_mode) { ValueTrack *vt = static_cast<ValueTrack *>(t); vt->update_mode = p_mode; + + capture_included = capture_included || (p_mode == UPDATE_CAPTURE); emit_changed(); } @@ -3870,9 +3895,13 @@ void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("compress", "page_size", "fps", "split_tolerance"), &Animation::compress, DEFVAL(8192), DEFVAL(120), DEFVAL(4.0)); + ClassDB::bind_method(D_METHOD("_set_capture_included", "capture_included"), &Animation::set_capture_included); + ClassDB::bind_method(D_METHOD("is_capture_included"), &Animation::is_capture_included); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0.001,99999,0.001,suffix:s"), "set_length", "get_length"); ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "None,Linear,Ping-Pong"), "set_loop_mode", "get_loop_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step", PROPERTY_HINT_RANGE, "0,4096,0.001,suffix:s"), "set_step", "get_step"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "capture_included", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_READ_ONLY | PROPERTY_USAGE_NO_EDITOR), "_set_capture_included", "is_capture_included"); BIND_ENUM_CONSTANT(TYPE_VALUE); BIND_ENUM_CONSTANT(TYPE_POSITION_3D); diff --git a/scene/resources/animation.h b/scene/resources/animation.h index 6005172c11..cc7bbae8a3 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -268,6 +268,8 @@ private: double length = 1.0; real_t step = 1.0 / 30; LoopMode loop_mode = LOOP_NONE; + bool capture_included = false; + void _check_capture_included(); void _track_update_hash(int p_track); @@ -392,6 +394,9 @@ public: int add_track(TrackType p_type, int p_at_pos = -1); void remove_track(int p_track); + void set_capture_included(bool p_capture_included); + bool is_capture_included() const; + int get_track_count() const; TrackType track_get_type(int p_track) const; diff --git a/scene/resources/audio_stream_wav.cpp b/scene/resources/audio_stream_wav.cpp index 0185c6ef85..ba5dad088f 100644 --- a/scene/resources/audio_stream_wav.cpp +++ b/scene/resources/audio_stream_wav.cpp @@ -86,15 +86,15 @@ void AudioStreamPlaybackWAV::seek(double p_time) { offset = uint64_t(p_time * base->mix_rate) << MIX_FRAC_BITS; } -template <typename Depth, bool is_stereo, bool is_ima_adpcm> -void AudioStreamPlaybackWAV::do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &p_offset, int32_t &p_increment, uint32_t p_amount, IMA_ADPCM_State *p_ima_adpcm) { +template <typename Depth, bool is_stereo, bool is_ima_adpcm, bool is_qoa> +void AudioStreamPlaybackWAV::do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &p_offset, int32_t &p_increment, uint32_t p_amount, IMA_ADPCM_State *p_ima_adpcm, QOA_State *p_qoa) { // this function will be compiled branchless by any decent compiler - int32_t final, final_r, next, next_r; + int32_t final = 0, final_r = 0, next = 0, next_r = 0; while (p_amount) { p_amount--; int64_t pos = p_offset >> MIX_FRAC_BITS; - if (is_stereo && !is_ima_adpcm) { + if (is_stereo && !is_ima_adpcm && !is_qoa) { pos <<= 1; } @@ -175,32 +175,77 @@ void AudioStreamPlaybackWAV::do_resample(const Depth *p_src, AudioFrame *p_dst, } } else { - final = p_src[pos]; - if (is_stereo) { - final_r = p_src[pos + 1]; - } + if (is_qoa) { + if (pos != p_qoa->cache_pos) { // Prevents triple decoding on lower mix rates. + for (int i = 0; i < 2; i++) { + // Sign operations prevent triple decoding on backward loops, maxing prevents pop. + uint32_t interp_pos = MIN(pos + (i * sign) + (sign < 0), p_qoa->desc->samples - 1); + uint32_t new_data_ofs = 8 + interp_pos / QOA_FRAME_LEN * p_qoa->frame_len; + + if (p_qoa->data_ofs != new_data_ofs) { + p_qoa->data_ofs = new_data_ofs; + const uint8_t *src_ptr = (const uint8_t *)base->data; + src_ptr += p_qoa->data_ofs + AudioStreamWAV::DATA_PAD; + qoa_decode_frame(src_ptr, p_qoa->frame_len, p_qoa->desc, p_qoa->dec, &p_qoa->dec_len); + } - if constexpr (sizeof(Depth) == 1) { /* conditions will not exist anymore when compiled! */ - final <<= 8; + uint32_t dec_idx = (interp_pos % QOA_FRAME_LEN) * p_qoa->desc->channels; + + if ((sign > 0 && i == 0) || (sign < 0 && i == 1)) { + final = p_qoa->dec[dec_idx]; + p_qoa->cache[0] = final; + if (is_stereo) { + final_r = p_qoa->dec[dec_idx + 1]; + p_qoa->cache_r[0] = final_r; + } + } else { + next = p_qoa->dec[dec_idx]; + p_qoa->cache[1] = next; + if (is_stereo) { + next_r = p_qoa->dec[dec_idx + 1]; + p_qoa->cache_r[1] = next_r; + } + } + } + p_qoa->cache_pos = pos; + } else { + final = p_qoa->cache[0]; + if (is_stereo) { + final_r = p_qoa->cache_r[0]; + } + + next = p_qoa->cache[1]; + if (is_stereo) { + next_r = p_qoa->cache_r[1]; + } + } + } else { + final = p_src[pos]; if (is_stereo) { - final_r <<= 8; + final_r = p_src[pos + 1]; } - } - if (is_stereo) { - next = p_src[pos + 2]; - next_r = p_src[pos + 3]; - } else { - next = p_src[pos + 1]; - } + if constexpr (sizeof(Depth) == 1) { /* conditions will not exist anymore when compiled! */ + final <<= 8; + if (is_stereo) { + final_r <<= 8; + } + } - if constexpr (sizeof(Depth) == 1) { - next <<= 8; if (is_stereo) { - next_r <<= 8; + next = p_src[pos + 2]; + next_r = p_src[pos + 3]; + } else { + next = p_src[pos + 1]; } - } + if constexpr (sizeof(Depth) == 1) { + next <<= 8; + if (is_stereo) { + next_r <<= 8; + } + } + } int32_t frac = int64_t(p_offset & MIX_FRAC_MASK); final = final + ((next - final) * frac >> MIX_FRAC_BITS); @@ -240,6 +285,9 @@ int AudioStreamPlaybackWAV::mix(AudioFrame *p_buffer, float p_rate_scale, int p_ case AudioStreamWAV::FORMAT_IMA_ADPCM: len *= 2; break; + case AudioStreamWAV::FORMAT_QOA: + len = qoa.desc->samples * qoa.desc->channels; + break; } if (base->stereo) { @@ -368,27 +416,34 @@ int AudioStreamPlaybackWAV::mix(AudioFrame *p_buffer, float p_rate_scale, int p_ switch (base->format) { case AudioStreamWAV::FORMAT_8_BITS: { if (is_stereo) { - do_resample<int8_t, true, false>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm); + do_resample<int8_t, true, false, false>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm, &qoa); } else { - do_resample<int8_t, false, false>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm); + do_resample<int8_t, false, false, false>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm, &qoa); } } break; case AudioStreamWAV::FORMAT_16_BITS: { if (is_stereo) { - do_resample<int16_t, true, false>((int16_t *)data, dst_buff, offset, increment, target, ima_adpcm); + do_resample<int16_t, true, false, false>((int16_t *)data, dst_buff, offset, increment, target, ima_adpcm, &qoa); } else { - do_resample<int16_t, false, false>((int16_t *)data, dst_buff, offset, increment, target, ima_adpcm); + do_resample<int16_t, false, false, false>((int16_t *)data, dst_buff, offset, increment, target, ima_adpcm, &qoa); } } break; case AudioStreamWAV::FORMAT_IMA_ADPCM: { if (is_stereo) { - do_resample<int8_t, true, true>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm); + do_resample<int8_t, true, true, false>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm, &qoa); } else { - do_resample<int8_t, false, true>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm); + do_resample<int8_t, false, true, false>((int8_t *)data, dst_buff, offset, increment, target, ima_adpcm, &qoa); } } break; + case AudioStreamWAV::FORMAT_QOA: { + if (is_stereo) { + do_resample<uint8_t, true, false, true>((uint8_t *)data, dst_buff, offset, increment, target, ima_adpcm, &qoa); + } else { + do_resample<uint8_t, false, false, true>((uint8_t *)data, dst_buff, offset, increment, target, ima_adpcm, &qoa); + } + } break; } dst_buff += target; @@ -412,6 +467,16 @@ void AudioStreamPlaybackWAV::tag_used_streams() { AudioStreamPlaybackWAV::AudioStreamPlaybackWAV() {} +AudioStreamPlaybackWAV::~AudioStreamPlaybackWAV() { + if (qoa.desc) { + memfree(qoa.desc); + } + + if (qoa.dec) { + memfree(qoa.dec); + } +} + ///////////////////// void AudioStreamWAV::set_format(Format p_format) { @@ -475,6 +540,10 @@ double AudioStreamWAV::get_length() const { case AudioStreamWAV::FORMAT_IMA_ADPCM: len *= 2; break; + case AudioStreamWAV::FORMAT_QOA: + qoa_desc desc = { 0, 0, 0, { { { 0 }, { 0 } } } }; + qoa_decode_header((uint8_t *)data + DATA_PAD, QOA_MIN_FILESIZE, &desc); + len = desc.samples * desc.channels; } if (stereo) { @@ -526,8 +595,8 @@ Vector<uint8_t> AudioStreamWAV::get_data() const { } Error AudioStreamWAV::save_to_wav(const String &p_path) { - if (format == AudioStreamWAV::FORMAT_IMA_ADPCM) { - WARN_PRINT("Saving IMA_ADPC samples are not supported yet"); + if (format == AudioStreamWAV::FORMAT_IMA_ADPCM || format == AudioStreamWAV::FORMAT_QOA) { + WARN_PRINT("Saving IMA_ADPCM and QOA samples is not supported yet"); return ERR_UNAVAILABLE; } @@ -548,6 +617,7 @@ Error AudioStreamWAV::save_to_wav(const String &p_path) { byte_pr_sample = 1; break; case AudioStreamWAV::FORMAT_16_BITS: + case AudioStreamWAV::FORMAT_QOA: byte_pr_sample = 2; break; case AudioStreamWAV::FORMAT_IMA_ADPCM: @@ -590,6 +660,7 @@ Error AudioStreamWAV::save_to_wav(const String &p_path) { } break; case AudioStreamWAV::FORMAT_16_BITS: + case AudioStreamWAV::FORMAT_QOA: for (unsigned int i = 0; i < data_bytes / 2; i++) { uint16_t data_point = decode_uint16(&read_data[i * 2]); file->store_16(data_point); @@ -607,6 +678,16 @@ Ref<AudioStreamPlayback> AudioStreamWAV::instantiate_playback() { Ref<AudioStreamPlaybackWAV> sample; sample.instantiate(); sample->base = Ref<AudioStreamWAV>(this); + + if (format == AudioStreamWAV::FORMAT_QOA) { + sample->qoa.desc = (qoa_desc *)memalloc(sizeof(qoa_desc)); + qoa_decode_header((uint8_t *)data + DATA_PAD, QOA_MIN_FILESIZE, sample->qoa.desc); + sample->qoa.frame_len = qoa_max_frame_size(sample->qoa.desc); + int samples_len = (sample->qoa.desc->samples > QOA_FRAME_LEN ? QOA_FRAME_LEN : sample->qoa.desc->samples); + int alloc_len = sample->qoa.desc->channels * samples_len * sizeof(int16_t); + sample->qoa.dec = (int16_t *)memalloc(alloc_len); + } + return sample; } @@ -639,7 +720,7 @@ void AudioStreamWAV::_bind_methods() { ClassDB::bind_method(D_METHOD("save_to_wav", "path"), &AudioStreamWAV::save_to_wav); ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "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, "format", PROPERTY_HINT_ENUM, "8-Bit,16-Bit,IMA-ADPCM,QOA"), "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"); ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_end"), "set_loop_end", "get_loop_end"); @@ -649,6 +730,7 @@ void AudioStreamWAV::_bind_methods() { BIND_ENUM_CONSTANT(FORMAT_8_BITS); BIND_ENUM_CONSTANT(FORMAT_16_BITS); BIND_ENUM_CONSTANT(FORMAT_IMA_ADPCM); + BIND_ENUM_CONSTANT(FORMAT_QOA); BIND_ENUM_CONSTANT(LOOP_DISABLED); BIND_ENUM_CONSTANT(LOOP_FORWARD); diff --git a/scene/resources/audio_stream_wav.h b/scene/resources/audio_stream_wav.h index 959d1ceca0..146142d8a4 100644 --- a/scene/resources/audio_stream_wav.h +++ b/scene/resources/audio_stream_wav.h @@ -31,7 +31,11 @@ #ifndef AUDIO_STREAM_WAV_H #define AUDIO_STREAM_WAV_H +#define QOA_IMPLEMENTATION +#define QOA_NO_STDIO + #include "servers/audio/audio_stream.h" +#include "thirdparty/misc/qoa.h" class AudioStreamWAV; @@ -54,14 +58,25 @@ class AudioStreamPlaybackWAV : public AudioStreamPlayback { int32_t window_ofs = 0; } ima_adpcm[2]; + struct QOA_State { + qoa_desc *desc = nullptr; + uint32_t data_ofs = 0; + uint32_t frame_len = 0; + int16_t *dec = nullptr; + uint32_t dec_len = 0; + int64_t cache_pos = -1; + int16_t cache[2] = { 0, 0 }; + int16_t cache_r[2] = { 0, 0 }; + } qoa; + int64_t offset = 0; int sign = 1; bool active = false; friend class AudioStreamWAV; Ref<AudioStreamWAV> base; - template <typename Depth, bool is_stereo, bool is_ima_adpcm> - void do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &p_offset, int32_t &p_increment, uint32_t p_amount, IMA_ADPCM_State *p_ima_adpcm); + template <typename Depth, bool is_stereo, bool is_ima_adpcm, bool is_qoa> + void do_resample(const Depth *p_src, AudioFrame *p_dst, int64_t &p_offset, int32_t &p_increment, uint32_t p_amount, IMA_ADPCM_State *p_ima_adpcm, QOA_State *p_qoa); public: virtual void start(double p_from_pos = 0.0) override; @@ -78,6 +93,7 @@ public: virtual void tag_used_streams() override; AudioStreamPlaybackWAV(); + ~AudioStreamPlaybackWAV(); }; class AudioStreamWAV : public AudioStream { @@ -88,7 +104,8 @@ public: enum Format { FORMAT_8_BITS, FORMAT_16_BITS, - FORMAT_IMA_ADPCM + FORMAT_IMA_ADPCM, + FORMAT_QOA, }; // Keep the ResourceImporterWAV `edit/loop_mode` enum hint in sync with these options. diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index b381096df8..15b40e776c 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -688,6 +688,9 @@ void BaseMaterial3D::_update_shader() { case BLEND_MODE_MUL: code += "blend_mul"; break; + case BLEND_MODE_PREMULT_ALPHA: + code += "blend_premul_alpha"; + break; case BLEND_MODE_MAX: break; // Internal value, skip. } @@ -1819,6 +1822,11 @@ void fragment() {)"; vec3 detail = mix(ALBEDO.rgb, ALBEDO.rgb * detail_tex.rgb, detail_tex.a); )"; } break; + case BLEND_MODE_PREMULT_ALPHA: { + // This is unlikely to ever be used for detail textures, and in order for it to function in the editor, another bit must be used in MaterialKey, + // but there are only 5 bits left, so I'm going to leave this disabled unless it's actually requested. + //code += "\tvec3 detail = (1.0-detail_tex.a)*ALBEDO.rgb+detail_tex.rgb;\n"; + } break; case BLEND_MODE_MAX: break; // Internal value, skip. } @@ -3040,7 +3048,7 @@ void BaseMaterial3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_hash_scale", PROPERTY_HINT_RANGE, "0,2,0.01"), "set_alpha_hash_scale", "get_alpha_hash_scale"); ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_antialiasing_mode", PROPERTY_HINT_ENUM, "Disabled,Alpha Edge Blend,Alpha Edge Clip"), "set_alpha_antialiasing", "get_alpha_antialiasing"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_antialiasing_edge", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_antialiasing_edge", "get_alpha_antialiasing_edge"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Subtract,Multiply"), "set_blend_mode", "get_blend_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Subtract,Multiply,Premultiplied Alpha"), "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); @@ -3269,6 +3277,7 @@ void BaseMaterial3D::_bind_methods() { BIND_ENUM_CONSTANT(BLEND_MODE_ADD); BIND_ENUM_CONSTANT(BLEND_MODE_SUB); BIND_ENUM_CONSTANT(BLEND_MODE_MUL); + BIND_ENUM_CONSTANT(BLEND_MODE_PREMULT_ALPHA); BIND_ENUM_CONSTANT(ALPHA_ANTIALIASING_OFF); BIND_ENUM_CONSTANT(ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE); diff --git a/scene/resources/material.h b/scene/resources/material.h index 073403f71e..ecf79c581b 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -219,6 +219,7 @@ public: BLEND_MODE_ADD, BLEND_MODE_SUB, BLEND_MODE_MUL, + BLEND_MODE_PREMULT_ALPHA, BLEND_MODE_MAX }; diff --git a/scene/resources/particle_process_material.cpp b/scene/resources/particle_process_material.cpp index 685625ab72..0b65b33240 100644 --- a/scene/resources/particle_process_material.cpp +++ b/scene/resources/particle_process_material.cpp @@ -634,7 +634,7 @@ void ParticleProcessMaterial::_update_shader() { if (emission_shape == EMISSION_SHAPE_RING) { code += " \n"; code += " float ring_spawn_angle = rand_from_seed(alt_seed) * 2.0 * pi;\n"; - code += " float ring_random_radius = rand_from_seed(alt_seed) * (emission_ring_radius - emission_ring_inner_radius) + emission_ring_inner_radius;\n"; + code += " float ring_random_radius = sqrt(rand_from_seed(alt_seed) * (emission_ring_radius - emission_ring_inner_radius * emission_ring_inner_radius) + emission_ring_inner_radius * emission_ring_inner_radius);\n"; code += " vec3 axis = emission_ring_axis == vec3(0.0) ? vec3(0.0, 0.0, 1.0) : normalize(emission_ring_axis);\n"; code += " vec3 ortho_axis = vec3(0.0);\n"; code += " if (abs(axis) == vec3(1.0, 0.0, 0.0)) {\n"; @@ -1136,9 +1136,9 @@ void ParticleProcessMaterial::_update_shader() { code += " if (COLLIDED) emit_count = sub_emitter_amount_at_collision;\n"; } break; case SUB_EMITTER_AT_END: { - 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"; + code += " if ((CUSTOM.y / CUSTOM.w * LIFETIME) > (LIFETIME - DELTA)) {\n"; + code += " emit_count = sub_emitter_amount_at_end;\n"; + code += " }\n"; } break; default: { } diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 6f1aa5c850..4b51f6c471 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -4928,6 +4928,10 @@ String VisualShaderNodeExpression::generate_code(Shader::Mode p_mode, VisualShad return code; } +bool VisualShaderNodeExpression::is_output_port_expandable(int p_port) const { + return false; +} + 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); diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index d7270f3ac6..d32e2465b9 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -878,6 +878,7 @@ public: 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 override; + virtual bool is_output_port_expandable(int p_port) const override; VisualShaderNodeExpression(); }; |
