From 706c72fda8eeb2437bef2404d2c99d4dca49072b Mon Sep 17 00:00:00 2001 From: Bruno Herbelin Date: Tue, 21 Dec 2021 00:19:39 +0100 Subject: [PATCH] More OSC control Grab and resize dynamically, select source by index, etc. --- ControlManager.cpp | 31 ++++++++++----- ControlManager.h | 11 ++++-- SourceCallback.cpp | 92 +++++++++++++++++++++++++++++++-------------- SourceCallback.h | 37 ++++++++++++++---- rsc/osc/vimix.tosc | Bin 1822 -> 4227 bytes 5 files changed, 123 insertions(+), 48 deletions(-) diff --git a/ControlManager.cpp b/ControlManager.cpp index e4153b7..f778eaa 100644 --- a/ControlManager.cpp +++ b/ControlManager.cpp @@ -97,11 +97,14 @@ void Control::RequestListener::ProcessMessage( const osc::ReceivedMessage& m, else if ( target.compare(OSC_CURRENT) == 0 ) { // attributes to change current - if ( attribute.compare(OSC_CURRENT_NONE) == 0) - Mixer::manager().unsetCurrentSource(); - else if ( attribute.compare(OSC_CURRENT_NEXT) == 0) + if ( attribute.compare(OSC_SET) == 0) { + int index = 0; + m.ArgumentStream() >> index >> osc::EndMessage; + Mixer::manager().setCurrentIndex(index); + } + else if ( attribute.compare(OSC_NEXT) == 0) Mixer::manager().setCurrentNext(); - else if ( attribute.compare(OSC_CURRENT_PREVIOUS) == 0) + else if ( attribute.compare(OSC_PREVIOUS) == 0) Mixer::manager().setCurrentPrevious(); // all other attributes operate on current source else @@ -259,17 +262,21 @@ void Control::setSourceAttribute(Source *target, const std::string &attribute, } target->call( new SetPlay(!on) ); } + /// e.g. '/vimix/current/replay' + else if ( attribute.compare(OSC_SOURCE_REPLAY) == 0) { + target->call( new RePlay() ); + } /// e.g. '/vimix/current/alpha f 0.3' else if ( attribute.compare(OSC_SOURCE_ALPHA) == 0) { - float x = 0.f; + float x = 1.f; arguments >> x >> osc::EndMessage; - target->call( new SetAlpha(x) ); + target->call( new SetAlpha(x), true ); } /// e.g. '/vimix/current/transparency f 0.7' else if ( attribute.compare(OSC_SOURCE_TRANSPARENCY) == 0) { float x = 0.f; arguments >> x >> osc::EndMessage; - target->call( new SetAlpha(1.f - x) ); + target->call( new SetAlpha(1.f - x), true ); } /// e.g. '/vimix/current/depth f 5.0' else if ( attribute.compare(OSC_SOURCE_DEPTH) == 0) { @@ -278,10 +285,16 @@ void Control::setSourceAttribute(Source *target, const std::string &attribute, target->call( new SetDepth(x) ); } /// e.g. '/vimix/current/translation ff 10.0 2.2' - else if ( attribute.compare(OSC_SOURCE_TRANSLATE) == 0) { + else if ( attribute.compare(OSC_SOURCE_GRAB) == 0) { float x = 0.f, y = 0.f; arguments >> x >> y >> osc::EndMessage; - target->call( new Translation( x, y), true ); + target->call( new Grab( x, y), true ); + } + /// e.g. '/vimix/current/scale ff 10.0 2.2' + else if ( attribute.compare(OSC_SOURCE_RESIZE) == 0) { + float x = 0.f, y = 0.f; + arguments >> x >> y >> osc::EndMessage; + target->call( new Resize( x, y), true ); } #ifdef CONTROL_DEBUG else { diff --git a/ControlManager.h b/ControlManager.h index c412a18..6701443 100644 --- a/ControlManager.h +++ b/ControlManager.h @@ -14,16 +14,19 @@ #define OSC_ALL "all" #define OSC_SELECTED "selected" #define OSC_CURRENT "current" -#define OSC_CURRENT_NONE "none" -#define OSC_CURRENT_NEXT "next" -#define OSC_CURRENT_PREVIOUS "previous" +#define OSC_NEXT "next" +#define OSC_PREVIOUS "previous" +#define OSC_SET "set" +//#define OSC_VERSION "version" #define OSC_SOURCE_PLAY "play" #define OSC_SOURCE_PAUSE "pause" +#define OSC_SOURCE_REPLAY "replay" #define OSC_SOURCE_ALPHA "alpha" #define OSC_SOURCE_TRANSPARENCY "transparency" #define OSC_SOURCE_DEPTH "depth" -#define OSC_SOURCE_TRANSLATE "translate" +#define OSC_SOURCE_GRAB "grab" +#define OSC_SOURCE_RESIZE "resize" class Session; class Source; diff --git a/SourceCallback.cpp b/SourceCallback.cpp index 96556d5..f8d6693 100644 --- a/SourceCallback.cpp +++ b/SourceCallback.cpp @@ -79,13 +79,14 @@ void SetDepth::update(Source *s, float dt) } // calculate amplitude of movement - progress_ += dt / duration_; + progress_ += dt; // perform movement - s->group(View::LAYER)->translation_.z = start_ + progress_ * (target_ - start_); + if ( ABS(duration_) > 0.f) + s->group(View::LAYER)->translation_.z = start_ + (progress_/duration_) * (target_ - start_); // end of movement - if ( progress_ > 1.f ) { + if ( progress_ > duration_ ) { // apply depth to target s->group(View::LAYER)->translation_.z = target_; // ensure reordering of view @@ -99,40 +100,41 @@ void SetDepth::update(Source *s, float dt) } -SetPlay::SetPlay(bool on, float delay) : SourceCallback(), play_(on), delay_(delay), progress_(0.f) +SetPlay::SetPlay(bool on) : SourceCallback(), play_(on) { } -void SetPlay::update(Source *s, float dt) +void SetPlay::update(Source *s, float) { if (s && s->playing() != play_) { - // reset on first run or upon call of reset() - if (!initialized_){ - progress_ = 0.f; - initialized_ = true; - } - - // increment time count - progress_ += dt; - - // timeout - if ( progress_ > delay_ ) { - // call play function - s->play(play_); - // done - finished_ = true; - } + // call play function + s->play(play_); } - else - finished_ = true; + + finished_ = true; } -Translation::Translation(float dx, float dy, float duration) : SourceCallback(), speed_(glm::vec2(dx,dy)), +RePlay::RePlay() : SourceCallback() +{ +} + +void RePlay::update(Source *s, float) +{ + if (s) { + // call replay function + s->replay(); + } + + finished_ = true; +} + + +Grab::Grab(float dx, float dy, float duration) : SourceCallback(), speed_(glm::vec2(dx,dy)), duration_(duration), progress_(0.f) { } -void Translation::update(Source *s, float dt) +void Grab::update(Source *s, float dt) { if (s && !s->locked()) { // reset on first run or upon call of reset() @@ -145,14 +147,48 @@ void Translation::update(Source *s, float dt) } // calculate amplitude of movement - progress_ += dt / duration_; + progress_ += dt; // perform movement - glm::vec2 pos = start_ + speed_ * dt; + glm::vec2 pos = start_ + speed_ * ( dt * 0.001f); s->group(View::GEOMETRY)->translation_ = glm::vec3(pos, s->group(View::GEOMETRY)->translation_.z); // timeout - if ( progress_ > 1.f ) { + if ( progress_ > duration_ ) { + // done + finished_ = true; + } + } + else + finished_ = true; +} + +Resize::Resize(float dx, float dy, float duration) : SourceCallback(), speed_(glm::vec2(dx,dy)), + duration_(duration), progress_(0.f) +{ +} + +void Resize::update(Source *s, float dt) +{ + if (s && !s->locked()) { + // reset on first run or upon call of reset() + if (!initialized_){ + // start animation + progress_ = 0.f; + // initial position + start_ = glm::vec2(s->group(View::GEOMETRY)->scale_); + initialized_ = true; + } + + // calculate amplitude of movement + progress_ += dt; + + // perform movement + glm::vec2 pos = start_ + speed_ * ( dt * 0.001f); + s->group(View::GEOMETRY)->scale_ = glm::vec3(pos, s->group(View::GEOMETRY)->scale_.z); + + // timeout + if ( progress_ > duration_ ) { // done finished_ = true; } diff --git a/SourceCallback.h b/SourceCallback.h index 30a8490..536de17 100644 --- a/SourceCallback.h +++ b/SourceCallback.h @@ -14,7 +14,9 @@ public: CALLBACK_ALPHA, CALLBACK_DEPTH, CALLBACK_PLAY, - CALLBACK_TRANSLATION + CALLBACK_REPLAY, + CALLBACK_GRAB, + CALLBACK_RESIZE } CallbackType; SourceCallback(); @@ -61,16 +63,23 @@ public: class SetPlay : public SourceCallback { bool play_; - float delay_; - float progress_; public: - SetPlay(bool on, float delay = 0.f); + SetPlay(bool on); void update(Source *s, float) override; CallbackType type () override { return CALLBACK_PLAY; } }; -class Translation : public SourceCallback +class RePlay : public SourceCallback +{ + +public: + RePlay(); + void update(Source *s, float) override; + CallbackType type () override { return CALLBACK_REPLAY; } +}; + +class Grab : public SourceCallback { glm::vec2 speed_; glm::vec2 start_; @@ -79,9 +88,23 @@ class Translation : public SourceCallback float progress_; public: - Translation(float dx, float dy, float duration = 0.f); + Grab(float dx, float dy, float duration = 0.f); void update(Source *s, float) override; - CallbackType type () override { return CALLBACK_TRANSLATION; } + CallbackType type () override { return CALLBACK_GRAB; } +}; + +class Resize : public SourceCallback +{ + glm::vec2 speed_; + glm::vec2 start_; + glm::vec2 target_; + float duration_; + float progress_; + +public: + Resize(float dx, float dy, float duration = 0.f); + void update(Source *s, float) override; + CallbackType type () override { return CALLBACK_RESIZE; } }; diff --git a/rsc/osc/vimix.tosc b/rsc/osc/vimix.tosc index cb65380efd9842483cbdf0fe826f23cfe36a35c6..aeb83374d48e83470b92264cfdf19e06d9e2f96e 100644 GIT binary patch literal 4227 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 literal 1822 zcmV+(2jTd5ob6q0bD}yF{=UD0`^omsRUiuD3}wgd%ihlPs$=cWc6Rndgs99?Z~}Ja z-`@lQU%;+LT4_yZT0;U)PQu}k=iy-W&+{ioct+T_J@=v_*QAPoT+_2`cYINK7~E8~ z%4b7&(AsXGV(6}CA>sDwq9Qd^wQeb(s!B?|D$B^MYEXsMrYTEi3p5lHqKXiNQ*=@J z+V4K}$iY+WO%V=krC=%&h4W3!3c)2tzZl zpECns!gDQj^l$$rH%USSd)2Q{2!1gAvhi&8rFd$bP4rxhix+KAS?vapTH^8a5Gc)Z2R^wJJMV%aWytY&3@_@YoLKQ zGbc;Pg-go;wKH++gR>FTdN+U$4ip zUrmC4y%ooPS|~X5GhKTxgnlNxw+j8pg-OUbo!HL=SU~L040wu>UyT1@8*>iCh-(5>;B-8&8XzI zQ=mZy&QiJNCtVR9WRbY=CWyzgCldGlO&ixP(G_dHbh~%g?aqr9&I>Sa#V|3thQ;N* zM5JVKl`>i_Q&XD_LK%n3f-*vgz^PM4siw5(Pr@8)s?-Ec5EDrG-4IBSh=%|q46>Q1 zht1-}!;@l=QwN5{^GBv3e{}8eJ@dypr+J*_ahk_z9;bQlm*$y^YoF7ZlG7PevrN@& zX_U^Wak4@SNV#;T-@dwS-@PfF$-tS2E{)h$t0(aMOHJvE9J3c$uE+ExDwTo1jImt| zx1~V$0h(sa0!1ffF!D5Vl?QCTdNh(Yf;82M)3oEHco3F0CAa)y3{1doh)-wZoGcZW zgi^9cew?{+=Ej*DXKsfww=%mOe?Z3{&>fx8-rRNDgHrKX00C0WCakKmY{ie~KttWe zXWRX9Cf}zFw5Dhc8K?;nt+f=OY3i~0XqJ}Gu%ENUWLaP?pss8`eO$EXI(TQY+-SyR zxh`o5TW+Onxpf@2yq)BJ&#vGP!h2-G%VqN!)0mMmMwNoeQ{u?<;zwroBcv_P&HV7T znCYiT#Z3QOX%!e+5Z6yECHXb9id~G%oEqQ6_B7ZoB+cAt6)bq}H`;PZn9mqlXJp^= zPl8~NgfrI*1Rpu0+G3eri#YbV5KNFu_7K+E=E8*_)uc>)nAVe}`zQMQX{G1hV%%r( z_D?|LWO>&<5U5n*>p MAM_ai1K8pBvK2$A9{>OV