Skip to content
Permalink
Browse files

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?
  • Loading branch information...
walachey committed Jan 31, 2016
1 parent 99d57c8 commit 6c5294a05f724e811823f0834f25cb5ec44dcc0b
Showing with 27 additions and 12 deletions.
  1. +25 −12 src/gui/C4ScriptGuiWindow.cpp
  2. +2 −0 src/gui/C4ScriptGuiWindow.h
@@ -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;
}
@@ -337,6 +337,8 @@ class C4ScriptGuiWindow : public C4GUI::ScrollWindow
// 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);

0 comments on commit 6c5294a

Please sign in to comment.
You can’t perform that action at this time.