commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
301
include/engine/ui/ui_cursor.cpp
Normal file
301
include/engine/ui/ui_cursor.cpp
Normal file
@ -0,0 +1,301 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <float.h>
|
||||
#include "ui/ui_cursor.h"
|
||||
#include "ui/ui.h"
|
||||
#include "ui/ui_window.h"
|
||||
#include "script/script_engine_types.h"
|
||||
#include "script/script_variant.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::S2D;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Scene::CallEventHandler(Cursor *cursor, EventCode event_code, EventTable *event_table)
|
||||
{
|
||||
EventHandler *handler = event_table ? event_table->GetHandler(event_code) : NULL;
|
||||
if (!handler)
|
||||
return false;
|
||||
|
||||
if (vm->SetupFunctionCall(NULL, handler->GetHandler(), handler->GetContext()))
|
||||
{
|
||||
AutoPtr <Script::Object> table_object(vm->CreateTable());
|
||||
|
||||
table_object->Set("sprite", Script::Variant(cursor->current_state.item, Script::typetag_Window));
|
||||
table_object->Set("window", Script::Variant(cursor->current_state.item, Script::typetag_Window));
|
||||
|
||||
table_object->Set("widget", Script::Variant(cursor->current_state.widget, Script::typetag_Widget));
|
||||
|
||||
if (cursor->current_state.widget)
|
||||
table_object->Set("id", Script::Variant(cursor->current_state.widget->GetId()));
|
||||
|
||||
table_object->Set("cursor_id", cursor->id);
|
||||
table_object->Set("x", cursor->current_state.x);
|
||||
table_object->Set("y", cursor->current_state.y);
|
||||
table_object->Set("dx", cursor->current_state.x - cursor->previous_state.x);
|
||||
table_object->Set("dy", cursor->current_state.y - cursor->previous_state.y);
|
||||
table_object->Set("down", cursor->current_state.down);
|
||||
|
||||
// Cursor position in sprite.
|
||||
if (cursor->current_state.item)
|
||||
{
|
||||
Vector2 c_pos = cursor->current_state.item->ScreenToLocal(Vector2(cursor->current_state.x, cursor->current_state.y));
|
||||
table_object->Set("local_x", c_pos.x);
|
||||
table_object->Set("local_y", c_pos.y);
|
||||
|
||||
if (cursor->previous_state.item == cursor->current_state.item)
|
||||
{
|
||||
Vector2 p_pos = cursor->previous_state.item->ScreenToLocal(Vector2(cursor->previous_state.x, cursor->previous_state.y));
|
||||
table_object->Set("local_dx", c_pos.x - p_pos.x);
|
||||
table_object->Set("local_dy", c_pos.y - p_pos.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
table_object->Set("local_dx", 0);
|
||||
table_object->Set("local_dy", 0);
|
||||
}
|
||||
}
|
||||
|
||||
vm->PushArgument(event_code);
|
||||
vm->PushArgument(table_object.c_ptr());
|
||||
|
||||
if (!vm->DoFunctionCall())
|
||||
__ERR__(__LOG_E__ << "Event handler (" << event_code << ") call failed. The handler parameters should be (event, table).\n", false)
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void Scene::CallEventHandler(Cursor *cursor, Widget *widget, EventCode event_code, bool can_propagate)
|
||||
{
|
||||
for (Widget *base = widget; base; base = base->GetParent())
|
||||
{
|
||||
if (CallEventHandler(cursor, event_code, base->GetEventTable()))
|
||||
return;
|
||||
if (!can_propagate)
|
||||
break;
|
||||
}
|
||||
|
||||
// Try the sprite event handler.
|
||||
if (can_propagate && cursor->current_state.item.IsValid())
|
||||
CallEventHandler(cursor, event_code, cursor->current_state.item->GetEventTable());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Widget *Scene::RecurseWidgetBelowCursor(Window *window, Widget *widget, int mx, int my)
|
||||
{
|
||||
if (!window || !widget)
|
||||
return NULL;
|
||||
|
||||
ListForeachPtr(Widget *, c, widget->GetChildren())
|
||||
{
|
||||
Rect <int> rect(c->GetRect());
|
||||
if (!c->IsHidden() && window->LocalToScreen(rect).Inside(mx, my))
|
||||
{
|
||||
Widget *sub_w = RecurseWidgetBelowCursor(window, c, mx, my);
|
||||
return sub_w ? sub_w : c;
|
||||
}
|
||||
}
|
||||
return widget;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::ProcessCursorEnterLeaveWidget(Cursor *cursor, Window *window, Widget *widget)
|
||||
{
|
||||
if (widget && !widget->IsHidden())
|
||||
{
|
||||
// Process on widget.
|
||||
iRect screen_rect = window->LocalToScreen(widget->GetRect());
|
||||
|
||||
if (screen_rect.Inside((int)cursor->current_state.x, (int)cursor->current_state.y))
|
||||
{
|
||||
if (!screen_rect.Inside((int)cursor->previous_state.x, (int)cursor->previous_state.y))
|
||||
CallEventHandler(cursor, widget, Event_CursorEnter, false);
|
||||
}
|
||||
else
|
||||
if (screen_rect.Inside((int)cursor->previous_state.x, (int)cursor->previous_state.y))
|
||||
CallEventHandler(cursor, widget, Event_CursorLeave, false);
|
||||
|
||||
// Process on widget children.
|
||||
ListForeachPtr(Widget *, c, widget->GetChildren())
|
||||
ProcessCursorEnterLeaveWidget(cursor, window, c);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Scene::UpdateCursor(Cursor *cursor)
|
||||
{
|
||||
Cursor::State &p_state = cursor->previous_state,
|
||||
&c_state = cursor->current_state,
|
||||
&down_state = cursor->down_state;
|
||||
|
||||
// Assert lock sprite validity.
|
||||
if (lock && !item_list.Find(lock))
|
||||
lock = NULL;
|
||||
|
||||
// Move cursor position in system reference.
|
||||
Vector4 c_ui = screen_to_ui * Vector4(c_state.x, c_state.y, 1);
|
||||
// __LOG__ << "x: " << c_ui.x << ", y: " << c_ui.y << "\n";
|
||||
|
||||
c_state.x = c_ui.x;
|
||||
c_state.y = c_ui.y;
|
||||
|
||||
// Determine the current sprite under the cursor.
|
||||
if (lock)
|
||||
c_state.item = lock;
|
||||
|
||||
else
|
||||
{
|
||||
float min_z_order = FLT_MAX;
|
||||
|
||||
c_state.item = NULL;
|
||||
for (List <Item *> ::Item *e = item_list.GetLast(); e; e = e->Previous())
|
||||
{
|
||||
Item *i = e->Object();
|
||||
|
||||
switch (i->GetItemType())
|
||||
{
|
||||
case Item::Type_Sprite:
|
||||
case Item::Type_Window:
|
||||
{
|
||||
Sprite *s = (Sprite *)i;
|
||||
|
||||
if (s->opacity == 0.0)
|
||||
break;
|
||||
if (s->sprite_flags.IsSet(Sprite::FlagNonSensitive))
|
||||
break;
|
||||
|
||||
Rect <int> wrect(s->GetRect());
|
||||
|
||||
if (s->LocalToScreen(wrect).Inside((int)c_state.x, (int)c_state.y) && (min_z_order > s->GetZOrder()))
|
||||
{
|
||||
min_z_order = s->GetZOrder();
|
||||
c_state.item = s;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the current widget under the cursor.
|
||||
c_state.widget = NULL;
|
||||
if (c_state.item && (c_state.item->GetItemType() == Item::Type_Window))
|
||||
{
|
||||
Window *w = (Window *)c_state.item.c_ptr();
|
||||
c_state.widget = RecurseWidgetBelowCursor(w, w->GetBaseWidget(), (int)c_state.x, (int)c_state.y);
|
||||
}
|
||||
|
||||
// State must be complete from here on.
|
||||
|
||||
// Store down state.
|
||||
if (c_state.down && !p_state.down)
|
||||
down_state = c_state;
|
||||
|
||||
// Handle cursor up event (done here so that the down_state widget/sprite will always catch the event).
|
||||
if (p_state.down && !c_state.down)
|
||||
{
|
||||
if (down_state.widget)
|
||||
CallEventHandler(cursor, down_state.widget, Event_CursorUp);
|
||||
else if (down_state.item)
|
||||
CallEventHandler(cursor, Event_CursorUp, down_state.item->GetEventTable());
|
||||
}
|
||||
|
||||
// Handle hit/down/move cursor events.
|
||||
if (c_state.widget)
|
||||
{
|
||||
if (p_state.down && !c_state.down)
|
||||
{
|
||||
if (c_state.widget == down_state.widget)
|
||||
CallEventHandler(cursor, c_state.widget, Event_CursorHit);
|
||||
}
|
||||
|
||||
if (!p_state.down && c_state.down)
|
||||
CallEventHandler(cursor, c_state.widget, Event_CursorDown);
|
||||
|
||||
if ((c_state.widget == p_state.widget) && ((c_state.x != p_state.x) || (c_state.y != p_state.y)))
|
||||
CallEventHandler(cursor, c_state.widget, Event_CursorMove);
|
||||
}
|
||||
else
|
||||
if (c_state.item)
|
||||
{
|
||||
if (p_state.down && !c_state.down)
|
||||
{
|
||||
if (c_state.item == down_state.item)
|
||||
CallEventHandler(cursor, Event_CursorHit, c_state.item->GetEventTable());
|
||||
}
|
||||
|
||||
if (!p_state.down && c_state.down)
|
||||
CallEventHandler(cursor, Event_CursorDown, c_state.item->GetEventTable());
|
||||
|
||||
if ((c_state.item == p_state.item) && ((c_state.x != p_state.x) || (c_state.y != p_state.y)))
|
||||
CallEventHandler(cursor, Event_CursorMove, c_state.item->GetEventTable());
|
||||
}
|
||||
|
||||
// Handle enter/leave cursor events.
|
||||
if (c_state.item)
|
||||
{
|
||||
if (c_state.item->GetItemType() == Item::Type_Window)
|
||||
{
|
||||
Window *w = (Window *)c_state.item.c_ptr();
|
||||
ProcessCursorEnterLeaveWidget(cursor, w, w->GetBaseWidget());
|
||||
}
|
||||
if (c_state.item != p_state.item)
|
||||
CallEventHandler(cursor, Event_CursorEnter, c_state.item->GetEventTable());
|
||||
}
|
||||
if (p_state.item)
|
||||
{
|
||||
if (p_state.item->GetItemType() == Item::Type_Window)
|
||||
{
|
||||
Window *w = (Window *)p_state.item.c_ptr();
|
||||
ProcessCursorEnterLeaveWidget(cursor, w, w->GetBaseWidget());
|
||||
}
|
||||
if (p_state.item != c_state.item)
|
||||
CallEventHandler(cursor, Event_CursorLeave, p_state.item->GetEventTable());
|
||||
}
|
||||
|
||||
#if 0
|
||||
if ((c_state.x != p_state.x) || (c_state.y != p_state.y))
|
||||
{
|
||||
__LOG__ << "CURSOR ID = " << cursor->id << "\n";
|
||||
__LOG__ << "\n";
|
||||
__LOG__ << "X = " << c_state.x << ", Y = " << c_state.y << "\n";
|
||||
|
||||
if (c_state.item)
|
||||
__LOG__ << "PX = " << c_state.item->GetPosition().x << ", PY = " << c_state.item->GetPosition().y << "\n";
|
||||
|
||||
if (Sprite *sprite = (Sprite *)c_state.item)
|
||||
{
|
||||
__LOG__ << "SPRITE = ";
|
||||
if (sprite)
|
||||
__LOG__ << (int)sprite;
|
||||
else
|
||||
__LOG__ << "None";
|
||||
}
|
||||
|
||||
__LOG__ << ", WIDGET = ";
|
||||
if (c_state.widget)
|
||||
{
|
||||
__LOG__ << (int)c_state.widget << " (Id = " << c_state.widget->GetId() << "), type = " << c_state.widget->GetType() << "\n";
|
||||
nRect <int> rect = c_state.widget->GetRect();
|
||||
__LOG__ << "SX = " << rect.sx << ", SY = " << rect.sy << ", W = " << rect.GetWidth() << ", EY = " << rect.GetHeight() << "\n";
|
||||
}
|
||||
else
|
||||
__LOG__ << "None";
|
||||
|
||||
__LOG__ << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
p_state = c_state;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user