Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add finished signal to CPUParticles #76853

Merged
merged 1 commit into from
Jul 14, 2023

Conversation

HolonProduction
Copy link
Member

Closes godotengine/godot-proposals#649.

Can be tested with this project.

@HolonProduction HolonProduction changed the title Add emission_finished signal to particles. Add emission_finished signal to CPUParticles. May 8, 2023
@HolonProduction
Copy link
Member Author

Just noticed that this breaks the resetting of emitting with high explosiveness values. (Might be related to the lifetime * 1.2 that Calinou pointed out before.)

@HolonProduction
Copy link
Member Author

HolonProduction commented May 9, 2023

emitting is set to false when a cycle ends. This means even with explosiveness = 1 emitting will only be false after lifetime. Combined with lifetime_randomness all particles can vanish before emitting is set to false. Therefore the internal process should only end if not emitting and not active.

@HolonProduction HolonProduction marked this pull request as ready for review May 9, 2023 08:24
Copy link
Member

@clayjohn clayjohn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works quite well for the most part. However, if emitting is set to true in the same frame that the particle is created (or the same frame that the particle is restarted), the signal will fire immediately. You probably need to also check if cycle is 0 or if time == 0.

I tested with a very simple script in a scene with a default CPUParticles2D node set to one_shot

extends Node2D

func _ready():

	$CPUParticles2D.emission_finished.connect(finished_emitt)
	$CPUParticles2D.restart() # this emits the signal in the first frame, but not when emission actually finishes
#	$CPUParticles2D.call_deferred("restart") # this works
	
func finished_emitt():
	print("done emitting")
	$Sprite2D.visible = false

@clayjohn clayjohn modified the milestones: 4.x, 4.2 Jul 6, 2023
@HolonProduction
Copy link
Member Author

HolonProduction commented Jul 7, 2023

This works quite well for the most part. However, if emitting is set to true in the same frame that the particle is created (or the same frame that the particle is restarted), the signal will fire immediately. You probably need to also check if cycle is 0 or if time == 0.

I tested with a very simple script in a scene with a default CPUParticles2D node set to one_shot

This seems to happen if restarting in _ready. The reason for this seems to be here. The internal process is called here but not from the process notification. Therefore the delta time is zero and the restart computation will fail. Therefore all particles are inactive during the first internal process. During this process the checks for emitting the signal run as well and since all particles are inactive it is emitted. The particles only become active during the second iteration of internal process when delta time is not zero.

Checking for time not to be zero as proposed by you seems to work.

@clayjohn
Copy link
Member

clayjohn commented Jul 7, 2023

Are there any implications with this (means: are there other valid cases with a delta time of zero)?

It looks like the particles will process when delta time is 0 if the pre_process_time is greater than 0 https://github.com/godotengine/godot/blob/1b03ec918edd50f1e926e8cf71259e14e1ee70d9/scene/2d/cpu_particles_2d.cpp#L577

edit: oops, I started this message in response to your message before getting edited. I think just checking time will result in issues when using pre_process

@HolonProduction
Copy link
Member Author

All preprocessing happens while time == 0 so the signal cannot be emmitted during pre processing. But after this it seems to work fine for me. Even if preprocess is higher than lifetime the internal processing will only be turned of after the signal gets emitted so internal process will run and the signal is emitted emediately.

If you find another case that makes problems with pre process I will look into it.

@clayjohn
Copy link
Member

clayjohn commented Jul 7, 2023

All preprocessing happens while time == 0 so the signal cannot be emmitted during pre processing. But after this it seems to work fine for me. Even if preprocess is higher than lifetime the internal processing will only be turned of after the signal gets emitted so internal process will run and the signal is emitted emediately.

If you find another case that makes problems with pre process I will look into it.

Ah, of course. You are right. It will never signal during the pre_process which is a good thing!

Copy link
Member

@clayjohn clayjohn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am happy with this implementation. I have tested locally and it appears to work well.

This should be a great early inclusion to 4.2.

Note for merger, this should be merged at the same time as its counterpart #76859 (for GPUParticles) which I still need to test/review

@YuriSizov YuriSizov changed the title Add emission_finished signal to CPUParticles. Add emission_finished signal to CPUParticles. Jul 7, 2023
@YuriSizov YuriSizov changed the title Add emission_finished signal to CPUParticles. Add emission_finished signal to CPUParticles Jul 7, 2023
@YuriSizov YuriSizov changed the title Add emission_finished signal to CPUParticles Add finished signal to CPUParticles Jul 14, 2023
@YuriSizov YuriSizov merged commit a91f0e6 into godotengine:master Jul 14, 2023
@YuriSizov
Copy link
Contributor

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make Particles emit a signal when all particles finished
4 participants