Index: ps/trunk/source/gui/CGUI.h =================================================================== --- ps/trunk/source/gui/CGUI.h +++ ps/trunk/source/gui/CGUI.h @@ -42,6 +42,11 @@ */ struct SGUIStyle { + // Take advantage of moving the entire map instead and avoiding unintended copies. + NONCOPYABLE(SGUIStyle); + MOVABLE(SGUIStyle); + SGUIStyle() = default; + std::map m_SettingsDefaults; }; @@ -235,9 +240,9 @@ bool IconExists(const CStr& str) const { return (m_Icons.count(str) != 0); } /** - * Get Icon (a copy, can never be changed) + * Get Icon (a const reference, can never be changed) */ - SGUIIcon GetIcon(const CStr& str) const { return m_Icons.find(str)->second; } + const SGUIIcon& GetIcon(const CStr& str) const { return m_Icons.find(str)->second; } /** * Get pre-defined color (if it exists) @@ -628,19 +633,21 @@ //-------------------------------------------------------- // Databases + // These are loaded from XML files and marked as noncopyable and const to + // rule out unintentional modification and copy, especially during Draw calls. //-------------------------------------------------------- // Sprites - std::map m_Sprites; + std::map m_Sprites; // Styles - std::map m_Styles; + std::map m_Styles; // Scroll-bar styles - std::map m_ScrollBarStyles; + std::map m_ScrollBarStyles; // Icons - std::map m_Icons; + std::map m_Icons; }; #endif // INCLUDED_CGUI Index: ps/trunk/source/gui/CGUI.cpp =================================================================== --- ps/trunk/source/gui/CGUI.cpp +++ ps/trunk/source/gui/CGUI.cpp @@ -383,7 +383,7 @@ } m_pAllObjects.clear(); - for (const std::pair& p : m_Sprites) + for (const std::pair& p : m_Sprites) delete p.second; m_Sprites.clear(); m_Icons.clear(); @@ -478,7 +478,7 @@ const SGUIScrollBarStyle* CGUI::GetScrollBarStyle(const CStr& style) const { - std::map::const_iterator it = m_ScrollBarStyles.find(style); + std::map::const_iterator it = m_ScrollBarStyles.find(style); if (it == m_ScrollBarStyles.end()) return nullptr; @@ -594,9 +594,9 @@ _y = y; // Get Size from Icon database - SGUIIcon icon = GetIcon(imgname); + const SGUIIcon& icon = GetIcon(imgname); - CSize size = icon.m_Size; + const CSize& size = icon.m_Size; Image.SetupSpriteCall((j == CGUIString::SFeedback::Left), SpriteCall, Width, _y, size, icon.m_SpriteName, BufferZone, icon.m_CellID); // Check if image is the lowest thing. @@ -1423,7 +1423,8 @@ delete effects; - m_Sprites[name] = Sprite; + m_Sprites.erase(name); + m_Sprites.emplace(name, Sprite); } void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite& parent) @@ -1595,10 +1596,11 @@ if (attr_name == "name") name = attr.Value; else - style.m_SettingsDefaults[attr_name] = attr.Value.FromUTF8(); + style.m_SettingsDefaults.emplace(attr_name, attr.Value.FromUTF8()); } - m_Styles[name] = style; + m_Styles.erase(name); + m_Styles.emplace(name, std::move(style)); } void CGUI::Xeromyces_ReadScrollBarStyle(XMBElement Element, CXeromyces* pFile) @@ -1680,7 +1682,8 @@ scrollbar.m_SpriteBarVerticalPressed = attr_value; } - m_ScrollBarStyles[name] = std::move(scrollbar); + m_ScrollBarStyles.erase(name); + m_ScrollBarStyles.emplace(name, std::move(scrollbar)); } void CGUI::Xeromyces_ReadIcon(XMBElement Element, CXeromyces* pFile) @@ -1720,7 +1723,8 @@ debug_warn(L"Invalid data - DTD shouldn't allow this"); } - m_Icons[name] = icon; + m_Icons.erase(name); + m_Icons.emplace(name, std::move(icon)); } void CGUI::Xeromyces_ReadTooltip(XMBElement Element, CXeromyces* pFile) Index: ps/trunk/source/gui/CGUISprite.h =================================================================== --- ps/trunk/source/gui/CGUISprite.h +++ ps/trunk/source/gui/CGUISprite.h @@ -157,16 +157,14 @@ // calculations between draw calls. class CGUISpriteInstance { +public: NONCOPYABLE(CGUISpriteInstance); + MOVABLE(CGUISpriteInstance); -public: CGUISpriteInstance(); CGUISpriteInstance(const CStr& SpriteName); - CGUISpriteInstance(CGUISpriteInstance&&) = default; - CGUISpriteInstance& operator=(CGUISpriteInstance&&) = default; - - void Draw(const CRect& Size, int CellID, std::map& Sprites, float Z) const; + void Draw(const CRect& Size, int CellID, std::map& Sprites, float Z) const; bool IsEmpty() const; const CStr& GetName() const { return m_SpriteName; } void SetName(const CStr& SpriteName); Index: ps/trunk/source/gui/CGUISprite.cpp =================================================================== --- ps/trunk/source/gui/CGUISprite.cpp +++ ps/trunk/source/gui/CGUISprite.cpp @@ -30,7 +30,7 @@ m_Images.push_back(image); } -void CGUISpriteInstance::Draw(const CRect& Size, int CellID, std::map& Sprites, float Z) const +void CGUISpriteInstance::Draw(const CRect& Size, int CellID, std::map& Sprites, float Z) const { if (m_CachedSize != Size || m_CachedCellID != CellID) { Index: ps/trunk/source/gui/GUIRenderer.h =================================================================== --- ps/trunk/source/gui/GUIRenderer.h +++ ps/trunk/source/gui/GUIRenderer.h @@ -79,7 +79,7 @@ namespace GUIRenderer { - void UpdateDrawCallCache(DrawCalls& Calls, const CStr& SpriteName, const CRect& Size, int CellID, std::map& Sprites); + void UpdateDrawCallCache(DrawCalls& Calls, const CStr& SpriteName, const CRect& Size, int CellID, std::map& Sprites); void Draw(DrawCalls& Calls, float Z); } Index: ps/trunk/source/gui/GUIRenderer.cpp =================================================================== --- ps/trunk/source/gui/GUIRenderer.cpp +++ ps/trunk/source/gui/GUIRenderer.cpp @@ -59,7 +59,7 @@ } -void GUIRenderer::UpdateDrawCallCache(DrawCalls& Calls, const CStr& SpriteName, const CRect& Size, int CellID, std::map& Sprites) +void GUIRenderer::UpdateDrawCallCache(DrawCalls& Calls, const CStr& SpriteName, const CRect& Size, int CellID, std::map& Sprites) { // This is called only when something has changed (like the size of the // sprite), so it doesn't need to be particularly efficient. @@ -74,7 +74,7 @@ return; - std::map::iterator it(Sprites.find(SpriteName)); + std::map::iterator it(Sprites.find(SpriteName)); if (it == Sprites.end()) { /* Index: ps/trunk/source/gui/GUIbase.h =================================================================== --- ps/trunk/source/gui/GUIbase.h +++ ps/trunk/source/gui/GUIbase.h @@ -148,6 +148,10 @@ // you use them in text owned by different objects... Such as CText. struct SGUIIcon { + // This struct represents an immutable type, so ensure to avoid copying the strings. + NONCOPYABLE(SGUIIcon); + MOVABLE(SGUIIcon); + SGUIIcon() : m_CellID(0) {} // Sprite name of icon Index: ps/trunk/source/gui/GUItext.cpp =================================================================== --- ps/trunk/source/gui/GUItext.cpp +++ ps/trunk/source/gui/GUItext.cpp @@ -124,9 +124,9 @@ SGUIText::SSpriteCall SpriteCall; // Get Icon from icon database in pGUI - SGUIIcon icon = pGUI->GetIcon(path); + const SGUIIcon& icon = pGUI->GetIcon(path); - CSize size = icon.m_Size; + const CSize& size = icon.m_Size; // append width, and make maximum height the height. Feedback.m_Size.cx += size.cx; Index: ps/trunk/source/gui/IGUIScrollBar.h =================================================================== --- ps/trunk/source/gui/IGUIScrollBar.h +++ ps/trunk/source/gui/IGUIScrollBar.h @@ -49,6 +49,11 @@ */ struct SGUIScrollBarStyle { + // CGUISpriteInstance makes this NONCOPYABLE implicitly, make it explicit + NONCOPYABLE(SGUIScrollBarStyle); + MOVABLE(SGUIScrollBarStyle); + SGUIScrollBarStyle() = default; + //-------------------------------------------------------- /** @name General Settings */ //-------------------------------------------------------- Index: ps/trunk/source/lib/code_annotation.h =================================================================== --- ps/trunk/source/lib/code_annotation.h +++ ps/trunk/source/lib/code_annotation.h @@ -218,6 +218,14 @@ className(const className&) = delete; \ className& operator=(const className&) = delete +/** + * Indicates that move semantics can be used, so that a NONCOPYABLE class can still be assigned by taking over the reference to the value. + * Make sure to use the macro with the necessary access modifier. + */ +#define MOVABLE(className) \ + className(className&&) = default; \ + className& operator=(className&&) = default + #if ICC_VERSION # define ASSUME_ALIGNED(ptr, multiple) __assume_aligned(ptr, multiple) #else