fixed invisible UI elements accepting player input

When an UI element was only visible to a player (via the Player property), it still allowed ALL players to click on buttons.
I am wondering why noone else noticed that bug before. It's possible that it didn't show when the visibility was set via the menu's Target (instead of the Player property).

Maybe this was the cause of the "clicks sometimes do nothing" bug?
epoxy
David Dormagen 2016-01-31 23:35:37 +01:00
parent 99d57c83fa
commit 6c5294a05f
2 changed files with 27 additions and 12 deletions

View File

@ -1797,11 +1797,7 @@ bool C4ScriptGuiWindow::Draw(C4TargetFacet &cgo, int32_t player, C4Rect *current
assert(!IsRoot()); // not root, root needs to receive DrawAll
// message hidden?
const int32_t &myPlayer = props[C4ScriptGuiWindowPropertyName::player].GetInt();
if (!IsVisible() || (myPlayer != ANY_OWNER && player != myPlayer) || (target && !target->IsVisible(player, false)))
{
return false;
}
if (!IsVisibleTo(player)) return false;
const int32_t &style = props[C4ScriptGuiWindowPropertyName::style].GetInt();
@ -2010,6 +2006,9 @@ bool C4ScriptGuiWindow::MouseInput(int32_t button, int32_t mouseX, int32_t mouse
{
// only called on root
assert(IsRoot());
// This is only called during a mouse move event, where the MouseControl's player is available.
const int32_t &player = ::MouseControl.GetPlayer();
assert(player != NO_OWNER);
// Only allow one window to catch the mouse input.
// Do not simply return, however, since other windows might need OnMouseOut().
bool oneActionAlreadyExecuted = false;
@ -2025,6 +2024,9 @@ bool C4ScriptGuiWindow::MouseInput(int32_t button, int32_t mouseX, int32_t mouse
if ((withMultipleFlag == 0) && (style & C4ScriptGuiWindowStyleFlag::Multiple)) continue;
if ((withMultipleFlag == 1) && !(style & C4ScriptGuiWindowStyleFlag::Multiple)) continue;
// Do the visibility check first. The child itself won't do it, because we are handling mouse in/out here, too.
if (!child->IsVisibleTo(player)) continue;
// we are root, we have to adjust the position for the "main" windows that are centered
int32_t adjustedMouseX = 0, adjustedMouseY = mouseY;
int32_t offsetX = 0, offsetY = 0;
@ -2076,13 +2078,7 @@ bool C4ScriptGuiWindow::ProcessMouseInput(int32_t button, int32_t mouseX, int32_
const int32_t &style = props[C4ScriptGuiWindowPropertyName::style].GetInt();
if (style & C4ScriptGuiWindowStyleFlag::IgnoreMouse)
return false;
// if the window belongs to an invisible object, don't show
// the "normal" visibility will be handed by the parent callback
if (target)
if (!target->IsVisible(player, false))
return false;
// we have mouse focus! Is this new?
if (!HasMouseFocus())
OnMouseIn(player, parentOffsetX, parentOffsetY);
@ -2098,6 +2094,10 @@ bool C4ScriptGuiWindow::ProcessMouseInput(int32_t button, int32_t mouseX, int32_
for (auto iter = rbegin(); iter != rend(); ++iter)
{
C4ScriptGuiWindow *child = static_cast<C4ScriptGuiWindow*>(*iter);
// Do the visibility check first. The child itself won't do it, because we are handling mouse in/out here, too.
if (!child->IsVisibleTo(player)) continue;
const int32_t childLeft = child->rcBounds.x;
const int32_t childRight = child->rcBounds.x + child->rcBounds.Wdt;
const int32_t childTop = child->rcBounds.y;
@ -2247,3 +2247,16 @@ bool C4ScriptGuiWindow::IsRoot()
{
return this == Game.ScriptGuiRoot.get();
}
bool C4ScriptGuiWindow::IsVisibleTo(int32_t player)
{
// Not visible at all?
if (!IsVisible()) return false;
// We have a player assigned and it's a different one?
const int32_t &myPlayer = props[C4ScriptGuiWindowPropertyName::player].GetInt();
if (myPlayer != ANY_OWNER && player != myPlayer) return false;
// We have a target object which is invisible to the player?
if (target && !target->IsVisible(player, false)) return false;
// Default to visible!
return true;
}

View File

@ -337,6 +337,8 @@ public:
// called by this window, sets the mouse focus; the offset is used to set the correct tooltip rectangle for ::MouseControl
void OnMouseIn(int32_t player, int32_t parentOffsetX, int32_t parentOffsetY);
bool HasMouseFocus() { return currentMouseState & MouseState::Focus; }
// Returns whether the menu can be seen (and interacted with) by a player. This includes checking the target's visibility.
bool IsVisibleTo(int32_t player);
private:
// Use the currently loaded font to determine on-screen size of 1 EM.
static float Em2Pix(float em);