11namespace tracktion {
inline namespace engine
14namespace AutomationScaleHelpers
16 inline float getQuadraticBezierControlPoint (
float y1,
float y2,
float curve)
noexcept
18 jassert (curve >= -0.5f && curve <= 0.5f);
25 auto yc =
y1 + rise / 2;
26 auto y = yc + rise / 2 * -c;
32 auto yc = y2 + rise / 2;
33 auto y = yc - rise / 2 * -c;
38 inline float getCurvedValue (
float value,
float start,
float end,
float curve)
noexcept
41 return ((end - start) * value) + start;
43 auto control = getQuadraticBezierControlPoint (start, end, curve);
44 return (
float) AutomationCurve::getBezierXfromT (value, start, control, end);
47 inline float mapValue (
float inputVal,
float offset,
float value,
float curve)
noexcept
49 return inputVal < 0.0 ? offset - getCurvedValue (-inputVal, 0.0f, value, curve)
50 : offset + getCurvedValue (inputVal, 0.0f, value, curve);
66AutomatableParameter::ModifierSource::~ModifierSource()
68 masterReference.clear();
108 assignment (std::move (ass))
112 virtual AutomatableParameter::ModifierSource* getModifierSource() = 0;
122 modifier (std::move (mod))
124 jassert (state.hasProperty (IDs::source));
129 return modifier.get();
138 editTimeToReturn = newEditTime;
148 float baseValue = modifier->getCurrentValue();
150 const auto currentTime = modifier->getCurrentTime();
151 const auto deltaTime = currentTime - editTimeToReturn;
153 if (deltaTime > 0s && deltaTime < Modifier::maxHistoryTime)
154 baseValue = modifier->getValueAt (deltaTime);
156 return AutomationScaleHelpers::mapValue (baseValue, assignment->offset, assignment->value, assignment->curve);
172 curve (ap.parentState, state)
174 deferredUpdateTimer.setCallback ([
this]
176 deferredUpdateTimer.stopTimer();
177 updateInterpolatedPoints();
180 curve.setOwnerParameter (&ap);
183 void triggerAsyncCurveUpdate()
185 if (! parameter.getEdit().isLoading())
186 deferredUpdateTimer.startTimer (10);
189 void updateInterpolatedPoints()
191 jassert (! parameter.getEdit().isLoading());
193 TRACKTION_ASSERT_MESSAGE_THREAD
197 if (curve.getNumPoints() > 0)
202 newStream = std::move (s);
208 parameterStream = std::move (newStream);
210 if (! parameterStream)
211 parameter.updateToFollowCurve (lastTime);
216 parameter.automatableEditElement.updateActiveParameters();
219 bool isActive()
const noexcept
226 TRACKTION_ASSERT_MESSAGE_THREAD
227 return curve.getValueAt (
time);
237 if (! parameter.getEdit().getAutomationRecordManager().isReadingAutomation())
238 if (
auto plugin = parameter.getPlugin())
239 if (! plugin->isClipEffectPlugin())
244 if (lastTime.exchange (
time) !=
time)
245 parameterStream->setPosition (
time);
256 return parameterStream->getCurrentValue();
271 auto v = ap.parentState.getChildWithProperty (IDs::paramID, ap.paramID);
276 auto oldAutomation = ap.parentState.getChildWithProperty (IDs::name, ap.paramName);
278 if (oldAutomation.isValid())
279 return oldAutomation;
282 return ap.parentState.getChildWithProperty (IDs::name, ap.paramID);
296 macro (¯oParameter)
298 jassert (state.hasType (IDs::MACRO) && state.hasProperty (IDs::source));
308 TRACKTION_ASSERT_MESSAGE_THREAD
309 auto macroValue = macro->getCurve().getValueAt (
time);
311 return AutomationScaleHelpers::mapValue (AutomationScaleHelpers::remapInputValue (macroValue, range),
312 assignment->offset, assignment->value, assignment->curve);
323 macro->updateFromAutomationSources (
time);
324 auto macroValue = macro->getCurrentValue();
327 currentValue.store (AutomationScaleHelpers::mapValue (AutomationScaleHelpers::remapInputValue (macroValue, range),
328 assignment->offset, assignment->value, assignment->curve),
361 updateCachedSources();
364 parameter.curveSource->triggerAsyncCurveUpdate();
372 bool isActive()
const
375 jassert (num == objects.size());
379 template<
typename Fn>
380 void visitSources (
Fn&& f)
382 if (
auto cs = cachedSources)
383 for (
auto* as : cs->sources)
389 TRACKTION_ASSERT_MESSAGE_THREAD
391 for (
auto o : objects)
392 if (o->assignment.get() == &ass)
400 TRACKTION_ASSERT_MESSAGE_THREAD
402 for (
auto o : objects)
403 if (o->assignment->isForModifierSource (mod))
422 void updateCachedSources()
424 if (objects.isEmpty())
426 cachedSources.
reset();
430 auto cs =
new CachedSources();
432 for (
auto o : objects)
441 if (v.hasType (IDs::LFO) || v.hasType (IDs::BREAKPOINTOSCILLATOR) || v.hasType (IDs::MACRO)
442 || v.hasType (IDs::STEP) || v.hasType (IDs::ENVELOPEFOLLOWER) || v.hasType (IDs::RANDOM)
443 || v.hasType (IDs::MIDITRACKER))
446 const auto isLegacyLFO = [&,
this] {
return v.hasType (IDs::LFO) && v[IDs::paramID].
toString() == parameter.paramName; };
448 if ((v[IDs::paramID] == parameter.paramID || isLegacyLFO())
449 && EditItemID::fromProperty (v, IDs::source).isValid())
463 if (v.hasType (IDs::LFO) && v[IDs::paramID].
toString() == parameter.paramName)
464 juce::ValueTree (v).setProperty (IDs::paramID, parameter.paramID,
nullptr);
469 for (
auto mp : mpl->getMacroParameters())
470 if (mp->paramID ==
id)
476 if (
auto mod =
findModifierForID (parameter.getEdit(), EditItemID::fromProperty (v, IDs::source)))
478 if (v.isAChildOf (mod->state))
483 else if (
auto macro = getMacroForID (v[IDs::source].toString()))
485 if (v.isAChildOf (macro->state))
495 as->incReferenceCount();
509 void objectOrderChanged()
override { objectAddedOrRemoved (
nullptr); }
513 updateCachedSources();
518 mas->modifier->changed();
519 else if (
auto macro =
dynamic_cast<MacroSource*
> (source))
520 macro->macro->changed();
523 for (
auto s : objects)
524 if (as ==
nullptr || s != as)
529 parameter.curveSource->triggerAsyncCurveUpdate();
541 virtual void setValue (
float v) = 0;
542 virtual float getValue() = 0;
543 virtual float getDefault() = 0;
546 virtual void updateParameterFromValue() = 0;
559 void handleAsyncUpdate()
override { value.setValue (parameter.currentValue,
nullptr); }
560 float getValue()
override {
return value; }
561 void setValue (
float v)
override { value = v; }
562 float getDefault()
override {
return value.getDefault(); }
567 if (i == value.getPropertyID() && v == value.getValueTree())
569 value.forceUpdateOfCachedValue();
575 void updateParameterFromValue()
override
591 void handleAsyncUpdate()
override { value.setValue (
juce::roundToInt (parameter.getCurrentValue()),
nullptr); }
592 float getValue()
override {
return (
float) value.get(); }
594 float getDefault()
override {
return (
float) value.getDefault(); }
599 if (i == value.getPropertyID() && v == value.getValueTree())
601 value.forceUpdateOfCachedValue();
607 void updateParameterFromValue()
override
623 void handleAsyncUpdate()
override { value.setValue (parameter.currentValue != 0.0f,
nullptr); }
624 float getValue()
override {
return value; }
625 void setValue (
float v)
override { value = v != 0 ? true :
false; }
626 float getDefault()
override {
return value.getDefault() ? 1.0f : 0.0f; }
631 if (i == value.getPropertyID() && v == value.getValueTree())
633 value.forceUpdateOfCachedValue();
639 void updateParameterFromValue()
override
649AutomatableParameter::AutomatableParameter (
const juce::String& paramID_,
653 : paramID (paramID_),
655 automatableEditElement (owner),
657 editRef (&automatableEditElement.edit)
659 if (
auto p =
dynamic_cast<Plugin*
> (&owner))
662 parentState = plugin->state;
664 else if (
auto m =
dynamic_cast<Modifier*
> (&owner))
667 parentState = modifierOwner->state;
672 parentState = mpl->state;
679 modifiersState = parentState.getOrCreateChildWithName (IDs::MODIFIERASSIGNMENTS, &owner.edit.
getUndoManager());
682 valueToStringFunction = [] (
float value) {
return juce::String (value, 3); };
683 stringToValueFunction = [] (
const juce::String& s) {
return s.getFloatValue(); };
685 parentState.addListener (
this);
688AutomatableParameter::~AutomatableParameter()
690 if (
auto edit = editRef.get())
691 edit->getAutomationRecordManager().parameterBeingDeleted (*
this);
693 notifyListenersOfDeletion();
695 automationSourceList.reset();
697 if (attachedValue !=
nullptr)
698 attachedValue->detach (
this);
701AutomatableParameter::ModifierAssignment::ModifierAssignment (Edit& e,
const juce::ValueTree& v)
702 : edit (e), state (v)
704 auto* um = &edit.getUndoManager();
705 offset.referTo (state, IDs::offset, um);
706 value.referTo (state, IDs::value, um);
707 curve.referTo (state, IDs::curve, um);
709 inputStart.referTo (state, IDs::start, um, 0.0f);
710 inputEnd.referTo (state, IDs::end, um, 1.0f);
715 if (
auto existing = getAutomationSourceList().getSourceFor (source))
716 return existing->assignment;
720 if (
auto mod =
dynamic_cast<Modifier*
> (&source))
722 if (mod == &automatableEditElement)
725 v = createValueTree (mod->state.getType(),
726 IDs::source, mod->itemID);
730 v = createValueTree (IDs::MACRO,
731 IDs::source, macro->paramID);
740 v.setProperty (IDs::paramID, paramID,
nullptr);
741 v.setProperty (IDs::value, value,
nullptr);
743 if (offset != 0.0f) v.setProperty (IDs::offset, offset,
nullptr);
744 if (curve != 0.5f) v.setProperty (IDs::curve, curve,
nullptr);
746 modifiersState.
addChild (v, -1, &getEdit().getUndoManager());
748 auto as = getAutomationSourceList().getSourceFor (source);
751 return as->assignment;
756 TRACKTION_ASSERT_MESSAGE_THREAD
758 if (
auto existing = getAutomationSourceList().getSourceFor (assignment))
759 existing->state.getParent().removeChild (existing->state, &getEdit().getUndoManager());
766 TRACKTION_ASSERT_MESSAGE_THREAD
768 if (
auto existing = getAutomationSourceList().getSourceFor (source))
769 existing->state.getParent().removeChild (existing->state, &getEdit().getUndoManager());
776 TRACKTION_ASSERT_MESSAGE_THREAD
777 return getAutomationSourceList().isActive();
782 TRACKTION_ASSERT_MESSAGE_THREAD
785 getAutomationSourceList()
795 getAutomationSourceList()
804 return curveSource->isActive() || getAutomationSourceList().isActive();
809 if (attachedValue !=
nullptr)
810 return attachedValue->getDefault();
817 curveSource->updateInterpolatedPoints();
822 if (updateParametersRecursionCheck)
826 float newModifierValue = 0.0f;
828 getAutomationSourceList()
831 m.setPosition (
time);
835 float currentModValue = m.getCurrentValue();
836 jassert (! std::isnan (currentModValue));
837 newModifierValue += currentModValue;
841 const float newBaseValue = [
this,
time]
843 if (curveSource->isActive())
845 curveSource->setPosition (
time);
846 return curveSource->getCurrentValue();
849 return currentParameterValue.
load();
852 if (newModifierValue != 0.0f)
854 auto normalisedBase = valueRange.
convertTo0to1 (newBaseValue);
859 currentModifierValue = 0.0f;
862 setParameterValue (newBaseValue,
true);
868 if (v == getCurve().state || v.isAChildOf (getCurve().state))
872 else if (attachedValue !=
nullptr && attachedValue->updateIfMatches (v, i))
877 TRACKTION_ASSERT_MESSAGE_THREAD
878 SCOPED_REALTIME_CHECK
888 if (parent == getCurve().state || parent == modifiersState)
890 else if (parent == parentState && newChild[IDs::name] == paramID)
891 getCurve().setState (newChild);
896 if (parent == getCurve().state || parent == modifiersState)
900void AutomatableParameter::valueTreeChildOrderChanged (
juce::ValueTree& parent,
int,
int)
902 if (parent == getCurve().state || parent == modifiersState)
912 currentParameterValue = currentValue = v;
913 jassert (attachedValue ==
nullptr);
915 v.getValueTree().addListener (
this);
920 currentParameterValue = currentValue = (
float) v.get();
921 jassert (attachedValue ==
nullptr);
923 v.getValueTree().addListener (
this);
928 currentParameterValue = currentValue = v;
929 jassert (attachedValue ==
nullptr);
931 v.getValueTree().addListener (
this);
934void AutomatableParameter::updateFromAttachedValue()
937 attachedValue->updateParameterFromValue();
940void AutomatableParameter::detachFromCurrentValue()
942 if (attachedValue ==
nullptr)
945 attachedValue->detach (
this);
946 attachedValue.reset();
949Engine& AutomatableParameter::getEngine() const noexcept
954Edit& AutomatableParameter::getEdit() const noexcept
956 return automatableEditElement.edit;
959Track* AutomatableParameter::getTrack() const noexcept
963 : macroOwner->getTrack();
966AutomationCurve& AutomatableParameter::getCurve() const noexcept
968 return curveSource->curve;
973 if (macroOwner !=
nullptr)
976 if (plugin !=
nullptr)
979 return modifierOwner;
984 if (plugin !=
nullptr)
990 if (modifierOwner !=
nullptr)
993 return modifierOwner->
itemID;
996 jassert (macroOwner !=
nullptr);
997 return macroOwner->
itemID;
1000juce::String AutomatableParameter::getPluginAndParamName()
const
1004 if (plugin !=
nullptr)
1005 s << plugin->
getName() +
" >> ";
1006 else if (modifierOwner !=
nullptr)
1007 s << modifierOwner->getName() +
" >> ";
1009 s << af->getName() +
" >> ";
1011 return s + getParameterName();
1018 if (
auto t = getTrack())
1019 s << t->getName() <<
" >> ";
1021 return s + getPluginAndParamName();
1027 isRecording =
false;
1031void AutomatableParameter::setParameterValue (
float value,
bool isFollowingCurve)
1033 auto& curve = getCurve();
1034 value = snapToState (getValueRange().clipValue (value));
1035 currentBaseValue = value;
1037 if (currentModifierValue != 0.0f)
1038 value = snapToState (getValueRange().clipValue (value + currentModifierValue));
1040 if (currentValue != value)
1042 parameterChanged (value, isFollowingCurve);
1044 auto& ed = getEdit();
1046 if (isFollowingCurve)
1048 ed.getParameterChangeHandler().parameterChanged (*
this,
true);
1050 currentValue = value;
1052 if (attachedValue !=
nullptr)
1053 attachedValue->triggerAsyncUpdate();
1057 if (! getEdit().isLoading())
1058 jassert (juce::MessageManager::getInstance()->currentThreadHasLockedMessageManager());
1062 if (
auto epc = ed.getTransport().getCurrentPlaybackContext())
1064 if (! epc->isDragging())
1066 auto numPoints = curve.getNumPoints();
1067 auto& arm = ed.getAutomationRecordManager();
1069 if (epc->isPlaying() && arm.isWritingAutomation())
1071 auto time = epc->getPosition();
1076 arm.postFirstAutomationChange (*
this, currentValue);
1079 arm.postAutomationChange (*
this, time, value);
1084 curve.movePoint (0, curve.getPointTime (0), value,
false);
1089 currentValue = value;
1091 if (attachedValue !=
nullptr)
1093 attachedValue->cancelPendingUpdate();
1094 attachedValue->setValue (value);
1099 SCOPED_REALTIME_CHECK
1107 currentParameterValue = value;
1108 setParameterValue (value,
false);
1113 TRACKTION_ASSERT_MESSAGE_THREAD
1116 if (attachedValue !=
nullptr)
1119 attachedValue->handleAsyncUpdate();
1129juce::String AutomatableParameter::getCurrentValueAsStringWithLabel()
1131 auto text = getCurrentValueAsString();
1132 auto label = getLabel();
1134 if (! (label.isEmpty() || text.endsWith (label)))
1135 return text +
' ' + label;
1140AutomatableParameter::AutomationSourceList& AutomatableParameter::getAutomationSourceList()
const
1142 if (! automationSourceList)
1145 return *automationSourceList;
1148void AutomatableParameter::updateToFollowCurve (TimePosition time)
1150 TRACKTION_ASSERT_MESSAGE_THREAD
1151 float newModifierValue = 0.0f;
1153 getAutomationSourceList()
1154 .visitSources ([&newModifierValue, time] (AutomationModifierSource& m)
mutable
1156 if (m.isEnabledAt (time))
1158 const float sourceModValue = m.getValueAt (time);
1159 jassert (! std::isnan (sourceModValue));
1160 newModifierValue += sourceModValue;
1164 const float newBaseValue = [
this,
time]
1166 if (hasAutomationPoints() && ! isRecording)
1167 return curveSource->getValueAt (time);
1169 return currentParameterValue.
load();
1172 if (newModifierValue != 0.0f)
1174 auto normalisedBase = valueRange.
convertTo0to1 (newBaseValue);
1179 currentModifierValue = 0.0f;
1182 setParameterValue (newBaseValue,
true);
1187 TRACKTION_ASSERT_MESSAGE_THREAD
1188 listeners.call (&Listener::parameterChangeGestureBegin, *
this);
1193 TRACKTION_ASSERT_MESSAGE_THREAD
1194 listeners.call (&Listener::parameterChangeGestureEnd, *
this);
1198void AutomatableParameter::midiControllerMoved (
float newPosition)
1203void AutomatableParameter::midiControllerPressed()
1207 int state = getStateForValue (getCurrentValue()) + 1;
1209 if (state >= getNumberOfStates())
1217void AutomatableParameter::curveHasChanged()
1219 TRACKTION_ASSERT_MESSAGE_THREAD
1221 curveSource->triggerAsyncCurveUpdate();
1230 if (ass.isForModifierSource (*modifier))
1242 for (
auto ass : param.getAssignments())
1244 if (ass->isForModifierSource (m))
1262 for (
auto ass : param.getAssignments())
1263 if (ass == &assignment)
1271AutomationIterator::AutomationIterator (
const AutomatableParameter& p)
1273 hiRes = ! p.automatableEditElement.edit.engine.getEngineBehaviour().interpolateAutomation();
1281void AutomationIterator::copy (
const AutomatableParameter& param)
1283 const auto& curve = param.getCurve();
1285 jassert (curve.getNumPoints() > 0);
1287 for (
int i = 0; i < curve.getNumPoints(); i++)
1289 auto src = curve.getPoint (i);
1292 dst.time = src.time;
1293 dst.value = src.value;
1294 dst.curve = src.curve;
1300void AutomationIterator::interpolate (
const AutomatableParameter& param)
1302 const auto& curve = param.getCurve();
1304 jassert (curve.getNumPoints() > 0);
1306 const auto timeDelta = TimeDuration::fromSeconds (1.0 / 100.0);
1307 const double minValueDelta = (param.getValueRange().getLength()) / 256.0;
1310 int lastCurveIndex = -1;
1312 float lastValue = 1.0e10;
1313 auto lastTime = curve.getPointTime (curve.getNumPoints() - 1) + TimeDuration::fromSeconds (1.0);
1315 auto t2 = curve.getPointTime (0);
1316 float v1 = curve.getValueAt (TimePosition());
1326 while (t < lastTime)
1330 if (curveIndex >= curve.getNumPoints() - 1)
1340 c = curve.getPointCurve (curveIndex);
1344 bp = curve.getBezierPoint (curveIndex);
1346 if (c < -0.5 || c > 0.5)
1347 curve.getBezierEnds (curveIndex, x1end, y1end, x2end, y2end);
1350 t2 = curve.getPointTime (++curveIndex);
1351 v2 = curve.getPointValue (curveIndex);
1360 v = v1 + (v2 - v1) * (
float) ((t - t1) / (t2 - t1));
1362 else if (c >= -0.5 && c <= 0.5)
1364 v = AutomationCurve::getBezierYFromX (t.inSeconds(), t1.inSeconds(), v1,
toTime (bp.time, param.getEdit().tempoSequence).
inSeconds(), bp.value, t2.inSeconds(), v2);
1368 if (t >= t1 && t <= TimePosition::fromSeconds (x1end))
1370 else if (t >= TimePosition::fromSeconds (x2end) && t <= t2)
1373 v = AutomationCurve::getBezierYFromX (t.inSeconds(), x1end, y1end,
toTime (bp.time, param.getEdit().tempoSequence).
inSeconds(), bp.value, x2end, y2end);
1377 if (std::abs (v - lastValue) >= minValueDelta || curveIndex != lastCurveIndex)
1385 jassert (points.isEmpty() || points.getLast().time <= t);
1387 if (points.size() >= 1 && t - points[points.size() - 1].time > timeDelta * 10)
1388 points.add ({t - timeDelta, vp});
1393 lastCurveIndex = curveIndex;
1401void AutomationIterator::setPosition (TimePosition newTime)
noexcept
1404 setPositionHiRes (newTime);
1406 setPositionInterpolated (newTime);
1409void AutomationIterator::setPositionHiRes (TimePosition newTime)
noexcept
1413 auto newIndex = updateIndex (newTime);
1415 if (newTime < points[0].time)
1417 currentIndex = newIndex;
1418 currentValue = points.getReference (0).value;
1422 if (newIndex == points.size() - 1)
1424 currentIndex = newIndex;
1425 currentValue = points.getReference (newIndex).value;
1429 const auto& p1 = points.getReference (newIndex);
1430 const auto& p2 = points.getReference (newIndex + 1);
1432 const auto t = newTime;
1434 const auto t1 = p1.time;
1435 const auto t2 = p2.time;
1437 const auto v1 = p1.value;
1438 const auto v2 = p2.value;
1440 const auto c = p1.curve;
1448 v = v1 + (v2 - v1) * (
float) ((t - t1) / (t2 - t1));
1450 else if (c >= -0.5 && c <= 0.5)
1452 auto bp = getBezierPoint (p1.time.inSeconds(), p1.value, p2.time.inSeconds(), p2.value, p1.curve);
1453 v =
float (getBezierYFromX (t.inSeconds(), t1.inSeconds(), v1, bp.first, bp.second, t2.inSeconds(), v2));
1457 double x1end = 0, x2end = 0;
1458 double y1end = 0, y2end = 0;
1460 auto bp = getBezierPoint (p1.time.inSeconds(), p1.value, p2.time.inSeconds(), p2.value, p1.curve);
1461 getBezierEnds (p1.time.inSeconds(), p1.value,
1462 p2.time.inSeconds(), p2.value,
1464 x1end, y1end, x2end, y2end);
1466 if (t >= t1 && t <= TimePosition::fromSeconds (x1end))
1468 else if (t >= TimePosition::fromSeconds (x2end) && t <= t2)
1471 v =
float (getBezierYFromX (t.inSeconds(), x1end, y1end, bp.first, bp.second, x2end, y2end));
1474 currentIndex = newIndex;
1478void AutomationIterator::setPositionInterpolated (TimePosition newTime)
noexcept
1482 auto newIndex = updateIndex (newTime);
1484 if (currentIndex != newIndex)
1487 currentIndex = newIndex;
1488 currentValue = points.getReference (newIndex).value;
1491 if (newTime >= points[0].time && newIndex < points.size() - 1)
1493 const auto& p1 = points.getReference (newIndex);
1494 const auto& p2 = points.getReference (newIndex + 1);
1496 const auto t = newTime.inSeconds();
1498 const auto t1 = p1.time.inSeconds();
1499 const auto t2 = p2.time.inSeconds();
1501 const auto v1 = p1.value;
1502 const auto v2 = p2.value;
1504 currentValue =
std::lerp (v1, v2,
float ((t - t1) / (t2 - t1)));
1508int AutomationIterator::updateIndex (TimePosition newTime)
1510 auto newIndex = currentIndex;
1515 if (newIndex > 0 && points.getReference (newIndex).time >= newTime)
1519 while (newIndex > 0 && points.getReference (newIndex).time >= newTime)
1524 while (newIndex < points.size() - 1 && points.getReference (newIndex + 1).time < newTime)
1531const char* AutomationDragDropTarget::automatableDragString =
"automatableParamDrag";
1533AutomationDragDropTarget::AutomationDragDropTarget() {}
1534AutomationDragDropTarget::~AutomationDragDropTarget() {}
1536bool AutomationDragDropTarget::isAutomatableParameterBeingDraggedOver()
const
1538 return isAutoParamCurrentlyOver;
1541bool AutomationDragDropTarget::isInterestedInDragSource (
const SourceDetails& details)
1543 return details.description == automatableDragString;
1546void AutomationDragDropTarget::itemDragEnter (
const SourceDetails&)
1548 isAutoParamCurrentlyOver = hasAnAutomatableParameter();
1554void AutomationDragDropTarget::itemDragExit (
const SourceDetails&)
1556 isAutoParamCurrentlyOver =
false;
1562void AutomationDragDropTarget::itemDropped (
const SourceDetails& dragSourceDetails)
1564 isAutoParamCurrentlyOver =
false;
1572 if (
auto source =
dynamic_cast<ParameterisableDragDropSource*
> (sourceCompRef.get()))
1574 source->draggedOntoAutomatableParameterTargetBeforeParamSelection();
1576 auto handleChosenParam = [sourceCompRef] (AutomatableParameter::Ptr param)
1578 if (
auto src =
dynamic_cast<ParameterisableDragDropSource*
> (sourceCompRef.get()))
1579 src->draggedOntoAutomatableParameterTarget (param);
1582 chooseAutomatableParameter (handleChosenParam,
1583 [thisRef, handleChosenParam]
1585 if (
auto t =
dynamic_cast<AutomationDragDropTarget*
> (thisRef.get()))
1586 t->startParameterLearn (handleChosenParam);
bool addIfNotAlreadyThere(ParameterType newElement)
void triggerAsyncUpdate()
bool isValid() const noexcept
const String & toString() const noexcept
ValueType convertFrom0to1(ValueType proportion) const noexcept
ValueType convertTo0to1(ValueType v) const noexcept
constexpr ValueType getStart() const noexcept
constexpr ValueType getEnd() const noexcept
ValueType clipValue(const ValueType value) const noexcept
static constexpr Range between(const ValueType position1, const ValueType position2) noexcept
bool contains(const ObjectClass *objectToLookFor) const noexcept
ObjectClass * add(ObjectClass *newObject)
ReferencedType * get() const noexcept
void decReferenceCount() noexcept
void addChild(const ValueTree &child, int index, UndoManager *undoManager)
Base class for elements that have some kind of automatable parameters.
juce::Array< ModifierSource * > getModifiers() const
Returns all the current ModifierSources currently in use by assignments.
Selectable * getOwnerSelectable() const
Returns the thing that you'd select if you wanted to show this param.
void removeModifier(ModifierAssignment &)
Removes an assignment.
void parameterChangeGestureBegin()
Call to indicate this parameter is about to be changed.
ModifierAssignment::Ptr addModifier(ModifierSource &, float value=1.0f, float offset=0.0f, float curve=0.5f)
Creates an assignment for a given source.
juce::ReferenceCountedArray< ModifierAssignment > getAssignments() const
Returns all the current ModifierAssignments.
bool hasActiveModifierAssignments() const
Returns true if any ModifierSources are currently in use by assignments.
void resetRecordingStatus()
this is called before and after playback or recording.
void updateStream()
Forces the parameter to update its automation stream for reading automation.
void updateFromAutomationSources(TimePosition)
Updates the parameter and modifier values from its current automation sources.
bool isAutomationActive() const
Returns true if the parameter is being dynamically changed somehow, either through automation or a Mo...
EditItemID getOwnerID() const
Returns the thing that you'd select if you wanted to show this param.
void parameterChangeGestureEnd()
Call to indicate this parameter has stopped being to be changed.
float getCurrentValue() override
Should return the current value of the source.
void setPosition(TimePosition time) override
Should set the position of the source to a specific time in the Edit.
bool isEnabledAt(TimePosition) override
Must return if the source is enabled at the given time.
bool isEnabled() override
Should return true if the source is enabled at the current position.
float getValueAt(TimePosition time) override
Must return the value of automation at the given time.
const EditItemID itemID
Every EditItem has an ID which is unique within the edit.
The Tracktion Edit class!
void visitAllAutomatableParams(bool includeTrackParams, const std::function< void(AutomatableParameter &)> &) const
Returns all automatable parameters in an Edit.
ParameterChangeHandler & getParameterChangeHandler() noexcept
Returns the ParameterChangeHandler for the Edit.
bool isLoading() const
Returns true if the Edit's not yet fully loaded.
juce::UndoManager & getUndoManager() noexcept
Returns the juce::UndoManager used for this Edit.
Engine & engine
A reference to the Engine.
A MacroParameter is an AutomatableParameter which is a collection of Mappings.
void parameterChanged(AutomatableParameter ¶meter, bool fromAutomation)
Called by parameters when they are changed.
virtual juce::String getName() const override=0
The name of the type, e.g.
Track * getOwnerTrack() const
Returns the track if it's a track or clip plugin.
Base class for things that can be selected, and whose properties can appear in the properties panel.
static bool isSelectableValid(const Selectable *) noexcept
checks whether this object has been deleted.
constexpr Type jmap(Type value0To1, Type targetRangeMin, Type targetRangeMax)
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
bool isPositiveAndNotGreaterThan(Type1 valueToTest, Type2 upperLimit) noexcept
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
int roundToInt(const FloatType value) noexcept
AutomatableParameter::ModifierSource * getSourceForAssignment(const AutomatableParameter::ModifierAssignment &ass)
Iterates an Edit looking for the source of this assignment.
juce::ReferenceCountedArray< AutomatableParameter > getAllParametersBeingModifiedBy(Edit &edit, AutomatableParameter::ModifierSource &m)
Iterates an Edit looking for all parameters that are being modified by the given ModifierSource.
juce::Array< MacroParameterList * > getAllMacroParameterLists(const Edit &edit)
Returns all the MacroParameterLists in an Edit.
juce::Array< AutomatableParameter::ModifierSource * > getAllModifierSources(const Edit &edit)
Returns all the ModifierSources in an Edit.
bool getBoolParamValue(const AutomatableParameter &ap)
Returns a bool version of an AutomatableParameter.
AutomatableParameter * getParameter(AutomatableParameter::ModifierAssignment &assignment)
Iterates an Edit looking for the parameter that this ModifierAssignment has been made from.
Modifier::Ptr findModifierForID(ModifierList &ml, EditItemID modifierID)
Returns a Modifier if it can be found in the list.
Track * getTrackContainingModifier(const Edit &edit, const Modifier::Ptr &m)
Returns the Track containing a Modifier.
TimePosition toTime(BeatPosition bp, const TempoSequence &ts)
Converts a BeatPosition to a TimePosition given a TempoSequence.
Plugin::Ptr getOwnerPlugin(MacroParameterList *mpl)
If this MacroParameterList belongs to an Plugin, this will return it.
Represents a position in real-life time.
constexpr double inSeconds() const
Returns the TimePosition as a number of seconds.
virtual void currentValueChanged(AutomatableParameter &)
Called when the current value of the parameter changed, either from setting the parameter,...
virtual void parameterChanged(AutomatableParameter &, float)
Called when the parameter is changed by the plugin or host, not from automation.
virtual void curveHasChanged(AutomatableParameter &)=0
Called when the automation curve has changed, point time, value or curve.
Connects a modifier source to an AutomatableParameter.
Base class for things that can be used to modify parameters.
virtual float getValueAt(TimePosition)=0
Must return the value of automation at the given time.
virtual bool isEnabledAt(TimePosition)=0
Must return if the source is enabled at the given time.
virtual bool isEnabled()=0
Should return true if the source is enabled at the current position.
virtual float getCurrentValue()=0
Should return the current value of the source.
virtual void setPosition(TimePosition)=0
Should set the position of the source to a specific time in the Edit.
ID for objects of type EditElement - e.g.
An Assignment between a MacroParameter and an AutomatableParameter.
float getCurrentValue() override
Should return the current value of the source.
void setPosition(TimePosition time) override
Should set the position of the source to a specific time in the Edit.
bool isEnabledAt(TimePosition) override
Must return if the source is enabled at the given time.
bool isEnabled() override
Should return true if the source is enabled at the current position.
float getValueAt(TimePosition time) override
Must return the value of automation at the given time.
bool isEnabledAt(TimePosition) override
Must return if the source is enabled at the given time.
float getValueAt(TimePosition) override
Must return the value of automation at the given time.
void setPosition(TimePosition newEditTime) override
Should set the position of the source to a specific time in the Edit.
float getCurrentValue() override
Should return the current value of the source.
bool isEnabled() override
Should return true if the source is enabled at the current position.
Bass class for parameter Modifiers.
float remapInputValue(float inputVal, juce::Range< float > inputRange)
Remaps an input value from a given input range to 0-1.
#define CRASH_TRACER
This macro adds the current location to a stack which gets logged if a crash happens.