#include "tparamset.h" #include "tundo.h" //#include "tparam.h" #include "tdoubleparam.h" #include "tstream.h" #include //--------------------------------------------------------- /* class ChangeBlock { public: ChangeBlock() : m_firstAffectedFrame ( TParamChange::m_maxFrame) , m_lastAffectedFrame ( TParamChange::m_minFrame) { } ~ChangeBlock() { } void add(const TParamChange &change) { m_firstAffectedFrame = tmin(m_firstAffectedFrame, change.m_firstAffectedFrame); m_lastAffectedFrame = tmax(m_lastAffectedFrame , change.m_lastAffectedFrame); m_changes.push_back(change.clone()); } vector m_changes; double m_firstAffectedFrame; double m_lastAffectedFrame; }; */ namespace { void doRelease(const pair ¶m) { param.first->release(); } }; //------------------------------------------------------------------------------ class TParamSetImp : public TParamObserver { friend class TParamSet; TParamSet *m_param; vector> m_params; // ChangeBlock *m_changeBlock; bool m_draggingEnabled, m_notificationEnabled; public: TParamSetImp(TParamSet *param) : m_param(param) //, m_changeBlock(0) , m_draggingEnabled(false), m_notificationEnabled(true) { } ~TParamSetImp() { std::for_each(m_params.begin(), m_params.end(), doRelease); } // std::set m_observers; std::set m_paramObservers; template void notify(const T &change); void onChange(const TParamChange &change) { /* if (!m_changeBlock) // se non stiamo modificando un blocco di parametri, invio la notifica { vector params; params.push_back(change.m_param); TParamSetChange psChange(m_param, change.m_firstAffectedFrame, change.m_lastAffectedFrame, params, change.m_undoing); notify(psChange); } else notify(change); if (!m_changeBlock) // se non stiamo modificando un blocco di parametri, invio la notifica notify(change); else { //metto da parte la TParamChange, per poi alla fine notificare una TParamSetChange m_changeBlock->add(change); } */ } }; //--------------------------------------------------------- TParamSet::TParamSet(string name) : TParam(name) , m_imp(new TParamSetImp(this)) { } //--------------------------------------------------------- TParamSet::TParamSet(const TParamSet &src) : TParam(src.getName()) , m_imp(new TParamSetImp(this)) { } //--------------------------------------------------------- TParamSet::~TParamSet() { } //--------------------------------------------------------- /* template class MyBackInsertIterator : public std::iterator { protected: Container &container; public: MyBackInsertIterator(Container &c) : container(c) {} MyBackInsertIterator &operator=(const typename Container::value_type &value) { container.push_back(value); return *this; } MyBackInsertIterator&operator*() { return *this; } MyBackInsertIterator&operator++() { return *this; } MyBackInsertIterator&operator++(int) { return *this; } }; */ //--------------------------------------------------------- void TParamSet::beginParameterChange() { // assert(0); //std::set::iterator it = m_imp->m_observers.begin(); //for (;it != m_imp->m_observers.end(); ++it) // (*it)->onBeginChangeBlock(this); //assert(!m_imp->m_changeBlock); vector params; /* MyBackInsertIterator > > myBackInsertIterator(params); copy(m_imp->m_params.begin(), m_imp->m_params.end(), myIterator); */ std::vector>::iterator it2 = m_imp->m_params.begin(); for (; it2 != m_imp->m_params.end(); ++it2) params.push_back(it2->first); // m_imp->m_changeBlock = new ChangeBlock; }; //--------------------------------------------------------- void TParamSet::endParameterChange(){ // assert(0); //assert(m_imp->m_changeBlock); /* TParamSetChange change(this, m_imp->m_changeBlock->m_firstAffectedFrame, m_imp->m_changeBlock->m_lastAffectedFrame, m_imp->m_changeBlock->m_changes, false); change.m_dragging = m_imp->m_draggingEnabled; //delete m_imp->m_changeBlock; //m_imp->m_changeBlock = 0; //m_imp->notify(change); //std::set::iterator it = m_imp->m_observers.begin(); //for (;it != m_imp->m_observers.end(); ++it) // (*it)->onEndChangeBlock(this); m_imp->notify(change); */ }; //--------------------------------------------------------- void TParamSet::addParam(const TParamP ¶m, const string &name) { pair paramToInsert = std::make_pair(param.getPointer(), name); std::vector>::iterator it = std::find(m_imp->m_params.begin(), m_imp->m_params.end(), paramToInsert); if (it == m_imp->m_params.end()) { param->addRef(); param->addObserver(m_imp); m_imp->m_params.push_back(paramToInsert); //TParamSetParamAdded psParamAdded(this, param.getPointer(), name, false); if (param->getName().empty()) param->setName(name); //m_imp->notify(psParamAdded); } } //--------------------------------------------------------- void TParamSet::insertParam(const TParamP ¶m, const string &name, int index) { pair paramToInsert = std::make_pair(param.getPointer(), name); std::vector>::iterator it = std::find(m_imp->m_params.begin(), m_imp->m_params.end(), paramToInsert); if (it == m_imp->m_params.end()) { param->addRef(); param->addObserver(m_imp); it = m_imp->m_params.begin(); int f; for (f = 0; f < index; f++) it++; m_imp->m_params.insert(it, paramToInsert); if (param->getName().empty()) param->setName(name); } } //--------------------------------------------------------- namespace { class matchesParam { TParamP m_param; public: matchesParam(const TParamP ¶m) : m_param(param) {} bool operator()(const pair ¶m) { return m_param.getPointer() == param.first; } }; } //--------------------------------------------------------- void TParamSet::removeParam(const TParamP ¶m) { std::vector>::iterator it = std::find_if(m_imp->m_params.begin(), m_imp->m_params.end(), matchesParam(param)); if (it != m_imp->m_params.end()) { param->removeObserver(m_imp); //TParamSetParamRemoved psParamRemoved(this, param.getPointer(), it->second, false); //m_imp->notify(psParamRemoved); param->release(); m_imp->m_params.erase(it); } } //--------------------------------------------------------- void TParamSet::removeAllParam() { while (!m_imp->m_params.empty()) { std::vector>::iterator it = m_imp->m_params.begin(); TParam *param = it->first; param->removeObserver(m_imp); param->release(); m_imp->m_params.erase(it); } } //--------------------------------------------------------- int TParamSet::getParamCount() const { return m_imp->m_params.size(); } //--------------------------------------------------------- TParamP TParamSet::getParam(int i) const { assert(i >= 0 && i < (int)m_imp->m_params.size()); return m_imp->m_params[i].first; } //--------------------------------------------------------- string TParamSet::getParamName(int i) const { assert(i >= 0 && i < (int)m_imp->m_params.size()); return m_imp->m_params[i].second; } //--------------------------------------------------------- int TParamSet::getParamIdx(const string &name) const { int i, paramsCount = m_imp->m_params.size(); for (i = 0; i < paramsCount; ++i) if (m_imp->m_params[i].second == name) break; return i; } //--------------------------------------------------------- void TParamSet::getAnimatableParams(vector ¶ms, bool recursive) { std::vector>::iterator it = m_imp->m_params.begin(); for (; it != m_imp->m_params.end(); ++it) { TParam *param = it->first; TDoubleParamP dparam = TParamP(param); if (dparam) params.push_back(dparam); else { TParamSetP paramset = TParamP(param); if (paramset && recursive) paramset->getAnimatableParams(params, recursive); } } } //--------------------------------------------------------- void TParamSet::addObserver(TParamObserver *observer) { //TParamSetObserver *obs = dynamic_cast(observer); //if (obs) // m_imp->m_observers.insert(obs); //else m_imp->m_paramObservers.insert(observer); } //--------------------------------------------------------- template void TParamSetImp::notify(const T &change) { if (m_notificationEnabled) { // for (std::set::iterator it = m_observers.begin(); // it!= m_observers.end(); // ++it) // (*it)->onChange(change); for (std::set::iterator paramIt = m_paramObservers.begin(); paramIt != m_paramObservers.end(); ++paramIt) (*paramIt)->onChange(change); } } //--------------------------------------------------------- void TParamSet::removeObserver(TParamObserver *observer) { //TParamSetObserver *obs = dynamic_cast(observer); //if (obs) // m_imp->m_observers.erase(obs); //else m_imp->m_paramObservers.erase(observer); } //--------------------------------------------------------- void TParamSet::enableDragging(bool on) { std::vector>::iterator it = m_imp->m_params.begin(); for (; it != m_imp->m_params.end(); ++it) { TDoubleParamP dparam(it->first); //if (dparam) // dparam->enableDragging(on); } m_imp->m_draggingEnabled = on; } //--------------------------------------------------------- /* namespace { class DoEnableNotification : public std::binary_function { public: DoEnableNotification() {} void operator() (const pair ¶m, bool on) { return param->first->enableNotification(on); } }; } */ //--------------------------------------------------------- void TParamSet::enableNotification(bool on) { // std::for_each(m_imp->m_params.begin(), m_imp->m_params.end(), std::bind2nd(DoEnableNotification, on)); std::vector>::iterator it = m_imp->m_params.begin(); for (; it != m_imp->m_params.end(); ++it) { it->first->enableNotification(on); } m_imp->m_notificationEnabled = on; } //--------------------------------------------------------- bool TParamSet::isNotificationEnabled() const { return m_imp->m_notificationEnabled; } //--------------------------------------------------------- bool TParamSet::isKeyframe(double frame) const { for (int i = 0; i < getParamCount(); i++) if (getParam(i)->isKeyframe(frame)) return true; return false; } //--------------------------------------------------------- void TParamSet::getKeyframes(std::set &frames) const { for (int i = 0; i < getParamCount(); i++) getParam(i)->getKeyframes(frames); } //--------------------------------------------------------- double TParamSet::keyframeIndexToFrame(int index) const { std::set frames; getKeyframes(frames); assert(0 <= index && index < (int)frames.size()); std::set::const_iterator it = frames.begin(); std::advance(it, index); return *it; } //--------------------------------------------------------- int TParamSet::getNextKeyframe(double frame) const { std::set frames; getKeyframes(frames); std::set::iterator it = frames.upper_bound(frame); if (it == frames.end()) return -1; else return std::distance(frames.begin(), it); } //--------------------------------------------------------- int TParamSet::getPrevKeyframe(double frame) const { std::set frames; getKeyframes(frames); std::set::iterator it = frames.lower_bound(frame); if (it == frames.begin()) return -1; else { --it; return std::distance(frames.begin(), it); } } //--------------------------------------------------------- bool TParamSet::hasKeyframes() const { for (int i = 0; i < getParamCount(); i++) if (getParam(i)->hasKeyframes()) return true; return false; } //--------------------------------------------------------- int TParamSet::getKeyframeCount() const { std::set frames; getKeyframes(frames); return frames.size(); } //--------------------------------------------------------- void TParamSet::deleteKeyframe(double frame) { for (int i = 0; i < getParamCount(); i++) getParam(i)->deleteKeyframe(frame); } //--------------------------------------------------------- void TParamSet::clearKeyframes() { for (int i = 0; i < getParamCount(); i++) getParam(i)->clearKeyframes(); } //--------------------------------------------------------- void TParamSet::assignKeyframe( double frame, const TParamP &src, double srcFrame, bool changedOnly) { TParamSetP paramSetSrc = src; if (!paramSetSrc) return; if (getParamCount() != paramSetSrc->getParamCount()) return; for (int i = 0; i < getParamCount(); i++) getParam(i)->assignKeyframe( frame, paramSetSrc->getParam(i), srcFrame, changedOnly); } //--------------------------------------------------------- TParam *TParamSet::clone() const { return new TParamSet(*this); } //--------------------------------------------------------- void TParamSet::copy(TParam *src) { TParamSet *p = dynamic_cast(src); if (!p) throw TException("invalid source for copy"); int srcParamCount = p->getParamCount(); removeAllParam(); int i; for (i = 0; i < srcParamCount; i++) { TParamP param = p->getParam(i); addParam(param->clone(), param->getName()); } } //--------------------------------------------------------- void TParamSet::loadData(TIStream &is) { string tagName; is.openChild(tagName); while (!is.eos()) { string paramName; is.openChild(paramName); TPersist *p = 0; is >> p; TParam *param = dynamic_cast(p); assert(param); addParam(param, paramName); is.closeChild(); } is.closeChild(); } //--------------------------------------------------------- void TParamSet::saveData(TOStream &os) { os.openChild(getName()); std::vector>::iterator it = m_imp->m_params.begin(); std::vector>::iterator end = m_imp->m_params.end(); while (it != end) { os.openChild(it->second); //it->first->saveData(os); os << it->first; os.closeChild(); ++it; } os.closeChild(); } //--------------------------------------------------------- string TParamSet::getValueAlias(double frame, int precision) { string alias = "("; std::vector>::iterator end = m_imp->m_params.begin(); std::advance(end, m_imp->m_params.size() - 1); std::vector>::iterator it = m_imp->m_params.begin(); for (; it != end; ++it) alias += it->first->getValueAlias(frame, precision) + ","; alias += it->first->getValueAlias(frame, precision); alias += ")"; return alias; } //--------------------------------------------------------- TPersistDeclarationT TParamSet::m_declaration("TParamSet");