Changeset View
Changeset View
Standalone View
Standalone View
source/gui/CGUI.cpp
Show First 20 Lines • Show All 122 Lines • ▼ Show 20 Lines | InReaction CGUI::HandleEvent(const SDL_Event_* ev) | ||||
{ | { | ||||
m_MousePos = CPos((float)ev->ev.button.x / g_GuiScale, (float)ev->ev.button.y / g_GuiScale); | m_MousePos = CPos((float)ev->ev.button.x / g_GuiScale, (float)ev->ev.button.y / g_GuiScale); | ||||
} | } | ||||
// Only one object can be hovered | // Only one object can be hovered | ||||
IGUIObject* pNearest = nullptr; | IGUIObject* pNearest = nullptr; | ||||
// TODO Gee: (2004-09-08) Big TODO, don't do the below if the SDL_Event is something like a keypress! | // TODO Gee: (2004-09-08) Big TODO, don't do the below if the SDL_Event is something like a keypress! | ||||
try | |||||
{ | { | ||||
PROFILE("mouse events"); | PROFILE("mouse events"); | ||||
// TODO Gee: Optimizations needed! | // TODO Gee: Optimizations needed! | ||||
// these two recursive function are quite overhead heavy. | // these two recursive function are quite overhead heavy. | ||||
// pNearest will after this point at the hovered object, possibly nullptr | // pNearest will after this point at the hovered object, possibly nullptr | ||||
pNearest = FindObjectUnderMouse(); | pNearest = FindObjectUnderMouse(); | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | else if (ev->ev.type == SDL_MOUSEBUTTONUP) | ||||
// 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)); | ||||
} | } | ||||
} | } | ||||
catch (PSERROR_GUI& e) | |||||
{ | |||||
UNUSED2(e); | |||||
debug_warn(L"CGUI::HandleEvent error"); | |||||
// TODO Gee: Handle | |||||
} | |||||
// 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) | ||||
{ | { | ||||
switch (ev->ev.button.button) | switch (ev->ev.button.button) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 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); | ||||
try | |||||
{ | |||||
m_BaseObject.RecurseObject(&IGUIObject::IsHidden, &IGUIObject::Draw); | m_BaseObject.RecurseObject(&IGUIObject::IsHidden, &IGUIObject::Draw); | ||||
} | } | ||||
catch (PSERROR_GUI& e) | |||||
{ | |||||
LOGERROR("GUI draw error: %s", e.what()); | |||||
} | |||||
} | |||||
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() | ||||
{ | { | ||||
// Update ALL cached | // Update ALL cached | ||||
m_BaseObject.RecurseObject(nullptr, &IGUIObject::UpdateCachedSize); | m_BaseObject.RecurseObject(nullptr, &IGUIObject::UpdateCachedSize); | ||||
} | } | ||||
void CGUI::AddObject(IGUIObject* pObject) | bool CGUI::AddObject(IGUIObject& parent, IGUIObject& child) | ||||
{ | { | ||||
try | if (child.m_Name.empty()) | ||||
{ | |||||
m_BaseObject.AddChild(pObject); | |||||
// Cache tree | |||||
pObject->RecurseObject(nullptr, &IGUIObject::UpdateCachedSize); | |||||
SGUIMessage msg(GUIM_LOAD); | |||||
pObject->RecurseObject(nullptr, &IGUIObject::HandleMessage, msg); | |||||
} | |||||
catch (PSERROR_GUI&) | |||||
{ | { | ||||
throw; | LOGERROR("Can't register object without name!"); | ||||
} | return false; | ||||
} | } | ||||
void CGUI::UpdateObjects() | if (m_pAllObjects.find(child.m_Name) != m_pAllObjects.end()) | ||||
{ | { | ||||
// We'll fill a temporary map until we know everything succeeded | LOGERROR("Can't register more than one object of the name %s", child.m_Name.c_str()); | ||||
map_pObjects AllObjects; | return false; | ||||
try | |||||
{ | |||||
// Fill freshly | |||||
m_BaseObject.RecurseObject(nullptr, &IGUIObject::AddToPointersMap, AllObjects); | |||||
} | |||||
catch (PSERROR_GUI&) | |||||
{ | |||||
throw; | |||||
} | } | ||||
// Else actually update the real one | m_pAllObjects[child.m_Name] = &child; | ||||
m_pAllObjects.swap(AllObjects); | parent.AddChild(child); | ||||
return true; | |||||
} | } | ||||
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 | ||||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
Paths.insert(Filename); | Paths.insert(Filename); | ||||
CXeromyces XeroFile; | CXeromyces XeroFile; | ||||
if (XeroFile.Load(g_VFS, Filename, "gui") != PSRETURN_OK) | if (XeroFile.Load(g_VFS, Filename, "gui") != PSRETURN_OK) | ||||
return; | return; | ||||
XMBElement node = XeroFile.GetRoot(); | XMBElement node = XeroFile.GetRoot(); | ||||
CStr root_name(XeroFile.GetElementString(node.GetNodeName())); | CStr root_name(XeroFile.GetElementString(node.GetNodeName())); | ||||
try | |||||
{ | |||||
if (root_name == "objects") | if (root_name == "objects") | ||||
Stan: Switch case ? | |||||
elexisAuthorUnsubmitted Done Inline ActionsSee https://en.cppreference.com/w/cpp/language/switch for the types supported. elexis: See https://en.cppreference.com/w/cpp/language/switch for the types supported.
| |||||
{ | |||||
Xeromyces_ReadRootObjects(node, &XeroFile, Paths); | Xeromyces_ReadRootObjects(node, &XeroFile, Paths); | ||||
// Re-cache all values so these gets cached too. | |||||
//UpdateResolution(); | |||||
} | |||||
else if (root_name == "sprites") | else if (root_name == "sprites") | ||||
Xeromyces_ReadRootSprites(node, &XeroFile); | Xeromyces_ReadRootSprites(node, &XeroFile); | ||||
else if (root_name == "styles") | else if (root_name == "styles") | ||||
Xeromyces_ReadRootStyles(node, &XeroFile); | Xeromyces_ReadRootStyles(node, &XeroFile); | ||||
else if (root_name == "setup") | else if (root_name == "setup") | ||||
Xeromyces_ReadRootSetup(node, &XeroFile); | Xeromyces_ReadRootSetup(node, &XeroFile); | ||||
else | else | ||||
debug_warn(L"CGUI::LoadXmlFile error"); | debug_warn(L"CGUI::LoadXmlFile error"); | ||||
} | |||||
catch (PSERROR_GUI& e) | // Cache tree | ||||
{ | m_BaseObject.RecurseObject(nullptr, &IGUIObject::UpdateCachedSize); | ||||
LOGERROR("Errors loading GUI file %s (%u)", Filename.string8(), e.getCode()); | |||||
return; | SGUIMessage msg(GUIM_LOAD); | ||||
} | m_BaseObject.RecurseObject(nullptr, &IGUIObject::HandleMessage, msg); | ||||
} | } | ||||
//=================================================================== | //=================================================================== | ||||
// XML Reading Xeromyces Specific Sub-Routines | // XML Reading Xeromyces Specific Sub-Routines | ||||
//=================================================================== | //=================================================================== | ||||
void CGUI::Xeromyces_ReadRootObjects(XMBElement Element, CXeromyces* pFile, boost::unordered_set<VfsPath>& Paths) | void CGUI::Xeromyces_ReadRootObjects(XMBElement Element, CXeromyces* pFile, boost::unordered_set<VfsPath>& Paths) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObject* pParent, std::vector<std::pair<CStr, CStr> >& NameSubst, boost::unordered_set<VfsPath>& Paths, u32 nesting_depth) | ||||
bool NameSet = false; | bool NameSet = false; | ||||
bool ManuallySetZ = false; | bool ManuallySetZ = false; | ||||
CStrW inclusionPath; | CStrW inclusionPath; | ||||
for (XMBAttribute attr : attributes) | for (XMBAttribute attr : attributes) | ||||
{ | { | ||||
// If value is "null", then it is equivalent as never being entered | // If value is "null", then it is equivalent as never being entered | ||||
if (CStr(attr.Value) == "null") | if (attr.Value == "null") | ||||
continue; | continue; | ||||
// Ignore "type" and "style", we've already checked it | // Ignore "type" and "style", we've already checked it | ||||
if (attr.Name == attr_type || attr.Name == attr_style) | if (attr.Name == attr_type || attr.Name == attr_style) | ||||
continue; | continue; | ||||
if (attr.Name == attr_name) | if (attr.Name == attr_name) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | else if (element_name == elmt_action) | ||||
// If there is a file, open it and use it as the code | // If there is a file, open it and use it as the code | ||||
if (!filename.empty()) | if (!filename.empty()) | ||||
{ | { | ||||
Paths.insert(filename); | Paths.insert(filename); | ||||
CVFSFile scriptfile; | CVFSFile scriptfile; | ||||
if (scriptfile.Load(g_VFS, filename) != PSRETURN_OK) | if (scriptfile.Load(g_VFS, filename) != PSRETURN_OK) | ||||
{ | { | ||||
LOGERROR("Error opening GUI script action file '%s'", utf8_from_wstring(filename)); | LOGERROR("Error opening GUI script action file '%s'", utf8_from_wstring(filename)); | ||||
throw PSERROR_GUI_JSOpenFailed(); | continue; | ||||
} | } | ||||
code = scriptfile.DecodeUTF8(); // assume it's UTF-8 | code = scriptfile.DecodeUTF8(); // assume it's UTF-8 | ||||
} | } | ||||
XMBElementList grandchildren = child.GetChildNodes(); | XMBElementList grandchildren = child.GetChildNodes(); | ||||
if (!grandchildren.empty()) // The <action> element contains <keep> and <translate> tags. | if (!grandchildren.empty()) // The <action> element contains <keep> and <translate> tags. | ||||
for (XMBElement grandchild : grandchildren) | for (XMBElement grandchild : grandchildren) | ||||
▲ Show 20 Lines • Show All 144 Lines • ▼ Show 20 Lines | if (object->m_Absolute) | ||||
// If the object is absolute, we'll have to get the parent's Z buffered, | // If the object is absolute, we'll have to get the parent's Z buffered, | ||||
// and add to that! | // and add to that! | ||||
object->SetSetting<float>("z", pParent->GetBufferedZ() + 10.f, false); | object->SetSetting<float>("z", pParent->GetBufferedZ() + 10.f, false); | ||||
else | else | ||||
// If the object is relative, then we'll just store Z as "10" | // If the object is relative, then we'll just store Z as "10" | ||||
object->SetSetting<float>("z", 10.f, false); | object->SetSetting<float>("z", 10.f, false); | ||||
} | } | ||||
try | if (!AddObject(*pParent, *object)) | ||||
{ | delete object; | ||||
if (pParent == &m_BaseObject) | |||||
AddObject(object); | |||||
else | |||||
pParent->AddChild(object); | |||||
} | |||||
catch (PSERROR_GUI& e) | |||||
{ | |||||
LOGERROR("GUI error: %s", e.what()); | |||||
} | |||||
} | } | ||||
void CGUI::Xeromyces_ReadRepeat(XMBElement Element, CXeromyces* pFile, IGUIObject* pParent, std::vector<std::pair<CStr, CStr> >& NameSubst, boost::unordered_set<VfsPath>& Paths, u32 nesting_depth) | void CGUI::Xeromyces_ReadRepeat(XMBElement Element, CXeromyces* pFile, IGUIObject* pParent, std::vector<std::pair<CStr, CStr> >& NameSubst, boost::unordered_set<VfsPath>& Paths, u32 nesting_depth) | ||||
{ | { | ||||
#define ELMT(x) int elmt_##x = pFile->GetElementID(#x) | #define ELMT(x) int elmt_##x = pFile->GetElementID(#x) | ||||
#define ATTR(x) int attr_##x = pFile->GetAttributeID(#x) | #define ATTR(x) int attr_##x = pFile->GetAttributeID(#x) | ||||
ELMT(object); | ELMT(object); | ||||
ATTR(count); | ATTR(count); | ||||
▲ Show 20 Lines • Show All 406 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); | ||||
} | } | ||||
AddObject(object); | if (!AddObject(m_BaseObject, *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")); | ||||
// Try parsing value | // Try parsing value | ||||
Show All 16 Lines |
Wildfire Games · Phabricator
Switch case ?