diff --git a/src/app/GUI/BoxesList/boxsinglewidget.cpp b/src/app/GUI/BoxesList/boxsinglewidget.cpp index 8c53bd7b6..64bd33a1b 100644 --- a/src/app/GUI/BoxesList/boxsinglewidget.cpp +++ b/src/app/GUI/BoxesList/boxsinglewidget.cpp @@ -690,7 +690,7 @@ void BoxSingleWidget::mouseMoveEvent(QMouseEvent *event) { const auto drag = new QDrag(this); { const auto prop = static_cast(mTarget->getTarget()); - const QString name = prop->prp_getName(); + const QString name = getDisplayName(prop); const int nameWidth = QApplication::fontMetrics().horizontalAdvance(name); QPixmap pixmap(mFillWidget->x() + nameWidth + eSizesUI::widget, height()); render(&pixmap); @@ -886,7 +886,7 @@ void BoxSingleWidget::paintEvent(QPaintEvent *) { } const QRect textRect(nameX, 0, width() - nameX - eSizesUI::widget, eSizesUI::widget); - const QString& name = prop->prp_getName(); + const QString name = getDisplayName(prop); QTextOption opts(Qt::AlignVCenter); opts.setWrapMode(QTextOption::NoWrap); p.drawText(textRect, name, opts); @@ -947,6 +947,27 @@ void BoxSingleWidget::switchBoxLockedAction() { update(); } +QString BoxSingleWidget::getDisplayName(Property* const prop) const { + if(!prop) return QString(); + + QString name = prop->prp_getName(); + + const auto rules = mParent->getRulesCollection(); + if(rules.fParamRule != SWT_ParamRule::animatedOnly) return name; + + const auto vecParent = prop->getFirstAncestor(); + if(!vecParent) return name; + const auto xAnim = vecParent->getXAnimator(); + const auto yAnim = vecParent->getYAnimator(); + if(!xAnim || !yAnim) return name; + if(prop != xAnim && prop != yAnim) return name; + + const auto parentName = vecParent->prp_getName(); + if(parentName.isEmpty()) return name; + + return parentName + " / " + name; +} + void BoxSingleWidget::updateValueSlidersForQPointFAnimator() { if(!mTarget) return; const auto target = mTarget->getTarget(); diff --git a/src/app/GUI/BoxesList/boxsinglewidget.h b/src/app/GUI/BoxesList/boxsinglewidget.h index 11fac85ee..c99790bf8 100644 --- a/src/app/GUI/BoxesList/boxsinglewidget.h +++ b/src/app/GUI/BoxesList/boxsinglewidget.h @@ -123,6 +123,8 @@ class BoxSingleWidget : public SingleWidget { void clearAndHideValueAnimators(); void updateValueSlidersForQPointFAnimator(); private: + QString getDisplayName(Property* const prop) const; + ContainerBox *getPromoteTargetGroup(); void clearSelected() { setSelected(false); } diff --git a/src/app/GUI/timelinewidget.cpp b/src/app/GUI/timelinewidget.cpp index 06a976866..9eb3e03a5 100644 --- a/src/app/GUI/timelinewidget.cpp +++ b/src/app/GUI/timelinewidget.cpp @@ -140,6 +140,24 @@ TimelineWidget::TimelineWidget(Document &document, typeActionAdder(SWT_Type::sound, "Sound"); typeActionAdder(SWT_Type::graphics, "Graphics"); + QMenu * const paramMenu = settingsMenu->addMenu(filterIcon, tr("Parameters")); + + const auto paramActionAdder = [this, paramMenu]( + const SWT_ParamRule paramRule, const QString& text) { + const auto slot = [this, paramRule]() { setParamRule(paramRule); }; + const auto action = paramMenu->addAction(text, this, slot); + action->setCheckable(true); + connect(this, &TimelineWidget::paramRuleChanged, + action, [action, paramRule](const SWT_ParamRule setRule) { + action->setChecked(paramRule == setRule); + }); + return action; + }; + + paramActionAdder(SWT_ParamRule::all, tr("All"))->setChecked(true); + paramActionAdder(SWT_ParamRule::animated, tr("Animated")); + paramActionAdder(SWT_ParamRule::animatedOnly, tr("Animated (plain)")); + settingsMenu->addSeparator(); { @@ -147,18 +165,21 @@ TimelineWidget::TimelineWidget(Document &document, setBoxRule(SWT_BoxRule::all); setTarget(SWT_Target::canvas); setType(SWT_Type::all); + setParamRule(SWT_ParamRule::all); }; const auto act = settingsMenu->addAction("Reset", this, op); const auto can = [this]() { const auto rules = mBoxesListWidget->getRulesCollection(); return rules.fRule != SWT_BoxRule::all || rules.fTarget != SWT_Target::canvas || - rules.fType != SWT_Type::all; + rules.fType != SWT_Type::all || + rules.fParamRule != SWT_ParamRule::all; }; const auto setEnabled = [act, can]() { act->setEnabled(can()); }; connect(this, &TimelineWidget::typeChanged, act, setEnabled); connect(this, &TimelineWidget::targetChanged, act, setEnabled); connect(this, &TimelineWidget::boxRuleChanged, act, setEnabled); + connect(this, &TimelineWidget::paramRuleChanged, act, setEnabled); } //QMenu *viewMenu = mBoxesListMenuBar->addMenu("View"); @@ -571,6 +592,11 @@ void TimelineWidget::setType(const SWT_Type type) { emit typeChanged(type); } +void TimelineWidget::setParamRule(const SWT_ParamRule rule) { + mBoxesListWidget->setCurrentParamRule(rule); + emit paramRuleChanged(rule); +} + void TimelineWidget::setSearchText(const QString &text) { mBoxesListWidget->setCurrentSearchText(text); } diff --git a/src/app/GUI/timelinewidget.h b/src/app/GUI/timelinewidget.h index 40a2125a1..6b563883f 100644 --- a/src/app/GUI/timelinewidget.h +++ b/src/app/GUI/timelinewidget.h @@ -58,6 +58,7 @@ class XevReadBoxesHandler; enum class SWT_Type : short; enum class SWT_BoxRule : short; enum class SWT_Target : short; +enum class SWT_ParamRule : short; class TimelineWidget : public QWidget { Q_OBJECT @@ -96,10 +97,12 @@ class TimelineWidget : public QWidget { void typeChanged(const SWT_Type target); void targetChanged(const SWT_Target target); void boxRuleChanged(const SWT_BoxRule rule); + void paramRuleChanged(const SWT_ParamRule rule); private: void setType(const SWT_Type type); void setBoxRule(const SWT_BoxRule rule); void setTarget(const SWT_Target target); + void setParamRule(const SWT_ParamRule rule); Canvas* mCurrentScene = nullptr; diff --git a/src/core/Properties/property.cpp b/src/core/Properties/property.cpp index 437a2de69..331c585a7 100644 --- a/src/core/Properties/property.cpp +++ b/src/core/Properties/property.cpp @@ -190,6 +190,48 @@ QMatrix Property::getTransform(const qreal relFrame) const { return QMatrix(); } +bool Property::SWT_shouldBeVisible(const SWT_RulesCollection &rules, + const bool parentSatisfies, + const bool parentMainTarget) const { + if(!parentSatisfies || parentMainTarget) return false; + + const auto paramRule = rules.fParamRule; + if(paramRule == SWT_ParamRule::all) return true; + + if(enve_cast(this) || enve_cast(this)) { + return true; + } + + const auto animator = enve_cast(this); + const bool animated = animator && animator->anim_isDescendantRecording(); + + if(paramRule == SWT_ParamRule::animated) { + return animated; + } + + if(paramRule == SWT_ParamRule::animatedOnly) { + if(!animated) return false; + if(const auto cAnim = enve_cast(this)) { + if(cAnim->ca_hasChildren()) return false; + } + return true; + } + + return true; +} + +bool Property::SWT_shouldPassThrough(const SWT_RulesCollection &rules) const { + if(rules.fParamRule != SWT_ParamRule::animatedOnly) return false; + if(enve_cast(this) || enve_cast(this)) { + return false; + } + const auto animator = enve_cast(this); + const auto complexAnimator = enve_cast(this); + if(!animator || !complexAnimator) return false; + if(!complexAnimator->ca_hasChildren()) return false; + return animator->anim_isDescendantRecording(); +} + void Property::prp_setSelected(const bool selected) { if(prp_mSelected == selected) return; prp_mSelected = selected; diff --git a/src/core/Properties/property.h b/src/core/Properties/property.h index 7edbd5c8e..9ef1f47c7 100644 --- a/src/core/Properties/property.h +++ b/src/core/Properties/property.h @@ -155,6 +155,12 @@ class CORE_EXPORT Property : public SingleWidgetTarget { virtual BasicTransformAnimator *getTransformAnimator() const; + bool SWT_shouldBeVisible(const SWT_RulesCollection &rules, + const bool parentSatisfies, + const bool parentMainTarget) const override; + + bool SWT_shouldPassThrough(const SWT_RulesCollection &rules) const override; + virtual void prp_afterChangedAbsRange(const FrameRange &range, const bool clip = true); diff --git a/src/core/singlewidgettarget.h b/src/core/singlewidgettarget.h index 73e5c0e31..a6600097f 100644 --- a/src/core/singlewidgettarget.h +++ b/src/core/singlewidgettarget.h @@ -76,6 +76,11 @@ class CORE_EXPORT SingleWidgetTarget : public SelfRef { return parentSatisfies && !parentMainTarget; } + virtual bool SWT_shouldPassThrough(const SWT_RulesCollection &rules) const { + Q_UNUSED(rules) + return false; + } + virtual QMimeData *SWT_createMimeData() { return nullptr; } diff --git a/src/core/swt_abstraction.cpp b/src/core/swt_abstraction.cpp index 27b00bbe8..6cefa9ce2 100644 --- a/src/core/swt_abstraction.cpp +++ b/src/core/swt_abstraction.cpp @@ -48,6 +48,9 @@ bool SWT_Abstraction::setAbstractions( if(currY > maxY) return true; const bool satisfiesRule = mTarget_k->SWT_shouldBeVisible( rules, parentSatisfiesRule, parentMainTarget); + const bool passThrough = (parentSatisfiesRule || parentMainTarget) && + !satisfiesRule && + mTarget_k->SWT_shouldPassThrough(rules); if(currY > minY && satisfiesRule && !mIsMainTarget) { setAbsFunc(this, currX); } @@ -56,7 +59,7 @@ bool SWT_Abstraction::setAbstractions( currY += swtHeight; } const bool childrenVisible = (satisfiesRule && mContentVisible) || - mIsMainTarget; + passThrough || mIsMainTarget; for(const auto& abs : mChildren) { if(abs->setAbstractions(minY, maxY, currY, currX, swtHeight, setAbsFunc, rules, @@ -76,13 +79,18 @@ int SWT_Abstraction::updateHeight(const SWT_RulesCollection &rules, if(mTarget_k->SWT_isVisible()) { const bool satisfiesRule = mTarget_k->SWT_shouldBeVisible( rules, parentSatisfiesRule, parentMainTarget); + const bool passThrough = (parentSatisfiesRule || parentMainTarget) && + !satisfiesRule && + mTarget_k->SWT_shouldPassThrough(rules); if(satisfiesRule && !mIsMainTarget) mHeight += swtHeight; const bool childrenVisible = (satisfiesRule && mContentVisible) || - mIsMainTarget; - for(const auto& abs : mChildren) { - mHeight += abs->updateHeight(rules, childrenVisible, - mIsMainTarget, swtHeight); + passThrough || mIsMainTarget; + if(childrenVisible) { + for(const auto& abs : mChildren) { + mHeight += abs->updateHeight(rules, childrenVisible, + mIsMainTarget, swtHeight); + } } } diff --git a/src/core/swt_rulescollection.cpp b/src/core/swt_rulescollection.cpp index 13ac53836..ce1752b32 100644 --- a/src/core/swt_rulescollection.cpp +++ b/src/core/swt_rulescollection.cpp @@ -31,10 +31,12 @@ SWT_RulesCollection::SWT_RulesCollection(const SWT_BoxRule rule, const bool alwaysShowChildren, const SWT_Target target, const SWT_Type type, + const SWT_ParamRule paramRule, const QString &searchString) { fRule = rule; fAlwaysShowChildren = alwaysShowChildren; fTarget = target; fType = type; + fParamRule = paramRule; fSearchString = searchString; } diff --git a/src/core/swt_rulescollection.h b/src/core/swt_rulescollection.h index 30070490d..e0420264a 100644 --- a/src/core/swt_rulescollection.h +++ b/src/core/swt_rulescollection.h @@ -53,18 +53,26 @@ enum class SWT_Type : short { sound }; +enum class SWT_ParamRule : short { + all, + animated, + animatedOnly +}; + struct CORE_EXPORT SWT_RulesCollection { SWT_RulesCollection(); SWT_RulesCollection(const SWT_BoxRule rule, const bool alwaysShowChildren, const SWT_Target target, const SWT_Type type, + const SWT_ParamRule paramRule, const QString &searchString); SWT_BoxRule fRule = SWT_BoxRule::all; bool fAlwaysShowChildren = false; SWT_Target fTarget = SWT_Target::canvas; SWT_Type fType = SWT_Type::all; + SWT_ParamRule fParamRule = SWT_ParamRule::all; QString fSearchString = ""; }; diff --git a/src/ui/optimalscrollarena/scrollwidget.cpp b/src/ui/optimalscrollarena/scrollwidget.cpp index eb7634660..b5c44746c 100644 --- a/src/ui/optimalscrollarena/scrollwidget.cpp +++ b/src/ui/optimalscrollarena/scrollwidget.cpp @@ -77,6 +77,10 @@ void ScrollWidget::setCurrentType(const SWT_Type type) { mVisiblePartWidget->setCurrentType(type); } +void ScrollWidget::setCurrentParamRule(const SWT_ParamRule rule) { + mVisiblePartWidget->setCurrentParamRule(rule); +} + SWT_RulesCollection ScrollWidget::getRulesCollection() { return mVisiblePartWidget->getRulesCollection(); } diff --git a/src/ui/optimalscrollarena/scrollwidget.h b/src/ui/optimalscrollarena/scrollwidget.h index c57a90c8e..d07112fd2 100644 --- a/src/ui/optimalscrollarena/scrollwidget.h +++ b/src/ui/optimalscrollarena/scrollwidget.h @@ -44,6 +44,7 @@ class ScrollArea; enum class SWT_BoxRule : short; enum class SWT_Target : short; enum class SWT_Type : short; +enum class SWT_ParamRule : short; class UI_EXPORT ScrollWidget : public MinimalScrollWidget { @@ -61,6 +62,7 @@ class UI_EXPORT ScrollWidget : public MinimalScrollWidget const SWT_Target target); void setCurrentSearchText(const QString &text); void setCurrentType(const SWT_Type type); + void setCurrentParamRule(const SWT_ParamRule rule); void scheduleContentUpdateIfIsCurrentRule(const SWT_BoxRule rule); bool isCurrentRule(const SWT_BoxRule rule); diff --git a/src/ui/optimalscrollarena/scrollwidgetvisiblepart.cpp b/src/ui/optimalscrollarena/scrollwidgetvisiblepart.cpp index a3ce1705e..d782b78ab 100644 --- a/src/ui/optimalscrollarena/scrollwidgetvisiblepart.cpp +++ b/src/ui/optimalscrollarena/scrollwidgetvisiblepart.cpp @@ -57,6 +57,11 @@ void ScrollWidgetVisiblePart::setCurrentType(const SWT_Type type) { updateParentHeightAndContent(); } +void ScrollWidgetVisiblePart::setCurrentParamRule(const SWT_ParamRule rule) { + mRulesCollection.fParamRule = rule; + updateParentHeightAndContent(); +} + void ScrollWidgetVisiblePart::setupUpdateFuncs() { const QPointer thisQPtr = this; mUpdateFuncs.fContentUpdateIfIsCurrentRule = diff --git a/src/ui/optimalscrollarena/scrollwidgetvisiblepart.h b/src/ui/optimalscrollarena/scrollwidgetvisiblepart.h index b6233d089..a99fd306f 100644 --- a/src/ui/optimalscrollarena/scrollwidgetvisiblepart.h +++ b/src/ui/optimalscrollarena/scrollwidgetvisiblepart.h @@ -56,6 +56,7 @@ class UI_EXPORT ScrollWidgetVisiblePart : public ScrollVisiblePartBase void setAlwaysShowChildren(const bool alwaysShowChildren); void setCurrentSearchText(const QString &text); void setCurrentType(const SWT_Type type); + void setCurrentParamRule(const SWT_ParamRule rule); void scheduleContentUpdateIfIsCurrentRule(const SWT_BoxRule rule); bool isCurrentRule(const SWT_BoxRule rule);