Skip to content

Commit

Permalink
Added ButtonProxy parent rect.
Browse files Browse the repository at this point in the history
The input manager checks that mouse clicks are inside the parent rect instead of every button proxy having to do it in its active func.
  • Loading branch information
afritz1 committed Jan 10, 2025
1 parent 4d2cbc8 commit c8386f9
Show file tree
Hide file tree
Showing 9 changed files with 23 additions and 35 deletions.
3 changes: 2 additions & 1 deletion OpenTESArena/src/Input/InputManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,8 @@ void InputManager::update(Game &game, double dt, BufferView<const ButtonProxy> b

DebugAssert(buttonProxy.rectFunc);
const Rect buttonRect = buttonProxy.rectFunc();
const bool isValidMouseSelection = buttonRect.contains(classicMousePos);
const Rect buttonParentRect = buttonProxy.parentRect;
const bool isValidMouseSelection = buttonRect.contains(classicMousePos) && (buttonParentRect.isEmpty() || buttonParentRect.contains(classicMousePos));
const bool matchesButtonType = *buttonType == buttonProxy.buttonType;
if (isValidMouseSelection && matchesButtonType)
{
Expand Down
14 changes: 1 addition & 13 deletions OpenTESArena/src/Interface/CharacterEquipmentPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,19 +86,7 @@ bool CharacterEquipmentPanel::init()

ButtonProxy::Callback itemCallback = this->inventoryListBox.getCallback(i);

ButtonProxy::ActiveFunction itemActiveFunction = [this, &game]()
{
// @todo: I don't like every button proxy having to handle mouse position, fix this design.
// - maybe should give the button proxy a parent rect that all clicks have to be inside, then
// the active func becomes obsolete
const InputManager &inputManager = game.inputManager;
const Int2 mousePosition = inputManager.getMousePosition();
const Int2 mouseClassicPosition = game.renderer.nativeToOriginal(mousePosition);
const Rect inventoryListBoxRect = this->inventoryListBox.getRect();
return inventoryListBoxRect.contains(mouseClassicPosition);
};

this->addButtonProxy(MouseButtonType::Left, itemRectFunc, itemCallback, itemActiveFunction);
this->addButtonProxy(MouseButtonType::Left, itemRectFunc, itemCallback, this->inventoryListBox.getRect());
}

this->backToStatsButton = Button<Game&>(
Expand Down
11 changes: 1 addition & 10 deletions OpenTESArena/src/Interface/ChooseClassPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,7 @@ bool ChooseClassPanel::init()

auto callback = this->classesListBox.getCallback(i);

auto isActiveFunc = [&game]()
{
const auto &inputManager = game.inputManager;
const Int2 mousePosition = inputManager.getMousePosition();
const Int2 classicPosition = game.renderer.nativeToOriginal(mousePosition);
const Rect classListRect = ChooseClassUiView::getListRect(game);
return classListRect.contains(classicPosition);
};

this->addButtonProxy(MouseButtonType::Left, rectFunc, callback, isActiveFunc);
this->addButtonProxy(MouseButtonType::Left, rectFunc, callback, this->classesListBox.getRect());
}

this->addInputActionListener(InputActionName::Back, ChooseClassUiController::onBackToChooseClassCreationInputAction);
Expand Down
8 changes: 4 additions & 4 deletions OpenTESArena/src/Interface/Panel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,16 +149,16 @@ void Panel::addTextInputListener(const TextInputCallback &callback)
}

void Panel::addButtonProxy(MouseButtonType buttonType, const ButtonProxy::RectFunction &rectFunc,
const ButtonProxy::Callback &callback, const ButtonProxy::ActiveFunction &isActiveFunc)
const ButtonProxy::Callback &callback, const Rect &parentRect, const ButtonProxy::ActiveFunction &isActiveFunc)
{
this->buttonProxies.emplace_back(buttonType, rectFunc, callback, isActiveFunc);
this->buttonProxies.emplace_back(buttonType, rectFunc, callback, parentRect, isActiveFunc);
}

void Panel::addButtonProxy(MouseButtonType buttonType, const Rect &rect, const ButtonProxy::Callback &callback,
const ButtonProxy::ActiveFunction &isActiveFunc)
const Rect &parentRect, const ButtonProxy::ActiveFunction &isActiveFunc)
{
auto rectFunc = [rect]() { return rect; };
this->addButtonProxy(buttonType, rectFunc, callback, isActiveFunc);
this->addButtonProxy(buttonType, rectFunc, callback, parentRect, isActiveFunc);
}

void Panel::clearButtonProxies()
Expand Down
5 changes: 3 additions & 2 deletions OpenTESArena/src/Interface/Panel.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,12 @@ class Panel

// Adds a button proxy for a dynamic button (i.e. ListBox items).
void addButtonProxy(MouseButtonType buttonType, const ButtonProxy::RectFunction &rectFunc,
const ButtonProxy::Callback &callback, const ButtonProxy::ActiveFunction &isActiveFunc = ButtonProxy::ActiveFunction());
const ButtonProxy::Callback &callback, const Rect &parentRect = Rect(),
const ButtonProxy::ActiveFunction &isActiveFunc = ButtonProxy::ActiveFunction());

// Adds a button proxy for a static button.
void addButtonProxy(MouseButtonType buttonType, const Rect &rect, const ButtonProxy::Callback &callback,
const ButtonProxy::ActiveFunction &isActiveFunc = ButtonProxy::ActiveFunction());
const Rect &parentRect = Rect(), const ButtonProxy::ActiveFunction &isActiveFunc = ButtonProxy::ActiveFunction());

void clearButtonProxies();

Expand Down
5 changes: 5 additions & 0 deletions OpenTESArena/src/Math/Rect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ Rect::Rect()
Rect::Rect(const Rect &rect)
: Rect(rect.x, rect.y, rect.w, rect.h) { }

bool Rect::isEmpty() const
{
return (this->w == 0) || (this->h == 0);
}

int Rect::getWidth() const
{
return this->w;
Expand Down
1 change: 1 addition & 0 deletions OpenTESArena/src/Math/Rect.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class Rect
Rect();
Rect(const Rect &rect);

bool isEmpty() const;
int getWidth() const;
int getHeight() const;
int getLeft() const;
Expand Down
4 changes: 2 additions & 2 deletions OpenTESArena/src/UI/Button.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#include "Button.h"

ButtonProxy::ButtonProxy(MouseButtonType buttonType, const RectFunction &rectFunc,
const Callback &callback, const ActiveFunction &isActiveFunc)
: rectFunc(rectFunc), callback(callback), isActiveFunc(isActiveFunc)
const Callback &callback, const Rect &parentRect, const ActiveFunction &isActiveFunc)
: rectFunc(rectFunc), callback(callback), parentRect(parentRect), isActiveFunc(isActiveFunc)
{
this->buttonType = buttonType;
}
Expand Down
7 changes: 4 additions & 3 deletions OpenTESArena/src/UI/Button.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,13 @@ struct ButtonProxy
using ActiveFunction = std::function<bool()>;

MouseButtonType buttonType; // Which mouse button triggers a click.
RectFunction rectFunc; // Position + size in classic UI space. Uses a function for dynamic buttons (ListBox, etc.).
RectFunction rectFunc; // Classic UI space rect for clickable button. Might move around due to being e.g. a ListBox item.
Rect parentRect; // Classic UI space rect that mouse clicks have to be within.
Callback callback; // Called if the button is clicked.
ActiveFunction isActiveFunc; // Contains a callable function if it can be inactive.

ButtonProxy(MouseButtonType buttonType, const RectFunction &rectFunc,
const Callback &callback, const ActiveFunction &isActiveFunc = ActiveFunction());
ButtonProxy(MouseButtonType buttonType, const RectFunction &rectFunc, const Callback &callback,
const Rect &parentRect = Rect(), const ActiveFunction &isActiveFunc = ActiveFunction());
ButtonProxy();
};

Expand Down

0 comments on commit c8386f9

Please sign in to comment.