diff --git a/Builds/VisualStudio2022/Chataigne_App.vcxproj b/Builds/VisualStudio2022/Chataigne_App.vcxproj
index 2d9218ca0..f26d9db19 100644
--- a/Builds/VisualStudio2022/Chataigne_App.vcxproj
+++ b/Builds/VisualStudio2022/Chataigne_App.vcxproj
@@ -48,11 +48,15 @@
Chataigne
true
$(LibraryPath);../../External/kinect/lib;../../External/joycon/lib/win;../../External/servus/lib/win/x64/debug;../../External/dnssd/lib;../../External/sdl/lib/win;../../External/hidapi/lib/win/x64;../../External/mosquitto/lib/win;../../External/simpleble/lib/win/debug;..\..\Modules\juce_sharedtexture\libs\VisualStudio2022\$(Platform)\MDd;..\..\Modules\juce_simpleweb\libs\VisualStudio2022\$(Platform)\MDd
+ true
+ true
.\..\..\Binaries\App\
$(Platform)\$(Configuration)\App\
Chataigne
true
$(LibraryPath);../../External/kinect/lib;../../External/joycon/lib/win;../../External/servus/lib/win/x64/release;../../External/dnssd/lib;../../External/sdl/lib/win;../../External/hidapi/lib/win/x64;../../External/mosquitto/lib/win;../../External/simpleble/lib/win/release;..\..\Modules\juce_sharedtexture\libs\VisualStudio2022\$(Platform)\MD;..\..\Modules\juce_simpleweb\libs\VisualStudio2022\$(Platform)\MD
+ true
+ true
diff --git a/Builds/VisualStudio2022_CI/Chataigne_App.vcxproj b/Builds/VisualStudio2022_CI/Chataigne_App.vcxproj
index 788a20e9b..93ac449a3 100644
--- a/Builds/VisualStudio2022_CI/Chataigne_App.vcxproj
+++ b/Builds/VisualStudio2022_CI/Chataigne_App.vcxproj
@@ -48,11 +48,15 @@
Chataigne
true
$(LibraryPath);../../External/kinect/lib;../../External/joycon/lib/win;../../External/servus/lib/win/x64/debug;../../External/dnssd/lib;../../External/sdl/lib/win;../../External/hidapi/lib/win/x64;../../External/mosquitto/lib/win;..\..\Modules\juce_sharedtexture\libs\VisualStudio2022\$(Platform)\MDd;..\..\Modules\juce_simpleweb\libs\VisualStudio2022\$(Platform)\MDd
+ true
+ true
.\..\..\Binaries\CI\App\
$(Platform)\$(Configuration)\App\
Chataigne
true
$(LibraryPath);../../External/kinect/lib;../../External/joycon/lib/win;../../External/servus/lib/win/x64/release;../../External/dnssd/lib;../../External/sdl/lib/win;../../External/hidapi/lib/win/x64;../../External/mosquitto/lib/win;..\..\Modules\juce_sharedtexture\libs\VisualStudio2022\$(Platform)\MD;..\..\Modules\juce_simpleweb\libs\VisualStudio2022\$(Platform)\MD
+ true
+ true
diff --git a/Builds/VisualStudio2022_Win7CI/Chataigne_App.vcxproj b/Builds/VisualStudio2022_Win7CI/Chataigne_App.vcxproj
index d9ab3cf7a..8229167bd 100644
--- a/Builds/VisualStudio2022_Win7CI/Chataigne_App.vcxproj
+++ b/Builds/VisualStudio2022_Win7CI/Chataigne_App.vcxproj
@@ -48,11 +48,15 @@
Chataigne
true
$(LibraryPath);../../External/joycon/lib/win;../../External/servus/lib/win/x64/debug;../../External/dnssd/lib;../../External/sdl/lib/win;../../External/hidapi/lib/win/x64;../../External/mosquitto/lib/win;..\..\Modules\juce_sharedtexture\libs\VisualStudio2022\$(Platform)\MDd;..\..\Modules\juce_simpleweb\libs\VisualStudio2022\$(Platform)\MDd
+ true
+ true
.\..\..\Binaries\CI\App\
$(Platform)\$(Configuration)\App\
Chataigne
true
$(LibraryPath);../../External/joycon/lib/win;../../External/servus/lib/win/x64/release;../../External/dnssd/lib;../../External/sdl/lib/win;../../External/hidapi/lib/win/x64;../../External/mosquitto/lib/win;..\..\Modules\juce_sharedtexture\libs\VisualStudio2022\$(Platform)\MD;..\..\Modules\juce_simpleweb\libs\VisualStudio2022\$(Platform)\MD
+ true
+ true
diff --git a/Chataigne.jucer b/Chataigne.jucer
index 596691b0b..46d9c3ef1 100644
--- a/Chataigne.jucer
+++ b/Chataigne.jucer
@@ -2011,9 +2011,9 @@
- boolValue() || forceDisabled) return;
-
+ if (isClearing) return;
+
if (!forceChecking)
{
if (triggerTrue) csmOn->triggerAll(multiplexIndex);
@@ -239,6 +240,7 @@ void Action::notifyActionTriggered(bool triggerTrue, int multiplexIndex)
void Action::conditionManagerValidationChanged(ConditionManager*, int multiplexIndex, bool dispatchOnChangeOnly)
{
if (forceChecking) return;
+ if (isClearing) return;
if (autoTriggerWhenAllConditionAreActives)
{
diff --git a/Source/Common/Processor/Action/Consequence/ConsequenceManager.cpp b/Source/Common/Processor/Action/Consequence/ConsequenceManager.cpp
index 2822669d3..315037682 100644
--- a/Source/Common/Processor/Action/Consequence/ConsequenceManager.cpp
+++ b/Source/Common/Processor/Action/Consequence/ConsequenceManager.cpp
@@ -1,258 +1,274 @@
-/*
- ==============================================================================
-
- ConsequenceManager.cpp
- Created: 28 Oct 2016 8:07:30pm
- Author: bkupe
-
- ==============================================================================
-*/
-
-#include "Common/Processor/ProcessorIncludes.h"
-
-ConsequenceManager::ConsequenceManager(const String& name, Multiplex* multiplex) :
- BaseManager(name),
- MultiplexTarget(multiplex),
- killDelaysOnTrigger(nullptr),
- forceDisabled(false),
- csmNotifier(5)
-{
- canBeDisabled = false;
- canBeCopiedAndPasted = true;
-
- selectItemWhenCreated = false;
-
- factory.defs.add(MultiplexTargetDefinition::createDef("", "Consequence", multiplex));
- factory.defs.add(MultiplexTargetDefinition::createDef("", "Group", multiplex));
-
- managerFactory = &factory;
-
- triggerPreview = addTrigger("Trigger", "Trigger all the consequences. Triggers at the previewed index if multiplexed");
- triggerPreview->hideInEditor = true;
-
- delay = addFloatParameter("Delay", "Delay the triggering of the commands", 0, 0);
- delay->defaultUI = FloatParameter::TIME;
- delay->hideInEditor = true;
- stagger = addFloatParameter("Stagger", "If multiple consequences are there, delay between each consequence trigger", 0, 0);
- stagger->defaultUI = FloatParameter::TIME;
- stagger->hideInEditor = true;
-
- killDelaysOnTrigger = addBoolParameter("Cancel delays on Trigger", "If checked, this will ensure that when triggering, all previous delayed consequences are cancelled", false, false);
-
- staggerProgression = addFloatParameter("Stagger Progression", "If stagger is used, this animates the progression of the stagger", 0, 0, 1);
- staggerProgression->hideInEditor = true;
- staggerProgression->setControllableFeedbackOnly(true);
-}
-
-ConsequenceManager::~ConsequenceManager()
-{
-
-}
-
-
-
-
-void ConsequenceManager::triggerAll(int multiplexIndex)
-{
- if (killDelaysOnTrigger->boolValue()) cancelDelayedConsequences();
-
- if (items.size() > 0)
- {
- if (delay->floatValue() == 0 && stagger->floatValue() == 0)
- {
- for (auto& bi : items)
- {
- if (Consequence* c = dynamic_cast(bi)) c->triggerCommand(multiplexIndex);
- else if (ConsequenceGroup* g = dynamic_cast(bi)) if (g->enabled->boolValue()) g->csm.triggerAll(multiplexIndex);
- }
- }
- else
- {
- staggerLaunchers.add(new StaggerLauncher(this, multiplexIndex));
- }
- }
-}
-
-void ConsequenceManager::cancelDelayedConsequences()
-{
- for (auto& launcher : staggerLaunchers) launcher->stopThread(100);
- staggerLaunchers.clear();
-}
-
-void ConsequenceManager::setForceDisabled(bool value, bool force)
-{
- if (forceDisabled == value && !force) return;
- forceDisabled = value;
- for (auto& i : items)
- {
- if (Consequence* c = dynamic_cast(i)) c->forceDisabled = value;
- else if (ConsequenceGroup* g = dynamic_cast(i)) g->csm.setForceDisabled(value);
- }
-}
-
-void ConsequenceManager::updateKillDelayTrigger()
-{
- bool showKill = items.size() > 1 && (delay->floatValue() > 0 || stagger->floatValue() > 0);
- killDelaysOnTrigger->setEnabled(showKill);
-
-}
-
-void ConsequenceManager::onContainerTriggerTriggered(Trigger* t)
-{
- if (forceDisabled) return;
-
- //for manual trigger eventually
- if (t == triggerPreview) triggerAll(getPreviewIndex());
-
- BaseManager::onContainerTriggerTriggered(t);
-}
-
-void ConsequenceManager::onContainerParameterChanged(Parameter* p)
-{
- BaseManager::onContainerParameterChanged(p);
- if (p == delay || p == stagger)
- {
- updateKillDelayTrigger();
- }
-}
-
-void ConsequenceManager::addItemInternal(BaseItem* bi, var data)
-{
- if (Consequence* c = dynamic_cast(bi)) c->forceDisabled = forceDisabled;
- else if (ConsequenceGroup* g = dynamic_cast(bi)) g->csm.setForceDisabled(forceDisabled);
-
- //triggerAll->hideInEditor = items.size() == 0;
- delay->hideInEditor = items.size() == 0;
- stagger->hideInEditor = items.size() < 2;
- if (!isClearing) csmNotifier.addMessage(new ConsequenceManagerEvent(ConsequenceManagerEvent::STAGGER_CHANGED, this));
- updateKillDelayTrigger();
-}
-
-void ConsequenceManager::addItemsInternal(Array items, var data)
-{
- for (auto& bi : items)
- {
- if (Consequence* c = dynamic_cast(bi)) c->forceDisabled = forceDisabled;
- else if (ConsequenceGroup* g = dynamic_cast(bi)) g->csm.setForceDisabled(forceDisabled);
- }
-
- //triggerAll->hideInEditor = items.size() == 0;
- delay->hideInEditor = items.size() == 0;
- stagger->hideInEditor = items.size() < 2;
- if (!isClearing) csmNotifier.addMessage(new ConsequenceManagerEvent(ConsequenceManagerEvent::STAGGER_CHANGED, this));
- updateKillDelayTrigger();
-}
-
-void ConsequenceManager::removeItemInternal(BaseItem*)
-{
- //triggerAll->hideInEditor = items.size() == 0;
- delay->hideInEditor = items.size() == 0;
- stagger->hideInEditor = items.size() < 2;
- if (!isClearing) csmNotifier.addMessage(new ConsequenceManagerEvent(ConsequenceManagerEvent::STAGGER_CHANGED, this));
- updateKillDelayTrigger();
-}
-
-void ConsequenceManager::removeItemsInternal(Array)
-{
- delay->hideInEditor = items.size() == 0;
- stagger->hideInEditor = items.size() < 2;
- if (!isClearing) csmNotifier.addMessage(new ConsequenceManagerEvent(ConsequenceManagerEvent::STAGGER_CHANGED, this));
- updateKillDelayTrigger();
-}
-
-void ConsequenceManager::launcherTriggered(StaggerLauncher* launcher)
-{
- if (staggerLaunchers.size() == 0 || items.size() == 0) return;
- if (launcher != staggerLaunchers.getLast()) return;
- staggerProgression->setValue((launcher->triggerIndex + 1) * 1.0f / items.size());
-}
-
-void ConsequenceManager::launcherFinished(StaggerLauncher* launcher)
-{
- MessageManager::getInstance()->callAsync([=]()
- {
- launcher->stopThread(100);
- staggerLaunchers.removeObject(launcher);
- }
- );
-}
-
-InspectableEditor* ConsequenceManager::getEditorInternal(bool isRoot, Array inspectables)
-{
- return new ConsequenceManagerEditor(this, CommandContext::ACTION, isRoot, isMultiplexed());
-}
-
-ConsequenceManager::StaggerLauncher::StaggerLauncher(ConsequenceManager* csm, int multiplexIndex) :
- Thread("Stagger Launcher"),
- csm(csm),
- multiplexIndex(multiplexIndex)
-{
- startThread();
-}
-
-ConsequenceManager::StaggerLauncher::~StaggerLauncher()
-{
- if (Engine::mainEngine->isClearing) stopThread(1000);
- else if (isThreadRunning())
- {
- MessageManager::callAsync([this] {
- stopThread(100);
- });
- }
-}
-
-void ConsequenceManager::StaggerLauncher::run()
-{
- timeAtRun = Time::getMillisecondCounter();
- triggerIndex = 0;
-
- uint32 d = (uint32)(csm->delay->floatValue() * 1000);
- uint32 s = (uint32)(csm->stagger->floatValue() * 1000);
-
- uint32 curTime = timeAtRun;
-
- Array consequencesToLaunch;
- for (auto& bi : csm->items)
- {
- if (!bi->enabled->boolValue()) continue;
- consequencesToLaunch.add(bi);
- }
-
- while (!threadShouldExit() && triggerIndex < consequencesToLaunch.size())
- {
- uint32 nextTriggerTime = timeAtRun + d + s * triggerIndex;
- while (nextTriggerTime > curTime)
- {
- if (threadShouldExit()) break;
- wait(jmin(nextTriggerTime - curTime, 20));
- curTime = Time::getMillisecondCounter();
- nextTriggerTime = timeAtRun + d + s * triggerIndex;
- }
-
- if (triggerIndex >= consequencesToLaunch.size()) break;
- BaseItem* bi = consequencesToLaunch[triggerIndex];
-
- while (bi != nullptr && !bi->enabled->boolValue())
- {
- triggerIndex++;
- if (triggerIndex >= consequencesToLaunch.size()) break;
- bi = csm->items[triggerIndex];
- }
-
-
- if (threadShouldExit() || bi == nullptr) break;
-
- if (Consequence* c = dynamic_cast(bi)) c->triggerCommand(multiplexIndex);
- else if (ConsequenceGroup* g = dynamic_cast(bi)) if (g->enabled->boolValue()) g->csm.triggerAll(multiplexIndex);
-
- csm->launcherTriggered(this);
- triggerIndex++;
- }
-
- if (!threadShouldExit()) csm->launcherFinished(this);
-}
-
-void ConsequenceManager::multiplexPreviewIndexChanged()
-{
- csmNotifier.addMessage(new ConsequenceManagerEvent(ConsequenceManagerEvent::MULTIPLEX_PREVIEW_CHANGED, this));
-}
\ No newline at end of file
+/*
+ ==============================================================================
+
+ ConsequenceManager.cpp
+ Created: 28 Oct 2016 8:07:30pm
+ Author: bkupe
+
+ ==============================================================================
+*/
+
+#include "Common/Processor/ProcessorIncludes.h"
+
+juce_ImplementSingleton(ConsequenceStaggerLauncher)
+
+ConsequenceManager::ConsequenceManager(const String& name, Multiplex* multiplex) :
+ BaseManager(name),
+ MultiplexTarget(multiplex),
+ killDelaysOnTrigger(nullptr),
+ forceDisabled(false),
+ csmNotifier(5)
+{
+ canBeDisabled = false;
+ canBeCopiedAndPasted = true;
+
+ selectItemWhenCreated = false;
+
+ factory.defs.add(MultiplexTargetDefinition::createDef("", "Consequence", multiplex));
+ factory.defs.add(MultiplexTargetDefinition::createDef("", "Group", multiplex));
+
+ managerFactory = &factory;
+
+ triggerPreview = addTrigger("Trigger", "Trigger all the consequences. Triggers at the previewed index if multiplexed");
+ triggerPreview->hideInEditor = true;
+
+ delay = addFloatParameter("Delay", "Delay the triggering of the commands", 0, 0);
+ delay->defaultUI = FloatParameter::TIME;
+ delay->hideInEditor = true;
+ stagger = addFloatParameter("Stagger", "If multiple consequences are there, delay between each consequence trigger", 0, 0);
+ stagger->defaultUI = FloatParameter::TIME;
+ stagger->hideInEditor = true;
+
+ killDelaysOnTrigger = addBoolParameter("Cancel delays on Trigger", "If checked, this will ensure that when triggering, all previous delayed consequences are cancelled", false, false);
+
+ staggerProgression = addFloatParameter("Stagger Progression", "If stagger is used, this animates the progression of the stagger", 0, 0, 1);
+ staggerProgression->hideInEditor = true;
+ staggerProgression->setControllableFeedbackOnly(true);
+}
+
+ConsequenceManager::~ConsequenceManager()
+{
+ cancelDelayedConsequences(-1);
+}
+
+void ConsequenceManager::triggerAll(int multiplexIndex)
+{
+ if (killDelaysOnTrigger->boolValue()) cancelDelayedConsequences(multiplexIndex);
+
+ if (items.size() > 0)
+ {
+ if (delay->floatValue() == 0 && stagger->floatValue() == 0)
+ {
+ for (auto& bi : items)
+ {
+ if (Consequence* c = dynamic_cast(bi)) c->triggerCommand(multiplexIndex);
+ else if (ConsequenceGroup* g = dynamic_cast(bi)) if (g->enabled->boolValue()) g->csm.triggerAll(multiplexIndex);
+ }
+ }
+ else
+ {
+ ConsequenceStaggerLauncher::getInstance()->addLaunch(this, multiplexIndex);
+ }
+ }
+}
+
+void ConsequenceManager::cancelDelayedConsequences(int multiplexIndex)
+{
+ ConsequenceStaggerLauncher::getInstance()->removeLaunchesFor(this, multiplexIndex);
+}
+
+void ConsequenceManager::setForceDisabled(bool value, bool force)
+{
+ if (forceDisabled == value && !force) return;
+ forceDisabled = value;
+ for (auto& i : items)
+ {
+ if (Consequence* c = dynamic_cast(i)) c->forceDisabled = value;
+ else if (ConsequenceGroup* g = dynamic_cast(i)) g->csm.setForceDisabled(value);
+ }
+}
+
+void ConsequenceManager::updateKillDelayTrigger()
+{
+ bool showKill = items.size() > 1 && (delay->floatValue() > 0 || stagger->floatValue() > 0);
+ killDelaysOnTrigger->setEnabled(showKill);
+
+}
+
+void ConsequenceManager::onContainerTriggerTriggered(Trigger* t)
+{
+ if (forceDisabled) return;
+
+ //for manual trigger eventually
+ if (t == triggerPreview) triggerAll(getPreviewIndex());
+
+ BaseManager::onContainerTriggerTriggered(t);
+}
+
+void ConsequenceManager::onContainerParameterChanged(Parameter* p)
+{
+ BaseManager::onContainerParameterChanged(p);
+ if (p == delay || p == stagger)
+ {
+ updateKillDelayTrigger();
+ }
+}
+
+void ConsequenceManager::addItemInternal(BaseItem* bi, var data)
+{
+ if (Consequence* c = dynamic_cast(bi)) c->forceDisabled = forceDisabled;
+ else if (ConsequenceGroup* g = dynamic_cast(bi)) g->csm.setForceDisabled(forceDisabled);
+
+ //triggerAll->hideInEditor = items.size() == 0;
+ delay->hideInEditor = items.size() == 0;
+ stagger->hideInEditor = items.size() < 2;
+ if (!isClearing) csmNotifier.addMessage(new ConsequenceManagerEvent(ConsequenceManagerEvent::STAGGER_CHANGED, this));
+ updateKillDelayTrigger();
+}
+
+void ConsequenceManager::addItemsInternal(Array items, var data)
+{
+ for (auto& bi : items)
+ {
+ if (Consequence* c = dynamic_cast(bi)) c->forceDisabled = forceDisabled;
+ else if (ConsequenceGroup* g = dynamic_cast(bi)) g->csm.setForceDisabled(forceDisabled);
+ }
+
+ //triggerAll->hideInEditor = items.size() == 0;
+ delay->hideInEditor = items.size() == 0;
+ stagger->hideInEditor = items.size() < 2;
+ if (!isClearing) csmNotifier.addMessage(new ConsequenceManagerEvent(ConsequenceManagerEvent::STAGGER_CHANGED, this));
+ updateKillDelayTrigger();
+}
+
+void ConsequenceManager::removeItemInternal(BaseItem*)
+{
+ //triggerAll->hideInEditor = items.size() == 0;
+ delay->hideInEditor = items.size() == 0;
+ stagger->hideInEditor = items.size() < 2;
+ if (!isClearing) csmNotifier.addMessage(new ConsequenceManagerEvent(ConsequenceManagerEvent::STAGGER_CHANGED, this));
+ updateKillDelayTrigger();
+}
+
+void ConsequenceManager::removeItemsInternal(Array)
+{
+ delay->hideInEditor = items.size() == 0;
+ stagger->hideInEditor = items.size() < 2;
+ if (!isClearing) csmNotifier.addMessage(new ConsequenceManagerEvent(ConsequenceManagerEvent::STAGGER_CHANGED, this));
+ updateKillDelayTrigger();
+}
+
+void ConsequenceManager::launcherTriggered(int multiplexIndex, int triggerIndex)
+{
+ staggerProgression->setValue((triggerIndex + 1) * 1.0f / items.size());
+}
+
+
+InspectableEditor* ConsequenceManager::getEditorInternal(bool isRoot, Array inspectables)
+{
+ return new ConsequenceManagerEditor(this, CommandContext::ACTION, isRoot, isMultiplexed());
+}
+
+ConsequenceStaggerLauncher::ConsequenceStaggerLauncher() :
+ Thread("Stagger Launcher")
+{
+ startThread();
+}
+
+ConsequenceStaggerLauncher::~ConsequenceStaggerLauncher()
+{
+ stopThread(1000);
+}
+
+void ConsequenceStaggerLauncher::run()
+{
+ Array toRemove;
+
+ while (!threadShouldExit())
+ {
+ {
+ GenericScopedLock lock(launches.getLock());
+ for (auto& l : launches)
+ {
+ processLaunch(l);
+ if (l->isFinished()) toRemove.add(l);
+ }
+
+ for (auto& l : toRemove) launches.removeObject(l);
+
+ if (launches.isEmpty()) break;
+ }
+
+ wait(10);
+ }
+
+}
+
+void ConsequenceStaggerLauncher::processLaunch(Launch* l)
+{
+
+ ConsequenceManager* csm = l->manager;
+ uint32 d = (uint32)(csm->delay->floatValue() * 1000);
+ uint32 s = (uint32)(csm->stagger->floatValue() * 1000);
+
+ //check if last item
+ if (l->triggerIndex >= csm->items.size()) return;
+
+
+ //get relative trigger index, not taking into account disabled items
+ int relativeIndex = 0;
+ for (int i = 0; i < l->triggerIndex; i++) if (csm->items[i]->enabled->boolValue()) relativeIndex++;
+
+ //Check if should trigger
+ uint32 curTime = Time::getMillisecondCounter();
+ uint32 triggerTime = l->startTime + d + s * relativeIndex;
+
+ if (curTime < triggerTime) return;
+
+ //Get first enabled item starting at index
+ {
+ GenericScopedLock lock(csm->items.getLock());
+ BaseItem* bi = csm->items[l->triggerIndex];
+ while (bi->enabled->boolValue() == false)
+ {
+ l->triggerIndex++;
+ if (l->triggerIndex >= csm->items.size()) return;
+ bi = csm->items[l->triggerIndex];
+ }
+
+
+ if (Consequence* c = dynamic_cast(bi)) c->triggerCommand(l->multiplexIndex);
+ else if (ConsequenceGroup* g = dynamic_cast(bi)) if (g->enabled->boolValue()) g->csm.triggerAll(l->multiplexIndex);
+ }
+
+ csm->launcherTriggered(l->multiplexIndex, l->triggerIndex);
+ l->triggerIndex++;
+}
+
+void ConsequenceStaggerLauncher::addLaunch(ConsequenceManager* csm, int multiplexIndex)
+{
+ launches.add(new Launch(csm, multiplexIndex));
+ if (!isThreadRunning()) startThread();
+ else notify();
+}
+
+void ConsequenceStaggerLauncher::removeLaunchesFor(ConsequenceManager* manager, int multiplexIndex)
+{
+ GenericScopedLock lock(launches.getLock());
+ Array toRemove;
+ for (auto& l : launches)
+ {
+ if (l->manager == manager && (multiplexIndex == -1 || l->multiplexIndex == multiplexIndex)) toRemove.add(l);
+ }
+
+ for (auto& l : toRemove) launches.removeObject(l);
+}
+
+void ConsequenceManager::multiplexPreviewIndexChanged()
+{
+ csmNotifier.addMessage(new ConsequenceManagerEvent(ConsequenceManagerEvent::MULTIPLEX_PREVIEW_CHANGED, this));
+}
+
+bool ConsequenceStaggerLauncher::Launch::isFinished() {
+ return triggerIndex >= manager->items.size();
+}
diff --git a/Source/Common/Processor/Action/Consequence/ConsequenceManager.h b/Source/Common/Processor/Action/Consequence/ConsequenceManager.h
index 8959da05e..ffaeb2d3d 100644
--- a/Source/Common/Processor/Action/Consequence/ConsequenceManager.h
+++ b/Source/Common/Processor/Action/Consequence/ConsequenceManager.h
@@ -1,92 +1,103 @@
-/*
- ==============================================================================
-
- ConsequenceManager.h
- Created: 28 Oct 2016 8:07:30pm
- Author: bkupe
-
- ==============================================================================
-*/
-
-#pragma once
-
-class ConsequenceManager :
- public BaseManager,
- public MultiplexTarget,
- public Consequence::ConsequenceListener
-{
-public:
- ConsequenceManager(const String& name = "Consequences", Multiplex* multiplex = nullptr);
- ~ConsequenceManager();
-
- Trigger* triggerPreview;
-
- FloatParameter* delay;
- FloatParameter* stagger;
- BoolParameter* killDelaysOnTrigger;
- FloatParameter* staggerProgression;
-
- Factory factory;
-
- bool forceDisabled;
-
-
- void triggerAll(int multiplexIndex = 0);
- void cancelDelayedConsequences();
-
- void setForceDisabled(bool value, bool force = false);
-
- void updateKillDelayTrigger();
-
- void onContainerTriggerTriggered(Trigger*) override;
- void onContainerParameterChanged(Parameter* p) override;
-
-
- void addItemInternal(BaseItem*, var data) override;
- void addItemsInternal(Array, var data) override;
- void removeItemInternal(BaseItem*) override;
- void removeItemsInternal(Array) override;
-
- class StaggerLauncher :
- public Thread
- {
- public:
- StaggerLauncher(ConsequenceManager* csm, int multiplexIndex);
- ~StaggerLauncher();
-
- ConsequenceManager* csm;
- int multiplexIndex;
-
- uint32 timeAtRun;
- int triggerIndex;
-
- void run() override;
- };
- OwnedArray staggerLaunchers;
-
- void launcherTriggered(StaggerLauncher* launcher);
- void launcherFinished(StaggerLauncher* launcher);
-
- void multiplexPreviewIndexChanged() override;
-
- InspectableEditor* getEditorInternal(bool isRoot, Array inspectables = Array()) override;
-
- class ConsequenceManagerListener
- {
- public:
- virtual ~ConsequenceManagerListener() {}
- virtual void consequenceEnableChanged(Consequence*) {}
- virtual void consequenceValidationChanged(Consequence*) {}
- virtual void consequenceTriggered(Consequence*) {}
- };
-
-
- ListenerList consequenceManagerListeners;
- void addConsequenceManagerListener(ConsequenceManagerListener* newListener) { consequenceManagerListeners.add(newListener); }
- void removeConsequenceManagerListener(ConsequenceManagerListener* listener) { consequenceManagerListeners.remove(listener); }
-
- DECLARE_ASYNC_EVENT(ConsequenceManager, ConsequenceManager, csm, ENUM_LIST(MULTIPLEX_PREVIEW_CHANGED, STAGGER_CHANGED), EVENT_INSPECTABLE_CHECK);
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ConsequenceManager)
-
+/*
+ ==============================================================================
+
+ ConsequenceManager.h
+ Created: 28 Oct 2016 8:07:30pm
+ Author: bkupe
+
+ ==============================================================================
+*/
+
+#pragma once
+
+class ConsequenceManager;
+
+class ConsequenceStaggerLauncher :
+ public Thread
+{
+public:
+ juce_DeclareSingleton(ConsequenceStaggerLauncher, false)
+
+ ConsequenceStaggerLauncher();
+ ~ConsequenceStaggerLauncher();
+
+ struct Launch
+ {
+ Launch(ConsequenceManager* c, int multiplexIndex) : manager(c), startTime(Time::getMillisecondCounter()), multiplexIndex(multiplexIndex), triggerIndex(0) {}
+
+ ConsequenceManager* manager;
+ uint32 startTime;
+ int multiplexIndex;
+ int triggerIndex;
+
+ bool isFinished();
+ };
+
+ OwnedArray launches;
+
+ void run() override;
+ void processLaunch(Launch* l);
+
+ void addLaunch(ConsequenceManager* c, int multiplexIndex);
+ void removeLaunchesFor(ConsequenceManager* manager, int multiplexIndex);
+};
+
+class ConsequenceManager :
+ public BaseManager,
+ public MultiplexTarget,
+ public Consequence::ConsequenceListener
+{
+public:
+ ConsequenceManager(const String& name = "Consequences", Multiplex* multiplex = nullptr);
+ ~ConsequenceManager();
+
+ Trigger* triggerPreview;
+
+ FloatParameter* delay;
+ FloatParameter* stagger;
+ BoolParameter* killDelaysOnTrigger;
+ FloatParameter* staggerProgression;
+
+ Factory factory;
+
+ bool forceDisabled;
+
+
+ void triggerAll(int multiplexIndex = 0);
+ void cancelDelayedConsequences(int multiplexIndex = 0);
+
+ void setForceDisabled(bool value, bool force = false);
+
+ void updateKillDelayTrigger();
+
+ void onContainerTriggerTriggered(Trigger*) override;
+ void onContainerParameterChanged(Parameter* p) override;
+
+
+ void addItemInternal(BaseItem*, var data) override;
+ void addItemsInternal(Array, var data) override;
+ void removeItemInternal(BaseItem*) override;
+ void removeItemsInternal(Array) override;
+
+ void launcherTriggered(int multiplexIndex, int triggerIndex);
+
+ void multiplexPreviewIndexChanged() override;
+
+ InspectableEditor* getEditorInternal(bool isRoot, Array inspectables = Array()) override;
+
+ class ConsequenceManagerListener
+ {
+ public:
+ virtual ~ConsequenceManagerListener() {}
+ virtual void consequenceEnableChanged(Consequence*) {}
+ virtual void consequenceValidationChanged(Consequence*) {}
+ virtual void consequenceTriggered(Consequence*) {}
+ };
+
+
+ DECLARE_INSPECTACLE_SAFE_LISTENER(ConsequenceManager, consequenceManager);
+
+ DECLARE_ASYNC_EVENT(ConsequenceManager, ConsequenceManager, csm, ENUM_LIST(MULTIPLEX_PREVIEW_CHANGED, STAGGER_CHANGED), EVENT_INSPECTABLE_CHECK);
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ConsequenceManager)
};
\ No newline at end of file