Changeset View
Changeset View
Standalone View
Standalone View
source/gui/CGUI.cpp
Show All 14 Lines | |||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. | * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. | ||||
*/ | */ | ||||
#include "precompiled.h" | #include "precompiled.h" | ||||
#include "CGUI.h" | #include "CGUI.h" | ||||
#include "gui/IGUIScrollBar.h" | #include "gui/IGUIScrollBar.h" | ||||
#include "gui/ObjectTypes/CGUIDummyObject.h" | |||||
#include "gui/ObjectTypes/CTooltip.h" | #include "gui/ObjectTypes/CTooltip.h" | ||||
#include "gui/Scripting/ScriptFunctions.h" | #include "gui/Scripting/ScriptFunctions.h" | ||||
#include "i18n/L10n.h" | #include "i18n/L10n.h" | ||||
#include "lib/bits.h" | #include "lib/bits.h" | ||||
#include "lib/input.h" | #include "lib/input.h" | ||||
#include "lib/sysdep/sysdep.h" | #include "lib/sysdep/sysdep.h" | ||||
#include "lib/timer.h" | #include "lib/timer.h" | ||||
#include "lib/utf8.h" | #include "lib/utf8.h" | ||||
Show All 27 Lines | |||||
const CStr CGUI::EventNameMouseWheelDown = "MouseWheelDown"; | const CStr CGUI::EventNameMouseWheelDown = "MouseWheelDown"; | ||||
const CStr CGUI::EventNameMouseWheelUp = "MouseWheelUp"; | const CStr CGUI::EventNameMouseWheelUp = "MouseWheelUp"; | ||||
const CStr CGUI::EventNameMouseLeftDoubleClick = "MouseLeftDoubleClick"; | const CStr CGUI::EventNameMouseLeftDoubleClick = "MouseLeftDoubleClick"; | ||||
const CStr CGUI::EventNameMouseLeftRelease = "MouseLeftRelease"; | const CStr CGUI::EventNameMouseLeftRelease = "MouseLeftRelease"; | ||||
const CStr CGUI::EventNameMouseRightDoubleClick = "MouseRightDoubleClick"; | const CStr CGUI::EventNameMouseRightDoubleClick = "MouseRightDoubleClick"; | ||||
const CStr CGUI::EventNameMouseRightRelease = "MouseRightRelease"; | const CStr CGUI::EventNameMouseRightRelease = "MouseRightRelease"; | ||||
CGUI::CGUI(const shared_ptr<ScriptContext>& context) | CGUI::CGUI(const shared_ptr<ScriptContext>& context) | ||||
: m_BaseObject(*this), | : m_BaseObject(new CGUIDummyObject(*this)), | ||||
m_FocusedObject(nullptr), | m_FocusedObject(nullptr), | ||||
m_InternalNameNumber(0), | m_InternalNameNumber(0), | ||||
m_MouseButtons(0) | m_MouseButtons(0) | ||||
{ | { | ||||
m_ScriptInterface.reset(new ScriptInterface("Engine", "GUIPage", context)); | m_ScriptInterface.reset(new ScriptInterface("Engine", "GUIPage", context)); | ||||
m_ScriptInterface->SetCallbackData(this); | m_ScriptInterface->SetCallbackData(this); | ||||
GuiScriptingInit(*m_ScriptInterface); | GuiScriptingInit(*m_ScriptInterface); | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | InReaction CGUI::HandleEvent(const SDL_Event_* ev) | ||||
else if (ev->ev.type == SDL_MOUSEMOTION) | else if (ev->ev.type == SDL_MOUSEMOTION) | ||||
{ | { | ||||
// Yes the mouse position is stored as float to avoid | // Yes the mouse position is stored as float to avoid | ||||
// constant conversions when operating in a | // constant conversions when operating in a | ||||
// float-based environment. | // float-based environment. | ||||
m_MousePos = CPos((float)ev->ev.motion.x / g_GuiScale, (float)ev->ev.motion.y / g_GuiScale); | m_MousePos = CPos((float)ev->ev.motion.x / g_GuiScale, (float)ev->ev.motion.y / g_GuiScale); | ||||
SGUIMessage msg(GUIM_MOUSE_MOTION); | SGUIMessage msg(GUIM_MOUSE_MOTION); | ||||
m_BaseObject.RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::HandleMessage, msg); | m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::HandleMessage, msg); | ||||
} | } | ||||
// Update m_MouseButtons. (BUTTONUP is handled later.) | // Update m_MouseButtons. (BUTTONUP is handled later.) | ||||
else if (ev->ev.type == SDL_MOUSEBUTTONDOWN) | else if (ev->ev.type == SDL_MOUSEBUTTONDOWN) | ||||
{ | { | ||||
switch (ev->ev.button.button) | switch (ev->ev.button.button) | ||||
{ | { | ||||
case SDL_BUTTON_LEFT: | case SDL_BUTTON_LEFT: | ||||
Show All 21 Lines | InReaction CGUI::HandleEvent(const SDL_Event_* ev) | ||||
// pNearest will after this point at the hovered object, possibly nullptr | // pNearest will after this point at the hovered object, possibly nullptr | ||||
IGUIObject* pNearest = FindObjectUnderMouse(); | IGUIObject* pNearest = FindObjectUnderMouse(); | ||||
if (ret == IN_PASS) | if (ret == IN_PASS) | ||||
{ | { | ||||
// Now we'll call UpdateMouseOver on *all* objects, | // Now we'll call UpdateMouseOver on *all* objects, | ||||
// we'll input the one hovered, and they will each | // we'll input the one hovered, and they will each | ||||
// update their own data and send messages accordingly | // update their own data and send messages accordingly | ||||
m_BaseObject.RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::UpdateMouseOver, static_cast<IGUIObject* const&>(pNearest)); | m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::UpdateMouseOver, static_cast<IGUIObject* const&>(pNearest)); | ||||
Stan: You said you had something to go back to value types | |||||
Done Inline ActionsI think I elected to not do that (yet?) after all. There are other cases of those owning unique_ptr (in the pathfinder), and I think we need a wrapping type. I _could_ use a reference, but then I'd have to manually delete the pointer & it must be initialised in the constructor init-list. It's probably better to create a custom wrapper, in a separate diff. wraitii: I think I elected to not do that (yet?) after all. There are other cases of those owning… | |||||
if (ev->ev.type == SDL_MOUSEBUTTONDOWN) | if (ev->ev.type == SDL_MOUSEBUTTONDOWN) | ||||
{ | { | ||||
switch (ev->ev.button.button) | switch (ev->ev.button.button) | ||||
{ | { | ||||
case SDL_BUTTON_LEFT: | case SDL_BUTTON_LEFT: | ||||
// Focus the clicked object (or focus none if nothing clicked on) | // Focus the clicked object (or focus none if nothing clicked on) | ||||
SetFocusedObject(pNearest); | SetFocusedObject(pNearest); | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | else if (ev->ev.type == SDL_MOUSEBUTTONUP) | ||||
ret = pNearest->SendMouseEvent(GUIM_MOUSE_DBLCLICK_RIGHT, EventNameMouseRightDoubleClick); | ret = pNearest->SendMouseEvent(GUIM_MOUSE_DBLCLICK_RIGHT, EventNameMouseRightDoubleClick); | ||||
else | else | ||||
ret = pNearest->SendMouseEvent(GUIM_MOUSE_RELEASE_RIGHT, EventNameMouseRightRelease); | ret = pNearest->SendMouseEvent(GUIM_MOUSE_RELEASE_RIGHT, EventNameMouseRightRelease); | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
// Reset all states on all visible objects | // Reset all states on all visible objects | ||||
m_BaseObject.RecurseObject(&IGUIObject::IsHidden, &IGUIObject::ResetStates); | m_BaseObject->RecurseObject(&IGUIObject::IsHidden, &IGUIObject::ResetStates); | ||||
// Since the hover state will have been reset, we reload it. | // Since the hover state will have been reset, we reload it. | ||||
m_BaseObject.RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::UpdateMouseOver, static_cast<IGUIObject* const&>(pNearest)); | m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::UpdateMouseOver, static_cast<IGUIObject* const&>(pNearest)); | ||||
} | } | ||||
} | } | ||||
// BUTTONUP's effect on m_MouseButtons is handled after | // BUTTONUP's effect on m_MouseButtons is handled after | ||||
// everything else, so that e.g. 'press' handlers (activated | // everything else, so that e.g. 'press' handlers (activated | ||||
// on button up) see which mouse button had been pressed. | // on button up) see which mouse button had been pressed. | ||||
if (ev->ev.type == SDL_MOUSEBUTTONUP) | if (ev->ev.type == SDL_MOUSEBUTTONUP) | ||||
{ | { | ||||
Show All 23 Lines | if (ret == IN_PASS && GetFocusedObject()) | ||||
// else will return IN_PASS because we never used the button. | // else will return IN_PASS because we never used the button. | ||||
} | } | ||||
return ret; | return ret; | ||||
} | } | ||||
void CGUI::TickObjects() | void CGUI::TickObjects() | ||||
{ | { | ||||
m_BaseObject.RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::Tick); | m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::Tick); | ||||
SendEventToAll(EventNameTick); | SendEventToAll(EventNameTick); | ||||
m_Tooltip.Update(FindObjectUnderMouse(), m_MousePos, *this); | m_Tooltip.Update(FindObjectUnderMouse(), m_MousePos, *this); | ||||
} | } | ||||
void CGUI::SendEventToAll(const CStr& eventName) | void CGUI::SendEventToAll(const CStr& eventName) | ||||
{ | { | ||||
auto it = m_EventIGUIObjects.find(eventName); | auto it = m_EventIGUIObjects.find(eventName); | ||||
if (it == m_EventIGUIObjects.end()) | if (it == m_EventIGUIObjects.end()) | ||||
Show All 16 Lines | |||||
} | } | ||||
void CGUI::Draw() | void CGUI::Draw() | ||||
{ | { | ||||
// Clear the depth buffer, so the GUI is | // Clear the depth buffer, so the GUI is | ||||
// drawn on top of everything else | // drawn on top of everything else | ||||
glClear(GL_DEPTH_BUFFER_BIT); | glClear(GL_DEPTH_BUFFER_BIT); | ||||
m_BaseObject.RecurseObject(&IGUIObject::IsHidden, &IGUIObject::Draw); | m_BaseObject->RecurseObject(&IGUIObject::IsHidden, &IGUIObject::Draw); | ||||
} | } | ||||
void CGUI::DrawSprite(const CGUISpriteInstance& Sprite, int CellID, const float& Z, const CRect& Rect, const CRect& UNUSED(Clipping)) | void CGUI::DrawSprite(const CGUISpriteInstance& Sprite, int CellID, const float& Z, const CRect& Rect, const CRect& UNUSED(Clipping)) | ||||
{ | { | ||||
// If the sprite doesn't exist (name == ""), don't bother drawing anything | // If the sprite doesn't exist (name == ""), don't bother drawing anything | ||||
if (!Sprite) | if (!Sprite) | ||||
return; | return; | ||||
// TODO: Clipping? | // TODO: Clipping? | ||||
Sprite.Draw(*this, Rect, CellID, m_Sprites, Z); | Sprite.Draw(*this, Rect, CellID, m_Sprites, Z); | ||||
} | } | ||||
void CGUI::UpdateResolution() | void CGUI::UpdateResolution() | ||||
{ | { | ||||
m_BaseObject.RecurseObject(nullptr, &IGUIObject::UpdateCachedSize); | m_BaseObject->RecurseObject(nullptr, &IGUIObject::UpdateCachedSize); | ||||
} | } | ||||
IGUIObject* CGUI::ConstructObject(const CStr& str) | IGUIObject* CGUI::ConstructObject(const CStr& str) | ||||
{ | { | ||||
std::map<CStr, ConstructObjectFunction>::iterator it = m_ObjectTypes.find(str); | std::map<CStr, ConstructObjectFunction>::iterator it = m_ObjectTypes.find(str); | ||||
if (it == m_ObjectTypes.end()) | if (it == m_ObjectTypes.end()) | ||||
return nullptr; | return nullptr; | ||||
Show All 15 Lines | if (m_pAllObjects.find(child.m_Name) != m_pAllObjects.end()) | ||||
return false; | return false; | ||||
} | } | ||||
m_pAllObjects[child.m_Name] = &child; | m_pAllObjects[child.m_Name] = &child; | ||||
parent.AddChild(child); | parent.AddChild(child); | ||||
return true; | return true; | ||||
} | } | ||||
IGUIObject* CGUI::GetBaseObject() | |||||
{ | |||||
return m_BaseObject.get(); | |||||
}; | |||||
bool CGUI::ObjectExists(const CStr& Name) const | bool CGUI::ObjectExists(const CStr& Name) const | ||||
{ | { | ||||
return m_pAllObjects.find(Name) != m_pAllObjects.end(); | return m_pAllObjects.find(Name) != m_pAllObjects.end(); | ||||
} | } | ||||
IGUIObject* CGUI::FindObjectByName(const CStr& Name) const | IGUIObject* CGUI::FindObjectByName(const CStr& Name) const | ||||
{ | { | ||||
map_pObjects::const_iterator it = m_pAllObjects.find(Name); | map_pObjects::const_iterator it = m_pAllObjects.find(Name); | ||||
if (it == m_pAllObjects.end()) | if (it == m_pAllObjects.end()) | ||||
return nullptr; | return nullptr; | ||||
return it->second; | return it->second; | ||||
} | } | ||||
IGUIObject* CGUI::FindObjectUnderMouse() | IGUIObject* CGUI::FindObjectUnderMouse() | ||||
{ | { | ||||
IGUIObject* pNearest = nullptr; | IGUIObject* pNearest = nullptr; | ||||
m_BaseObject.RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::ChooseMouseOverAndClosest, pNearest); | m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::ChooseMouseOverAndClosest, pNearest); | ||||
return pNearest; | return pNearest; | ||||
} | } | ||||
void CGUI::SetFocusedObject(IGUIObject* pObject) | void CGUI::SetFocusedObject(IGUIObject* pObject) | ||||
{ | { | ||||
if (pObject == m_FocusedObject) | if (pObject == m_FocusedObject) | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | void CGUI::LoadXmlFile(const VfsPath& Filename, std::unordered_set<VfsPath>& Paths) | ||||
else if (root_name == "setup") | else if (root_name == "setup") | ||||
Xeromyces_ReadRootSetup(node, &XeroFile); | Xeromyces_ReadRootSetup(node, &XeroFile); | ||||
else | else | ||||
LOGERROR("CGUI::LoadXmlFile encountered an unknown XML root node type: %s", root_name.c_str()); | LOGERROR("CGUI::LoadXmlFile encountered an unknown XML root node type: %s", root_name.c_str()); | ||||
} | } | ||||
void CGUI::LoadedXmlFiles() | void CGUI::LoadedXmlFiles() | ||||
{ | { | ||||
m_BaseObject.RecurseObject(nullptr, &IGUIObject::UpdateCachedSize); | m_BaseObject->RecurseObject(nullptr, &IGUIObject::UpdateCachedSize); | ||||
SGUIMessage msg(GUIM_LOAD); | SGUIMessage msg(GUIM_LOAD); | ||||
m_BaseObject.RecurseObject(nullptr, &IGUIObject::HandleMessage, msg); | m_BaseObject->RecurseObject(nullptr, &IGUIObject::HandleMessage, msg); | ||||
SendEventToAll(EventNameLoad); | SendEventToAll(EventNameLoad); | ||||
} | } | ||||
//=================================================================== | //=================================================================== | ||||
// XML Reading Xeromyces Specific Sub-Routines | // XML Reading Xeromyces Specific Sub-Routines | ||||
//=================================================================== | //=================================================================== | ||||
void CGUI::Xeromyces_ReadRootObjects(XMBElement Element, CXeromyces* pFile, std::unordered_set<VfsPath>& Paths) | void CGUI::Xeromyces_ReadRootObjects(XMBElement Element, CXeromyces* pFile, std::unordered_set<VfsPath>& Paths) | ||||
{ | { | ||||
int el_script = pFile->GetElementID("script"); | int el_script = pFile->GetElementID("script"); | ||||
std::vector<std::pair<CStr, CStr> > subst; | std::vector<std::pair<CStr, CStr> > subst; | ||||
// Iterate main children | // Iterate main children | ||||
// they should all be <object> or <script> elements | // they should all be <object> or <script> elements | ||||
for (XMBElement child : Element.GetChildNodes()) | for (XMBElement child : Element.GetChildNodes()) | ||||
{ | { | ||||
if (child.GetNodeName() == el_script) | if (child.GetNodeName() == el_script) | ||||
// Execute the inline script | // Execute the inline script | ||||
Xeromyces_ReadScript(child, pFile, Paths); | Xeromyces_ReadScript(child, pFile, Paths); | ||||
else | else | ||||
// Read in this whole object into the GUI | // Read in this whole object into the GUI | ||||
Xeromyces_ReadObject(child, pFile, &m_BaseObject, subst, Paths, 0); | Xeromyces_ReadObject(child, pFile, m_BaseObject.get(), subst, Paths, 0); | ||||
} | } | ||||
} | } | ||||
void CGUI::Xeromyces_ReadRootSprites(XMBElement Element, CXeromyces* pFile) | void CGUI::Xeromyces_ReadRootSprites(XMBElement Element, CXeromyces* pFile) | ||||
{ | { | ||||
for (XMBElement child : Element.GetChildNodes()) | for (XMBElement child : Element.GetChildNodes()) | ||||
Xeromyces_ReadSprite(child, pFile); | Xeromyces_ReadSprite(child, pFile); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 728 Lines • ▼ Show 20 Lines | for (XMBAttribute attr : Element.GetAttributes()) | ||||
CStr attr_value(attr.Value); | CStr attr_value(attr.Value); | ||||
if (attr_name == "name") | if (attr_name == "name") | ||||
object->SetName("__tooltip_" + attr_value); | object->SetName("__tooltip_" + attr_value); | ||||
else | else | ||||
object->SetSettingFromString(attr_name, attr_value.FromUTF8(), true); | object->SetSettingFromString(attr_name, attr_value.FromUTF8(), true); | ||||
} | } | ||||
if (!AddObject(m_BaseObject, *object)) | if (!AddObject(*m_BaseObject, *object)) | ||||
delete object; | delete object; | ||||
} | } | ||||
void CGUI::Xeromyces_ReadColor(XMBElement Element, CXeromyces* pFile) | void CGUI::Xeromyces_ReadColor(XMBElement Element, CXeromyces* pFile) | ||||
{ | { | ||||
XMBAttributeList attributes = Element.GetAttributes(); | XMBAttributeList attributes = Element.GetAttributes(); | ||||
CStr name = attributes.GetNamedItem(pFile->GetAttributeID("name")); | CStr name = attributes.GetNamedItem(pFile->GetAttributeID("name")); | ||||
Show All 17 Lines |
Wildfire Games · Phabricator
You said you had something to go back to value types