Index: ps/trunk/binaries/data/mods/mod/gui/gui.rng
===================================================================
--- ps/trunk/binaries/data/mods/mod/gui/gui.rng (revision 25407)
+++ ps/trunk/binaries/data/mods/mod/gui/gui.rng (revision 25408)
@@ -1,872 +1,877 @@
truefalseleftcenterrighttopcenterbottomrepeatmirrored_repeatclamp_to_edge
-?\d*\.?\d+%?([\+\-]\d*\.?\d+%?)*
0
255
0
255
0
255
0
255
[A-Za-z]+
0
+
+
+
+
+
1
1
Index: ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMap.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMap.xml (revision 25407)
+++ ps/trunk/binaries/data/mods/public/gui/session/minimap/MiniMap.xml (revision 25408)
@@ -1,37 +1,38 @@
Index: ps/trunk/source/gui/ObjectTypes/CButton.cpp
===================================================================
--- ps/trunk/source/gui/ObjectTypes/CButton.cpp (revision 25407)
+++ ps/trunk/source/gui/ObjectTypes/CButton.cpp (revision 25408)
@@ -1,106 +1,116 @@
/* Copyright (C) 2021 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#include "precompiled.h"
#include "CButton.h"
#include "gui/CGUI.h"
#include "gui/CGUIText.h"
#include "gui/SettingTypes/CGUIColor.h"
CButton::CButton(CGUI& pGUI)
: IGUIObject(pGUI),
IGUIButtonBehavior(*static_cast(this)),
IGUITextOwner(*static_cast(this)),
m_BufferZone(this, "buffer_zone"),
m_Caption(this, "caption"),
m_Font(this, "font"),
m_Sprite(this, "sprite"),
m_SpriteOver(this, "sprite_over"),
m_SpritePressed(this, "sprite_pressed"),
m_SpriteDisabled(this, "sprite_disabled"),
m_TextColor(this, "textcolor"),
m_TextColorOver(this, "textcolor_over"),
m_TextColorPressed(this, "textcolor_pressed"),
- m_TextColorDisabled(this, "textcolor_disabled")
+ m_TextColorDisabled(this, "textcolor_disabled"),
+ m_MouseEventMask(this)
{
AddText();
}
CButton::~CButton()
{
}
void CButton::SetupText()
{
ENSURE(m_GeneratedTexts.size() == 1);
m_GeneratedTexts[0] = CGUIText(m_pGUI, m_Caption, m_Font, m_CachedActualSize.GetWidth(), m_BufferZone, m_TextAlign, this);
CalculateTextPosition(m_CachedActualSize, m_TextPos, m_GeneratedTexts[0]);
}
void CButton::ResetStates()
{
IGUIObject::ResetStates();
IGUIButtonBehavior::ResetStates();
}
void CButton::UpdateCachedSize()
{
IGUIObject::UpdateCachedSize();
IGUITextOwner::UpdateCachedSize();
}
CSize2D CButton::GetTextSize()
{
UpdateText();
return m_GeneratedTexts[0].GetSize();
}
void CButton::HandleMessage(SGUIMessage& Message)
{
IGUIObject::HandleMessage(Message);
IGUIButtonBehavior::HandleMessage(Message);
IGUITextOwner::HandleMessage(Message);
}
void CButton::Draw()
{
const float bz = GetBufferedZ();
m_pGUI.DrawSprite(
GetButtonSprite(m_Sprite, m_SpriteOver, m_SpritePressed, m_SpriteDisabled),
bz,
m_CachedActualSize);
DrawText(0, ChooseColor(), m_TextPos, bz + 0.1f);
}
+bool CButton::IsMouseOver() const
+{
+ if (!IGUIObject::IsMouseOver())
+ return false;
+ if (!m_MouseEventMask)
+ return true;
+ return m_MouseEventMask.IsMouseOver(m_pGUI.GetMousePos(), m_CachedActualSize);
+}
+
const CGUIColor& CButton::ChooseColor()
{
if (!m_Enabled)
return *m_TextColorDisabled ? m_TextColorDisabled : m_TextColor;
if (!m_MouseHovering)
return m_TextColor;
if (m_Pressed)
return *m_TextColorPressed ? m_TextColorPressed : m_TextColor;
return *m_TextColorOver ? m_TextColorOver : m_TextColor;
}
Index: ps/trunk/source/gui/ObjectTypes/CButton.h
===================================================================
--- ps/trunk/source/gui/ObjectTypes/CButton.h (revision 25407)
+++ ps/trunk/source/gui/ObjectTypes/CButton.h (revision 25408)
@@ -1,93 +1,100 @@
/* Copyright (C) 2021 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see .
*/
#ifndef INCLUDED_CBUTTON
#define INCLUDED_CBUTTON
#include "gui/CGUISprite.h"
#include "gui/ObjectBases/IGUIButtonBehavior.h"
#include "gui/ObjectBases/IGUIObject.h"
#include "gui/ObjectBases/IGUITextOwner.h"
#include "gui/SettingTypes/CGUIString.h"
+#include "gui/SettingTypes/MouseEventMask.h"
#include "maths/Vector2D.h"
class CButton : public IGUIObject, public IGUITextOwner, public IGUIButtonBehavior
{
GUI_OBJECT(CButton)
public:
CButton(CGUI& pGUI);
virtual ~CButton();
/**
* @see IGUIObject#ResetStates()
*/
virtual void ResetStates();
/**
* @see IGUIObject#UpdateCachedSize()
*/
virtual void UpdateCachedSize();
/**
* @return the object text size.
*/
CSize2D GetTextSize();
/**
* @see IGUIObject#HandleMessage()
*/
virtual void HandleMessage(SGUIMessage& Message);
/**
* Draws the Button
*/
virtual void Draw();
+ /**
+ * @see IGUIObject#IsMouseOver()
+ */
+ virtual bool IsMouseOver() const;
+
protected:
/**
* Sets up text, should be called every time changes has been
* made that can change the visual.
*/
void SetupText();
/**
* Picks the text color depending on current object settings.
*/
const CGUIColor& ChooseColor();
/**
* Placement of text.
*/
CVector2D m_TextPos;
virtual void CreateJSObject();
// Settings
CGUISimpleSetting m_BufferZone;
CGUISimpleSetting m_Caption;
CGUISimpleSetting m_Font;
CGUISimpleSetting m_Sprite;
CGUISimpleSetting m_SpriteOver;
CGUISimpleSetting m_SpritePressed;
CGUISimpleSetting m_SpriteDisabled;
CGUISimpleSetting m_TextColor;
CGUISimpleSetting m_TextColorOver;
CGUISimpleSetting m_TextColorPressed;
CGUISimpleSetting m_TextColorDisabled;
+ CGUIMouseEventMask m_MouseEventMask;
};
#endif // INCLUDED_CBUTTON
Index: ps/trunk/source/gui/SettingTypes/MouseEventMask.cpp
===================================================================
--- ps/trunk/source/gui/SettingTypes/MouseEventMask.cpp (nonexistent)
+++ ps/trunk/source/gui/SettingTypes/MouseEventMask.cpp (revision 25408)
@@ -0,0 +1,165 @@
+/* Copyright (C) 2021 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "precompiled.h"
+
+#include "MouseEventMask.h"
+
+#include "gui/CGUISetting.h"
+#include "lib/tex/tex.h"
+#include "ps/Filesystem.h"
+#include "ps/CLogger.h"
+#include "ps/CStr.h"
+#include "scriptinterface/ScriptInterface.h"
+
+namespace
+{
+ const std::string MOUSE_EVENT_MASK = "mouse_event_mask";
+}
+
+class CGUIMouseEventMask::Impl
+{
+public:
+ virtual ~Impl() = default;
+ virtual bool IsMouseOver(const CVector2D& mousePos, const CRect& objectSize) const = 0;
+};
+
+CGUIMouseEventMask::CGUIMouseEventMask(IGUIObject* owner) : IGUISetting(MOUSE_EVENT_MASK, owner)
+{
+}
+
+CGUIMouseEventMask::~CGUIMouseEventMask()
+{
+}
+
+void CGUIMouseEventMask::ToJSVal(const ScriptRequest& rq, JS::MutableHandleValue Value)
+{
+ ScriptInterface::ToJSVal(rq, Value, m_Spec);
+}
+
+bool CGUIMouseEventMask::DoFromJSVal(const ScriptRequest& rq, JS::HandleValue value)
+{
+ CStrW spec;
+ if (!ScriptInterface::FromJSVal(rq, value, spec))
+ return false;
+ return DoFromString(spec);
+}
+
+CStr CGUIMouseEventMask::GetName() const
+{
+ return MOUSE_EVENT_MASK;
+}
+
+bool CGUIMouseEventMask::IsMouseOver(const CVector2D& mousePos, const CRect& objectSize) const
+{
+ if (m_Impl)
+ return m_Impl->IsMouseOver(mousePos, objectSize);
+ return false;
+}
+
+class CGUIMouseEventMaskTexture final : public CGUIMouseEventMask::Impl
+{
+public:
+ static constexpr const char* identifier = "texture:";
+ static constexpr size_t specOffset = sizeof(identifier);
+
+ static std::unique_ptr Create(const std::string& spec)
+ {
+ std::shared_ptr shapeFile;
+ size_t size;
+ if (g_VFS->LoadFile(VfsPath("art") / L"textures" / L"ui" / spec.substr(specOffset), shapeFile, size) != INFO::OK)
+ {
+ LOGWARNING("Mouse event mask texture not found ('%s')", spec);
+ return nullptr;
+ }
+ Tex tex;
+ if (tex.decode(shapeFile, size) != INFO::OK)
+ {
+ LOGERROR("Could not decode mouse event mask texture '%s'", spec);
+ return nullptr;
+ }
+ // TODO > would be nice to downscale, maybe.
+ if (tex.m_Width == 0 || tex.m_Height == 0)
+ {
+ LOGERROR("Mouse event mask texture must have a non-null size ('%s')", spec);
+ return nullptr;
+ }
+
+ auto mask = std::make_unique();
+ mask->m_Width = tex.m_Width;
+ mask->m_Height = tex.m_Height;
+ mask->m_Data.reserve(mask->m_Width * mask->m_Height);
+ for (u8* ptr = tex.get_data(); ptr < tex.get_data() + tex.m_DataSize; ptr += tex.m_Bpp/8)
+ {
+ if (tex.m_Bpp == 32)
+ mask->m_Data.push_back(*(ptr + 3) > 0);
+ else
+ mask->m_Data.push_back(*ptr > 0);
+ }
+ return mask;
+ }
+
+ virtual bool IsMouseOver(const CVector2D& mousePos, const CRect& objectSize) const override
+ {
+ if (m_Data.empty())
+ return false;
+
+ CVector2D delta = mousePos - objectSize.TopLeft();
+ int x = floor(delta.X * m_Width / objectSize.GetWidth());
+ int y = floor(delta.Y * m_Height / objectSize.GetHeight());
+ if (x < 0 || y < 0 || x >= m_Width || y >= m_Height)
+ return false;
+
+ return m_Data[x + y * m_Width] > 0;
+ }
+
+private:
+ // This uses the bool specialization on purpose for the 'compression' effect.
+ std::vector m_Data;
+ u16 m_Width;
+ u16 m_Height;
+};
+
+bool CGUIMouseEventMask::DoFromString(const CStrW& Value)
+{
+ std::string spec = Value.ToUTF8();
+ if (spec == m_Spec)
+ return true;
+
+ // Empty spec - reset the mask and return.
+ if (spec.empty())
+ {
+ m_Impl.reset();
+ return true;
+ }
+
+ if (spec.find(CGUIMouseEventMaskTexture::identifier) != std::string::npos)
+ {
+ std::unique_ptr newImpl = CGUIMouseEventMaskTexture::Create(spec);
+ if (newImpl)
+ {
+ m_Impl = std::move(newImpl);
+ m_Spec = spec;
+ return true;
+ }
+ else
+ LOGERROR("Could not create shape for: %s", spec);
+ }
+ else
+ LOGWARNING("Unknown clickable shape: %s", spec);
+ return false;
+}
Property changes on: ps/trunk/source/gui/SettingTypes/MouseEventMask.cpp
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: ps/trunk/source/gui/SettingTypes/MouseEventMask.h
===================================================================
--- ps/trunk/source/gui/SettingTypes/MouseEventMask.h (nonexistent)
+++ ps/trunk/source/gui/SettingTypes/MouseEventMask.h (revision 25408)
@@ -0,0 +1,65 @@
+/* Copyright (C) 2021 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#ifndef INCLUDED_GUI_MOUSE_EVENT_MASK
+#define INCLUDED_GUI_MOUSE_EVENT_MASK
+
+#include
+#include
+
+class CRect;
+class CVector2D;
+class IGUIObject;
+
+/**
+ * A custom shape that changes the object's "over-ability", and thus where one can click on it.
+ * Supported:
+ * - "texture:[path]" loads a texture and uses either the alpha or the red channel. Any non-0 is clickable.
+ * The texture is always 'stretched' in sprite terminology.
+ *
+ * TODO:
+ * - the minimap circular shape should be moved here.
+ */
+class CGUIMouseEventMask : public IGUISetting
+{
+public:
+ CGUIMouseEventMask(IGUIObject* owner);
+ ~CGUIMouseEventMask();
+
+ /**
+ * @return true if the mask is initialised <=> its spec is not ""
+ */
+ explicit operator bool() const { return !!m_Impl; }
+
+ /**
+ * @return true if the mouse pointer is over the mask. False if the mask is not initialised.
+ */
+ bool IsMouseOver(const CVector2D& mousePos, const CRect& objectSize) const;
+
+ void ToJSVal(const ScriptRequest& rq, JS::MutableHandleValue value) override;
+
+ class Impl;
+protected:
+ bool DoFromString(const CStrW& value) override;
+ bool DoFromJSVal(const ScriptRequest& rq, JS::HandleValue value) override;
+ CStr GetName() const override;
+
+ std::string m_Spec;
+ std::unique_ptr m_Impl;
+};
+
+#endif // INCLUDED_GUI_MOUSE_EVENT_MASK
Property changes on: ps/trunk/source/gui/SettingTypes/MouseEventMask.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property