diff --git a/engine/includes/components/actor.h b/engine/includes/components/actor.h index ee45e11f3..318d66738 100644 --- a/engine/includes/components/actor.h +++ b/engine/includes/components/actor.h @@ -54,6 +54,8 @@ class ENGINE_EXPORT Actor : public Object { return static_cast(component(T::metaClass()->name())); } + std::list components(const TString &type); + Component *componentInChild(const TString &type); template diff --git a/engine/includes/components/component.h b/engine/includes/components/component.h index 19c691c26..683cc41fb 100644 --- a/engine/includes/components/component.h +++ b/engine/includes/components/component.h @@ -54,8 +54,6 @@ class ENGINE_EXPORT Component : public Object { TString tr(const TString &source); - virtual void actorParentChanged(); - virtual void composeComponent(); virtual void drawGizmos(); diff --git a/engine/includes/components/transform.h b/engine/includes/components/transform.h index 57aa28d57..351bd2393 100644 --- a/engine/includes/components/transform.h +++ b/engine/includes/components/transform.h @@ -31,7 +31,7 @@ class ENGINE_EXPORT Transform : public Component { ~Transform(); Vector3 position() const; - void setPosition(const Vector3 &position); + virtual void setPosition(const Vector3 &position); Vector3 rotation() const; void setRotation(const Vector3 &angles); diff --git a/engine/src/components/actor.cpp b/engine/src/components/actor.cpp index de451766f..009a98f16 100644 --- a/engine/src/components/actor.cpp +++ b/engine/src/components/actor.cpp @@ -224,6 +224,20 @@ Component *Actor::component(const TString &type) { } return nullptr; } +/*! + Returns a list of the components with \a type attached to this Actor. +*/ +std::list Actor::components(const TString &type) { + PROFILE_FUNCTION(); + std::list result; + for(auto it : getChildren()) { + const MetaObject *meta = it->metaObject(); + if(meta->canCastTo(type.data())) { + result.push_back(static_cast(it)); + } + } + return result; +} /*! Returns the component with \a type in the Actor's children using depth search. A component is returned only if it's found on a current Actor; otherwise returns nullptr. @@ -293,7 +307,9 @@ void Actor::clearCloneRef() { */ void Actor::setParent(Object *parent, int32_t position, bool force) { PROFILE_FUNCTION(); - if(parent == this || (Object::parent() == parent && position == -1)) { + Object *oldParent = Object::parent(); + + if(parent == this || (oldParent == parent && position == -1)) { return; } @@ -304,19 +320,13 @@ void Actor::setParent(Object *parent, int32_t position, bool force) { } else { setScene(dynamic_cast(parent)); } + + Object::setParent(parent, position, force); if(m_transform) { - Object::setParent(parent, position, force); if(actor) { m_transform->setParentTransform(actor->transform(), force); - } - } else { - Object::setParent(parent, position); - } - - for(auto it : getChildren()) { - Component *component = dynamic_cast(it); - if(component) { - component->actorParentChanged(); + } else { + m_transform->setParentTransform(nullptr, force); } } } diff --git a/engine/src/components/component.cpp b/engine/src/components/component.cpp index bf852ddb6..fe5e26a2b 100644 --- a/engine/src/components/component.cpp +++ b/engine/src/components/component.cpp @@ -135,13 +135,6 @@ Actor *Component::instantiate(Prefab *prefab, Vector3 position, Quaternion rotat */ TString Component::tr(const TString &source) { return Engine::translate(source); -} -/*! - This method will be triggered in case of Actor will change its own parent. - \internal -*/ -void Component::actorParentChanged() { - } /*! \internal diff --git a/modules/uikit/includes/components/abstractslider.h b/modules/uikit/includes/components/abstractslider.h index 36055bacc..5576dd145 100644 --- a/modules/uikit/includes/components/abstractslider.h +++ b/modules/uikit/includes/components/abstractslider.h @@ -3,8 +3,6 @@ #include "widget.h" -class Frame; - class UIKIT_EXPORT AbstractSlider : public Widget { A_OBJECT(AbstractSlider, Widget, General) @@ -19,18 +17,7 @@ class UIKIT_EXPORT AbstractSlider : public Widget { A_SIGNAL(AbstractSlider::pressed), A_SIGNAL(AbstractSlider::valueChanged) ) - A_ENUMS( - A_ENUM(Orientation, - A_VALUE(Horizontal), - A_VALUE(Vertical) - ) - ) - -public: - enum Orientation { - Horizontal, - Vertical - }; + A_NOENUMS() public: AbstractSlider(); diff --git a/modules/uikit/includes/components/layout.h b/modules/uikit/includes/components/layout.h index 29980becc..4378aedcc 100644 --- a/modules/uikit/includes/components/layout.h +++ b/modules/uikit/includes/components/layout.h @@ -20,13 +20,15 @@ class UIKIT_EXPORT Layout { int indexOf(const Layout *layout) const; int indexOf(const RectTransform *transform) const; + RectTransform *transformAt(int index); + RectTransform *rectTransform(); void setRectTransform(RectTransform *transform); int count() const; - float spacing() const; - void setSpacing(float spacing); + int spacing() const; + void setSpacing(int spacing); int orientation() const; void setOrientation(int orientation); @@ -48,7 +50,7 @@ class UIKIT_EXPORT Layout { RectTransform *m_rectTransform; - float m_spacing; + int m_spacing; int m_orientation; diff --git a/modules/uikit/includes/components/progressbar.h b/modules/uikit/includes/components/progressbar.h index 4c7f99ffd..20ac0cc9b 100644 --- a/modules/uikit/includes/components/progressbar.h +++ b/modules/uikit/includes/components/progressbar.h @@ -7,7 +7,7 @@ class UIKIT_EXPORT ProgressBar : public Widget { A_OBJECT(ProgressBar, Widget, Components/UI) A_PROPERTIES( - A_PROPERTYEX(ProgressOrientation, orientation, ProgressBar::orientation, ProgressBar::setOrientation, "enum=ProgressOrientation"), + A_PROPERTYEX(Orientation, orientation, ProgressBar::orientation, ProgressBar::setOrientation, "enum=Orientation"), A_PROPERTY(float, from, ProgressBar::from, ProgressBar::setFrom), A_PROPERTY(float, to, ProgressBar::to, ProgressBar::setTo), A_PROPERTY(float, value, ProgressBar::value, ProgressBar::setValue), @@ -17,18 +17,7 @@ class UIKIT_EXPORT ProgressBar : public Widget { A_PROPERTYEX(Frame *, chunk, ProgressBar::chunk, ProgressBar::setChunk, "editor=Component") ) A_NOMETHODS() - A_ENUMS( - A_ENUM(BarOrientation, - A_VALUE(Horizontal), - A_VALUE(Vertical) - ) - ) - -public: - enum ProgressOrientation { - Horizontal, - Vertical - }; + A_NOENUMS() public: ProgressBar(); diff --git a/modules/uikit/includes/components/recttransform.h b/modules/uikit/includes/components/recttransform.h index 7092b6e08..121a71614 100644 --- a/modules/uikit/includes/components/recttransform.h +++ b/modules/uikit/includes/components/recttransform.h @@ -33,6 +33,8 @@ class UIKIT_EXPORT RectTransform : public Transform { RectTransform(); ~RectTransform(); + void setPosition(const Vector3 &position) override; + Vector2 size() const; void setSize(const Vector2 &size); @@ -59,8 +61,11 @@ class UIKIT_EXPORT RectTransform : public Transform { bool mouseTracking() const; void setMouseTracking(bool tracking); + Vector2 mapFromGlobal(float x, float y); bool isHovered(float x, float y) const; + Widget *widget(); + RectTransform *hoveredTransform(float x, float y); void subscribe(Widget *widget); @@ -87,6 +92,7 @@ class UIKIT_EXPORT RectTransform : public Transform { private: friend class Layout; + friend class Widget; void cleanDirty() const override; @@ -94,6 +100,8 @@ class UIKIT_EXPORT RectTransform : public Transform { void recalcParent(); + void applyStyle(); + private: std::list m_subscribers; diff --git a/modules/uikit/includes/components/widget.h b/modules/uikit/includes/components/widget.h index 9e0f29408..db0853109 100644 --- a/modules/uikit/includes/components/widget.h +++ b/modules/uikit/includes/components/widget.h @@ -17,8 +17,15 @@ class UIKIT_EXPORT Widget : public NativeBehaviour { A_SLOT(Widget::lower), A_SLOT(Widget::raise) ) + A_ENUMS( + A_ENUM(Orientation, + A_VALUE(Horizontal), + A_VALUE(Vertical) + ) + ) + public: - enum Orentation { + enum Orientation { Horizontal, Vertical }; @@ -35,9 +42,9 @@ class UIKIT_EXPORT Widget : public NativeBehaviour { Widget *parentWidget() const; std::list &childWidgets(); - RectTransform *rectTransform() const; + RectTransform *rectTransform(); - bool isSubWidget(Widget *widget) const; + bool isSubWidget() const; static Widget *focusWidget(); @@ -57,12 +64,10 @@ class UIKIT_EXPORT Widget : public NativeBehaviour { void setRectTransform(RectTransform *transform); - void actorParentChanged() override; + void onHierarchyUpdated(); void composeComponent() override; - void setParent(Object *parent, int32_t position = -1, bool force = false) override; - float styleLength(const TString &key, float value, bool &pixels); Vector2 styleBlock2Length(const TString &property, const Vector2 &value, bool &pixels); Vector4 styleBlock4Length(const TString &property, const Vector4 &value, bool &pixels); @@ -72,6 +77,8 @@ class UIKIT_EXPORT Widget : public NativeBehaviour { static void setFocusWidget(Widget *widget); + void updateStyleProperty(const TString &name, const float *v, int32_t size); + private: void addStyleRules(const std::map &rules, uint32_t weight); @@ -80,8 +87,6 @@ class UIKIT_EXPORT Widget : public NativeBehaviour { protected: std::map> m_styleRules; - std::list m_subWidgets; - std::list m_childWidgets; private: @@ -96,6 +101,8 @@ class UIKIT_EXPORT Widget : public NativeBehaviour { RectTransform *m_transform; + bool m_subWidget; + static Widget *m_focusWidget; }; diff --git a/modules/uikit/includes/editor/uiedit.h b/modules/uikit/includes/editor/uiedit.h index c224423f1..0b2ed3450 100644 --- a/modules/uikit/includes/editor/uiedit.h +++ b/modules/uikit/includes/editor/uiedit.h @@ -33,7 +33,7 @@ private slots: void onObjectCreate(TString type) override; void onObjectsSelected(Object::ObjectList objects, bool force) override; void onObjectsDeleted(Object::ObjectList objects) override; - void onObjectsChanged(const Object::ObjectList &objects, const TString &property, const Variant &value) override; + void onObjectsChanged(const Object::ObjectList &objects, const TString &propertyName, const Variant &value) override; void onCutAction() override; void onCopyAction() override; diff --git a/modules/uikit/includes/resources/stylesheet.h b/modules/uikit/includes/resources/stylesheet.h index 0788e12d9..233ce2cee 100644 --- a/modules/uikit/includes/resources/stylesheet.h +++ b/modules/uikit/includes/resources/stylesheet.h @@ -30,6 +30,8 @@ class UIKIT_EXPORT StyleSheet : public Resource { static void setStyleProperty(Widget *widget, const TString &key, const TString &value); static Vector4 toColor(const TString &value); + static TString toColor(const Vector4 &value); + static float toLength(const TString &value, bool &pixels); private: diff --git a/modules/uikit/src/components/abstractbutton.cpp b/modules/uikit/src/components/abstractbutton.cpp index d124158bc..a3de86033 100644 --- a/modules/uikit/src/components/abstractbutton.cpp +++ b/modules/uikit/src/components/abstractbutton.cpp @@ -20,6 +20,8 @@ namespace { const char *gIcon("icon"); const float gCorner = 4.0f; + + const char *gCssBackgroundColor("background-color"); } /*! \class AbstractButton @@ -144,6 +146,12 @@ void AbstractButton::setColor(const Vector4 &color) { if(back) { back->setColor(m_normalColor); } + +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + StyleSheet::setStyleProperty(this, gCssBackgroundColor, StyleSheet::toColor(m_normalColor)); + } +#endif } /*! Returns the color used when the button is highlighted. @@ -277,7 +285,9 @@ void AbstractButton::update() { m_currentFade += 1.0f / m_fadeDuration * Timer::deltaTime(); m_currentFade = CLAMP(m_currentFade, 0.0f, 1.0f); + back->blockSignals(true); back->setColor(MIX(back->color(), color, m_currentFade)); + back->blockSignals(false); } } @@ -291,7 +301,7 @@ void AbstractButton::applyStyle() { Widget::applyStyle(); // Background color - auto it = m_styleRules.find("background-color"); + auto it = m_styleRules.find(gCssBackgroundColor); if(it != m_styleRules.end()) { setColor(StyleSheet::toColor(it->second.second)); } diff --git a/modules/uikit/src/components/frame.cpp b/modules/uikit/src/components/frame.cpp index e51cff40f..c9a4dd238 100644 --- a/modules/uikit/src/components/frame.cpp +++ b/modules/uikit/src/components/frame.cpp @@ -23,6 +23,14 @@ namespace { const char *gRightColor("rightColor"); const char *gBottomColor("bottomColor"); const char *gLeftColor("leftColor"); + + const char *gCssBackgroundColor("background-color"); + const char *gCssBorderColor("border-color"); + const char *gCssBorderTopColor("border-top-color"); + const char *gCssBorderRightColor("border-right-color"); + const char *gCssBorderBottomColor("border-bottom-color"); + const char *gCssBorderLeftColor("border-left-color"); + const char *gCssBorderRadius("border-radius"); }; /*! @@ -87,34 +95,35 @@ void Frame::draw(CommandBuffer &buffer) { void Frame::applyStyle() { Widget::applyStyle(); + blockSignals(true); // Background color - auto it = m_styleRules.find("background-color"); + auto it = m_styleRules.find(gCssBackgroundColor); if(it != m_styleRules.end()) { setColor(StyleSheet::toColor(it->second.second)); } // Border color - it = m_styleRules.find("border-color"); + it = m_styleRules.find(gCssBorderColor); if(it != m_styleRules.end()) { setBorderColor(StyleSheet::toColor(it->second.second)); } - it = m_styleRules.find("border-top-color"); + it = m_styleRules.find(gCssBorderTopColor); if(it != m_styleRules.end()) { setTopColor(StyleSheet::toColor(it->second.second)); } - it = m_styleRules.find("border-right-color"); + it = m_styleRules.find(gCssBorderRightColor); if(it != m_styleRules.end()) { setRightColor(StyleSheet::toColor(it->second.second)); } - it = m_styleRules.find("border-bottom-color"); + it = m_styleRules.find(gCssBorderBottomColor); if(it != m_styleRules.end()) { setBottomColor(StyleSheet::toColor(it->second.second)); } - it = m_styleRules.find("border-left-color"); + it = m_styleRules.find(gCssBorderLeftColor); if(it != m_styleRules.end()) { setLeftColor(StyleSheet::toColor(it->second.second)); } @@ -122,7 +131,7 @@ void Frame::applyStyle() { // Border radius bool pixels; Vector4 radius(corners()); - radius = styleBlock4Length("border-radius", radius, pixels); + radius = styleBlock4Length(gCssBorderRadius, radius, pixels); radius.x = styleLength("border-top-left-radius", radius.x, pixels); radius.y = styleLength("border-top-right-radius", radius.y, pixels); @@ -130,6 +139,8 @@ void Frame::applyStyle() { radius.w = styleLength("border-bottom-right-radius", radius.w, pixels); setCorners(radius); + + blockSignals(false); } /*! Returns the corners radiuses of the frame. @@ -149,6 +160,12 @@ void Frame::setCorners(const Vector4 &corners) { m_material->setVector4(gBorderRadius, &normCorners); } } + +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + updateStyleProperty(gCssBorderRadius, m_borderRadius.v, 4); + } +#endif } /*! Returns the color of the frame to be drawn. @@ -164,6 +181,12 @@ void Frame::setColor(const Vector4 &color) { if(m_material) { m_material->setVector4(gBackgroundColor, &m_backgroundColor); } + +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + StyleSheet::setStyleProperty(this, gCssBackgroundColor, StyleSheet::toColor(m_backgroundColor)); + } +#endif } /*! Returns the top border color of the frame. @@ -179,6 +202,12 @@ void Frame::setTopColor(const Vector4 &color) { if(m_material) { m_material->setVector4(gTopColor, &m_topColor); } + +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + StyleSheet::setStyleProperty(this, gCssBorderTopColor, StyleSheet::toColor(m_topColor)); + } +#endif } /*! Returns the right border color of the frame. @@ -194,6 +223,12 @@ void Frame::setRightColor(const Vector4 &color) { if(m_material) { m_material->setVector4(gRightColor, &m_rightColor); } + +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + StyleSheet::setStyleProperty(this, gCssBorderRightColor, StyleSheet::toColor(m_rightColor)); + } +#endif } /*! Returns the bottom border color of the frame. @@ -209,6 +244,12 @@ void Frame::setBottomColor(const Vector4 &color) { if(m_material) { m_material->setVector4(gBottomColor, &m_bottomColor); } + +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + StyleSheet::setStyleProperty(this, gCssBorderBottomColor, StyleSheet::toColor(m_bottomColor)); + } +#endif } /*! Returns the left border color of the frame. @@ -224,6 +265,12 @@ void Frame::setLeftColor(const Vector4 &color) { if(m_material) { m_material->setVector4(gLeftColor, &m_leftColor); } + +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + StyleSheet::setStyleProperty(this, gCssBorderLeftColor, StyleSheet::toColor(m_leftColor)); + } +#endif } /*! Sets the border \a color of the frame. diff --git a/modules/uikit/src/components/label.cpp b/modules/uikit/src/components/label.cpp index 70c4683ec..f588c9868 100644 --- a/modules/uikit/src/components/label.cpp +++ b/modules/uikit/src/components/label.cpp @@ -22,6 +22,12 @@ namespace { const char *gTexture("mainTexture"); const char *gWeight("weight"); const char *gUseSDF("useSdf"); + + const char *gCssColor("color"); + const char *gCssFontSize("font-size"); + const char *gCssFontWeight("font-weight"); + const char *gCssFontKerning("font-kerning"); + const char *gCssWhiteSpace("white-space"); }; /*! @@ -94,17 +100,18 @@ void Label::draw(CommandBuffer &buffer) { void Label::applyStyle() { Widget::applyStyle(); - auto it = m_styleRules.find("color"); + blockSignals(true); + auto it = m_styleRules.find(gCssColor); if(it != m_styleRules.end()) { setColor(StyleSheet::toColor(it->second.second)); } - it = m_styleRules.find("font-size"); + it = m_styleRules.find(gCssFontSize); if(it != m_styleRules.end()) { setFontSize(it->second.second.toInt()); } - it = m_styleRules.find("font-weight"); + it = m_styleRules.find(gCssFontWeight); if(it != m_styleRules.end()) { m_fontWeight = 0.5f; if(it->second.second == "normal") { @@ -120,11 +127,16 @@ void Label::applyStyle() { } } - it = m_styleRules.find("white-space"); + it = m_styleRules.find(gCssWhiteSpace); + if(it != m_styleRules.end()) { + setWordWrap(it->second.second != "nowrap"); + } + + it = m_styleRules.find(gCssFontKerning); if(it != m_styleRules.end()) { - bool wordWrap = it->second.second != "nowrap"; - setWordWrap(wordWrap); + setKerning(it->second.second != "none"); } + blockSignals(false); } /*! Returns the text which will be drawn. @@ -177,6 +189,11 @@ void Label::setFontSize(int size) { if(m_size != size) { m_size = size; m_dirty = true; +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + StyleSheet::setStyleProperty(this, gCssFontSize, TString::number(m_size) + "px"); + } +#endif } } /*! @@ -194,6 +211,11 @@ void Label::setColor(const Vector4 &color) { if(m_material) { m_material->setVector4(gColor, &m_color); } +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + StyleSheet::setStyleProperty(this, gCssWhiteSpace, StyleSheet::toColor(m_color)); + } +#endif } /*! Returns true if text in label must be translated; othewise returns false. @@ -227,6 +249,11 @@ void Label::setWordWrap(bool wrap) { m_flags &= ~Font::Wrap; } m_dirty = true; +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + StyleSheet::setStyleProperty(this, gCssWhiteSpace, wrap ? "normal" : "nowrap"); + } +#endif } } /*! @@ -262,6 +289,11 @@ void Label::setKerning(const bool enable) { m_flags &= ~Font::Kerning; } m_dirty = true; +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + StyleSheet::setStyleProperty(this, gCssFontKerning, enable ? "normal" : "none"); + } +#endif } } /*! @@ -295,13 +327,13 @@ void Label::loadUserData(const VariantMap &data) { */ VariantMap Label::saveUserData() const { VariantMap result = Widget::saveUserData(); - { - Font *o = font(); - TString ref = Engine::reference(o); - if(!ref.isEmpty()) { - result[gFont] = ref; - } + + Font *o = font(); + TString ref = Engine::reference(o); + if(!ref.isEmpty()) { + result[gFont] = ref; } + return result; } /*! diff --git a/modules/uikit/src/components/layout.cpp b/modules/uikit/src/components/layout.cpp index ff3e262b5..fdac244fe 100644 --- a/modules/uikit/src/components/layout.cpp +++ b/modules/uikit/src/components/layout.cpp @@ -18,7 +18,7 @@ Layout::Layout() : m_parentLayout(nullptr), m_attachedTransform(nullptr), m_rectTransform(nullptr), - m_spacing(0.0f), + m_spacing(0), m_orientation(Widget::Vertical), m_dirty(false) { @@ -81,6 +81,10 @@ void Layout::insertTransform(int index, RectTransform *transform) { transform->m_attachedLayout = this; insertLayout(index, layout); + + // Tranfering the ownership + RectTransform *rect = rectTransform(); + transform->actor()->setParent(rect->actor(), index); } } /*! @@ -100,6 +104,9 @@ void Layout::removeTransform(RectTransform *transform) { Layout *tmp = it; m_items.remove(tmp); delete tmp; + + transform->m_attachedLayout = nullptr; + invalidate(); if(m_rectTransform) { @@ -137,6 +144,16 @@ int Layout::indexOf(const RectTransform *transform) const { } return result; } +/*! + Returns transform located at \a index. +*/ +RectTransform *Layout::transformAt(int index) { + if(index > -1 && index < m_items.size()) { + auto it = std::next(m_items.begin(), index); + return (*it)->m_attachedTransform; + } + return nullptr; +} /*! Returns the parent rect transform of this layout, or nullptr if this layout is not installed on any rect transform. If the layout is a sub-layout, this function returns the parent rect transform of the parent layout. @@ -166,13 +183,13 @@ int Layout::count() const { /*! Returns the spacing between items in the layout. */ -float Layout::spacing() const { +int Layout::spacing() const { return m_spacing; } /*! Sets the \a spacing between items in the layout. */ -void Layout::setSpacing(float spacing) { +void Layout::setSpacing(int spacing) { m_spacing = spacing; invalidate(); } diff --git a/modules/uikit/src/components/recttransform.cpp b/modules/uikit/src/components/recttransform.cpp index 6e97a3a7e..933625b5c 100644 --- a/modules/uikit/src/components/recttransform.cpp +++ b/modules/uikit/src/components/recttransform.cpp @@ -2,6 +2,19 @@ #include "components/widget.h" #include "components/layout.h" +#include "stylesheet.h" + +namespace { + const char *gCssSize("-uikit-size"); + const char *gCssPosition("-uikit-position"); + const char *gCssPivot("-uikit-pivot"); + const char *gCssMinAchors("-uikit-min-anchors"); + const char *gCssMaxAchors("-uikit-max-anchors"); + const char *gCssBorder("border-width"); + const char *gCssMargin("margin"); + const char *gCssPadding("padding"); + const char *gCssDisplay("display"); +} /*! \class RectTransform @@ -36,6 +49,21 @@ RectTransform::~RectTransform() { delete m_layout; } +/*! + Changes \a position of the Transform in local space. +*/ +void RectTransform::setPosition(const Vector3 &position) { + Transform::setPosition(position); + +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + Widget *widget = RectTransform::widget(); + if(widget) { + widget->updateStyleProperty(gCssPosition, position.v, 2); + } + } +#endif +} /*! Returns the size of the associated UI element. */ @@ -57,6 +85,14 @@ void RectTransform::setSize(const Vector2 &size) { setDirty(); recalcChilds(); +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + Widget *widget = RectTransform::widget(); + if(widget) { + widget->updateStyleProperty(gCssSize, m_size.v, 2); + } + } +#endif } } /*! @@ -74,6 +110,14 @@ void RectTransform::setPivot(const Vector2 &pivot) { setDirty(); recalcChilds(); +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + Widget *widget = RectTransform::widget(); + if(widget) { + widget->updateStyleProperty(gCssPivot, m_pivot.v, 2); + } + } +#endif } } /*! @@ -91,6 +135,14 @@ void RectTransform::setMinAnchors(const Vector2 &anchors) { setDirty(); recalcChilds(); +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + Widget *widget = RectTransform::widget(); + if(widget) { + widget->updateStyleProperty(gCssMinAchors, m_minAnchors.v, 2); + } + } +#endif } } /*! @@ -108,6 +160,14 @@ void RectTransform::setMaxAnchors(const Vector2 &anchors) { setDirty(); recalcChilds(); +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + Widget *widget = RectTransform::widget(); + if(widget) { + widget->updateStyleProperty(gCssMaxAchors, m_maxAnchors.v, 2); + } + } +#endif } } /*! @@ -116,10 +176,26 @@ void RectTransform::setMaxAnchors(const Vector2 &anchors) { void RectTransform::setAnchors(const Vector2 &minimum, const Vector2 &maximum) { if(m_minAnchors != minimum) { m_minAnchors = minimum; +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + Widget *widget = RectTransform::widget(); + if(widget) { + widget->updateStyleProperty(gCssMinAchors, m_minAnchors.v, 2); + } + } +#endif } if(m_maxAnchors != maximum) { m_maxAnchors = maximum; +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + Widget *widget = RectTransform::widget(); + if(widget) { + widget->updateStyleProperty(gCssMaxAchors, m_maxAnchors.v, 2); + } + } +#endif } setDirty(); @@ -141,6 +217,14 @@ void RectTransform::setMargin(const Vector4 &margin) { setDirty(); recalcChilds(); +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + Widget *widget = RectTransform::widget(); + if(widget) { + widget->updateStyleProperty(gCssMargin, m_margin.v, 4); + } + } +#endif } } /*! @@ -159,6 +243,14 @@ void RectTransform::setBorder(const Vector4 &border) { setDirty(); recalcChilds(); +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + Widget *widget = RectTransform::widget(); + if(widget) { + widget->updateStyleProperty(gCssMargin, m_border.v, 4); + } + } +#endif } } /*! @@ -177,6 +269,14 @@ void RectTransform::setPadding(const Vector4 &padding) { setDirty(); recalcChilds(); +#ifdef SHARED_DEFINE + if(!isSignalsBlocked()) { + Widget *widget = RectTransform::widget(); + if(widget) { + widget->updateStyleProperty(gCssPadding, m_border.v, 4); + } + } +#endif } } /*! @@ -192,6 +292,13 @@ bool RectTransform::mouseTracking() const { void RectTransform::setMouseTracking(bool tracking) { m_mouseTracking = tracking; } +/*! + Translates the global screen \a x and \a y coordinates to widget space. +*/ +Vector2 RectTransform::mapFromGlobal(float x, float y) { + return Vector2(x - m_worldTransform[12], + y - m_worldTransform[13]); +} /*! Returns true if the point with coordinates \a x and \a y is within the bounds, otherwise false. */ @@ -210,6 +317,15 @@ bool RectTransform::isHovered(float x, float y) const { return false; } +/*! + Returns the first widget associated with this rect transform. +*/ +Widget *RectTransform::widget() { + if(!m_subscribers.empty()) { + return m_subscribers.front(); + } + return nullptr; +} /*! Returns the most top RectTransform in hierarchy wich contains the point with coodinates \a x and \a y. Returns null if no bounds. @@ -252,9 +368,18 @@ Layout *RectTransform::layout() const { Sets the \a layout for the RectTransform. */ void RectTransform::setLayout(Layout *layout) { - m_layout = layout; - if(m_layout) { - m_layout->setRectTransform(this); + if(m_layout != layout) { + m_layout = layout; + if(m_layout) { + m_layout->setRectTransform(this); + + for(auto &it : m_children) { + RectTransform *rect = dynamic_cast(it); + if(rect) { + m_layout->addTransform(rect); + } + } + } } } /*! @@ -309,13 +434,35 @@ void RectTransform::setHorizontalPolicy(SizePolicy policy) { In addition adds current transfrom to the parent layout if it exists. */ void RectTransform::setParentTransform(Transform *parent, bool force) { - Transform::setParentTransform(parent, force); + if(parent != m_parent || force) { + RectTransform *parentRect = dynamic_cast(m_parent); + if(parentRect) { + Layout *layout = parentRect->layout(); + if(layout) { + layout->removeTransform(this); + } - RectTransform *parentRect = dynamic_cast(m_parent); - if(parentRect) { - Layout *layout = parentRect->layout(); - if(layout) { - layout->addTransform(this); + for(auto it : parentRect->m_subscribers) { + it->onHierarchyUpdated(); + } + } + + Transform::setParentTransform(parent, force); + + parentRect = dynamic_cast(m_parent); + if(parentRect) { + Layout *layout = parentRect->layout(); + if(layout) { + layout->addTransform(this); + } + + for(auto it : parentRect->m_subscribers) { + it->onHierarchyUpdated(); + } + } else { + for(auto it : m_subscribers) { + it->m_parent = nullptr; + } } } } @@ -482,3 +629,89 @@ void RectTransform::recalcParent() { } } } + +void RectTransform::applyStyle() { + Widget *widget = RectTransform::widget(); + + blockSignals(true); + + bool pixels; + + // Position + Vector2 position(RectTransform::position()); + position = widget->styleBlock2Length(gCssPosition, position, pixels); + position.x = widget->styleLength("top", position.x, pixels); + position.y = widget->styleLength("left", position.y, pixels); + setPosition(Vector3(position, 0.0f)); + + // Size + Vector2 size(RectTransform::size()); + size = widget->styleBlock2Length(gCssSize, size, pixels); + size.x = widget->styleLength("width", size.x, pixels); + size.y = widget->styleLength("height", size.y, pixels); + setSize(size); + + // Pivot point + Vector2 pivot(RectTransform::pivot()); + pivot = widget->styleBlock2Length(gCssPivot, pivot, pixels); + setPivot(pivot); + + // Anchors + Vector2 minAnchors(RectTransform::minAnchors()); + minAnchors = widget->styleBlock2Length(gCssMinAchors, minAnchors, pixels); + setMinAnchors(minAnchors); + + Vector2 maxAnchors(RectTransform::maxAnchors()); + maxAnchors = widget->styleBlock2Length(gCssMaxAchors, maxAnchors, pixels); + setMaxAnchors(maxAnchors); + + // Border width + Vector4 border(RectTransform::border()); + border = widget->styleBlock4Length(gCssBorder, border, pixels); + border.x = widget->styleLength("border-top-width", border.x, pixels); + border.y = widget->styleLength("border-right-width", border.y, pixels); + border.z = widget->styleLength("border-bottom-width", border.z, pixels); + border.w = widget->styleLength("border-left-width", border.w, pixels); + setBorder(border); + + // Margins + Vector4 margin(RectTransform::margin()); + margin = widget->styleBlock4Length(gCssMargin, margin, pixels); + margin.x = widget->styleLength("margin-top", margin.x, pixels); + margin.y = widget->styleLength("margin-right", margin.y, pixels); + margin.z = widget->styleLength("margin-bottom", margin.z, pixels); + margin.w = widget->styleLength("margin-left", margin.w, pixels); + setMargin(margin); + + // Padding + Vector4 padding(RectTransform::padding()); + padding = widget->styleBlock4Length(gCssPadding, padding, pixels); + padding.x = widget->styleLength("padding-top", padding.x, pixels); + padding.y = widget->styleLength("padding-right", padding.y, pixels); + padding.z = widget->styleLength("padding-bottom", padding.z, pixels); + padding.w = widget->styleLength("padding-left", padding.w, pixels); + setPadding(padding); + + // Display + auto it = widget->m_styleRules.find(gCssDisplay); + if(it != widget->m_styleRules.end()) { + TString layoutMode = it->second.second; + if(layoutMode == "none") { + actor()->setEnabled(false); + } else { + Layout *layout = RectTransform::layout(); + if(layout == nullptr) { + layout = new Layout; + } + + if(layoutMode == "block") { + layout->setOrientation(Widget::Vertical); + } else if(layoutMode == "inline") { + layout->setOrientation(Widget::Horizontal); + } + setLayout(layout); + } + } + + blockSignals(false); +} diff --git a/modules/uikit/src/components/slider.cpp b/modules/uikit/src/components/slider.cpp index c9b4a9eb3..b4a6d02da 100644 --- a/modules/uikit/src/components/slider.cpp +++ b/modules/uikit/src/components/slider.cpp @@ -31,6 +31,26 @@ void Slider::update() { } } +void Slider::setOrientation(int value) { + AbstractSlider::setOrientation(value); + + ProgressBar *bar = background(); + if(bar) { + bar->setOrientation(value); + + RectTransform *rectBar = bar->rectTransform(); + if(m_orientation == Horizontal) { + rectBar->setSize(Vector2(0.0f, 10.0f)); + rectBar->setAnchors(Vector2(0.0f, 0.5f), Vector2(1.0f, 0.5f)); + } else { + rectBar->setSize(Vector2(10.0f, 0.0f)); + rectBar->setAnchors(Vector2(0.5f, 0.0f), Vector2(0.5f, 1.0f)); + } + } + + setValue(m_value); +} + ProgressBar *Slider::background() const { return static_cast(subWidget(gBackground)); } @@ -83,26 +103,6 @@ void Slider::setMaximum(int value) { } } -void Slider::setOrientation(int value) { - AbstractSlider::setOrientation(value); - - ProgressBar *bar = background(); - if(bar) { - bar->setOrientation(value); - - RectTransform *rectBar = bar->rectTransform(); - if(m_orientation == Horizontal) { - rectBar->setSize(Vector2(0.0f, 10.0f)); - rectBar->setAnchors(Vector2(0.0f, 0.5f), Vector2(1.0f, 0.5f)); - } else { - rectBar->setSize(Vector2(10.0f, 0.0f)); - rectBar->setAnchors(Vector2(0.5f, 0.0f), Vector2(0.5f, 1.0f)); - } - } - - setValue(m_value); -} - void Slider::composeComponent() { AbstractSlider::composeComponent(); diff --git a/modules/uikit/src/components/uiloader.cpp b/modules/uikit/src/components/uiloader.cpp index d77a66a32..0470d60fb 100644 --- a/modules/uikit/src/components/uiloader.cpp +++ b/modules/uikit/src/components/uiloader.cpp @@ -166,9 +166,11 @@ void UiLoader::setStyleSheet(StyleSheet *style) { */ void UiLoader::resolveStyleSheet(Widget *widget) { for(auto it : widget->childWidgets()) { - m_styleSheet->resolve(it); - if(widget != this) { - resolveStyleSheet(widget); + if(!it->isSubWidget()) { + m_styleSheet->resolve(it); + if(widget != this) { + resolveStyleSheet(widget); + } } } } @@ -179,6 +181,8 @@ void UiLoader::cleanHierarchy(Widget *widget) { std::list childen = widget->childWidgets(); for(auto it : childen) { - delete it->actor(); + if(!it->isSubWidget()) { + delete it->actor(); + } } } diff --git a/modules/uikit/src/components/widget.cpp b/modules/uikit/src/components/widget.cpp index 8db635666..9978ba577 100644 --- a/modules/uikit/src/components/widget.cpp +++ b/modules/uikit/src/components/widget.cpp @@ -1,7 +1,6 @@ #include "components/widget.h" #include "components/recttransform.h" -#include "components/layout.h" #include "stylesheet.h" #include "uisystem.h" @@ -29,7 +28,8 @@ Widget *Widget::m_focusWidget = nullptr; Widget::Widget() : m_parent(nullptr), - m_transform(nullptr) { + m_transform(nullptr), + m_subWidget(false) { } @@ -42,13 +42,8 @@ Widget::~Widget() { it->m_parent = nullptr; } - for(auto it : m_subWidgets) { - it->m_parent = nullptr; - } - if(m_parent) { m_parent->m_childWidgets.remove(this); - m_parent->m_subWidgets.remove(this); } static_cast(system())->removeWidget(this); @@ -87,7 +82,7 @@ void Widget::draw(CommandBuffer &buffer) { drawSub(buffer); for(auto it : m_childWidgets) { - if(it->actor()->isEnabled() && it->isEnabled()) { + if(!it->m_subWidget && it->actor()->isEnabled() && it->isEnabled()) { it->draw(buffer); } } @@ -97,8 +92,8 @@ void Widget::draw(CommandBuffer &buffer) { Internal method called to draw the sub widget using the provided command buffer. */ void Widget::drawSub(CommandBuffer &buffer) { - for(auto it : m_subWidgets) { - if(it && it->actor()->isEnabled() && it->isEnabled()) { + for(auto it : m_childWidgets) { + if(it->m_subWidget && it->actor()->isEnabled() && it->isEnabled()) { it->draw(buffer); } } @@ -137,97 +132,15 @@ void Widget::boundChanged(const Vector2 &size) { Applies style settings assigned to widget. */ void Widget::applyStyle() { - // Size - bool pixels; - Vector2 size = m_transform->size(); - - size = styleBlock2Length("-uikit-size", size, pixels); - - size.x = styleLength("width", size.x, pixels); - size.y = styleLength("height", size.y, pixels); - - m_transform->setSize(size); - - // Pivot point - Vector2 pivot = m_transform->pivot(); - pivot = styleBlock2Length("-uikit-pivot", pivot, pixels); - m_transform->setPivot(pivot); - - // Anchors - Vector2 minAnchors = m_transform->minAnchors(); - minAnchors = styleBlock2Length("-uikit-min-anchors", minAnchors, pixels); - m_transform->setMinAnchors(minAnchors); - - Vector2 maxAnchors = m_transform->maxAnchors(); - maxAnchors = styleBlock2Length("-uikit-max-anchors", maxAnchors, pixels); - m_transform->setMaxAnchors(maxAnchors); - - // Border width - Vector4 border(m_transform->border()); - border = styleBlock4Length("border-width", border, pixels); - - border.x = styleLength("border-top-width", border.x, pixels); - border.y = styleLength("border-right-width", border.y, pixels); - border.z = styleLength("border-bottom-width", border.z, pixels); - border.w = styleLength("border-left-width", border.w, pixels); - - m_transform->setBorder(border); - - // Margins - Vector4 margin(m_transform->margin()); - margin = styleBlock4Length("margin", margin, pixels); - - margin.x = styleLength("margin-top", margin.x, pixels); - margin.y = styleLength("margin-right", margin.y, pixels); - margin.z = styleLength("margin-bottom", margin.z, pixels); - margin.w = styleLength("margin-left", margin.w, pixels); - - m_transform->setMargin(margin); - - // Padding - Vector4 padding(m_transform->padding()); - padding = styleBlock4Length("padding", padding, pixels); - - padding.x = styleLength("padding-top", padding.x, pixels); - padding.y = styleLength("padding-right", padding.y, pixels); - padding.z = styleLength("padding-bottom", padding.z, pixels); - padding.w = styleLength("padding-left", padding.w, pixels); - - m_transform->setPadding(padding); - - // Display - auto it = m_styleRules.find("display"); - if(it != m_styleRules.end()) { - TString layoutMode = it->second.second; - if(layoutMode == "none") { - actor()->setEnabled(false); - } else { - Layout *layout = m_transform->layout(); - if(layout == nullptr) { - layout = new Layout; - } - - if(layoutMode == "block") { - layout->setOrientation(Vertical); - } else if(layoutMode == "inline") { - layout->setOrientation(Horizontal); - } - - m_transform->setLayout(layout); - - for(auto it : m_childWidgets) { - layout->addTransform(it->rectTransform()); - } - } + blockSignals(true); + if(m_transform) { + m_transform->applyStyle(); } + blockSignals(false); for(auto it : m_childWidgets) { it->applyStyle(); } - - for(auto it : m_subWidgets) { - it->applyStyle(); - } } /*! Returns the parent Widget. @@ -244,19 +157,17 @@ std::list &Widget::childWidgets() { /*! Returns RectTransform component attached to parent Actor. */ -RectTransform *Widget::rectTransform() const { +RectTransform *Widget::rectTransform() { + if(m_transform == nullptr) { + setRectTransform(dynamic_cast(transform())); + } return m_transform; } /*! Returns true if provided \a widget is a part of complex widget; otherwise returns false. */ -bool Widget::isSubWidget(Widget *widget) const { - for(auto it : m_subWidgets) { - if(it == widget) { - return true; - } - } - return false; +bool Widget::isSubWidget() const { + return m_subWidget; } /*! Returns the application widget that has the keyboard input focus, or nullptr if no widget in this application has the focus. @@ -264,27 +175,28 @@ bool Widget::isSubWidget(Widget *widget) const { Widget *Widget::focusWidget() { return m_focusWidget; } - +/*! + Return a sub widget (a part of more complex widget) with specified \a name. +*/ Widget *Widget::subWidget(const TString &name) const { - for(auto it : m_subWidgets) { - if(it->actor()->name() == name) { + for(auto it : m_childWidgets) { + if(it->m_subWidget && it->actor()->name() == name) { return it; } } return nullptr; } - +/*! + \internal + Marks \a widget as a part of more complex widget. +*/ void Widget::setSubWidget(Widget *widget) { Widget *current = subWidget(widget->actor()->name()); if(current != widget) { - if(current) { - m_subWidgets.remove(current); - m_childWidgets.push_back(current); - } + widget->m_subWidget = true; - if(widget) { - m_subWidgets.push_back(widget); - m_childWidgets.remove(widget); + if(current) { + current->m_subWidget = false; } } } @@ -297,45 +209,37 @@ void Widget::setFocusWidget(Widget *widget) { } /*! \internal - Internal method to set the RectTransform component for the widget. + Internal method to set the RectTransform component for the widget. */ void Widget::setRectTransform(RectTransform *transform) { - if(m_transform) { - m_transform->unsubscribe(this); - } + if(m_transform != transform) { + if(m_transform) { + m_transform->unsubscribe(this); + } - m_transform = transform; - if(m_transform) { - m_transform->subscribe(this); + m_transform = transform; + if(m_transform) { + m_transform->subscribe(this); + onHierarchyUpdated(); + } } } -/*! - \internal - Internal method to set the parent of the widget and handle changes. -*/ -void Widget::setParent(Object *parent, int32_t position, bool force) { - NativeBehaviour::setParent(parent, position, force); - - actorParentChanged(); -} /*! \internal Internal method called when the parent actor of the widget changes. */ -void Widget::actorParentChanged() { +void Widget::onHierarchyUpdated() { Actor *object = actor(); if(object) { - setRectTransform(dynamic_cast(object->transform())); - - object = dynamic_cast(object->parent()); - if(object) { - if(m_parent) { - m_parent->m_childWidgets.remove(this); - } - - m_parent = object->getComponent(); - if(m_parent) { - m_parent->m_childWidgets.push_back(this); + m_childWidgets.clear(); + for(auto it : object->getChildren()) { + Actor *childActor = dynamic_cast(it); + if(childActor) { + for(auto widgetIt : childActor->components("Widget")) { + Widget *widget = static_cast(widgetIt); + widget->m_parent = this; + m_childWidgets.push_back(widget); + } } } } @@ -345,10 +249,9 @@ void Widget::actorParentChanged() { Internal method to compose the widget component, creating and setting the RectTransform. */ void Widget::composeComponent() { - Actor *a = actor(); - - if(a) { - Transform *transform = a->transform(); + Actor *object = Widget::actor(); + if(object) { + Transform *transform = object->transform(); RectTransform *rect = dynamic_cast(transform); if(rect == nullptr) { @@ -356,8 +259,8 @@ void Widget::composeComponent() { delete transform; } - rect = Engine::objectCreate("RectTransform", a); - a->setTransform(rect); + rect = Engine::objectCreate("RectTransform", object); + object->setTransform(rect); setRectTransform(rect); } @@ -386,8 +289,10 @@ void Widget::addStyleRules(const std::map &rules, uint32_t wei } } - for(auto it : m_subWidgets) { - it->addStyleRules(rules, weight); + for(auto it : m_childWidgets) { + if(it->m_subWidget) { + it->addStyleRules(rules, weight); + } } } /*! @@ -466,3 +371,14 @@ Vector4 Widget::styleBlock4Length(const TString &property, const Vector4 &value, return result; } + +void Widget::updateStyleProperty(const TString &name, const float *v, int32_t size) { + if(!isSignalsBlocked()) { + TString data; + for(uint32_t i = 0; i < size; i++) { + data += TString::number((int)v[i]) + "px "; + } + data.removeLast(); + StyleSheet::setStyleProperty(this, name, data); + } +} diff --git a/modules/uikit/src/editor/tools/widgettool.cpp b/modules/uikit/src/editor/tools/widgettool.cpp index 0887e4ac4..898406492 100644 --- a/modules/uikit/src/editor/tools/widgettool.cpp +++ b/modules/uikit/src/editor/tools/widgettool.cpp @@ -103,7 +103,9 @@ void WidgetTool::cancelControl() { const MetaObject *meta = component->metaObject(); for(int i = 0; i < meta->propertyCount(); i++) { MetaProperty property = meta->property(i); + component->blockSignals(true); property.write(component, properties[property.name()]); + component->blockSignals(false); } } } diff --git a/modules/uikit/src/editor/uiedit.cpp b/modules/uikit/src/editor/uiedit.cpp index cb59c7815..f21ab10d0 100644 --- a/modules/uikit/src/editor/uiedit.cpp +++ b/modules/uikit/src/editor/uiedit.cpp @@ -46,9 +46,8 @@ UiEdit::UiEdit() : m_loader = actor->getComponent(); m_controller->setRoot(m_loader); - m_controller->doRotation(Vector3()); + m_controller->activateCamera(1, true); m_controller->setGridAxis(CameraController::Axis::Z); - m_controller->blockRotations(true); m_controller->setZoomLimits(Vector2(300, 1500)); ui->preview->setController(m_controller); @@ -167,92 +166,12 @@ void UiEdit::onWidgetDuplicate() { m_undoRedo->push(new PasteWidget(m_controller, "Duplicate Widget")); } -void UiEdit::onObjectsChanged(const Object::ObjectList &objects, const TString &property, const Variant &value) { - for(auto object : objects) { - const MetaObject *meta = object->metaObject(); - - int32_t index = meta->indexOfProperty(property.data()); - if(index > -1) { - MetaProperty property = meta->property(index); - - TString tag(propertyTag(property, gCss)); - if(!tag.isEmpty()) { - TString editor(propertyTag(property, gEditorTag)); - - std::string data; - - switch(value.userType()) { - case MetaType::BOOLEAN: { - bool v = value.toBool(); - if(tag == "white-space") { - data = v ? "normal" : "nowrap"; - } else if(tag == "font-kerning") { - data = v ? "normal" : "none"; - } - } break; - case MetaType::INTEGER: { - if(tag == "text-align") { - value.toInt(); - } else { - data += std::to_string(value.toInt()) + "px"; - } - } break; - case MetaType::FLOAT: { - data += std::to_string(value.toFloat()) + "px"; - } break; - case MetaType::VECTOR2: { - Vector2 v = value.toVector2(); - for(uint32_t i = 0; i < 2; i++) { - data += std::to_string(v[i]) + "px "; - } - data.pop_back(); - } break; - case MetaType::VECTOR3: { - Vector3 v = value.toVector3(); - for(uint32_t i = 0; i < 3; i++) { - data += std::to_string(v[i]) + "px "; - } - data.pop_back(); - } break; - case MetaType::VECTOR4: { - Vector4 v = value.toVector4(); - if(editor == "Color") { - std::stringstream ss; - ss << "#"; - - for(uint32_t i = 0; i < 4; i++) { - uint32_t c = v[i] * 255.0f; - - if(c == 0) { - ss << "00"; - } else { - ss << std::hex << c; - } - } - - data = ss.str(); - } else { - for(uint32_t i = 0; i < 4; i++) { - data += std::to_string(v[i]) + "px "; - } - data.pop_back(); - } - } break; - } - - Widget *widget = dynamic_cast(object); - if(widget) { - StyleSheet::setStyleProperty(widget, tag, data); - } - } - } - } - - TString capital = property; +void UiEdit::onObjectsChanged(const Object::ObjectList &objects, const TString &propertyName, const Variant &value) { + TString capital = propertyName; capital[0] = std::toupper(capital.at(0)); - TString name(QObject::tr("Change %1").arg(capital.data()).toStdString()); + TString name(Engine::translate("Change %1").arg(capital)); - m_undoRedo->push(new ChangeProperty(objects, property, value, m_controller, name)); + m_undoRedo->push(new ChangeProperty(objects, propertyName, value, m_controller, name)); } void UiEdit::loadAsset(AssetConverterSettings *settings) { @@ -302,7 +221,7 @@ void UiEdit::saveAsset(const TString &path) { void UiEdit::saveElementHelper(pugi::xml_node &parent, Widget *widget) { for(auto it : widget->childWidgets()) { - if(widget->isSubWidget(it)) { + if(it->isSubWidget()) { continue; } auto originIt = m_widgets.find(it->typeName()); @@ -350,7 +269,6 @@ void UiEdit::saveElementHelper(pugi::xml_node &parent, Widget *widget) { saveElementHelper(element, it); } - } } diff --git a/modules/uikit/src/editor/widgetcontroller.cpp b/modules/uikit/src/editor/widgetcontroller.cpp index 07c81a4c7..3a21bca3f 100644 --- a/modules/uikit/src/editor/widgetcontroller.cpp +++ b/modules/uikit/src/editor/widgetcontroller.cpp @@ -3,12 +3,11 @@ #include "components/widget.h" #include "components/recttransform.h" -#include - #include #include #include +#include #include #include @@ -108,9 +107,11 @@ void WidgetController::drawHandles() { Widget *widgetHoverHelper(Widget *widget, float x, float y) { for(auto it : widget->childWidgets()) { - Widget *result = widgetHoverHelper(it, x, y); - if(result) { - return result; + if(!widget->isSubWidget()) { + Widget *result = widgetHoverHelper(it, x, y); + if(result) { + return result; + } } } @@ -195,7 +196,6 @@ void WidgetController::cameraZoom(float delta) { Vector3 world(m_activeCamera->unproject(rect->position())); Transform *cameraTransform = m_activeCamera->transform(); - Vector3 worldCamera(m_activeCamera->unproject(cameraTransform->position())); float scale = 1.1f - ((float)m_zoom / 10.0f); m_activeCamera->setOrthoSize(m_screenSize.y / scale); diff --git a/modules/uikit/src/resources/stylesheet.cpp b/modules/uikit/src/resources/stylesheet.cpp index dc4baa695..f88bfbc09 100644 --- a/modules/uikit/src/resources/stylesheet.cpp +++ b/modules/uikit/src/resources/stylesheet.cpp @@ -209,6 +209,25 @@ Vector4 StyleSheet::toColor(const TString &value) { return result; } + +TString StyleSheet::toColor(const Vector4 &value) { + std::stringstream ss; + ss << "#"; + + for(uint32_t i = 0; i < 4; i++) { // ARGB + uint32_t index = (i == 0) ? 3 : (i - 1); + uint32_t c = value[index] * 255.0f; + + if(c == 0) { + ss << "00"; + } else { + ss << std::hex << c; + } + } + + return ss.str(); +} + /*! Converts a length \a value (e.g., "10px" or "50%") into a numeric value and returns whether the value is in \a pixels or percentages. */ diff --git a/modules/uikit/src/uikit.cpp b/modules/uikit/src/uikit.cpp index 12a0aa566..ec928be3e 100644 --- a/modules/uikit/src/uikit.cpp +++ b/modules/uikit/src/uikit.cpp @@ -40,6 +40,8 @@ static const char *meta = \ " \"ProgressBar\"," " \"RectTransform\"," " \"ScrollBar\"," +" \"Slider\"," +" \"Splitter\"," " \"Switch\"," " \"TextInput\"," " \"ToolButton\"," diff --git a/modules/uikit/src/utils/combineselector.cpp b/modules/uikit/src/utils/combineselector.cpp index 046edd84c..1ce8ff91d 100644 --- a/modules/uikit/src/utils/combineselector.cpp +++ b/modules/uikit/src/utils/combineselector.cpp @@ -84,11 +84,11 @@ void CombineSelector::initialNormalInhericalList(Selector *root, Selector *child } void CombineSelector::initialInstanceInhericalList(Selector *root, Selector *child) { - if (m_combineType != NoCombine) { + if(m_combineType != NoCombine) { assert(0); } - if (!root || !child) { + if(!root || !child) { return; } @@ -134,18 +134,7 @@ bool CombineSelector::isMeet(Widget *widget) { } switch(m_combineType) { - case CombineSelector::NormalSibling: { // Unsupported - //int idx = widget->GetIndexWithinParent(); - //for(const auto &sibling : parent->childWidgets()) { - // if(sibling->GetIndexWithinParent() >= idx) { - // continue; - // } - // if(doesWidgetSelector(sibling, before)) { - // selector->matchingWidgets.push_back(sibling); - // } - //} - break; - } + case CombineSelector::NormalSibling: break; case CombineSelector::InstanceSibling: { Widget *lastWidget = nullptr; for(const auto &sibling : parent->childWidgets()) {