mirror of
https://github.com/edubart/otclient.git
synced 2025-11-05 21:16:24 +01:00
Minimap, hotkeys and lot of other changes
* Begin working on a new layout system for UIMinimap and later UIMap, this new layout system allows to add widgets to the minimap * Add option to disable motd * Rework hotkey binding * Lots of fixes in hotkeys manager * Add fullmap view using Ctrl+Shift+M * Prevent some crashs in ThingType draw * Add function to load minimap from PNG files * Fixes in minimap saving * Fixes in Tile::isClickable * Add UIMapAnchorLayout, new layout for maps * Fix freezes in win32 when pressing alt key
This commit is contained in:
@@ -33,6 +33,8 @@ class UIBoxLayout;
|
||||
class UIHorizontalLayout;
|
||||
class UIVerticalLayout;
|
||||
class UIGridLayout;
|
||||
class UIAnchor;
|
||||
class UIAnchorGroup;
|
||||
class UIAnchorLayout;
|
||||
class UIParticles;
|
||||
|
||||
@@ -44,8 +46,11 @@ typedef stdext::shared_object_ptr<UIBoxLayout> UIBoxLayoutPtr;
|
||||
typedef stdext::shared_object_ptr<UIHorizontalLayout> UIHorizontalLayoutPtr;
|
||||
typedef stdext::shared_object_ptr<UIVerticalLayout> UIVerticalLayoutPtr;
|
||||
typedef stdext::shared_object_ptr<UIGridLayout> UIGridLayoutPtr;
|
||||
typedef stdext::shared_object_ptr<UIAnchor> UIAnchorPtr;
|
||||
typedef stdext::shared_object_ptr<UIAnchorGroup> UIAnchorGroupPtr;
|
||||
typedef stdext::shared_object_ptr<UIAnchorLayout> UIAnchorLayoutPtr;
|
||||
|
||||
typedef std::deque<UIWidgetPtr> UIWidgetList;
|
||||
typedef std::vector<UIAnchorPtr> UIAnchorList;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,11 +23,81 @@
|
||||
#include "uianchorlayout.h"
|
||||
#include "uiwidget.h"
|
||||
|
||||
void UIAnchorGroup::addAnchor(const UIAnchor& anchor)
|
||||
UIWidgetPtr UIAnchor::getHookedWidget(const UIWidgetPtr& widget, const UIWidgetPtr& parentWidget)
|
||||
{
|
||||
// determine hooked widget
|
||||
UIWidgetPtr hookedWidget;
|
||||
if(parentWidget) {
|
||||
if(m_hookedWidgetId == "parent")
|
||||
hookedWidget = parentWidget;
|
||||
else if(m_hookedWidgetId == "next")
|
||||
hookedWidget = parentWidget->getChildAfter(widget);
|
||||
else if(m_hookedWidgetId == "prev")
|
||||
hookedWidget = parentWidget->getChildBefore(widget);
|
||||
else
|
||||
hookedWidget = parentWidget->getChildById(m_hookedWidgetId);
|
||||
}
|
||||
return hookedWidget;
|
||||
}
|
||||
|
||||
int UIAnchor::getHookedPoint(const UIWidgetPtr& hookedWidget, const UIWidgetPtr& parentWidget)
|
||||
{
|
||||
// determine hooked widget edge point
|
||||
Rect hookedWidgetRect = hookedWidget->getRect();
|
||||
if(hookedWidget == parentWidget)
|
||||
hookedWidgetRect = parentWidget->getPaddingRect();
|
||||
|
||||
int point = 0;
|
||||
switch(m_hookedEdge) {
|
||||
case Fw::AnchorLeft:
|
||||
point = hookedWidgetRect.left();
|
||||
break;
|
||||
case Fw::AnchorRight:
|
||||
point = hookedWidgetRect.right();
|
||||
break;
|
||||
case Fw::AnchorTop:
|
||||
point = hookedWidgetRect.top();
|
||||
break;
|
||||
case Fw::AnchorBottom:
|
||||
point = hookedWidgetRect.bottom();
|
||||
break;
|
||||
case Fw::AnchorHorizontalCenter:
|
||||
point = hookedWidgetRect.horizontalCenter();
|
||||
break;
|
||||
case Fw::AnchorVerticalCenter:
|
||||
point = hookedWidgetRect.verticalCenter();
|
||||
break;
|
||||
default:
|
||||
// must never happens
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if(hookedWidget == parentWidget) {
|
||||
switch(m_hookedEdge) {
|
||||
case Fw::AnchorLeft:
|
||||
case Fw::AnchorRight:
|
||||
case Fw::AnchorHorizontalCenter:
|
||||
point -= parentWidget->getVirtualOffset().x;
|
||||
break;
|
||||
case Fw::AnchorBottom:
|
||||
case Fw::AnchorTop:
|
||||
case Fw::AnchorVerticalCenter:
|
||||
point -= parentWidget->getVirtualOffset().y;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
void UIAnchorGroup::addAnchor(const UIAnchorPtr& anchor)
|
||||
{
|
||||
// duplicated anchors must be replaced
|
||||
for(UIAnchor& other : m_anchors) {
|
||||
if(other.getAnchoredEdge() == anchor.getAnchoredEdge()) {
|
||||
for(UIAnchorPtr& other : m_anchors) {
|
||||
if(other->getAnchoredEdge() == anchor->getAnchoredEdge()) {
|
||||
other = anchor;
|
||||
return;
|
||||
}
|
||||
@@ -43,9 +113,12 @@ void UIAnchorLayout::addAnchor(const UIWidgetPtr& anchoredWidget, Fw::AnchorEdge
|
||||
|
||||
assert(anchoredWidget != getParentWidget());
|
||||
|
||||
UIAnchor anchor(anchoredEdge, hookedWidgetId, hookedEdge);
|
||||
UIAnchorGroup& anchorGroup = m_anchorsGroups[anchoredWidget];
|
||||
anchorGroup.addAnchor(anchor);
|
||||
UIAnchorPtr anchor(new UIAnchor(anchoredEdge, hookedWidgetId, hookedEdge));
|
||||
UIAnchorGroupPtr& anchorGroup = m_anchorsGroups[anchoredWidget];
|
||||
if(!anchorGroup)
|
||||
anchorGroup = UIAnchorGroupPtr(new UIAnchorGroup);
|
||||
|
||||
anchorGroup->addAnchor(anchor);
|
||||
|
||||
// layout must be updated because a new anchor got in
|
||||
update();
|
||||
@@ -86,7 +159,7 @@ void UIAnchorLayout::removeWidget(const UIWidgetPtr& widget)
|
||||
removeAnchors(widget);
|
||||
}
|
||||
|
||||
bool UIAnchorLayout::updateWidget(const UIWidgetPtr& widget, UIAnchorGroup& anchorGroup, UIWidgetPtr first)
|
||||
bool UIAnchorLayout::updateWidget(const UIWidgetPtr& widget, const UIAnchorGroupPtr& anchorGroup, UIWidgetPtr first)
|
||||
{
|
||||
UIWidgetPtr parentWidget = getParentWidget();
|
||||
if(!parentWidget)
|
||||
@@ -105,23 +178,13 @@ bool UIAnchorLayout::updateWidget(const UIWidgetPtr& widget, UIAnchorGroup& anch
|
||||
bool horizontalMoved = false;
|
||||
|
||||
// calculates new rect based on anchors
|
||||
for(const UIAnchor& anchor : anchorGroup.getAnchors()) {
|
||||
for(const UIAnchorPtr& anchor : anchorGroup->getAnchors()) {
|
||||
// skip invalid anchors
|
||||
if(anchor.getHookedEdge() == Fw::AnchorNone)
|
||||
if(anchor->getHookedEdge() == Fw::AnchorNone)
|
||||
continue;
|
||||
|
||||
// determine hooked widget
|
||||
UIWidgetPtr hookedWidget;
|
||||
if(parentWidget) {
|
||||
if(anchor.getHookedWidgetId() == "parent")
|
||||
hookedWidget = parentWidget;
|
||||
else if(anchor.getHookedWidgetId() == "next")
|
||||
hookedWidget = parentWidget->getChildAfter(widget);
|
||||
else if(anchor.getHookedWidgetId() == "prev")
|
||||
hookedWidget = parentWidget->getChildBefore(widget);
|
||||
else
|
||||
hookedWidget = parentWidget->getChildById(anchor.getHookedWidgetId());
|
||||
}
|
||||
UIWidgetPtr hookedWidget = anchor->getHookedWidget(widget, parentWidget);
|
||||
|
||||
// skip invalid anchors
|
||||
if(!hookedWidget)
|
||||
@@ -131,61 +194,15 @@ bool UIAnchorLayout::updateWidget(const UIWidgetPtr& widget, UIAnchorGroup& anch
|
||||
// update this hooked widget anchors
|
||||
auto it = m_anchorsGroups.find(hookedWidget);
|
||||
if(it != m_anchorsGroups.end()) {
|
||||
UIAnchorGroup& hookedAnchorGroup = it->second;
|
||||
if(!hookedAnchorGroup.isUpdated())
|
||||
const UIAnchorGroupPtr& hookedAnchorGroup = it->second;
|
||||
if(!hookedAnchorGroup->isUpdated())
|
||||
updateWidget(hookedWidget, hookedAnchorGroup, first);
|
||||
}
|
||||
}
|
||||
|
||||
// determine hooked widget edge point
|
||||
Rect hookedWidgetRect = hookedWidget->getRect();
|
||||
if(hookedWidget == parentWidget)
|
||||
hookedWidgetRect = parentWidget->getPaddingRect();
|
||||
int point = anchor->getHookedPoint(hookedWidget, parentWidget);
|
||||
|
||||
int point = 0;
|
||||
switch(anchor.getHookedEdge()) {
|
||||
case Fw::AnchorLeft:
|
||||
point = hookedWidgetRect.left();
|
||||
break;
|
||||
case Fw::AnchorRight:
|
||||
point = hookedWidgetRect.right();
|
||||
break;
|
||||
case Fw::AnchorTop:
|
||||
point = hookedWidgetRect.top();
|
||||
break;
|
||||
case Fw::AnchorBottom:
|
||||
point = hookedWidgetRect.bottom();
|
||||
break;
|
||||
case Fw::AnchorHorizontalCenter:
|
||||
point = hookedWidgetRect.horizontalCenter();
|
||||
break;
|
||||
case Fw::AnchorVerticalCenter:
|
||||
point = hookedWidgetRect.verticalCenter();
|
||||
break;
|
||||
default:
|
||||
// must never happens
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if(hookedWidget == parentWidget) {
|
||||
switch(anchor.getHookedEdge()) {
|
||||
case Fw::AnchorLeft:
|
||||
case Fw::AnchorRight:
|
||||
case Fw::AnchorHorizontalCenter:
|
||||
point -= parentWidget->getVirtualOffset().x;
|
||||
break;
|
||||
case Fw::AnchorBottom:
|
||||
case Fw::AnchorTop:
|
||||
case Fw::AnchorVerticalCenter:
|
||||
point -= parentWidget->getVirtualOffset().y;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch(anchor.getAnchoredEdge()) {
|
||||
switch(anchor->getAnchoredEdge()) {
|
||||
case Fw::AnchorHorizontalCenter:
|
||||
newRect.moveHorizontalCenter(point + widget->getMarginLeft() - widget->getMarginRight());
|
||||
horizontalMoved = true;
|
||||
@@ -230,7 +247,7 @@ bool UIAnchorLayout::updateWidget(const UIWidgetPtr& widget, UIAnchorGroup& anch
|
||||
bool changed = false;
|
||||
if(widget->setRect(newRect))
|
||||
changed = true;
|
||||
anchorGroup.setUpdated(true);
|
||||
anchorGroup->setUpdated(true);
|
||||
return changed;
|
||||
}
|
||||
|
||||
@@ -240,15 +257,15 @@ bool UIAnchorLayout::internalUpdate()
|
||||
|
||||
// reset all anchors groups update state
|
||||
for(auto& it : m_anchorsGroups) {
|
||||
UIAnchorGroup& anchorGroup = it.second;
|
||||
anchorGroup.setUpdated(false);
|
||||
const UIAnchorGroupPtr& anchorGroup = it.second;
|
||||
anchorGroup->setUpdated(false);
|
||||
}
|
||||
|
||||
// update all anchors
|
||||
for(auto& it : m_anchorsGroups) {
|
||||
const UIWidgetPtr& widget = it.first;
|
||||
UIAnchorGroup& anchorGroup = it.second;
|
||||
if(!anchorGroup.isUpdated()) {
|
||||
const UIAnchorGroupPtr& anchorGroup = it.second;
|
||||
if(!anchorGroup->isUpdated()) {
|
||||
if(updateWidget(widget, anchorGroup))
|
||||
changed = true;
|
||||
}
|
||||
|
||||
@@ -25,30 +25,30 @@
|
||||
|
||||
#include "uilayout.h"
|
||||
|
||||
class UIAnchor
|
||||
class UIAnchor : public stdext::shared_object
|
||||
{
|
||||
public:
|
||||
UIAnchor(Fw::AnchorEdge anchoredEdge, const std::string& hookedWidgetId, Fw::AnchorEdge hookedEdge) :
|
||||
m_anchoredEdge(anchoredEdge), m_hookedEdge(hookedEdge), m_hookedWidgetId(hookedWidgetId) { }
|
||||
|
||||
Fw::AnchorEdge getAnchoredEdge() const { return m_anchoredEdge; }
|
||||
std::string getHookedWidgetId() const { return m_hookedWidgetId; }
|
||||
Fw::AnchorEdge getHookedEdge() const { return m_hookedEdge; }
|
||||
|
||||
private:
|
||||
virtual UIWidgetPtr getHookedWidget(const UIWidgetPtr& widget, const UIWidgetPtr& parentWidget);
|
||||
virtual int getHookedPoint(const UIWidgetPtr& hookedWidget, const UIWidgetPtr& parentWidget);
|
||||
|
||||
protected:
|
||||
Fw::AnchorEdge m_anchoredEdge;
|
||||
Fw::AnchorEdge m_hookedEdge;
|
||||
std::string m_hookedWidgetId;
|
||||
};
|
||||
|
||||
typedef std::vector<UIAnchor> UIAnchorList;
|
||||
|
||||
class UIAnchorGroup
|
||||
class UIAnchorGroup : public stdext::shared_object
|
||||
{
|
||||
public:
|
||||
UIAnchorGroup() : m_updated(true) { }
|
||||
|
||||
void addAnchor(const UIAnchor& anchor);
|
||||
void addAnchor(const UIAnchorPtr& anchor);
|
||||
const UIAnchorList& getAnchors() { return m_anchors; }
|
||||
bool isUpdated() { return m_updated; }
|
||||
void setUpdated(bool updated) { m_updated = updated; }
|
||||
@@ -77,11 +77,9 @@ public:
|
||||
bool isUIAnchorLayout() { return true; }
|
||||
|
||||
protected:
|
||||
bool internalUpdate();
|
||||
|
||||
private:
|
||||
bool updateWidget(const UIWidgetPtr& widget, UIAnchorGroup& anchorGroup, UIWidgetPtr first = nullptr);
|
||||
std::unordered_map<UIWidgetPtr, UIAnchorGroup> m_anchorsGroups;
|
||||
virtual bool internalUpdate();
|
||||
virtual bool updateWidget(const UIWidgetPtr& widget, const UIAnchorGroupPtr& anchorGroup, UIWidgetPtr first = nullptr);
|
||||
std::unordered_map<UIWidgetPtr, UIAnchorGroupPtr> m_anchorsGroups;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <framework/platform/platformwindow.h>
|
||||
#include <framework/graphics/texturemanager.h>
|
||||
#include <framework/core/application.h>
|
||||
#include <framework/luaengine/luainterface.h>
|
||||
|
||||
UIWidget::UIWidget()
|
||||
{
|
||||
|
||||
@@ -407,4 +407,4 @@ void UIWidget::setIcon(const std::string& iconFile)
|
||||
m_icon = g_textures.getTexture(iconFile);
|
||||
if(m_icon && !m_iconClipRect.isValid())
|
||||
m_iconClipRect = Rect(0, 0, m_icon->getSize());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user