void CParticleEditor::play(CWorkspaceNode &node) { if (isRunning(&node)) return; // NB : node must be stopped, no check is done nlassert(node.isLoaded()); // if node not started, start it node.memorizeState(); // enable the system to take the right date from the scene node.getPSModel()->enableAutoGetEllapsedTime(true); node.getPSPointer()->setSystemDate(0.f); node.getPSPointer()->reactivateSound(); node.getPSModel()->activateEmitters(true); if (node.getPSPointer()->getAutoCountFlag()) { if (node.getResetAutoCountFlag()) { // reset particle size arrays node.getPSPointer()->matchArraySize(); } resetAutoCount(&node, false); } // Set speed playback particle system node.getPSModel()->setEllapsedTimeRatio(_Speed); }
NL3D::CParticleSystemModel *CParticleEditor::getModelFromPS(NL3D::CParticleSystem *ps) const { if (!ps) return NULL; CWorkspaceNode *node = _PW->getNodeFromPS(ps); if (!node) return NULL; return node->getPSModel(); }
void CParticleEditor::pause(CWorkspaceNode &node) { if (!isRunning(&node)) return; nlassert(node.isLoaded()); node.getPSModel()->enableAutoGetEllapsedTime(false); node.getPSModel()->setEllapsedTime(0.f); }
void CWorkspacePage::insertPS() { QString fileName = QFileDialog::getOpenFileName(this, tr("Open NeL data file"), ".", tr("Particle System file (*.ps);;")); if (!fileName.isEmpty()) { // TODO: create method particle editor insertNewPS and multiple add CWorkspaceNode *node = Modules::psEdit().getParticleWorkspace()->addNode(NLMISC::CFile::getFilename(fileName.toUtf8().constData())); if (node != 0) { try { node->loadPS(); } catch(NLMISC::EStream &e) { QMessageBox::critical(this, tr("NeL particle system editor"), QString(e.what()), QMessageBox::Ok); } if (!node->isLoaded()) Modules::psEdit().getParticleWorkspace()->removeNode(Modules::psEdit().getParticleWorkspace()->getNumNode() - 1); else { QModelIndex index = _treeModel->index(0, 0); _treeModel->insertRows(node, static_cast<CParticleTreeItem *>(index.internalPointer())->childCount(), index); } } } }
void CParticleLinkDialog::setUnlink() { CWorkspaceNode *node = Modules::psEdit().getActiveNode(); if (node == NULL) return; node->unstickPSFromSkeleton(); }
void CParticleEditor::startMultiple() { switch(_State) { case State::Stopped: { if (!_PW) return; nlassert(_PlayingNodes.empty()); TPWNodeItr itr = _PW->getNodeList().begin(); while(itr != _PW->getNodeList().end()) { CWorkspaceNode *node = (*itr); if (node->isLoaded()) if (checkHasLoop(*node)) return; itr++; } itr = _PW->getNodeList().begin(); while(itr != _PW->getNodeList().end()) { CWorkspaceNode *node = (*itr); if (node->isLoaded()) { // really start the node only if there's no trigger anim if (node->getTriggerAnim().empty()) play(*node); _PlayingNodes.push_back(node); } itr++; } } break; case State::PausedSingle: case State::RunningSingle: stop(); startMultiple(); break; case State::RunningMultiple: // no-op return; break; case State::PausedMultiple: for(uint k = 0; k < _PlayingNodes.size(); ++k) { if (_PlayingNodes[k]) { unpause(*_PlayingNodes[k]); } } break; default: nlassert(0); break; } _State = State::RunningMultiple; }
void CParticleEditor::saveWorkspaceContent() { TPWNodeItr itr = _PW->getNodeList().begin(); while(itr != _PW->getNodeList().end()) { CWorkspaceNode *node = (*itr); if (node->isModified()) node->savePS(); node->setModified(false); itr++; } }
void CParticleEditor::setSpeed(float value) { _Speed = value; if (!isRunning()) return; TPWNodeItr itr = _PW->getNodeList().begin(); while(itr != _PW->getNodeList().end()) { CWorkspaceNode *node = (*itr); if (node->isLoaded()) node->getPSModel()->setEllapsedTimeRatio(value); itr++; } }
void CParticleLinkDialog::setLink() { CWorkspaceNode *node = Modules::psEdit().getActiveNode(); if (node == NULL) return; std::string curObj = Modules::objView().getCurrentObject(); if (curObj.empty()) return; CSkeletonTreeItem *item = static_cast<CSkeletonTreeItem *>(_ui.treeView->currentIndex().internalPointer()); NL3D::CSkeletonModel *skel = Modules::objView().getEntity(curObj).getSkeleton().getObjectPtr(); uint boneIndex = item->getId(); std::string parentSkelName = Modules::objView().getEntity(curObj).getFileNameSkeleton(); std::string parentBoneName = skel->Bones[boneIndex].getBoneName(); node->stickPSToSkeleton(skel, boneIndex, parentSkelName, parentBoneName); }
void CParticleEditor::loadWorkspace(const std::string &fullPath) { // Add to the path std::auto_ptr<CParticleWorkspace> newPW(new CParticleWorkspace); newPW->init(fullPath); // save empty workspace try { newPW->load(); } catch(NLMISC::EStream &e) { nlerror(e.what()); return; } // try to load each ps CWorkspaceNode *firstLoadedNode = NULL; TPWNodeItr itr = newPW->getNodeList().begin(); while(itr != newPW->getNodeList().end()) { CWorkspaceNode *node = (*itr); try { node->loadPS(); } catch(NLMISC::EStream &e) { nlwarning(e.what()); } if (node->isLoaded() && !firstLoadedNode) firstLoadedNode = node; itr++; } closeWorkspace(); _PW = newPW.release(); setActiveNode(firstLoadedNode); }
void CWorkspacePage::createPS() { QString fileName = QFileDialog::getSaveFileName(this, tr("Create new particle system file"), ".", tr("ps files (*.ps)")); if (!fileName.isEmpty()) { // TODO: create method particle editor createNewPS if (Modules::psEdit().getParticleWorkspace()->containsFile(NLMISC::CFile::getFilename(fileName.toUtf8().constData()))) { QMessageBox::critical(this, tr("NeL particle system editor"), tr("Failed to create new particle system"), QMessageBox::Ok); return; } CWorkspaceNode *node = Modules::psEdit().getParticleWorkspace()->addNode(NLMISC::CFile::getFilename(fileName.toUtf8().constData())); // should always succeed because we tested if file already exists nlassert(node); node->createEmptyPS(); try { node->savePS(); node->setModified(false); } catch (NLMISC::Exception &e) { QMessageBox::critical(this, tr("NeL particle system editor"), QString(e.what()), QMessageBox::Ok); return; } QModelIndex index = _treeModel->index(0, 0); _treeModel->insertRows(node, static_cast<CParticleTreeItem *>(index.internalPointer())->childCount(), index); } }
void CParticleEditor::stop(CWorkspaceNode &node) { if (!isRunning(&node)) return; nlassert(node.isLoaded()); node.restoreState(); node.getPSModel()->enableAutoGetEllapsedTime(false); node.getPSModel()->setEllapsedTime(0.f); node.getPSModel()->activateEmitters(true); node.getPSPointer()->stopSound(); }
bool CParticleEditor::checkHasLoop(CWorkspaceNode &node) { nlassert(node.isLoaded()); if (!node.getPSPointer()->hasLoop()) return false; return true; }
void CParticleEditor::update() { if (!_ActiveNode) return; if (_PW == NULL) return; NL3D::CParticleSystem *currPS = _ActiveNode->getPSPointer(); // compute BBox if (_DisplayBBox) { if (_AutoUpdateBBox) { NLMISC::CAABBox currBBox; currPS->forceComputeBBox(currBBox); if (_EmptyBBox) { _EmptyBBox = false; _CurrBBox = currBBox; } else { _CurrBBox = NLMISC::CAABBox::computeAABBoxUnion(currBBox, _CurrBBox); } currPS->setPrecomputedBBox(_CurrBBox); } } // auto repeat feature if (_AutoRepeat) { if (isRunning()) { bool allFXFinished = true; bool fxStarted = false; TPWNodeItr itr = _PlayingNodes.begin(); while(itr != _PlayingNodes.end()) { CWorkspaceNode *node = (*itr); if (node->isLoaded()) { if (isRunning(node)) { fxStarted = true; if (node->getPSPointer()->getSystemDate() <= node->getPSPointer()->evalDuration()) { allFXFinished = false; break; } else { if (node->getPSPointer()->getCurrNumParticles() != 0) { allFXFinished = false; break; } } } } itr++; } if (fxStarted && allFXFinished) restartAllFX(); } } // draw PSmodel TPWNodeItr itr = _PW->getNodeList().begin(); while(itr != _PW->getNodeList().end()) { CWorkspaceNode *node = (*itr); if (node->isLoaded()) { if (node == _ActiveNode) node->getPSModel()->enableDisplayTools(!isRunning(node) || _DisplayHelpers); else node->getPSModel()->enableDisplayTools(false); // hide / show the node if (_State == State::RunningMultiple || _State == State::PausedMultiple) { if (isRunning(node)) node->getPSModel()->show(); else node->getPSModel()->hide(); } else { if (node == _ActiveNode) node->getPSModel()->show(); else node->getPSModel()->hide(); } } itr++; } }