diff --git a/src/ControlManager.cpp b/src/ControlManager.cpp index 121f319..18f868f 100644 --- a/src/ControlManager.cpp +++ b/src/ControlManager.cpp @@ -632,7 +632,7 @@ bool Control::receiveSourceAttribute(Source *target, const std::string &attribut else if ( attribute.compare(OSC_SOURCE_LOOM) == 0) { float x = 1.f; arguments >> x >> osc::EndMessage; - target->call( new Loom(x, 0.f), true ); + target->call( new Loom(x, 0.f) ); // this will require to send feedback status about source send_feedback = true; } @@ -662,7 +662,7 @@ bool Control::receiveSourceAttribute(Source *target, const std::string &attribut catch (osc::WrongArgumentTypeException &) { } arguments >> osc::EndMessage; - target->call( new Grab( x, y, 0.f), true ); + target->call( new Grab( x, y, 0.f) ); } /// e.g. '/vimix/current/position ff 10.0 2.2' else if ( attribute.compare(OSC_SOURCE_POSITION) == 0) { @@ -699,7 +699,7 @@ bool Control::receiveSourceAttribute(Source *target, const std::string &attribut catch (osc::WrongArgumentTypeException &) { } arguments >> osc::EndMessage; - target->call( new Resize( x, y, 0.f), true ); + target->call( new Resize( x, y, 0.f) ); } /// e.g. '/vimix/current/size ff 1.0 2.2' else if ( attribute.compare(OSC_SOURCE_SIZE) == 0) { @@ -730,7 +730,7 @@ bool Control::receiveSourceAttribute(Source *target, const std::string &attribut arguments >> osc::EndMessage; else arguments >> t >> osc::EndMessage; - target->call( new Turn( x, t), true ); + target->call( new Turn( x, t) ); } /// e.g. '/vimix/current/angle f 3.1416' else if ( attribute.compare(OSC_SOURCE_ANGLE) == 0) { diff --git a/src/Session.cpp b/src/Session.cpp index 528741e..ae6cfcf 100644 --- a/src/Session.cpp +++ b/src/Session.cpp @@ -76,13 +76,18 @@ Session::Session(uint64_t id) : id_(id), active_(true), activation_threshold_(MI } -void Session::InputSourceCallback::clearReverse() +void Session::InputSourceCallback::clear() { - for (auto rev = reverse_.begin(); rev != reverse_.end(); ++rev) { - if (rev->second != nullptr) - delete rev->second; + // go through all instances stored in InputSourceCallback + for (auto clb = instances_.begin(); clb != instances_.end(); ++clb) { + // finish all + if (clb->second.first != nullptr) + clb->second.first->finish(); + if (clb->second.second != nullptr) + clb->second.second->finish(); } - reverse_.clear(); + // do not keep references: will be deleted when terminated + instances_.clear(); } Session::~Session() @@ -105,7 +110,7 @@ Session::~Session() iter = input_callbacks_.erase(iter)) { if ( iter->second.model_ != nullptr) delete iter->second.model_; - iter->second.clearReverse(); + iter->second.clear(); } delete config_[View::RENDERING]; @@ -151,13 +156,10 @@ void Session::update(float dt) if ( k->second.model_ != nullptr && k->second.target_.index() > 0) { // if the value referenced as pressed changed state - // or repeat key if there is no reverse callback - if ( input_active != k->second.active_ || k->second.reverse_.empty()) { + if ( input_active != k->second.active_ ) { // ON PRESS if (input_active) { - // delete the reverse if was not released - k->second.clearReverse(); // Add callback to the target(s) // 1. Case of variant as Source pointer @@ -165,15 +167,18 @@ void Session::update(float dt) // verify variant value if ( *v != nullptr ) { // generate a new callback from the model - SourceCallback *C = k->second.model_->clone(); + SourceCallback *forward = k->second.model_->clone(); // apply value multiplyer from input - C->multiply( Control::manager().inputValue(k->first) ); + forward->multiply( Control::manager().inputValue(k->first) ); // add delay - C->delay( Metronome::manager().timeToSync( (Metronome::Synchronicity) input_sync_[k->first] ) ); + forward->delay( Metronome::manager().timeToSync( (Metronome::Synchronicity) input_sync_[k->first] ) ); // add callback to source - (*v)->call( C, true ); - // get the reverse if the callback, and remember it (can be null) - k->second.reverse_[(*v)->id()] = C->reverse(*v); + (*v)->call( forward ); + // get the reverse of the callback (can be null) + SourceCallback *backward = forward->reverse(*v);; + // remember instances + k->second.instances_[(*v)->id()] = {forward, backward}; + } } // 2. Case of variant as index of batch @@ -186,15 +191,17 @@ void Session::update(float dt) SourceList::const_iterator sit = std::find_if(sources_.begin(), sources_.end(), Source::hasId(*sid));; if ( sit != sources_.end()) { // generate a new callback from the model - SourceCallback *C = k->second.model_->clone(); + SourceCallback *forward = k->second.model_->clone(); // apply value multiplyer from input - C->multiply( Control::manager().inputValue(k->first) ); + forward->multiply( Control::manager().inputValue(k->first) ); // add delay - C->delay( Metronome::manager().timeToSync( (Metronome::Synchronicity) input_sync_[k->first] ) ); + forward->delay( Metronome::manager().timeToSync( (Metronome::Synchronicity) input_sync_[k->first] ) ); // add callback to source - (*sit)->call( C, true ); - // get the reverse if the callback, and remember it (can be null) - k->second.reverse_[*sid] = C->reverse(*sit); + (*sit)->call( forward ); + // get the reverse of the callback (can be null) + SourceCallback *backward = forward->reverse(*sit);; + // remember instances + k->second.instances_[*sid] = {forward, backward}; } } } @@ -202,15 +209,22 @@ void Session::update(float dt) } // ON RELEASE else { - // call all the reverse of sources (NB: invalid value tested in call) - for (auto rev = k->second.reverse_.begin(); rev != k->second.reverse_.end(); ++rev) { - SourceList::const_iterator sit = std::find_if(sources_.begin(), sources_.end(), Source::hasId(rev->first));; + // go through all instances stored for that action + for (auto clb = k->second.instances_.begin(); clb != k->second.instances_.end(); ++clb) { + // find the source referenced by each instance + SourceList::const_iterator sit = std::find_if(sources_.begin(), sources_.end(), Source::hasId(clb->first));; + // if the source is valid if ( sit != sources_.end()) { - (*sit)->call( rev->second, true ); + // either call the reverse if exists (stored as second element in pair) + if (clb->second.second != nullptr) + (*sit)->call( clb->second.second, true ); + // or finish the called + else + (*sit)->finish( clb->second.first ); } } - // do not keep reference to reverse: will be deleted when terminated - k->second.reverse_.clear(); + // do not keep reference to instances: will be deleted when finished + k->second.instances_.clear(); } // remember state of callback @@ -779,7 +793,7 @@ void Session::assignInputCallback(uint input, Target target, SourceCallback *cal if ( k->second.model_ == callback) { k->second.target_ = target; // reverse became invalid - k->second.clearReverse(); + k->second.clear(); break; } } @@ -837,7 +851,7 @@ void Session::deleteInputCallback(SourceCallback *callback) { if ( k->second.model_ == callback) { delete callback; - k->second.clearReverse(); + k->second.clear(); input_callbacks_.erase(k); break; } @@ -851,7 +865,7 @@ void Session::deleteInputCallbacks(uint input) if ( k->first == input) { if (k->second.model_) delete k->second.model_; - k->second.clearReverse(); + k->second.clear(); k = input_callbacks_.erase(k); } else @@ -866,7 +880,7 @@ void Session::deleteInputCallbacks(Target target) if ( k->second.target_ == target) { if (k->second.model_) delete k->second.model_; - k->second.clearReverse(); + k->second.clear(); k = input_callbacks_.erase(k); } else @@ -881,7 +895,7 @@ void Session::clearInputCallbacks() { if (k->second.model_) delete k->second.model_; - k->second.clearReverse(); + k->second.clear(); k = input_callbacks_.erase(k); } diff --git a/src/Session.h b/src/Session.h index f4c20d2..7797eaa 100644 --- a/src/Session.h +++ b/src/Session.h @@ -217,14 +217,14 @@ protected: struct InputSourceCallback { bool active_; SourceCallback *model_; - std::map reverse_; + std::map > instances_; Target target_; InputSourceCallback() { active_ = false; model_ = nullptr; target_ = nullptr; } - void clearReverse(); + void clear(); }; std::multimap input_callbacks_; std::vector input_sync_; diff --git a/src/Source.cpp b/src/Source.cpp index ee8f354..1eea993 100644 --- a/src/Source.cpp +++ b/src/Source.cpp @@ -655,38 +655,17 @@ void Source::call(SourceCallback *callback, bool override) // lock access to callbacks list access_callbacks_.lock(); - bool add = true; - - // look for callbacks of same type - for (auto iter=update_callbacks_.begin(); iter != update_callbacks_.end(); ) - { - // Test if the new callback would overlap an existing one - SourceCallback *c = *iter; - if ( SourceCallback::overlap( callback, c) ) { - if (override) { - // either remove and delete all overlapping callbacks if override... - iter = update_callbacks_.erase(iter); - delete c; - } - else { - // ...or cancel adding overlapping callbacks if not override - add = false; - break; - } + // if operation should override previous callbacks of same type + if (override) { + // finish all callbacks of the same type + for (auto iter=update_callbacks_.begin(); iter != update_callbacks_.end(); ++iter) { + if ( callback->type() == (*iter)->type() ) + (*iter)->finish(); } - // iterate - else - ++iter; } - // we can add the callback : its either not overlapping or we override it - if (add) { - // add callback to callbacks list - update_callbacks_.push_back(callback); - } - // or delete it if couln't be added (overlapping but not override) - else - delete callback; + // allways add the given callback to list of callbacks + update_callbacks_.push_back(callback); // release access to callbacks list access_callbacks_.unlock(); @@ -694,10 +673,29 @@ void Source::call(SourceCallback *callback, bool override) } +void Source::finish(SourceCallback *callback) +{ + if (callback != nullptr) { + + // lock access to callbacks list + access_callbacks_.lock(); + + // make sure the given pointer is a callback listed in this source + auto cb = std::find(update_callbacks_.begin(), update_callbacks_.end(), callback); + if (cb != update_callbacks_.end()) + // set found callback to finish state + (*cb)->finish(); + + // release access to callbacks list + access_callbacks_.unlock(); + } +} + void Source::updateCallbacks(float dt) { // lock access to callbacks list access_callbacks_.lock(); + // call callback functions for (auto iter=update_callbacks_.begin(); iter != update_callbacks_.end(); ) { @@ -716,9 +714,9 @@ void Source::updateCallbacks(float dt) else ++iter; } + // release access to callbacks list access_callbacks_.unlock(); - } CloneSource *Source::clone(uint64_t id) diff --git a/src/Source.h b/src/Source.h index 9fb31fe..f7ed9cd 100644 --- a/src/Source.h +++ b/src/Source.h @@ -149,6 +149,7 @@ public: // add callback to each update void call(SourceCallback *callback, bool override = false); + void finish(SourceCallback *callback); // update mode inline bool active () const { return active_; } diff --git a/src/SourceCallback.cpp b/src/SourceCallback.cpp index ba1ce0b..1b0e659 100644 --- a/src/SourceCallback.cpp +++ b/src/SourceCallback.cpp @@ -22,9 +22,7 @@ #include "ImageProcessingShader.h" #include "MediaSource.h" #include "MediaPlayer.h" -#include "UpdateCallback.h" #include "Visitor.h" -#include "Log.h" #include "SourceCallback.h" @@ -101,53 +99,6 @@ SourceCallback *SourceCallback::create(CallbackType type) return loadedcallback; } - -bool SourceCallback::overlap( SourceCallback *a, SourceCallback *b) -{ - bool ret = false; - - if (a->type() == b->type()) { - - // same type means overlap - ret = true; - - // but there are some exceptions.. - switch (a->type()) { - case SourceCallback::CALLBACK_GRAB: - { - const Grab *_a = static_cast(a); - const Grab *_b = static_cast(b); - if ( ABS_DIFF(_a->value().x, _b->value().x) > EPSILON || ABS_DIFF(_a->value().y, _b->value().y) > EPSILON ) - ret = false; - -// // there is no overlap if the X or Y of a vector is zero -// if ( ABS(_a->value().x) < EPSILON || ABS(_b->value().x) < EPSILON ) -// ret = false; -// else if ( ABS(_a->value().y) < EPSILON || ABS(_b->value().y) < EPSILON ) -// ret = false; - } - break; - case SourceCallback::CALLBACK_RESIZE: - { - const Resize *_a = static_cast(a); - const Resize *_b = static_cast(b); - if ( ABS_DIFF(_a->value().x, _b->value().x) > EPSILON || ABS_DIFF(_a->value().y, _b->value().y) > EPSILON ) - ret = false; -// if ( ABS(_a->value().x) < EPSILON || ABS(_b->value().x) < EPSILON ) -// ret = false; -// else if ( ABS(_a->value().y) < EPSILON || ABS(_b->value().y) < EPSILON ) -// ret = false; - } - break; - default: - break; - } - - } - - return ret; -} - SourceCallback::SourceCallback(): status_(PENDING), delay_(0.f), elapsed_(0.f) { } @@ -384,7 +335,6 @@ SourceCallback *Lock::clone() const Loom::Loom(float speed, float ms) : SourceCallback(), speed_(speed), duration_(ms) { - pos_ = glm::vec2(); step_ = glm::normalize(glm::vec2(1.f, 1.f)); // step in diagonal by default } @@ -395,13 +345,14 @@ void Loom::update(Source *s, float dt) if (s->locked()) status_ = FINISHED; + // current position + glm::vec2 pos = glm::vec2(s->group(View::MIXING)->translation_); + // set start on first time it is ready if ( status_ == READY ){ - // initial position - pos_ = glm::vec2(s->group(View::MIXING)->translation_); // step in direction of source translation if possible - if ( glm::length(pos_) > DELTA_ALPHA) - step_ = glm::normalize(pos_); + if ( glm::length(pos) > DELTA_ALPHA) + step_ = glm::normalize(pos); status_ = ACTIVE; } @@ -410,12 +361,12 @@ void Loom::update(Source *s, float dt) float progress = elapsed_ - delay_; // move target by speed vector (in the direction of step_, amplitude of speed * time (in second)) - pos_ -= step_ * ( speed_ * dt * 0.001f ); + pos -= step_ * ( speed_ * dt * 0.001f ); - // apply alpha if pos in range [0 MIXING_MIN_THRESHOLD] - float l = glm::length( pos_ ); - if ( (l > 0.01f && speed_ > 0.f ) || (l < MIXING_MIN_THRESHOLD && speed_ < 0.f ) ) - s->group(View::MIXING)->translation_ = glm::vec3(pos_, s->group(View::MIXING)->translation_.z); + // apply alpha if pos in range [0 MIXING_MAX_THRESHOLD] + float l = glm::length( pos ); + if ( (l > 0.01f && speed_ > 0.f ) || (l < MIXING_MAX_THRESHOLD && speed_ < 0.f ) ) + s->group(View::MIXING)->translation_ = glm::vec3(pos, s->group(View::MIXING)->translation_.z); else status_ = FINISHED; @@ -436,11 +387,6 @@ SourceCallback *Loom::clone() const return new Loom(speed_, duration_); } -SourceCallback *Loom::reverse(Source *) const -{ - return new Loom(speed_, 0.f); -} - void Loom::accept(Visitor& v) { SourceCallback::accept(v); @@ -696,15 +642,15 @@ void Grab::update(Source *s, float dt) // set start on first time it is ready if ( status_ == READY ) { // initial position - pos_ = glm::vec2(s->group(View::GEOMETRY)->translation_); status_ = ACTIVE; } if ( status_ == ACTIVE ) { // move target by speed vector * time (in second) - pos_ += speed_ * ( dt * 0.001f); - s->group(View::GEOMETRY)->translation_ = glm::vec3(pos_, s->group(View::GEOMETRY)->translation_.z); + glm::vec2 pos = glm::vec2(s->group(View::GEOMETRY)->translation_); + pos += speed_ * ( dt * 0.001f); + s->group(View::GEOMETRY)->translation_ = glm::vec3(pos, s->group(View::GEOMETRY)->translation_.z); // time-out if ( (elapsed_ - delay_) > duration_ ) @@ -723,11 +669,6 @@ SourceCallback *Grab::clone() const return new Grab(speed_.x, speed_.y, duration_); } -SourceCallback *Grab::reverse(Source *) const -{ - return new Grab(speed_.x, speed_.y, 0.f); -} - void Grab::accept(Visitor& v) { SourceCallback::accept(v); @@ -770,11 +711,6 @@ SourceCallback *Resize::clone() const return new Resize(speed_.x, speed_.y, duration_); } -SourceCallback *Resize::reverse(Source *) const -{ - return new Resize(speed_.x, speed_.y, 0.f); -} - void Resize::accept(Visitor& v) { SourceCallback::accept(v); @@ -795,16 +731,17 @@ void Turn::update(Source *s, float dt) // set start on first time it is ready if ( status_ == READY ){ - // initial position - angle_ = s->group(View::GEOMETRY)->rotation_.z; status_ = ACTIVE; } if ( status_ == ACTIVE ) { + // current position + float angle = s->group(View::GEOMETRY)->rotation_.z; + // perform movement - angle_ -= speed_ * ( dt * 0.001f ); - s->group(View::GEOMETRY)->rotation_.z = angle_; + angle -= speed_ * ( dt * 0.001f ); + s->group(View::GEOMETRY)->rotation_.z = angle; // timeout if ( (elapsed_ - delay_) > duration_ ) @@ -823,11 +760,6 @@ SourceCallback *Turn::clone() const return new Turn(speed_, duration_); } -SourceCallback *Turn::reverse(Source *) const -{ - return new Turn(speed_, 0.f); -} - void Turn::accept(Visitor& v) { SourceCallback::accept(v); diff --git a/src/SourceCallback.h b/src/SourceCallback.h index 12cfb49..fe7b788 100644 --- a/src/SourceCallback.h +++ b/src/SourceCallback.h @@ -50,7 +50,6 @@ public: } CallbackType; static SourceCallback *create(CallbackType type); - static bool overlap(SourceCallback *a, SourceCallback *b); SourceCallback(); virtual ~SourceCallback() {} @@ -62,8 +61,9 @@ public: virtual CallbackType type () const { return CALLBACK_GENERIC; } virtual void accept (Visitor& v); - inline bool finished () const { return status_ > ACTIVE; } inline void reset () { status_ = PENDING; } + inline void finish () { status_ = FINISHED; } + inline bool finished () const { return status_ > ACTIVE; } inline void delay (float milisec) { delay_ = milisec;} protected: @@ -146,7 +146,6 @@ public: class Loom : public SourceCallback { float speed_; - glm::vec2 pos_; glm::vec2 step_; float duration_; @@ -161,7 +160,6 @@ public: void update (Source *s, float) override; void multiply (float factor) override; SourceCallback *clone() const override; - SourceCallback *reverse(Source *) const override; CallbackType type () const override { return CALLBACK_LOOM; } void accept (Visitor& v) override; }; @@ -273,7 +271,6 @@ public: class Grab : public SourceCallback { glm::vec2 speed_; - glm::vec2 pos_; float duration_; public: @@ -287,7 +284,6 @@ public: void update (Source *s, float) override; void multiply (float factor) override; SourceCallback *clone () const override; - SourceCallback *reverse(Source *) const override; CallbackType type () const override { return CALLBACK_GRAB; } void accept (Visitor& v) override; }; @@ -308,7 +304,6 @@ public: void update (Source *s, float) override; void multiply (float factor) override; SourceCallback *clone () const override; - SourceCallback *reverse(Source *) const override; CallbackType type () const override { return CALLBACK_RESIZE; } void accept (Visitor& v) override; }; @@ -316,7 +311,6 @@ public: class Turn : public SourceCallback { float speed_; - float angle_; float duration_; public: @@ -330,7 +324,6 @@ public: void update (Source *s, float) override; void multiply (float factor) override; SourceCallback *clone () const override; - SourceCallback *reverse(Source *) const override; CallbackType type () const override { return CALLBACK_TURN; } void accept (Visitor& v) override; }; diff --git a/src/UserInterfaceManager.cpp b/src/UserInterfaceManager.cpp index 6e8dbe8..546853d 100644 --- a/src/UserInterfaceManager.cpp +++ b/src/UserInterfaceManager.cpp @@ -1207,7 +1207,7 @@ void UserInterface::RenderMetrics(bool *p_open, int* p_corner, int *p_mode) float v = s->alpha(); ImGui::SetNextItemWidth(rightalign); if ( ImGui::DragFloat("Alpha", &v, 0.01f, 0.f, 1.f) ) - s->call(new SetAlpha(v)); + s->call(new SetAlpha(v), true); if ( ImGui::IsItemDeactivatedAfterEdit() ) { info << "Alpha " << std::fixed << std::setprecision(3) << v; Action::manager().store(info.str());