Jump to content

Particles enable disable by API


photo

Recommended Posts

Hi,

I try to turn on and off a object particles which I loaded by Unigine::World::get()->loadNode, but nothing happens.

The code below will be visited in debug. But particles are still spawning.

Unigine::Vector<Unigine::NodePtr> hierarchy;
myloadednode->getHierarchy(hierarchy);
for (auto & node : hierarchy) {
	if (node->getType() == Unigine::Node::OBJECT_PARTICLES) {
		Unigine::ObjectParticlesPtr particle = Unigine::ObjectParticles::cast(node);
		particle->setNumberPerSpawn(0);
		particle->setEmitterEnabled(0);
	}
}

Did I forget something?

Thanks,

Sebastian

Edited by sebastian.vesenmayer
Link to comment

No, because it disables all spawned particles and does not fade out slowly.

 

In the editor it is working, but not by c++ api.

Edited by sebastian.vesenmayer
Link to comment

So, you want to stop spawning particles and let the ones already spawned fade away...

In this case disabling the emitter by calling

particle->setEmitterEnabled(0);

should work.

Could you provide a small test sample that reproduces the issue, to identify the problem?

Thank you!

Link to comment

Hi Sebastian,

I've double-checked it and everything seems to work. At least the following code (AppWorldLogic.cpp):

#include <UnigineWorld.h>
#include <UnigineGame.h>

// ...
  
NodePtr n;
int AppWorldLogic::init()
{
	// loading a particle system created in the UnigineEditor and exported to the my_particles.node file
	n = Unigine::World::get()->loadNode("my_particles.node");
	// ...
}

// ...
// some stupid flag to disable the particle system emitter only once
bool flag = true;

int AppWorldLogic::update()
{
    // disabling the particle system emitter after 5 seconds
    if (flag && (Game::get()->getTime() > 5))
    {
	if (n)
        //-----------PART OF YOUR CODE----------------------------------------------------
		if (n->getType() == Unigine::Node::OBJECT_PARTICLES) {
			Unigine::ObjectParticlesPtr particle = Unigine::ObjectParticles::cast(n);
          	// disabling the particle system emitter
			particle->setEmitterEnabled(0);
			flag = false;
		}
      	//--------------------------------------------------------------------------------
    }
}

works ok with a particle system created by default in the UnigineEditor and exported to a *.node file.

Are you sure you're running the right version (debug or release). This might happen, for example, when you make modifications to a debug version, but launching a release one.

Thanks!

 

Link to comment

Thank you Fox,

I checked our code and it seems that we did create the node more than 1 time and lost the Pointer.

The Object loaded by

Unigine::World::get()->loadNode("my_particles.node");

won't get destroyed when the smart pointer goes out of scope.

 

Edited by sebastian.vesenmayer
Link to comment

Ok,

next problem, I cannot destroy the particle system.

 

int AppWorldLogic::init() {
	// Write here code to be called on world initialization: initialize resources for your world scene during the world start.
	smokeNode = Unigine::World::get()->loadNode("Smoke/Smoke_Gray.node");
	smokeNode->grab();
	return 1;
}

// start of the main loop
int AppWorldLogic::update() {
	// Write here code to be called before updating each render frame: specify all graphics-related functions you want to be called every frame while your application executes.
	smokeNode.destroy();

	return 1;
}

 

It is still visible in the small example.

Link to comment

You're welcome, Sebastian!

Ok, again I'd ask for a sample, as in my case everything works as it should:

#include <UnigineWorld.h>
#include <UnigineGame.h>

// ...
  
NodePtr n;
int AppWorldLogic::init()
{
	// loading a particle system created in the UnigineEditor and exported to the my_particles.node file
	n = Unigine::World::get()->loadNode("my_particles.node");
	n->grab();
	// ...
}

// ...
int AppWorldLogic::update()
{
    // destroying the particle system after 5 seconds
    if (Game::get()->getTime() > 5)
    {
	if (n)
		n.destroy();
    }
}

Please check this out!

Thank you!

Link to comment

Hi Sebastien, 

Now it's clear!

There is a hierarchy in your *.node file with a couple of particle systems and a dummy node as a root. There is one thing about the destroy() method, that you should be aware of: you can load a large hierarchy of objects via World::get()->loadNode(), but when you delete a smart pointer of the root node of the hierarchy (e.g. by calling the destroy() method), only the node pointed by the interface will be deleted. All its children will become orphans and will remain in the world.

In case of a NodeReference things are simple: as you delete it, the whole its hierachy is deleted as well, so there's nothing to worry about. In all other cases we'll have to delete all children recursively. Therefore, at run time it is recommended either to create NodeReferences or single nodes via the World's loadNode() method.

Moreover, you can pass node ownership to the Editor (it always exists, even when you don't see it) and use the following:

  • Editor::get()->addNode() - now the Editor will own the object and manage it. Don't forget to call release() for all interfaces before adding nodes to the Editor.
  • Editor::get()->releaseNode() - release Editor ownership. Now the object can be controlled by you - just call grab() and it's yours.
  • Editor::get()->removeNode() - deletes the node. The best thing in this case is that when the Editor is the owner it deletes the node with all its hierarchy automatically.

Generally, if you need to manage (create and delete) complex node hierarchies and change worlds, the best option might be to pass ownership to the Editor, after previously calling release() for all interfaces.

// ...

Unigine::NodePtr smokeNode;

int AppWorldLogic::init() {
	// ...
	// loading a node from a file and passing it to the Editor
	smokeNode = Unigine::World::get()->loadNode("Smoke/Smoke_Gray.node");
	smokeNode->release();
	Unigine::Editor::get()->addNode(smokeNode);
	return 1;
}

int AppWorldLogic::update() {
	if (Unigine::Game::get()->getTime() > 5) {
		if (smokeNode)
		{
			// deleting a node with all its hierarchy (second parameter of the removeNode is set to 1) and clearing a pointer
			Unigine::Editor::get()->removeNode(smokeNode,1);
			smokeNode.clear();
		}
	}
	return 1;
}
// ...

In this case, when you change worlds, no orphan nodes will remain in memory, as the Editor deletes all nodes it owns on unloading a world.

Hope this helps, Sebastien!

Thank you!

Link to comment

Hi fox, it works now.

But does it make sense, because when I destroy a root object, shouldn't the reference counter decrement for every child object and  they delete themself when they reach zero?

What is the benefit to have orphans, when they are not controllable anymore?

Is this mentioned in the documentation? I didn't find the hint.

Thank you,

Sebastian

Link to comment

Glad to hear that, Sebastien!

Unfortunately hierarchies don't work that way, a pointer to root object is just a pointer to root object and it doesn't manage all the hierarchy. There were hints in the docs here and there, but with the upcoming release a new article on working with smart pointers will be available, with this particular topic included, to make programmer's life easier.

Thank you!

Link to comment
×
×
  • Create New...