More UI scripting progress
This commit is contained in:
parent
0184920bb5
commit
4311c52176
@ -10,7 +10,6 @@
|
|||||||
#include "ui_scripting.hpp"
|
#include "ui_scripting.hpp"
|
||||||
|
|
||||||
#include "game/ui_scripting/lua/engine.hpp"
|
#include "game/ui_scripting/lua/engine.hpp"
|
||||||
#include "game/ui_scripting/lua/context.hpp"
|
|
||||||
|
|
||||||
#include <utils/string.hpp>
|
#include <utils/string.hpp>
|
||||||
|
|
||||||
@ -46,7 +45,7 @@ namespace ui_scripting
|
|||||||
const std::string name = params.get(1);
|
const std::string name = params.get(1);
|
||||||
scheduler::once([name]()
|
scheduler::once([name]()
|
||||||
{
|
{
|
||||||
ui_scripting::lua::open_menu(name);
|
ui_scripting::lua::engine::open_menu(name);
|
||||||
}, scheduler::pipeline::renderer);
|
}, scheduler::pipeline::renderer);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -55,7 +54,7 @@ namespace ui_scripting
|
|||||||
const std::string name = params.get(1);
|
const std::string name = params.get(1);
|
||||||
scheduler::once([name]()
|
scheduler::once([name]()
|
||||||
{
|
{
|
||||||
ui_scripting::lua::close_menu(name);
|
ui_scripting::lua::engine::close_menu(name);
|
||||||
}, scheduler::pipeline::renderer);
|
}, scheduler::pipeline::renderer);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -148,11 +148,25 @@ namespace ui_scripting
|
|||||||
|
|
||||||
if (font_map.find(lowercase) == font_map.end())
|
if (font_map.find(lowercase) == font_map.end())
|
||||||
{
|
{
|
||||||
this->font = font_map["default"];
|
this->font = "default";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->font = font_map[lowercase];
|
this->font = lowercase;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void element::set_font(const std::string& _font)
|
||||||
|
{
|
||||||
|
const auto lowercase = utils::string::to_lower(_font);
|
||||||
|
|
||||||
|
if (font_map.find(lowercase) == font_map.end())
|
||||||
|
{
|
||||||
|
this->font = "default";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->font = lowercase;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +317,8 @@ namespace ui_scripting
|
|||||||
|
|
||||||
if (!this->text.empty())
|
if (!this->text.empty())
|
||||||
{
|
{
|
||||||
const auto _font = game::R_RegisterFont(this->font.data(), relative(this->fontsize));
|
const auto fontname = font_map[this->font];
|
||||||
|
const auto _font = game::R_RegisterFont(fontname.data(), relative(this->fontsize));
|
||||||
const auto text_width = game::R_TextWidth(this->text.data(), 0x7FFFFFFF, _font);
|
const auto text_width = game::R_TextWidth(this->text.data(), 0x7FFFFFFF, _font);
|
||||||
|
|
||||||
auto _horzalign = get_align_value(this->horzalign, (float)text_width, relative(this->w));
|
auto _horzalign = get_align_value(this->horzalign, (float)text_width, relative(this->w));
|
||||||
|
@ -19,6 +19,7 @@ namespace ui_scripting
|
|||||||
void set_vertalign(const std::string& value);
|
void set_vertalign(const std::string& value);
|
||||||
|
|
||||||
void set_text(const std::string& text);
|
void set_text(const std::string& text);
|
||||||
|
void set_font(const std::string& _font);
|
||||||
void set_font(const std::string& _font, const int _fontsize);
|
void set_font(const std::string& _font, const int _fontsize);
|
||||||
void set_color(float r, float g, float b, float a);
|
void set_color(float r, float g, float b, float a);
|
||||||
void set_text_offset(float x, float y);
|
void set_text_offset(float x, float y);
|
||||||
|
@ -9,36 +9,18 @@
|
|||||||
#include "component/scheduler.hpp"
|
#include "component/scheduler.hpp"
|
||||||
|
|
||||||
#include <utils/string.hpp>
|
#include <utils/string.hpp>
|
||||||
|
#include <utils/nt.hpp>
|
||||||
|
|
||||||
namespace ui_scripting::lua
|
namespace ui_scripting::lua
|
||||||
{
|
|
||||||
namespace
|
|
||||||
{
|
{
|
||||||
std::unordered_map<std::string, menu> menus;
|
std::unordered_map<std::string, menu> menus;
|
||||||
std::vector<element*> elements;
|
std::vector<element*> elements;
|
||||||
element ui_element;
|
element ui_element;
|
||||||
float screen_max[2];
|
int mouse[2];
|
||||||
|
|
||||||
void check_resize()
|
namespace
|
||||||
{
|
{
|
||||||
screen_max[0] = game::ScrPlace_GetViewPlacement()->realViewportSize[0];
|
const auto animation_script = utils::nt::load_resource(LUA_ANIMATION_SCRIPT);
|
||||||
screen_max[1] = game::ScrPlace_GetViewPlacement()->realViewportSize[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
int relative_mouse(int value)
|
|
||||||
{
|
|
||||||
return (int)(((float)value / screen_max[0]) * 1920.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
int relative(int value)
|
|
||||||
{
|
|
||||||
return (int)(((float)value / 1920.f) * screen_max[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
float relative(float value)
|
|
||||||
{
|
|
||||||
return (value / 1920.f) * screen_max[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
scripting::script_value convert(const sol::lua_value& value)
|
scripting::script_value convert(const sol::lua_value& value)
|
||||||
{
|
{
|
||||||
@ -79,286 +61,6 @@ namespace ui_scripting::lua
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool point_in_rect(int px, int py, int x, int y, int w, int h)
|
|
||||||
{
|
|
||||||
return (px > x && px < x + w && py > y && py < y + h);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_menu_visible(const menu& menu)
|
|
||||||
{
|
|
||||||
return menu.visible || (menu.type == menu_type::overlay && game::Menu_IsMenuOpenAndVisible(0, menu.overlay_menu.data()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void render_menus()
|
|
||||||
{
|
|
||||||
check_resize();
|
|
||||||
|
|
||||||
for (const auto& menu : menus)
|
|
||||||
{
|
|
||||||
if (is_menu_visible(menu.second))
|
|
||||||
{
|
|
||||||
menu.second.render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<element*> elements_in_point(int x, int y)
|
|
||||||
{
|
|
||||||
std::vector<element*> result;
|
|
||||||
|
|
||||||
for (const auto& menu : menus)
|
|
||||||
{
|
|
||||||
if (!is_menu_visible(menu.second))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& child : menu.second.children)
|
|
||||||
{
|
|
||||||
const auto in_rect = point_in_rect(
|
|
||||||
x, y,
|
|
||||||
(int)child->x,
|
|
||||||
(int)child->y,
|
|
||||||
(int)child->w + (int)child->border_width[1] + (int)child->border_width[3],
|
|
||||||
(int)child->h + (int)child->border_width[0] + (int)child->border_width[2]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (in_rect)
|
|
||||||
{
|
|
||||||
result.push_back(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mouse[2];
|
|
||||||
|
|
||||||
void handle_key_event(sol::state& state, event_handler& handler, const int key, const int down)
|
|
||||||
{
|
|
||||||
const auto _elements = elements_in_point(mouse[0], mouse[1]);
|
|
||||||
|
|
||||||
switch (key)
|
|
||||||
{
|
|
||||||
case game::K_MOUSE2:
|
|
||||||
case game::K_MOUSE1:
|
|
||||||
{
|
|
||||||
const auto click_name = key == game::K_MOUSE1
|
|
||||||
? "click"
|
|
||||||
: "rightclick";
|
|
||||||
|
|
||||||
const auto key_name = key == game::K_MOUSE1
|
|
||||||
? "mouse"
|
|
||||||
: "rightmouse";
|
|
||||||
|
|
||||||
{
|
|
||||||
event main_event;
|
|
||||||
main_event.element = &ui_element;
|
|
||||||
main_event.name = utils::string::va("%s%s", key_name, down ? "down" : "up");
|
|
||||||
main_event.arguments =
|
|
||||||
{
|
|
||||||
{state, mouse[0]},
|
|
||||||
{state, mouse[1]},
|
|
||||||
};
|
|
||||||
|
|
||||||
handler.dispatch(main_event);
|
|
||||||
|
|
||||||
for (const auto& element : _elements)
|
|
||||||
{
|
|
||||||
event event;
|
|
||||||
event.element = element;
|
|
||||||
event.name = utils::string::va("%s%s", key_name, down ? "down" : "up");
|
|
||||||
event.arguments =
|
|
||||||
{
|
|
||||||
{state, mouse[0]},
|
|
||||||
{state, mouse[1]},
|
|
||||||
};
|
|
||||||
|
|
||||||
handler.dispatch(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!down)
|
|
||||||
{
|
|
||||||
event main_event;
|
|
||||||
main_event.element = &ui_element;
|
|
||||||
main_event.name = click_name;
|
|
||||||
main_event.arguments =
|
|
||||||
{
|
|
||||||
{state, mouse[0]},
|
|
||||||
{state, mouse[1]},
|
|
||||||
};
|
|
||||||
|
|
||||||
handler.dispatch(main_event);
|
|
||||||
|
|
||||||
for (const auto& element : _elements)
|
|
||||||
{
|
|
||||||
event event;
|
|
||||||
event.element = element;
|
|
||||||
event.name = click_name;
|
|
||||||
event.arguments =
|
|
||||||
{
|
|
||||||
{state, mouse[0]},
|
|
||||||
{state, mouse[1]},
|
|
||||||
};
|
|
||||||
|
|
||||||
handler.dispatch(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case game::K_MWHEELUP:
|
|
||||||
case game::K_MWHEELDOWN:
|
|
||||||
{
|
|
||||||
const auto key_name = key == game::K_MWHEELUP
|
|
||||||
? "scrollup"
|
|
||||||
: "scrolldown";
|
|
||||||
|
|
||||||
if (!down)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
event main_event;
|
|
||||||
main_event.element = &ui_element;
|
|
||||||
main_event.name = key_name;
|
|
||||||
main_event.arguments =
|
|
||||||
{
|
|
||||||
{state, mouse[0]},
|
|
||||||
{state, mouse[1]},
|
|
||||||
};
|
|
||||||
|
|
||||||
handler.dispatch(main_event);
|
|
||||||
|
|
||||||
for (const auto& element : _elements)
|
|
||||||
{
|
|
||||||
event event;
|
|
||||||
event.element = element;
|
|
||||||
event.name = key_name;
|
|
||||||
event.arguments =
|
|
||||||
{
|
|
||||||
{state, mouse[0]},
|
|
||||||
{state, mouse[1]},
|
|
||||||
};
|
|
||||||
|
|
||||||
handler.dispatch(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
event event;
|
|
||||||
event.element = &ui_element;
|
|
||||||
event.name = down
|
|
||||||
? "keydown"
|
|
||||||
: "keyup";
|
|
||||||
event.arguments =
|
|
||||||
{
|
|
||||||
{state, key},
|
|
||||||
};
|
|
||||||
|
|
||||||
handler.dispatch(event);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void handle_char_event(sol::state& state, event_handler& handler, const int key)
|
|
||||||
{
|
|
||||||
std::string key_str = {(char)key};
|
|
||||||
event event;
|
|
||||||
event.element = &ui_element;
|
|
||||||
event.name = "keypress";
|
|
||||||
event.arguments =
|
|
||||||
{
|
|
||||||
{state, key_str},
|
|
||||||
};
|
|
||||||
|
|
||||||
handler.dispatch(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<element*> previous_elements;
|
|
||||||
void handle_mousemove_event(sol::state& state, event_handler& handler, const int x, const int y)
|
|
||||||
{
|
|
||||||
mouse[0] = x;
|
|
||||||
mouse[1] = y;
|
|
||||||
|
|
||||||
{
|
|
||||||
event event;
|
|
||||||
event.element = &ui_element;
|
|
||||||
event.name = "mousemove";
|
|
||||||
event.arguments =
|
|
||||||
{
|
|
||||||
{state, x},
|
|
||||||
{state, y},
|
|
||||||
};
|
|
||||||
|
|
||||||
handler.dispatch(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto _elements = elements_in_point(x, y);
|
|
||||||
for (const auto& element : _elements)
|
|
||||||
{
|
|
||||||
event event;
|
|
||||||
event.element = element;
|
|
||||||
event.name = "mouseover";
|
|
||||||
|
|
||||||
handler.dispatch(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& element : previous_elements)
|
|
||||||
{
|
|
||||||
auto found = false;
|
|
||||||
|
|
||||||
for (const auto& _element : _elements)
|
|
||||||
{
|
|
||||||
if (element == _element)
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
event event;
|
|
||||||
event.element = element;
|
|
||||||
event.name = "mouseleave";
|
|
||||||
|
|
||||||
handler.dispatch(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& element : _elements)
|
|
||||||
{
|
|
||||||
auto found = false;
|
|
||||||
|
|
||||||
for (const auto& _element : previous_elements)
|
|
||||||
{
|
|
||||||
if (element == _element)
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
event event;
|
|
||||||
event.element = element;
|
|
||||||
event.name = "mouseenter";
|
|
||||||
|
|
||||||
handler.dispatch(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
previous_elements = _elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool valid_dvar_name(const std::string& name)
|
bool valid_dvar_name(const std::string& name)
|
||||||
{
|
{
|
||||||
for (const auto c : name)
|
for (const auto c : name)
|
||||||
@ -372,22 +74,9 @@ namespace ui_scripting::lua
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_menus()
|
|
||||||
{
|
|
||||||
menus.clear();
|
|
||||||
for (const auto element : elements)
|
|
||||||
{
|
|
||||||
delete element;
|
|
||||||
}
|
|
||||||
|
|
||||||
elements.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup_types(sol::state& state, event_handler& handler, scheduler& scheduler)
|
void setup_types(sol::state& state, event_handler& handler, scheduler& scheduler)
|
||||||
{
|
{
|
||||||
clear_menus();
|
auto vector_type = state.new_usertype<scripting::vector>("vector", sol::constructors<scripting::vector(float, float, float)>());
|
||||||
|
|
||||||
auto vector_type = state.new_usertype<scripting::vector>("scripting::vector", sol::constructors<scripting::vector(float, float, float)>());
|
|
||||||
vector_type["x"] = sol::property(&scripting::vector::get_x, &scripting::vector::set_x);
|
vector_type["x"] = sol::property(&scripting::vector::get_x, &scripting::vector::set_x);
|
||||||
vector_type["y"] = sol::property(&scripting::vector::get_y, &scripting::vector::set_y);
|
vector_type["y"] = sol::property(&scripting::vector::get_y, &scripting::vector::set_y);
|
||||||
vector_type["z"] = sol::property(&scripting::vector::get_z, &scripting::vector::set_z);
|
vector_type["z"] = sol::property(&scripting::vector::get_z, &scripting::vector::set_z);
|
||||||
@ -499,7 +188,10 @@ namespace ui_scripting::lua
|
|||||||
element_type["setvertalign"] = &element::set_vertalign;
|
element_type["setvertalign"] = &element::set_vertalign;
|
||||||
element_type["sethorzalign"] = &element::set_horzalign;
|
element_type["sethorzalign"] = &element::set_horzalign;
|
||||||
element_type["setrect"] = &element::set_rect;
|
element_type["setrect"] = &element::set_rect;
|
||||||
element_type["setfont"] = &element::set_font;
|
element_type["setfont"] = sol::overload(
|
||||||
|
static_cast<void(element::*)(const std::string&)>(&element::set_font),
|
||||||
|
static_cast<void(element::*)(const std::string&, int)>(&element::set_font)
|
||||||
|
);
|
||||||
element_type["settext"] = &element::set_text;
|
element_type["settext"] = &element::set_text;
|
||||||
element_type["setmaterial"] = &element::set_material;
|
element_type["setmaterial"] = &element::set_material;
|
||||||
element_type["setcolor"] = &element::set_color;
|
element_type["setcolor"] = &element::set_color;
|
||||||
@ -537,6 +229,148 @@ namespace ui_scripting::lua
|
|||||||
return rect;
|
return rect;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
element_type["x"] = sol::property(
|
||||||
|
[](element& element)
|
||||||
|
{
|
||||||
|
return element.x;
|
||||||
|
},
|
||||||
|
[](element& element, float x)
|
||||||
|
{
|
||||||
|
element.x = x;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
element_type["y"] = sol::property(
|
||||||
|
[](element& element)
|
||||||
|
{
|
||||||
|
return element.y;
|
||||||
|
},
|
||||||
|
[](element& element, float y)
|
||||||
|
{
|
||||||
|
element.y = y;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
element_type["w"] = sol::property(
|
||||||
|
[](element& element)
|
||||||
|
{
|
||||||
|
return element.w;
|
||||||
|
},
|
||||||
|
[](element& element, float w)
|
||||||
|
{
|
||||||
|
element.w = w;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
element_type["h"] = sol::property(
|
||||||
|
[](element& element)
|
||||||
|
{
|
||||||
|
return element.h;
|
||||||
|
},
|
||||||
|
[](element& element, float h)
|
||||||
|
{
|
||||||
|
element.h = h;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
element_type["color"] = sol::property(
|
||||||
|
[](element& element, const sol::this_state s)
|
||||||
|
{
|
||||||
|
auto color = sol::table::create(s.lua_state());
|
||||||
|
color["r"] = element.color[0];
|
||||||
|
color["g"] = element.color[1];
|
||||||
|
color["b"] = element.color[2];
|
||||||
|
color["a"] = element.color[3];
|
||||||
|
return color;
|
||||||
|
},
|
||||||
|
[](element& element, const sol::lua_table color)
|
||||||
|
{
|
||||||
|
element.color[0] = color["r"].get_type() == sol::type::number ? color["r"].get<float>() : 0.f;
|
||||||
|
element.color[1] = color["g"].get_type() == sol::type::number ? color["g"].get<float>() : 0.f;
|
||||||
|
element.color[2] = color["b"].get_type() == sol::type::number ? color["b"].get<float>() : 0.f;
|
||||||
|
element.color[3] = color["a"].get_type() == sol::type::number ? color["a"].get<float>() : 0.f;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
element_type["backcolor"] = sol::property(
|
||||||
|
[](element& element, const sol::this_state s)
|
||||||
|
{
|
||||||
|
auto color = sol::table::create(s.lua_state());
|
||||||
|
color["r"] = element.background_color[0];
|
||||||
|
color["g"] = element.background_color[1];
|
||||||
|
color["b"] = element.background_color[2];
|
||||||
|
color["a"] = element.background_color[3];
|
||||||
|
return color;
|
||||||
|
},
|
||||||
|
[](element& element, const sol::lua_table color)
|
||||||
|
{
|
||||||
|
element.background_color[0] = color["r"].get_type() == sol::type::number ? color["r"].get<float>() : 0.f;
|
||||||
|
element.background_color[1] = color["g"].get_type() == sol::type::number ? color["g"].get<float>() : 0.f;
|
||||||
|
element.background_color[2] = color["b"].get_type() == sol::type::number ? color["b"].get<float>() : 0.f;
|
||||||
|
element.background_color[3] = color["a"].get_type() == sol::type::number ? color["a"].get<float>() : 0.f;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
element_type["bordercolor"] = sol::property(
|
||||||
|
[](element& element, const sol::this_state s)
|
||||||
|
{
|
||||||
|
auto color = sol::table::create(s.lua_state());
|
||||||
|
color["r"] = element.border_color[0];
|
||||||
|
color["g"] = element.border_color[1];
|
||||||
|
color["b"] = element.border_color[2];
|
||||||
|
color["a"] = element.border_color[3];
|
||||||
|
return color;
|
||||||
|
},
|
||||||
|
[](element& element, const sol::lua_table color)
|
||||||
|
{
|
||||||
|
element.border_color[0] = color["r"].get_type() == sol::type::number ? color["r"].get<float>() : 0.f;
|
||||||
|
element.border_color[1] = color["g"].get_type() == sol::type::number ? color["g"].get<float>() : 0.f;
|
||||||
|
element.border_color[2] = color["b"].get_type() == sol::type::number ? color["b"].get<float>() : 0.f;
|
||||||
|
element.border_color[3] = color["a"].get_type() == sol::type::number ? color["a"].get<float>() : 0.f;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
element_type["borderwidth"] = sol::property(
|
||||||
|
[](element& element, const sol::this_state s)
|
||||||
|
{
|
||||||
|
auto color = sol::table::create(s.lua_state());
|
||||||
|
color["top"] = element.border_width[0];
|
||||||
|
color["right"] = element.border_width[1];
|
||||||
|
color["bottom"] = element.border_width[2];
|
||||||
|
color["left"] = element.border_width[3];
|
||||||
|
return color;
|
||||||
|
},
|
||||||
|
[](element& element, const sol::lua_table color)
|
||||||
|
{
|
||||||
|
element.border_width[0] = color["top"].get_type() == sol::type::number ? color["top"].get<float>() : 0.f;
|
||||||
|
element.border_width[1] = color["right"].get_type() == sol::type::number ? color["right"].get<float>() : element.border_width[1];
|
||||||
|
element.border_width[2] = color["bottom"].get_type() == sol::type::number ? color["bottom"].get<float>() : element.border_width[2];
|
||||||
|
element.border_width[3] = color["left"].get_type() == sol::type::number ? color["left"].get<float>() : element.border_width[3];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
element_type["font"] = sol::property(
|
||||||
|
[](element& element)
|
||||||
|
{
|
||||||
|
return element.font;
|
||||||
|
},
|
||||||
|
[](element& element, const std::string& font)
|
||||||
|
{
|
||||||
|
element.set_font(font);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
element_type["fontsize"] = sol::property(
|
||||||
|
[](element& element)
|
||||||
|
{
|
||||||
|
return element.fontsize;
|
||||||
|
},
|
||||||
|
[](element& element, float fontsize)
|
||||||
|
{
|
||||||
|
element.fontsize = (int)fontsize;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
element_type["onnotifyonce"] = [&handler](element& element, const std::string& event,
|
element_type["onnotifyonce"] = [&handler](element& element, const std::string& event,
|
||||||
const event_callback& callback)
|
const event_callback& callback)
|
||||||
{
|
{
|
||||||
@ -549,6 +383,29 @@ namespace ui_scripting::lua
|
|||||||
return handler.add_event_listener(std::move(listener));
|
return handler.add_event_listener(std::move(listener));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
element_type["notify"] = [&handler](element& element, const sol::this_state s, const std::string& _event,
|
||||||
|
sol::variadic_args va)
|
||||||
|
{
|
||||||
|
event event;
|
||||||
|
event.element = &element;
|
||||||
|
event.name = _event;
|
||||||
|
|
||||||
|
for (auto arg : va)
|
||||||
|
{
|
||||||
|
if (arg.get_type() == sol::type::number)
|
||||||
|
{
|
||||||
|
event.arguments.push_back(arg.as<int>());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg.get_type() == sol::type::string)
|
||||||
|
{
|
||||||
|
event.arguments.push_back(arg.as<std::string>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.dispatch(event);
|
||||||
|
};
|
||||||
|
|
||||||
auto menu_type = state.new_usertype<menu>("menu");
|
auto menu_type = state.new_usertype<menu>("menu");
|
||||||
|
|
||||||
menu_type["addchild"] = [](const sol::this_state s, menu& menu, element& element)
|
menu_type["addchild"] = [](const sol::this_state s, menu& menu, element& element)
|
||||||
@ -573,6 +430,12 @@ namespace ui_scripting::lua
|
|||||||
auto game_type = state.new_usertype<game>("game_");
|
auto game_type = state.new_usertype<game>("game_");
|
||||||
state["game"] = game();
|
state["game"] = game();
|
||||||
|
|
||||||
|
game_type["time"] = []()
|
||||||
|
{
|
||||||
|
const auto now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
|
||||||
|
return now.count();
|
||||||
|
};
|
||||||
|
|
||||||
game_type["newmenu"] = [](const sol::lua_value&, const std::string& name)
|
game_type["newmenu"] = [](const sol::lua_value&, const std::string& name)
|
||||||
{
|
{
|
||||||
menus[name] = {};
|
menus[name] = {};
|
||||||
@ -621,6 +484,18 @@ namespace ui_scripting::lua
|
|||||||
return scheduler.add(callback, 0, false);
|
return scheduler.add(callback, 0, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
game_type["ontimeout"] = [&scheduler](const game&, const sol::protected_function& callback,
|
||||||
|
const long long milliseconds)
|
||||||
|
{
|
||||||
|
return scheduler.add(callback, milliseconds, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
game_type["oninterval"] = [&scheduler](const game&, const sol::protected_function& callback,
|
||||||
|
const long long milliseconds)
|
||||||
|
{
|
||||||
|
return scheduler.add(callback, milliseconds, false);
|
||||||
|
};
|
||||||
|
|
||||||
game_type["onnotify"] = [&handler](const game&, const std::string& event,
|
game_type["onnotify"] = [&handler](const game&, const std::string& event,
|
||||||
const event_callback& callback)
|
const event_callback& callback)
|
||||||
{
|
{
|
||||||
@ -836,27 +711,9 @@ namespace ui_scripting::lua
|
|||||||
::game::g_entities[0].client->velocity[1] = velocity.get_y();
|
::game::g_entities[0].client->velocity[1] = velocity.get_y();
|
||||||
::game::g_entities[0].client->velocity[2] = velocity.get_z();
|
::game::g_entities[0].client->velocity[2] = velocity.get_z();
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void open_menu(const std::string& name)
|
state.script(animation_script);
|
||||||
{
|
|
||||||
if (menus.find(name) == menus.end())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
menus[name].open();
|
|
||||||
}
|
|
||||||
|
|
||||||
void close_menu(const std::string& name)
|
|
||||||
{
|
|
||||||
if (menus.find(name) == menus.end())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
menus[name].close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
context::context(std::string folder)
|
context::context(std::string folder)
|
||||||
@ -905,28 +762,14 @@ namespace ui_scripting::lua
|
|||||||
|
|
||||||
void context::run_frame()
|
void context::run_frame()
|
||||||
{
|
{
|
||||||
render_menus();
|
|
||||||
this->scheduler_.run_frame();
|
this->scheduler_.run_frame();
|
||||||
this->state_.collect_garbage();
|
this->state_.collect_garbage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void context::ui_event(const std::string& type, const std::vector<int>& arguments)
|
void context::notify(const event& e)
|
||||||
{
|
{
|
||||||
if (type == "key")
|
this->scheduler_.dispatch(e);
|
||||||
{
|
this->event_handler_.dispatch(e);
|
||||||
handle_key_event(this->state_, this->event_handler_, arguments[0], arguments[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == "char")
|
|
||||||
{
|
|
||||||
handle_char_event(this->state_, this->event_handler_, arguments[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == "mousemove")
|
|
||||||
{
|
|
||||||
handle_mousemove_event(this->state_, this->event_handler_,
|
|
||||||
relative_mouse(arguments[0]), relative_mouse(arguments[1]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void context::load_script(const std::string& script)
|
void context::load_script(const std::string& script)
|
||||||
|
@ -14,8 +14,10 @@
|
|||||||
|
|
||||||
namespace ui_scripting::lua
|
namespace ui_scripting::lua
|
||||||
{
|
{
|
||||||
void open_menu(const std::string& name);
|
extern std::unordered_map<std::string, menu> menus;
|
||||||
void close_menu(const std::string& name);
|
extern std::vector<element*> elements;
|
||||||
|
extern element ui_element;
|
||||||
|
extern int mouse[2];
|
||||||
|
|
||||||
class context
|
class context
|
||||||
{
|
{
|
||||||
@ -30,7 +32,7 @@ namespace ui_scripting::lua
|
|||||||
context& operator=(const context&) = delete;
|
context& operator=(const context&) = delete;
|
||||||
|
|
||||||
void run_frame();
|
void run_frame();
|
||||||
void ui_event(const std::string&, const std::vector<int>&);
|
void notify(const event& e);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sol::state state_{};
|
sol::state state_{};
|
||||||
|
@ -7,8 +7,284 @@
|
|||||||
|
|
||||||
namespace ui_scripting::lua::engine
|
namespace ui_scripting::lua::engine
|
||||||
{
|
{
|
||||||
|
void notify(const event& e);
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
float screen_max[2];
|
||||||
|
|
||||||
|
void check_resize()
|
||||||
|
{
|
||||||
|
screen_max[0] = game::ScrPlace_GetViewPlacement()->realViewportSize[0];
|
||||||
|
screen_max[1] = game::ScrPlace_GetViewPlacement()->realViewportSize[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
int relative_mouse(int value)
|
||||||
|
{
|
||||||
|
return (int)(((float)value / screen_max[0]) * 1920.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int relative(int value)
|
||||||
|
{
|
||||||
|
return (int)(((float)value / 1920.f) * screen_max[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
float relative(float value)
|
||||||
|
{
|
||||||
|
return (value / 1920.f) * screen_max[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool point_in_rect(int px, int py, int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
return (px > x && px < x + w && py > y && py < y + h);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_menu_visible(const menu& menu)
|
||||||
|
{
|
||||||
|
return menu.visible || (menu.type == menu_type::overlay && game::Menu_IsMenuOpenAndVisible(0, menu.overlay_menu.data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<element*> elements_in_point(int x, int y)
|
||||||
|
{
|
||||||
|
std::vector<element*> result;
|
||||||
|
|
||||||
|
for (const auto& menu : menus)
|
||||||
|
{
|
||||||
|
if (!is_menu_visible(menu.second))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& child : menu.second.children)
|
||||||
|
{
|
||||||
|
const auto in_rect = point_in_rect(
|
||||||
|
x, y,
|
||||||
|
(int)child->x,
|
||||||
|
(int)child->y,
|
||||||
|
(int)child->w + (int)child->border_width[1] + (int)child->border_width[3],
|
||||||
|
(int)child->h + (int)child->border_width[0] + (int)child->border_width[2]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (in_rect)
|
||||||
|
{
|
||||||
|
result.push_back(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_key_event(const int key, const int down)
|
||||||
|
{
|
||||||
|
const auto _elements = elements_in_point(mouse[0], mouse[1]);
|
||||||
|
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case game::K_MOUSE2:
|
||||||
|
case game::K_MOUSE1:
|
||||||
|
{
|
||||||
|
const auto click_name = key == game::K_MOUSE1
|
||||||
|
? "click"
|
||||||
|
: "rightclick";
|
||||||
|
|
||||||
|
const auto key_name = key == game::K_MOUSE1
|
||||||
|
? "mouse"
|
||||||
|
: "rightmouse";
|
||||||
|
|
||||||
|
{
|
||||||
|
event main_event;
|
||||||
|
main_event.element = &ui_element;
|
||||||
|
main_event.name = utils::string::va("%s%s", key_name, down ? "down" : "up");
|
||||||
|
main_event.arguments =
|
||||||
|
{
|
||||||
|
mouse[0],
|
||||||
|
mouse[1],
|
||||||
|
};
|
||||||
|
|
||||||
|
engine::notify(main_event);
|
||||||
|
|
||||||
|
for (const auto& element : _elements)
|
||||||
|
{
|
||||||
|
event event;
|
||||||
|
event.element = element;
|
||||||
|
event.name = utils::string::va("%s%s", key_name, down ? "down" : "up");
|
||||||
|
event.arguments =
|
||||||
|
{
|
||||||
|
mouse[0],
|
||||||
|
mouse[1],
|
||||||
|
};
|
||||||
|
|
||||||
|
engine::notify(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!down)
|
||||||
|
{
|
||||||
|
event main_event;
|
||||||
|
main_event.element = &ui_element;
|
||||||
|
main_event.name = click_name;
|
||||||
|
main_event.arguments =
|
||||||
|
{
|
||||||
|
mouse[0],
|
||||||
|
mouse[1],
|
||||||
|
};
|
||||||
|
|
||||||
|
engine::notify(main_event);
|
||||||
|
|
||||||
|
for (const auto& element : _elements)
|
||||||
|
{
|
||||||
|
event event;
|
||||||
|
event.element = element;
|
||||||
|
event.name = click_name;
|
||||||
|
event.arguments =
|
||||||
|
{
|
||||||
|
mouse[0],
|
||||||
|
mouse[1],
|
||||||
|
};
|
||||||
|
|
||||||
|
engine::notify(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case game::K_MWHEELUP:
|
||||||
|
case game::K_MWHEELDOWN:
|
||||||
|
{
|
||||||
|
const auto key_name = key == game::K_MWHEELUP
|
||||||
|
? "scrollup"
|
||||||
|
: "scrolldown";
|
||||||
|
|
||||||
|
if (!down)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
event main_event;
|
||||||
|
main_event.element = &ui_element;
|
||||||
|
main_event.name = key_name;
|
||||||
|
main_event.arguments =
|
||||||
|
{
|
||||||
|
mouse[0],
|
||||||
|
mouse[1],
|
||||||
|
};
|
||||||
|
|
||||||
|
engine::notify(main_event);
|
||||||
|
|
||||||
|
for (const auto& element : _elements)
|
||||||
|
{
|
||||||
|
event event;
|
||||||
|
event.element = element;
|
||||||
|
event.name = key_name;
|
||||||
|
event.arguments = {mouse[0], mouse[1]};
|
||||||
|
|
||||||
|
engine::notify(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
event event;
|
||||||
|
event.element = &ui_element;
|
||||||
|
event.name = down
|
||||||
|
? "keydown"
|
||||||
|
: "keyup";
|
||||||
|
event.arguments = {key};
|
||||||
|
|
||||||
|
notify(event);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_char_event(const int key)
|
||||||
|
{
|
||||||
|
std::string key_str = {(char)key};
|
||||||
|
event event;
|
||||||
|
event.element = &ui_element;
|
||||||
|
event.name = "keypress";
|
||||||
|
event.arguments = {key_str};
|
||||||
|
|
||||||
|
engine::notify(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<element*> previous_elements;
|
||||||
|
void handle_mousemove_event(const int x, const int y)
|
||||||
|
{
|
||||||
|
mouse[0] = x;
|
||||||
|
mouse[1] = y;
|
||||||
|
|
||||||
|
{
|
||||||
|
event event;
|
||||||
|
event.element = &ui_element;
|
||||||
|
event.name = "mousemove";
|
||||||
|
event.arguments = {x, y};
|
||||||
|
|
||||||
|
engine::notify(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto _elements = elements_in_point(x, y);
|
||||||
|
for (const auto& element : _elements)
|
||||||
|
{
|
||||||
|
event event;
|
||||||
|
event.element = element;
|
||||||
|
event.name = "mouseover";
|
||||||
|
|
||||||
|
engine::notify(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& element : previous_elements)
|
||||||
|
{
|
||||||
|
auto found = false;
|
||||||
|
|
||||||
|
for (const auto& _element : _elements)
|
||||||
|
{
|
||||||
|
if (element == _element)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
event event;
|
||||||
|
event.element = element;
|
||||||
|
event.name = "mouseleave";
|
||||||
|
|
||||||
|
engine::notify(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& element : _elements)
|
||||||
|
{
|
||||||
|
auto found = false;
|
||||||
|
|
||||||
|
for (const auto& _element : previous_elements)
|
||||||
|
{
|
||||||
|
if (element == _element)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
event event;
|
||||||
|
event.element = element;
|
||||||
|
event.name = "mouseenter";
|
||||||
|
|
||||||
|
engine::notify(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
previous_elements = _elements;
|
||||||
|
}
|
||||||
|
|
||||||
auto& get_scripts()
|
auto& get_scripts()
|
||||||
{
|
{
|
||||||
static std::vector<std::unique_ptr<context>> scripts{};
|
static std::vector<std::unique_ptr<context>> scripts{};
|
||||||
@ -34,29 +310,96 @@ namespace ui_scripting::lua::engine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void render_menus()
|
||||||
|
{
|
||||||
|
check_resize();
|
||||||
|
|
||||||
|
for (const auto& menu : menus)
|
||||||
|
{
|
||||||
|
if (is_menu_visible(menu.second))
|
||||||
|
{
|
||||||
|
menu.second.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_menus()
|
||||||
|
{
|
||||||
|
menus.clear();
|
||||||
|
for (const auto element : elements)
|
||||||
|
{
|
||||||
|
delete element;
|
||||||
|
}
|
||||||
|
|
||||||
|
elements.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void open_menu(const std::string& name)
|
||||||
|
{
|
||||||
|
if (menus.find(name) == menus.end())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
menus[name].open();
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_menu(const std::string& name)
|
||||||
|
{
|
||||||
|
if (menus.find(name) == menus.end())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
menus[name].close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void start()
|
void start()
|
||||||
{
|
{
|
||||||
|
clear_menus();
|
||||||
get_scripts().clear();
|
get_scripts().clear();
|
||||||
load_scripts();
|
load_scripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop()
|
void stop()
|
||||||
{
|
{
|
||||||
|
clear_menus();
|
||||||
get_scripts().clear();
|
get_scripts().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_event(const std::string& type, const std::vector<int>& arguments)
|
void ui_event(const std::string& type, const std::vector<int>& arguments)
|
||||||
|
{
|
||||||
|
if (type == "key")
|
||||||
|
{
|
||||||
|
handle_key_event(arguments[0], arguments[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == "char")
|
||||||
|
{
|
||||||
|
handle_char_event(arguments[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == "mousemove")
|
||||||
|
{
|
||||||
|
handle_mousemove_event(relative_mouse(arguments[0]), relative_mouse(arguments[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void notify(const event& e)
|
||||||
{
|
{
|
||||||
for (auto& script : get_scripts())
|
for (auto& script : get_scripts())
|
||||||
{
|
{
|
||||||
script->ui_event(type, arguments);
|
script->notify(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_frame()
|
void run_frame()
|
||||||
{
|
{
|
||||||
|
check_resize();
|
||||||
|
render_menus();
|
||||||
|
|
||||||
for (auto& script : get_scripts())
|
for (auto& script : get_scripts())
|
||||||
{
|
{
|
||||||
script->run_frame();
|
script->run_frame();
|
||||||
|
@ -5,6 +5,9 @@ namespace ui_scripting::lua::engine
|
|||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
void close_menu(const std::string& name);
|
||||||
|
void open_menu(const std::string& name);
|
||||||
|
|
||||||
void ui_event(const std::string&, const std::vector<int>&);
|
void ui_event(const std::string&, const std::vector<int>&);
|
||||||
void run_frame();
|
void run_frame();
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,6 @@ namespace ui_scripting::lua
|
|||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
element* element{};
|
element* element{};
|
||||||
std::vector<sol::lua_value> arguments;
|
std::vector<std::variant<int, std::string>> arguments;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "std_include.hpp"
|
#include "std_include.hpp"
|
||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
#include "error.hpp"
|
#include "error.hpp"
|
||||||
|
#include "../../scripting/lua/value_conversion.hpp"
|
||||||
|
|
||||||
#include "event_handler.hpp"
|
#include "event_handler.hpp"
|
||||||
|
|
||||||
@ -15,13 +16,22 @@ namespace ui_scripting::lua
|
|||||||
{
|
{
|
||||||
this->remove(handle);
|
this->remove(handle);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
event_listener_handle_type["endon"] = [this](const event_listener_handle& handle, const element* entity, const std::string& event)
|
||||||
|
{
|
||||||
|
this->add_endon_condition(handle, entity, event);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void event_handler::dispatch(const event& event)
|
void event_handler::dispatch(const event& event)
|
||||||
{
|
{
|
||||||
|
bool has_built_arguments = false;
|
||||||
|
event_arguments arguments{};
|
||||||
|
|
||||||
callbacks_.access([&](task_list& tasks)
|
callbacks_.access([&](task_list& tasks)
|
||||||
{
|
{
|
||||||
this->merge_callbacks();
|
this->merge_callbacks();
|
||||||
|
this->handle_endon_conditions(event);
|
||||||
|
|
||||||
for (auto i = tasks.begin(); i != tasks.end();)
|
for (auto i = tasks.begin(); i != tasks.end();)
|
||||||
{
|
{
|
||||||
@ -33,7 +43,13 @@ namespace ui_scripting::lua
|
|||||||
|
|
||||||
if (!i->is_deleted)
|
if (!i->is_deleted)
|
||||||
{
|
{
|
||||||
handle_error(i->callback(sol::as_args(event.arguments)));
|
if (!has_built_arguments)
|
||||||
|
{
|
||||||
|
has_built_arguments = true;
|
||||||
|
arguments = this->build_arguments(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_error(i->callback(sol::as_args(arguments)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i->is_volatile || i->is_deleted)
|
if (i->is_volatile || i->is_deleted)
|
||||||
@ -62,6 +78,27 @@ namespace ui_scripting::lua
|
|||||||
return {id};
|
return {id};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void event_handler::add_endon_condition(const event_listener_handle& handle, const element* element,
|
||||||
|
const std::string& event)
|
||||||
|
{
|
||||||
|
auto merger = [&](task_list& tasks)
|
||||||
|
{
|
||||||
|
for (auto& task : tasks)
|
||||||
|
{
|
||||||
|
if (task.id == handle.id)
|
||||||
|
{
|
||||||
|
task.endon_conditions.emplace_back(element->id, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
callbacks_.access([&](task_list& tasks)
|
||||||
|
{
|
||||||
|
merger(tasks);
|
||||||
|
new_callbacks_.access(merger);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void event_handler::clear()
|
void event_handler::clear()
|
||||||
{
|
{
|
||||||
callbacks_.access([&](task_list& tasks)
|
callbacks_.access([&](task_list& tasks)
|
||||||
@ -104,4 +141,49 @@ namespace ui_scripting::lua
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void event_handler::handle_endon_conditions(const event& event)
|
||||||
|
{
|
||||||
|
auto deleter = [&](task_list& tasks)
|
||||||
|
{
|
||||||
|
for (auto& task : tasks)
|
||||||
|
{
|
||||||
|
for (auto& condition : task.endon_conditions)
|
||||||
|
{
|
||||||
|
if (condition.first == event.element->id && condition.second == event.name)
|
||||||
|
{
|
||||||
|
task.is_deleted = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
callbacks_.access(deleter);
|
||||||
|
}
|
||||||
|
|
||||||
|
event_arguments event_handler::build_arguments(const event& event) const
|
||||||
|
{
|
||||||
|
event_arguments arguments;
|
||||||
|
|
||||||
|
for (const auto& argument : event.arguments)
|
||||||
|
{
|
||||||
|
const auto index = argument.index();
|
||||||
|
|
||||||
|
if (index == 0)
|
||||||
|
{
|
||||||
|
const sol::lua_value value = {this->state_, std::get<int>(argument)};
|
||||||
|
arguments.emplace_back(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == 1)
|
||||||
|
{
|
||||||
|
const sol::lua_value value = {this->state_, std::get<std::string>(argument)};
|
||||||
|
arguments.emplace_back(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return arguments;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <utils/concurrency.hpp>
|
#include <utils/concurrency.hpp>
|
||||||
#include "../element.hpp"
|
|
||||||
|
|
||||||
namespace ui_scripting::lua
|
namespace ui_scripting::lua
|
||||||
{
|
{
|
||||||
@ -21,6 +20,7 @@ namespace ui_scripting::lua
|
|||||||
event_callback callback = {};
|
event_callback callback = {};
|
||||||
bool is_volatile = false;
|
bool is_volatile = false;
|
||||||
bool is_deleted = false;
|
bool is_deleted = false;
|
||||||
|
std::vector<std::pair<uint64_t, std::string>> endon_conditions{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class event_handler final
|
class event_handler final
|
||||||
@ -50,5 +50,10 @@ namespace ui_scripting::lua
|
|||||||
|
|
||||||
void remove(const event_listener_handle& handle);
|
void remove(const event_listener_handle& handle);
|
||||||
void merge_callbacks();
|
void merge_callbacks();
|
||||||
|
void handle_endon_conditions(const event& event);
|
||||||
|
|
||||||
|
void add_endon_condition(const event_listener_handle& handle, const element* element, const std::string& event);
|
||||||
|
|
||||||
|
event_arguments build_arguments(const event& event) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,35 @@ namespace ui_scripting::lua
|
|||||||
{
|
{
|
||||||
this->remove(handle);
|
this->remove(handle);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
task_handle_type["endon"] = [this](const task_handle& handle, const element* element, const std::string& event)
|
||||||
|
{
|
||||||
|
this->add_endon_condition(handle, element, event);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void scheduler::dispatch(const event& event)
|
||||||
|
{
|
||||||
|
auto deleter = [&](task_list& tasks)
|
||||||
|
{
|
||||||
|
for (auto& task : tasks)
|
||||||
|
{
|
||||||
|
for (auto& condition : task.endon_conditions)
|
||||||
|
{
|
||||||
|
if (condition.first == event.element->id && condition.second == event.name)
|
||||||
|
{
|
||||||
|
task.is_deleted = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
callbacks_.access([&](task_list& tasks)
|
||||||
|
{
|
||||||
|
deleter(tasks);
|
||||||
|
new_callbacks_.access(deleter);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheduler::run_frame()
|
void scheduler::run_frame()
|
||||||
@ -89,6 +118,26 @@ namespace ui_scripting::lua
|
|||||||
return {id};
|
return {id};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scheduler::add_endon_condition(const task_handle& handle, const element* element, const std::string& event)
|
||||||
|
{
|
||||||
|
auto merger = [&](task_list& tasks)
|
||||||
|
{
|
||||||
|
for (auto& task : tasks)
|
||||||
|
{
|
||||||
|
if (task.id == handle.id)
|
||||||
|
{
|
||||||
|
task.endon_conditions.emplace_back(element->id, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
callbacks_.access([&](task_list& tasks)
|
||||||
|
{
|
||||||
|
merger(tasks);
|
||||||
|
new_callbacks_.access(merger);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void scheduler::remove(const task_handle& handle)
|
void scheduler::remove(const task_handle& handle)
|
||||||
{
|
{
|
||||||
auto mask_as_deleted = [&](task_list& tasks)
|
auto mask_as_deleted = [&](task_list& tasks)
|
||||||
|
@ -19,6 +19,7 @@ namespace ui_scripting::lua
|
|||||||
std::chrono::milliseconds delay{};
|
std::chrono::milliseconds delay{};
|
||||||
bool is_volatile = false;
|
bool is_volatile = false;
|
||||||
bool is_deleted = false;
|
bool is_deleted = false;
|
||||||
|
std::vector<std::pair<uint64_t, std::string>> endon_conditions{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class scheduler final
|
class scheduler final
|
||||||
@ -32,6 +33,7 @@ namespace ui_scripting::lua
|
|||||||
scheduler(const scheduler&) = delete;
|
scheduler(const scheduler&) = delete;
|
||||||
scheduler& operator=(const scheduler&) = delete;
|
scheduler& operator=(const scheduler&) = delete;
|
||||||
|
|
||||||
|
void dispatch(const event& event);
|
||||||
void run_frame();
|
void run_frame();
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
@ -44,6 +46,8 @@ namespace ui_scripting::lua
|
|||||||
utils::concurrency::container<task_list, std::recursive_mutex> callbacks_;
|
utils::concurrency::container<task_list, std::recursive_mutex> callbacks_;
|
||||||
std::atomic_int64_t current_task_id_ = 0;
|
std::atomic_int64_t current_task_id_ = 0;
|
||||||
|
|
||||||
|
void add_endon_condition(const task_handle& handle, const element* element, const std::string& event);
|
||||||
|
|
||||||
void remove(const task_handle& handle);
|
void remove(const task_handle& handle);
|
||||||
void merge_callbacks();
|
void merge_callbacks();
|
||||||
};
|
};
|
||||||
|
@ -20,3 +20,5 @@
|
|||||||
#define RUNNER 312
|
#define RUNNER 312
|
||||||
|
|
||||||
#define ICON_IMAGE 313
|
#define ICON_IMAGE 313
|
||||||
|
|
||||||
|
#define LUA_ANIMATION_SCRIPT 314
|
||||||
|
@ -97,6 +97,8 @@ ID_ICON ICON "resources/icon.ico"
|
|||||||
|
|
||||||
MENU_MAIN RCDATA "resources/main.html"
|
MENU_MAIN RCDATA "resources/main.html"
|
||||||
|
|
||||||
|
LUA_ANIMATION_SCRIPT RCDATA "resources/animation.lua"
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
TLS_DLL RCDATA "../../build/bin/x64/Debug/tlsdll.dll"
|
TLS_DLL RCDATA "../../build/bin/x64/Debug/tlsdll.dll"
|
||||||
#else
|
#else
|
||||||
|
87
src/client/resources/animation.lua
Normal file
87
src/client/resources/animation.lua
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
function element:animate(state, animationtime)
|
||||||
|
self:notify("cancel_animation")
|
||||||
|
|
||||||
|
local doanimation = function()
|
||||||
|
local start = {
|
||||||
|
x = self.x,
|
||||||
|
y = self.y,
|
||||||
|
w = self.w,
|
||||||
|
h = self.h,
|
||||||
|
color = self.color,
|
||||||
|
backcolor = self.backcolor,
|
||||||
|
bordercolor = self.bordercolor,
|
||||||
|
borderwidth = self.borderwidth,
|
||||||
|
fontsize = self.fontsize
|
||||||
|
}
|
||||||
|
|
||||||
|
local _end = {}
|
||||||
|
for k, v in pairs(start) do
|
||||||
|
_end[k] = state[k] or v
|
||||||
|
end
|
||||||
|
|
||||||
|
local diffs = {}
|
||||||
|
for k, v in pairs(_end) do
|
||||||
|
if (type(v) == "table") then
|
||||||
|
local value = {}
|
||||||
|
|
||||||
|
for _k, _v in pairs(v) do
|
||||||
|
value[_k] = _v - start[k][_k]
|
||||||
|
end
|
||||||
|
|
||||||
|
diffs[k] = value
|
||||||
|
else
|
||||||
|
diffs[k] = v - start[k]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local timeout = nil
|
||||||
|
local interval = nil
|
||||||
|
local starttime = game:time()
|
||||||
|
|
||||||
|
interval = game:onframe(function()
|
||||||
|
local time = game:time()
|
||||||
|
local percentage = (time - starttime) / animationtime
|
||||||
|
if (percentage >= 1) then
|
||||||
|
for k, v in pairs(_end) do
|
||||||
|
self[k] = v
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for k, v in pairs(diffs) do
|
||||||
|
if (type(v) == "table") then
|
||||||
|
local value = {}
|
||||||
|
|
||||||
|
for _k, _v in pairs(v) do
|
||||||
|
value[_k] = start[k][_k] + _v * percentage
|
||||||
|
end
|
||||||
|
|
||||||
|
self[k] = value
|
||||||
|
else
|
||||||
|
self[k] = start[k] + v * percentage
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
timeout = game:ontimeout(function()
|
||||||
|
interval:clear()
|
||||||
|
for k, v in pairs(_end) do
|
||||||
|
self[k] = v
|
||||||
|
end
|
||||||
|
end, animationtime)
|
||||||
|
|
||||||
|
self:onnotifyonce("cancel_animation", function()
|
||||||
|
timeout:clear()
|
||||||
|
interval:clear()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
game:ontimeout(doanimation, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
function element:cancelanimations(callback)
|
||||||
|
self:notify("cancel_animation")
|
||||||
|
if (type(callback) == "function") then
|
||||||
|
game:ontimeout(callback, 0)
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user