Reduce heap-allocations on possible hot-paths.

This commit is contained in:
Martín Lucas Golini
2026-09-06 21:02:58 -03:00
parent bd9360cf3e
commit 3d4aea6df4
12 changed files with 43 additions and 29 deletions

View File

@@ -27,7 +27,7 @@ class EE_API StyleSheetSelector {
bool hasPseudoClasses() const;
std::vector<UIWidget*> getRelatedElements( UIWidget* element, bool applyPseudo = true ) const;
SmallVector<UIWidget*, 8> getRelatedElements( UIWidget* element, bool applyPseudo = true ) const;
bool isStructurallyVolatile() const;

View File

@@ -123,7 +123,7 @@ template <typename T> class UIProperty {
}
/** @return All currently connected widgets, or an empty vector after expiration. */
std::vector<UIWidget*> widgets() const {
SmallVector<UIWidget*, 8> widgets() const {
auto state = mState.lock();
if ( !state || !state->property || !state->property->databind().isInitialized() )
return {};

View File

@@ -1516,8 +1516,14 @@ class EE_API UINode : public Node {
/** @brief Get a widget's computed absolute font size in pixels. */
Float getAbsoluteFontSize( const UIWidget* widget ) const;
/** Returns true if the node is currently being created, this state is not used by all node
* types.
*/
bool isCreatingNode() const;
/** Forces a left mouse click event over the node */
void click();
protected:
Vector2f mDpPos;
Sizef mDpSize;

View File

@@ -858,7 +858,8 @@ class EE_API UISceneNode : public SceneNode {
* @param marker Marker for style association.
* @return Vector of root widgets created.
*/
std::vector<UIWidget*> loadNode( pugi::xml_node node, Node* parent, const Uint32& marker = 0 );
SmallVector<UIWidget*, 8> loadNode( pugi::xml_node node, Node* parent,
const Uint32& marker = 0 );
/** Sets the document / scene URI used to resolve paths of inner elements */
void setURI( const URI& uri );

View File

@@ -23,6 +23,7 @@ namespace EE { namespace UI {
class UITooltip;
class UIStyle;
class UIWidget;
struct MarginAuto {
static constexpr auto Left = ( 1 << 0 );
@@ -31,6 +32,8 @@ struct MarginAuto {
static constexpr auto Bottom = ( 1 << 3 );
};
using WidgetQueryResult = SmallVector<UIWidget*, 8>;
/**
* @brief Base class for all UI widgets in the eepp framework.
*
@@ -1118,7 +1121,7 @@ class EE_API UIWidget : public UINode {
* @param className The CSS class to search for.
* @return Vector of matching UIWidget pointers.
*/
std::vector<UIWidget*> findAllByClass( const std::string& className );
WidgetQueryResult findAllByClass( const std::string& className );
/**
* @brief Finds all widgets by CSS tag.
@@ -1128,7 +1131,7 @@ class EE_API UIWidget : public UINode {
* @param tag The CSS tag to search for.
* @return Vector of matching UIWidget pointers.
*/
std::vector<UIWidget*> findAllByTag( const std::string& tag );
WidgetQueryResult findAllByTag( const std::string& tag );
/**
* @brief Finds a widget by CSS class.
@@ -1190,7 +1193,7 @@ class EE_API UIWidget : public UINode {
* @param selector The CSS selector to use.
* @return Vector of all matching UIWidget pointers.
*/
std::vector<UIWidget*> querySelectorAll( const CSS::StyleSheetSelector& selector );
WidgetQueryResult querySelectorAll( const CSS::StyleSheetSelector& selector );
/**
* @brief Queries all widgets using a CSS selector string.
@@ -1200,7 +1203,7 @@ class EE_API UIWidget : public UINode {
* @param selector The CSS selector string to use.
* @return Vector of all matching UIWidget pointers.
*/
std::vector<UIWidget*> querySelectorAll( const std::string& selector );
WidgetQueryResult querySelectorAll( const std::string& selector );
/**
* @brief Gets a property value as a string.

View File

@@ -237,10 +237,10 @@ bool StyleSheetSelector::selectComplex( UIWidget* element, const bool& applyPseu
return true;
}
std::vector<UIWidget*> StyleSheetSelector::getRelatedElements( UIWidget* element,
bool applyPseudo ) const {
static std::vector<UIWidget*> EMPTY_ELEMENTS;
std::vector<UIWidget*> elements;
SmallVector<UIWidget*, 8> StyleSheetSelector::getRelatedElements( UIWidget* element,
bool applyPseudo ) const {
static SmallVector<UIWidget*, 8> EMPTY_ELEMENTS;
SmallVector<UIWidget*, 8> elements;
if ( mSelectorRules.empty() )
return elements;

View File

@@ -1905,4 +1905,10 @@ bool UINode::isCreatingNode() const {
return mFlags & UI_CREATING_NODE;
}
void UINode::click() {
Vector2f pos;
nodeToWorld( pos );
getEventDispatcher()->sendMouseClick( this, pos.ceil().asInt(), EE_BUTTON_LMASK );
}
}} // namespace EE::UI

View File

@@ -546,12 +546,12 @@ bool UISceneNode::windowExists( UIWindow* win ) {
return mWindowsList.end() != std::find( mWindowsList.begin(), mWindowsList.end(), win );
}
std::vector<UIWidget*> UISceneNode::loadNode( pugi::xml_node node, Node* parent,
SmallVector<UIWidget*, 8> UISceneNode::loadNode( pugi::xml_node node, Node* parent,
const Uint32& marker ) {
Uint32 oldMarker = mCurrentMarker;
mCurrentMarker = marker;
std::vector<UIWidget*> rootWidgets;
SmallVector<UIWidget*, 8> rootWidgets;
if ( NULL == parent )
parent = this;
@@ -646,7 +646,7 @@ UIWidget* UISceneNode::loadLayoutNodes( pugi::xml_node node, Node* parent, const
std::string id( node.attribute( "id" ).as_string() );
mIsLoading = true;
Clock innerClock;
std::vector<UIWidget*> widgets = loadNode( node, parent, marker );
SmallVector<UIWidget*, 8> widgets = loadNode( node, parent, marker );
if ( mVerbose ) {
std::sort(

View File

@@ -581,8 +581,7 @@ void UIStyle::subscribeNonCacheableStyles() {
return;
for ( auto& style : mGlobalDefinition->getStyles() ) {
if ( !style->getSelector().isCacheable() ) {
std::vector<UIWidget*> elements =
style->getSelector().getRelatedElements( mWidget, false );
auto elements = style->getSelector().getRelatedElements( mWidget, false );
if ( !elements.empty() ) {
for ( auto& element : elements ) {

View File

@@ -1557,8 +1557,8 @@ const Uint32& UIWidget::getStylePreviousState() const {
return NULL != mStyle ? mStyle->getPreviousState() : mState;
}
std::vector<UIWidget*> UIWidget::findAllByClass( const std::string& className ) {
std::vector<UIWidget*> widgets;
WidgetQueryResult UIWidget::findAllByClass( const std::string& className ) {
WidgetQueryResult widgets;
if ( !isClosing() && hasClass( className ) && !inClosingTree() ) {
widgets.push_back( this );
@@ -1568,8 +1568,7 @@ std::vector<UIWidget*> UIWidget::findAllByClass( const std::string& className )
while ( NULL != child ) {
if ( child->isWidget() ) {
std::vector<UIWidget*> foundWidgets =
child->asType<UIWidget>()->findAllByClass( className );
WidgetQueryResult foundWidgets = child->asType<UIWidget>()->findAllByClass( className );
if ( !foundWidgets.empty() )
widgets.insert( widgets.end(), foundWidgets.begin(), foundWidgets.end() );
@@ -1581,8 +1580,8 @@ std::vector<UIWidget*> UIWidget::findAllByClass( const std::string& className )
return widgets;
}
std::vector<UIWidget*> UIWidget::findAllByTag( const std::string& tag ) {
std::vector<UIWidget*> widgets;
WidgetQueryResult UIWidget::findAllByTag( const std::string& tag ) {
WidgetQueryResult widgets;
if ( !isClosing() && getElementTag() == tag && !inClosingTree() ) {
widgets.push_back( this );
@@ -1592,7 +1591,7 @@ std::vector<UIWidget*> UIWidget::findAllByTag( const std::string& tag ) {
while ( NULL != child ) {
if ( child->isWidget() ) {
std::vector<UIWidget*> foundWidgets = child->asType<UIWidget>()->findAllByTag( tag );
WidgetQueryResult foundWidgets = child->asType<UIWidget>()->findAllByTag( tag );
if ( !foundWidgets.empty() )
widgets.insert( widgets.end(), foundWidgets.begin(), foundWidgets.end() );
@@ -1667,8 +1666,8 @@ UIWidget* UIWidget::querySelector( const CSS::StyleSheetSelector& selector ) {
return NULL;
}
std::vector<UIWidget*> UIWidget::querySelectorAll( const CSS::StyleSheetSelector& selector ) {
std::vector<UIWidget*> widgets;
WidgetQueryResult UIWidget::querySelectorAll( const CSS::StyleSheetSelector& selector ) {
WidgetQueryResult widgets;
if ( !isClosing() && !inClosingTree() && selector.select( this ) ) {
widgets.push_back( this );
@@ -1678,7 +1677,7 @@ std::vector<UIWidget*> UIWidget::querySelectorAll( const CSS::StyleSheetSelector
while ( NULL != child ) {
if ( child->isWidget() ) {
std::vector<UIWidget*> foundWidgets =
WidgetQueryResult foundWidgets =
child->asType<UIWidget>()->querySelectorAll( selector );
if ( !foundWidgets.empty() )
@@ -1714,7 +1713,7 @@ UIWidget* UIWidget::querySelector( const std::string& selector ) {
return querySelector( CSS::StyleSheetSelector( selector ) );
}
std::vector<UIWidget*> UIWidget::querySelectorAll( const std::string& selector ) {
WidgetQueryResult UIWidget::querySelectorAll( const std::string& selector ) {
return querySelectorAll( CSS::StyleSheetSelector( selector ) );
}

View File

@@ -5837,7 +5837,7 @@ UTEST( UIHTML, RonStonerDeferredImagesUpdateDocumentHeight ) {
ASSERT_TRUE( documentScene != nullptr );
UIWidget* body = nullptr;
std::vector<UIWidget*> images;
WidgetQueryResult images;
for ( int i = 0; i < 300; ++i ) {
pump();
body = documentScene->getRoot()->findByType( UI_TYPE_HTML_BODY )->asType<UIWidget>();

View File

@@ -157,7 +157,7 @@ class GitPlugin : public PluginBase {
UIDropDownList* mPanelSwicher{ nullptr };
UIDropDownList* mRepoDropDown{ nullptr };
UIStackWidget* mStackWidget{ nullptr };
std::vector<UIWidget*> mStackMap;
SmallVector<UIWidget*, 4> mStackMap;
UIWidget* mGitContentView{ nullptr };
UIWidget* mGitNoContentView{ nullptr };
UIWidget* mConflictStateBar{ nullptr };