Remove custom UI stuff

This commit is contained in:
Federico Cecchetto 2022-02-06 21:36:49 +01:00
parent f67a8c1cfb
commit f8e19bfed2
27 changed files with 125 additions and 1926 deletions

View File

@ -22,14 +22,14 @@ namespace branding
ui_scripting::push_value(VERSION);
return 1;
}
}
void draw()
{
const auto font = game::R_RegisterFont("fonts/defaultBold.otf", 22);
game::R_AddCmdDrawText("h2-mod", 0x7FFFFFFF, font, 15.f,
15.f + static_cast<float>(font->pixelHeight),
1.f, 1.f, 0.f, color, 0);
void draw()
{
const auto font = game::R_RegisterFont("fonts/defaultBold.otf", 22);
game::R_AddCmdDrawText("h2-mod", 0x7FFFFFFF, font, 15.f,
15.f + static_cast<float>(font->pixelHeight),
1.f, 1.f, 0.f, color, 0);
}
}
class component final : public component_interface
@ -37,6 +37,8 @@ namespace branding
public:
void post_unpack() override
{
scheduler::loop(draw, scheduler::pipeline::renderer);
localized_strings::override("MENU_SP_CAMPAIGN", "H2-MOD");
localized_strings::override("MENU_SYSINFO_CUSTOMER_SUPPORT_LINK", "Github Page:");
localized_strings::override("MENU_SYSINFO_CUSTOMER_SUPPORT_URL", "https://github.com/fedddddd/h2-mod");

View File

@ -1,6 +0,0 @@
#pragma once
namespace branding
{
void draw();
}

View File

@ -279,21 +279,21 @@ namespace fps
game::R_AddCmdDrawText(pos_string, 0x7FFFFFFF, font, x,
60.f, 1.0f, 1.0f, 0.0f, fps_color_ok, 0);
}
}
void draw()
{
check_resize();
draw_fps();
if (!game::CL_IsCgameInitialized() || !game::g_entities[0].client)
void draw()
{
return;
}
check_resize();
draw_fps();
draw_pos();
draw_speed();
draw_speed_graph();
if (!game::CL_IsCgameInitialized() || !game::g_entities[0].client)
{
return;
}
draw_pos();
draw_speed();
draw_speed_graph();
}
}
class component final : public component_interface
@ -301,6 +301,8 @@ namespace fps
public:
void post_unpack() override
{
scheduler::loop(draw, scheduler::pipeline::renderer);
sub_7C55D0_hook.create(0x7C55D0_b, perf_update);
cg_drawSpeed = dvars::register_bool("cg_drawSpeed", 0, game::DVAR_FLAG_SAVED);

View File

@ -1,6 +0,0 @@
#pragma once
namespace fps
{
void draw();
}

View File

@ -354,25 +354,25 @@ namespace game_console
draw_output_scrollbar(x, y, width, height);
draw_output_text(x, y);
}
}
void draw_console()
{
check_resize();
if (*game::keyCatchers & 1)
void draw_console()
{
if (!(*game::keyCatchers & 1))
{
con.output_visible = false;
}
check_resize();
if (con.output_visible)
if (*game::keyCatchers & 1)
{
draw_output_window();
}
if (!(*game::keyCatchers & 1))
{
con.output_visible = false;
}
draw_input();
if (con.output_visible)
{
draw_output_window();
}
draw_input();
}
}
}
@ -719,6 +719,8 @@ namespace game_console
public:
void post_unpack() override
{
scheduler::loop(draw_console, scheduler::pipeline::renderer);
con.cursor = 0;
con.visible_line_count = 0;
con.output_visible = false;

View File

@ -9,8 +9,6 @@ namespace game_console
con_type_info = 7
};
void draw_console();
void print(int type, const char* fmt, ...);
bool console_char_event(int local_client_num, int key);

View File

@ -97,6 +97,11 @@ namespace scheduler
void r_end_frame_stub()
{
execute(pipeline::renderer);
if (game::Sys_IsMainThread())
{
execute(pipeline::lui);
}
r_end_frame_hook.invoke<void>();
}

View File

@ -10,6 +10,8 @@ namespace scheduler
// The game's rendering pipeline
renderer,
lui,
// The game's server thread
server,

View File

@ -8,10 +8,6 @@
#include "scheduler.hpp"
#include "command.hpp"
#include "game_console.hpp"
#include "fps.hpp"
#include "branding.hpp"
#include "ui_scripting.hpp"
#include "game/ui_scripting/lua/engine.hpp"
@ -23,41 +19,17 @@
namespace ui_scripting
{
std::unordered_map<std::string, game::hks::lua_function> functions;
std::unordered_map<std::string, game::hks::lua_function> methods;
namespace
{
std::unordered_map<game::hks::cclosure*, sol::protected_function> converted_functions;
utils::hook::detour hksi_open_lib_hook;
utils::hook::detour hksi_lual_error_hook;
utils::hook::detour hksi_lual_error_hook2;
utils::hook::detour hksi_add_function_hook;
utils::hook::detour hks_start_hook;
utils::hook::detour hks_shutdown_hook;
bool error_hook_enabled = false;
void* hksi_open_lib_stub(game::hks::lua_State* s, const char* libname, game::hks::luaL_Reg* l)
{
for (auto i = l; i->name; ++i)
{
if (i->name == "__gc"s)
{
continue;
}
const auto lower = utils::string::to_lower(i->name);
libname
? functions[lower] = i->function
: methods[lower] = i->function;
}
return hksi_open_lib_hook.invoke<void*>(s, libname, l);
}
void hksi_lual_error_stub(game::hks::lua_State* s, const char* fmt, ...)
{
char va_buffer[2048] = {0};
@ -86,8 +58,6 @@ namespace ui_scripting
ui_scripting::lua::engine::start();
});
functions = {};
methods = {};
return hks_start_hook.invoke<void*>(a1);
}
@ -96,18 +66,6 @@ namespace ui_scripting
ui_scripting::lua::engine::stop();
hks_shutdown_hook.invoke<void*>();
}
void hksi_add_function_stub(game::hks::lua_State* s, game::hks::lua_function f, int a3, const char* name, int a5)
{
if (name != "( lua_CFunction )LUI_CoD_LuaCall_UIExpression"s)
{
std::string name_ = name;
const auto sub = utils::string::to_lower(name_.substr(13, name_.size() - 14));
functions[sub] = f;
}
hksi_add_function_hook.invoke<void>(s, f, a3, name, a5);
}
}
int main_function_handler(game::hks::lua_State* state)
@ -167,26 +125,6 @@ namespace ui_scripting
error_hook_enabled = false;
}
game::hks::lua_function find_function(const std::string& name)
{
const auto lower = utils::string::to_lower(name);
if (functions.find(lower) == functions.end())
{
return 0;
}
return functions[lower];
}
game::hks::lua_function find_method(const std::string& name)
{
const auto lower = utils::string::to_lower(name);
if (methods.find(lower) == methods.end())
{
return 0;
}
return methods[lower];
}
void notify(const event& e)
{
lua::engine::notify(e);
@ -198,47 +136,12 @@ namespace ui_scripting
void post_unpack() override
{
scheduler::loop([]()
{
if (game::Sys_IsMainThread())
{
ui_scripting::lua::engine::run_frame();
}
fps::draw();
branding::draw();
game_console::draw_console();
}, scheduler::pipeline::renderer);
command::add("reloadmenus", []()
{
scheduler::once(ui_scripting::lua::engine::start, scheduler::pipeline::renderer);
});
command::add("openluamenu", [](const command::params& params)
{
const std::string name = params.get(1);
scheduler::once([name]()
{
ui_scripting::lua::engine::open_menu(name);
}, scheduler::pipeline::renderer);
});
command::add("closeluamenu", [](const command::params& params)
{
const std::string name = params.get(1);
scheduler::once([name]()
{
ui_scripting::lua::engine::close_menu(name);
}, scheduler::pipeline::renderer);
});
scheduler::loop(ui_scripting::lua::engine::run_frame, scheduler::pipeline::lui);
hks_start_hook.create(0x328BE0_b, hks_start_stub);
hks_shutdown_hook.create(0x3203B0_b, hks_shutdown_stub);
hksi_open_lib_hook.create(0x2E4530_b, hksi_open_lib_stub);
hksi_lual_error_hook.create(0x2E3E40_b, hksi_lual_error_stub);
hksi_lual_error_hook2.create(0x2DCB40_b, hksi_lual_error_stub);
hksi_add_function_hook.create(0x2DB570_b, hksi_add_function_stub);
}
};
}

View File

@ -1,13 +1,9 @@
#pragma once
#include "game/ui_scripting/lua/value_conversion.hpp"
#include "game/ui_scripting/menu.hpp"
#include "game/ui_scripting/event.hpp"
namespace ui_scripting
{
extern std::unordered_map<std::string, game::hks::lua_function> functions;
extern std::unordered_map<std::string, game::hks::lua_function> methods;
int main_function_handler(game::hks::lua_State* state);
void add_converted_function(game::hks::cclosure* closure, const sol::protected_function& function);
void clear_converted_functions();
@ -15,8 +11,5 @@ namespace ui_scripting
void enable_error_hook();
void disable_error_hook();
game::hks::lua_function find_function(const std::string& name);
game::hks::lua_function find_method(const std::string& name);
void notify(const event& e);
}

View File

@ -1,409 +0,0 @@
#include <std_include.hpp>
#include "element.hpp"
#include <utils/string.hpp>
#define fps_font game::R_RegisterFont("fonts/fira_mono_regular.ttf", 25)
namespace ui_scripting
{
namespace
{
uint64_t next_id;
float screen_max[2];
struct point
{
float x;
float y;
float f2;
float f3;
};
struct rectangle
{
point p0;
point p1;
point p2;
point p3;
};
std::unordered_map<std::string, std::string> font_map =
{
{"bank", "fonts/bank.ttf"},
{"fira_mono_bold", "fonts/fira_mono_bold.ttf"},
{"fira_mono_regular", "fonts/fira_mono_regular.ttf"},
{"defaultbold", "fonts/defaultbold.otf"},
{"objective", "fonts/defaultbold.otf"},
{"default", "fonts/default.otf"},
};
std::unordered_map<std::string, alignment> alignment_map =
{
{"left", alignment::start},
{"top", alignment::start},
{"center", alignment::middle},
{"right", alignment::end},
{"bottom", alignment::end},
};
float get_align_value(alignment align, float text_width, float w)
{
switch (align)
{
case (alignment::start):
return 0.f;
case (alignment::middle):
return (w / 2.f) - (text_width / 2.f);
case (alignment::end):
return w - text_width;
default:
return 0.f;
}
}
void draw_image(float x, float y, float w, float h, float* transform, float* color, game::Material* material)
{
game::rectangle rect;
rect.p0.x = x;
rect.p0.y = y;
rect.p0.f2 = 0.f;
rect.p0.f3 = 1.f;
rect.p1.x = x + w;
rect.p1.y = y;
rect.p1.f2 = 0.f;
rect.p1.f3 = 1.f;
rect.p2.x = x + w;
rect.p2.y = y + h;
rect.p2.f2 = 0.f;
rect.p2.f3 = 1.f;
rect.p3.x = x;
rect.p3.y = y + h;
rect.p3.f2 = 0.f;
rect.p3.f3 = 1.f;
game::R_DrawRectangle(&rect, transform[0], transform[1], transform[2], transform[3], color, material);
}
void check_resize()
{
screen_max[0] = game::ScrPlace_GetViewPlacement()->realViewportSize[0];
screen_max[1] = game::ScrPlace_GetViewPlacement()->realViewportSize[1];
}
float relative(float value)
{
return ceil((value / 1920.f) * screen_max[0]);
}
int relative(int value)
{
return (int)ceil(((float)value / 1920.f) * screen_max[0]);
}
game::rgba float_to_rgba(const float* color)
{
game::rgba rgba;
rgba.r = (uint8_t)(color[0] * 255.f);
rgba.g = (uint8_t)(color[1] * 255.f);
rgba.b = (uint8_t)(color[2] * 255.f);
rgba.a = (uint8_t)(color[3] * 255.f);
return rgba;
}
void draw_text(const char* text, game::Font_s* font, float x, float y, float x_scale, float y_scale, float rotation,
int style, float* color, float* second_color, float* glow_color)
{
const auto result = (uint64_t)game::R_AddCmdDrawText(text, 0x7FFFFFFF, font, x, y, x_scale, y_scale, rotation, color, style);
if (result)
{
*reinterpret_cast<float*>(result + 188) = glow_color[0];
*reinterpret_cast<float*>(result + 192) = glow_color[1];
*reinterpret_cast<float*>(result + 196) = glow_color[2];
*reinterpret_cast<float*>(result + 200) = glow_color[3];
*reinterpret_cast<game::rgba*>(result + 228) = float_to_rgba(second_color);
}
}
}
element::element()
: id(next_id++)
{
}
void element::set_horzalign(const std::string& value)
{
const auto lower = utils::string::to_lower(value);
if (alignment_map.find(lower) == alignment_map.end())
{
this->horzalign = alignment::start;
return;
}
const auto align = alignment_map[lower];
this->horzalign = align;
}
void element::set_vertalign(const std::string& value)
{
const auto lower = utils::string::to_lower(value);
if (alignment_map.find(lower) == alignment_map.end())
{
this->vertalign = alignment::start;
return;
}
const auto align = alignment_map[lower];
this->vertalign = align;
}
void element::set_text(const std::string& _text)
{
this->text = _text;
}
void element::set_font(const std::string& _font, const int _fontsize)
{
this->fontsize = _fontsize;
const auto lowercase = utils::string::to_lower(_font);
if (font_map.find(lowercase) == font_map.end())
{
this->font = "default";
}
else
{
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;
}
}
void element::set_text_offset(float _x, float _y)
{
this->text_offset[0] = _x;
this->text_offset[1] = _y;
}
void element::set_scale(float _x, float _y)
{
this->x_scale = _x;
this->y_scale = _y;
}
void element::set_rotation(float _rotation)
{
this->rotation = _rotation;
}
void element::set_style(int _style)
{
this->style = _style;
}
void element::set_background_color(float r, float g, float b, float a)
{
this->background_color[0] = r;
this->background_color[1] = g;
this->background_color[2] = b;
this->background_color[3] = a;
}
void element::set_color(float r, float g, float b, float a)
{
this->color[0] = r;
this->color[1] = g;
this->color[2] = b;
this->color[3] = a;
}
void element::set_second_color(float r, float g, float b, float a)
{
this->use_gradient = true;
this->second_color[0] = r;
this->second_color[1] = g;
this->second_color[2] = b;
this->second_color[3] = a;
}
void element::set_glow_color(float r, float g, float b, float a)
{
this->glow_color[0] = r;
this->glow_color[1] = g;
this->glow_color[2] = b;
this->glow_color[3] = a;
}
void element::set_border_material(const std::string& _material)
{
this->border_material = _material;
}
void element::set_border_color(float r, float g, float b, float a)
{
this->border_color[0] = r;
this->border_color[1] = g;
this->border_color[2] = b;
this->border_color[3] = a;
}
void element::set_border_width(float top)
{
this->border_width[0] = top;
this->border_width[1] = top;
this->border_width[2] = top;
this->border_width[3] = top;
}
void element::set_border_width(float top, float right)
{
this->border_width[0] = top;
this->border_width[1] = right;
this->border_width[2] = top;
this->border_width[3] = right;
}
void element::set_border_width(float top, float right, float bottom)
{
this->border_width[0] = top;
this->border_width[1] = right;
this->border_width[2] = bottom;
this->border_width[3] = bottom;
}
void element::set_border_width(float top, float right, float bottom, float left)
{
this->border_width[0] = top;
this->border_width[1] = right;
this->border_width[2] = bottom;
this->border_width[3] = left;
}
void element::set_slice(float left_percent, float top_percent, float right_percent, float bottom_percent)
{
this->slice[0] = left_percent;
this->slice[1] = top_percent;
this->slice[2] = right_percent;
this->slice[3] = bottom_percent;
}
void element::set_material(const std::string& _material)
{
this->material = _material;
}
void element::set_rect(const float _x, const float _y, const float _w, const float _h)
{
this->x = _x;
this->y = _y;
this->w = _w;
this->h = _h;
}
void element::render() const
{
check_resize();
if (this->background_color[3] > 0)
{
const auto background_material = game::Material_RegisterHandle(this->material.data());
draw_image(
relative(this->x) + relative(this->border_width[3]),
relative(this->y) + relative(this->border_width[0]),
relative(this->w) - relative(this->border_width[1]) - relative(this->border_width[3]),
relative(this->h) - relative(this->border_width[0]) - relative(this->border_width[2]),
(float*)this->slice,
(float*)this->background_color,
background_material
);
}
if (this->border_color[3] > 0)
{
const auto _border_material = game::Material_RegisterHandle(this->border_material.data());
draw_image(
relative(this->x),
relative(this->y),
relative(this->w),
relative(this->border_width[0]),
(float*)this->slice,
(float*)this->border_color,
_border_material
);
draw_image(
relative(this->x) + relative(this->w) - relative(this->border_width[1]),
relative(this->y) + relative(this->border_width[0]),
relative(this->border_width[1]),
relative(this->h) - relative(this->border_width[0]) - relative(this->border_width[2]),
(float*)this->slice,
(float*)this->border_color,
_border_material
);
draw_image(
relative(this->x),
relative(this->y) + relative(this->h) - relative(this->border_width[2]),
relative(this->w),
relative(this->border_width[2]),
(float*)this->slice,
(float*)this->border_color,
_border_material
);
draw_image(
relative(this->x),
relative(this->y) + relative(this->border_width[0]),
relative(this->border_width[3]),
relative(this->h) - relative(this->border_width[0]) - relative(this->border_width[2]),
(float*)this->slice,
(float*)this->border_color,
_border_material
);
}
if (!this->text.empty())
{
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 _horzalign = get_align_value(this->horzalign, (float)text_width, relative(this->w));
const auto _vertalign = get_align_value(this->vertalign, (float)relative(this->fontsize), relative(this->h));
const auto _x = relative(this->x) + relative(this->text_offset[0]) + _horzalign + relative(this->border_width[3]);
const auto _y = relative(this->y) + relative(this->text_offset[1]) + _vertalign + relative(this->fontsize) + relative(this->border_width[0]);
draw_text(
this->text.data(),
_font,
_x, _y,
this->x_scale,
this->y_scale,
this->rotation,
this->style,
(float*)this->color,
(float*)(this->use_gradient ? this->second_color : this->color),
(float*)this->glow_color
);
}
}
}

View File

@ -1,85 +0,0 @@
#pragma once
#include "game/game.hpp"
#include "script_value.hpp"
namespace ui_scripting
{
enum alignment
{
start,
middle,
end,
};
class element final
{
public:
element();
void set_horzalign(const std::string& value);
void set_vertalign(const std::string& value);
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_color(float r, float g, float b, float a);
void set_second_color(float r, float g, float b, float a);
void set_glow_color(float r, float g, float b, float a);
void set_text_offset(float x, float y);
void set_scale(float x, float y);
void set_rotation(float rotation);
void set_style(int style);
void set_background_color(float r, float g, float b, float a);
void set_material(const std::string& material);
void set_border_material(const std::string& material);
void set_border_color(float r, float g, float b, float a);
void set_border_width(float top);
void set_border_width(float top, float right);
void set_border_width(float top, float right, float bottom);
void set_border_width(float top, float right, float bottom, float left);
void set_slice(float left_percent, float top_percent, float right_percent, float bottom_percent);
void set_rect(const float _x, const float _y, const float _w, const float _h);
uint64_t id;
void render() const;
bool hidden = false;
bool use_gradient = false;
float x = 0.f;
float y = 0.f;
float w = 0.f;
float h = 0.f;
float rotation = 0;
float x_scale = 1.f;
float y_scale = 1.f;
int style = 0;
int fontsize = 20;
float text_offset[2] = {0.f, 0.f};
float color[4] = {1.f, 1.f, 1.f, 1.f};
float second_color[4] = {1.f, 1.f, 1.f, 1.f};
float glow_color[4] = {0.f, 0.f, 0.f, 0.f};
float background_color[4] = {0.f, 0.f, 0.f, 0.f};
float border_color[4] = {0.f, 0.f, 0.f, 0.f};
float border_width[4] = {0.f, 0.f, 0.f, 0.f};
float slice[4] = {0.f, 0.f, 1.f, 1.f};
alignment horzalign = alignment::start;
alignment vertalign = alignment::start;
std::unordered_map<std::string, script_value> attributes = {};
std::string font = "default";
std::string material = "white";
std::string border_material = "white";
std::string text{};
};
}

View File

@ -6,7 +6,6 @@ namespace ui_scripting
struct event
{
std::string name;
const void* element{};
arguments arguments;
};
}

View File

@ -158,71 +158,4 @@ namespace ui_scripting
throw std::runtime_error(std::string("Error setting table field: ") + e.what());
}
}
arguments call_method(const userdata& self, const std::string& name, const arguments& arguments)
{
const auto function = ui_scripting::find_method(name);
if (!function)
{
throw std::runtime_error("Function " + name + " not found");
}
const auto state = *game::hks::lua_state;
state->m_apistack.top = state->m_apistack.base;
push_value(self);
for (auto i = arguments.begin(); i != arguments.end(); ++i)
{
push_value(*i);
}
enable_error_hook();
const auto __ = gsl::finally([]()
{
disable_error_hook();
});
try
{
const auto count = function(*game::hks::lua_state);
return get_return_values(count);
}
catch (const std::exception& e)
{
throw std::runtime_error("Error executing method " + name + ": " + e.what());
}
}
arguments call(const std::string& name, const arguments& arguments)
{
const auto function = ui_scripting::find_function(name);
if (!function)
{
throw std::runtime_error("Function " + name + " not found");
}
const auto state = *game::hks::lua_state;
state->m_apistack.top = state->m_apistack.base;
for (auto i = arguments.begin(); i != arguments.end(); ++i)
{
push_value(*i);
}
enable_error_hook();
const auto __ = gsl::finally([]()
{
disable_error_hook();
});
try
{
const auto count = function(*game::hks::lua_state);
return get_return_values(count);
}
catch (const std::exception& e)
{
throw std::runtime_error("Error executing function " + name + ": " + e.what());
}
}
}

View File

@ -15,7 +15,4 @@ namespace ui_scripting
script_value get_field(const table& self, const script_value& key);
void set_field(const userdata& self, const script_value& key, const script_value& value);
void set_field(const table& self, const script_value& key, const script_value& value);
arguments call_method(const userdata& self, const std::string& name, const arguments& arguments);
arguments call(const std::string& name, const arguments& arguments);
}

View File

@ -23,14 +23,8 @@
namespace ui_scripting::lua
{
std::unordered_map<std::string, menu> menus;
std::vector<element*> elements;
element ui_element;
int mouse[2];
namespace
{
const auto animation_script = utils::nt::load_resource(LUA_ANIMATION_SCRIPT);
const auto json_script = utils::nt::load_resource(LUA_JSON_SCRIPT);
scripting::script_value script_convert(const sol::lua_value& value)
@ -213,506 +207,6 @@ namespace ui_scripting::lua
};
}
void setup_element_type(sol::state& state, event_handler& handler, scheduler& scheduler)
{
auto element_type = state.new_usertype<element>("element", "new", []()
{
const auto el = new element();
elements.push_back(el);
return el;
});
element_type["setvertalign"] = &element::set_vertalign;
element_type["sethorzalign"] = &element::set_horzalign;
element_type["setrect"] = &element::set_rect;
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["setmaterial"] = &element::set_material;
element_type["setcolor"] = &element::set_color;
element_type["setsecondcolor"] = &element::set_second_color;
element_type["setglowcolor"] = &element::set_glow_color;
element_type["setbackcolor"] = &element::set_background_color;
element_type["setbordercolor"] = &element::set_border_color;
element_type["setborderwidth"] = sol::overload(
static_cast<void(element::*)(float)>(&element::set_border_width),
static_cast<void(element::*)(float, float)>(&element::set_border_width),
static_cast<void(element::*)(float, float, float)>(&element::set_border_width),
static_cast<void(element::*)(float, float, float, float)>(&element::set_border_width)
);
element_type["settextoffset"] = &element::set_text_offset;
element_type["setscale"] = &element::set_scale;
element_type["setrotation"] = &element::set_rotation;
element_type["setyle"] = &element::set_style;
element_type["setslice"] = &element::set_slice;
element_type["getrect"] = [](const sol::this_state s, element& element)
{
auto rect = sol::table::create(s.lua_state());
rect["x"] = element.x;
rect["y"] = element.y;
rect["w"] = element.w + element.border_width[1] + element.border_width[3];
rect["h"] = element.h + element.border_width[0] + element.border_width[2];
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["scalex"] = sol::property(
[](element& element)
{
return element.x_scale;
},
[](element& element, float x_scale)
{
element.x_scale = x_scale;
}
);
element_type["scaley"] = sol::property(
[](element& element)
{
return element.y_scale;
},
[](element& element, float y_scale)
{
element.y_scale = y_scale;
}
);
element_type["rotation"] = sol::property(
[](element& element)
{
return element.rotation;
},
[](element& element, float rotation)
{
element.rotation = rotation;
}
);
element_type["style"] = sol::property(
[](element& element)
{
return element.style;
},
[](element& element, int style)
{
element.style = style;
}
);
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["secondcolor"] = sol::property(
[](element& element, const sol::this_state s)
{
auto color = sol::table::create(s.lua_state());
color["r"] = element.second_color[0];
color["g"] = element.second_color[1];
color["b"] = element.second_color[2];
color["a"] = element.second_color[3];
return color;
},
[](element& element, const sol::lua_table color)
{
element.use_gradient = true;
element.second_color[0] = color["r"].get_type() == sol::type::number ? color["r"].get<float>() : 0.f;
element.second_color[1] = color["g"].get_type() == sol::type::number ? color["g"].get<float>() : 0.f;
element.second_color[2] = color["b"].get_type() == sol::type::number ? color["b"].get<float>() : 0.f;
element.second_color[3] = color["a"].get_type() == sol::type::number ? color["a"].get<float>() : 0.f;
}
);
element_type["usegradient"] = sol::property(
[](element& element, const sol::this_state s)
{
return element.use_gradient;
},
[](element& element, bool use_gradient)
{
element.use_gradient = use_gradient;
}
);
element_type["glowcolor"] = sol::property(
[](element& element, const sol::this_state s)
{
auto color = sol::table::create(s.lua_state());
color["r"] = element.glow_color[0];
color["g"] = element.glow_color[1];
color["b"] = element.glow_color[2];
color["a"] = element.glow_color[3];
return color;
},
[](element& element, const sol::lua_table color)
{
element.glow_color[0] = color["r"].get_type() == sol::type::number ? color["r"].get<float>() : 0.f;
element.glow_color[1] = color["g"].get_type() == sol::type::number ? color["g"].get<float>() : 0.f;
element.glow_color[2] = color["b"].get_type() == sol::type::number ? color["b"].get<float>() : 0.f;
element.glow_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["onnotify"] = [&handler](element& element, const std::string& event,
const event_callback& callback)
{
event_listener listener{};
listener.callback = callback;
listener.element = &element;
listener.event = event;
listener.is_volatile = false;
return handler.add_event_listener(std::move(listener));
};
element_type["onnotifyonce"] = [&handler](element& element, const std::string& event,
const event_callback& callback)
{
event_listener listener{};
listener.callback = callback;
listener.element = &element;
listener.event = event;
listener.is_volatile = true;
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)
{
event.arguments.push_back(convert({s, arg}));
}
notify(event);
};
element_type["hidden"] = sol::property(
[](element& element)
{
return element.hidden;
},
[](element& element, bool hidden)
{
element.hidden = hidden;
}
);
element_type[sol::meta_function::new_index] = [](element& element, const sol::this_state s, const std::string& attribute, const sol::lua_value& value)
{
element.attributes[attribute] = convert({s, value});
};
element_type[sol::meta_function::index] = [](element& element, const sol::this_state s, const std::string& attribute)
{
if (element.attributes.find(attribute) == element.attributes.end())
{
return sol::lua_value{s, sol::lua_nil};
}
return sol::lua_value{s, convert(s, element.attributes[attribute])};
};
}
void setup_menu_type(sol::state& state, event_handler& handler, scheduler& scheduler)
{
auto menu_type = state.new_usertype<menu>("menu");
menu_type["onnotify"] = [&handler](menu& menu, const std::string& event,
const event_callback& callback)
{
event_listener listener{};
listener.callback = callback;
listener.element = &menu;
listener.event = event;
listener.is_volatile = false;
return handler.add_event_listener(std::move(listener));
};
menu_type["onnotifyonce"] = [&handler](menu& menu, const std::string& event,
const event_callback& callback)
{
event_listener listener{};
listener.callback = callback;
listener.element = &menu;
listener.event = event;
listener.is_volatile = true;
return handler.add_event_listener(std::move(listener));
};
menu_type["notify"] = [&handler](menu& 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)
{
event.arguments.push_back(convert({s, arg}));
}
notify(event);
};
menu_type["addchild"] = [](const sol::this_state s, menu& menu, element& element)
{
menu.add_child(&element);
};
menu_type["cursor"] = sol::property(
[](menu& menu)
{
return menu.cursor;
},
[](menu& menu, bool cursor)
{
menu.cursor = cursor;
}
);
menu_type["hidden"] = sol::property(
[](menu& menu)
{
return menu.hidden;
},
[](menu& menu, bool hidden)
{
menu.hidden = hidden;
}
);
menu_type["ignoreevents"] = sol::property(
[](menu& menu)
{
return menu.ignoreevents;
},
[](menu& menu, bool ignoreevents)
{
menu.ignoreevents = ignoreevents;
}
);
menu_type["isopen"] = [](menu& menu)
{
return menu.visible || (menu.type == menu_type::overlay && game::Menu_IsMenuOpenAndVisible(0, menu.overlay_menu.data()));
};
menu_type["open"] = [&handler](menu& menu)
{
event event;
event.element = &menu;
event.name = "close";
notify(event);
menu.open();
};
menu_type["close"] = [&handler](menu& menu)
{
event event;
event.element = &menu;
event.name = "close";
notify(event);
menu.close();
};
menu_type["getelement"] = [](menu& menu, const sol::this_state s, const sol::lua_value& value, const std::string& attribute)
{
const auto value_ = convert({s, value});
for (const auto& element : menu.children)
{
if (element->attributes.find(attribute) != element->attributes.end() && element->attributes[attribute] == value_)
{
return sol::lua_value{s, element};
}
}
return sol::lua_value{s, sol::lua_nil};
};
menu_type["getelements"] = sol::overload
(
[](menu& menu, const sol::this_state s, const sol::lua_value& value, const std::string& attribute)
{
const auto value_ = convert({s, value});
auto result = sol::table::create(s.lua_state());
for (const auto& element : menu.children)
{
if (element->attributes.find(attribute) != element->attributes.end() && element->attributes[attribute] == value_)
{
result.add(element);
}
}
return result;
},
[](menu& menu, const sol::this_state s)
{
auto result = sol::table::create(s.lua_state());
for (const auto& element : menu.children)
{
result.add(element);
}
return result;
}
);
}
void setup_game_type(sol::state& state, event_handler& handler, scheduler& scheduler)
{
struct game
@ -721,137 +215,17 @@ namespace ui_scripting::lua
auto game_type = state.new_usertype<game>("game_");
state["game"] = game();
game_type["getmenu"] = [](const game&, const sol::this_state s, const std::string& name)
{
if (menus.find(name) == menus.end())
{
return sol::lua_value{s, sol::lua_nil};
}
return sol::lua_value{s, &menus[name]};
};
game_type["getelement"] = [](const game&, const sol::this_state s, const sol::lua_value& value, const std::string& attribute)
{
const auto value_ = convert({s, value});
for (const auto& element : elements)
{
if (element->attributes.find(attribute) != element->attributes.end() && element->attributes[attribute] == value_)
{
return sol::lua_value{s, element};
}
}
return sol::lua_value{s, sol::lua_nil};
};
game_type["getelements"] = sol::overload
(
[](const game&, const sol::this_state s, const sol::lua_value& value, const std::string& attribute)
{
const auto value_ = convert({s, value});
auto result = sol::table::create(s.lua_state());
for (const auto& element : elements)
{
if (element->attributes.find(attribute) != element->attributes.end() && element->attributes[attribute] == value_)
{
result.add(element);
}
}
return result;
},
[](const game&, const sol::this_state s)
{
auto result = sol::table::create(s.lua_state());
for (const auto& element : elements)
{
result.add(element);
}
return result;
}
);
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 game&, const std::string& name)
{
menus[name] = {};
return &menus[name];
};
game_type["executecommand"] = [](const game&, const std::string& command)
{
command::execute(command, false);
};
game_type["luiopen"] = [](const game&, const std::string& menu)
{
::scheduler::once([menu]()
{
::game::LUI_OpenMenu(0, menu.data(), 0, 0, 0);
}, ::scheduler::pipeline::renderer);
};
game_type["newmenuoverlay"] = [](const game&, const std::string& name, const std::string& menu_name)
{
menus[name] = {};
menus[name].type = menu_type::overlay;
menus[name].overlay_menu = menu_name;
return &menus[name];
};
game_type["getmouseposition"] = [](const sol::this_state s, const game&)
{
auto pos = sol::table::create(s.lua_state());
pos["x"] = mouse[0];
pos["y"] = mouse[1];
return pos;
};
game_type["openmenu"] = [&handler](const game&, const std::string& name)
{
if (menus.find(name) == menus.end())
{
return;
}
const auto menu = &menus[name];
event event;
event.element = menu;
event.name = "open";
notify(event);
menu->open();
};
game_type["closemenu"] = [&handler](const game&, const std::string& name)
{
if (menus.find(name) == menus.end())
{
return;
}
const auto menu = &menus[name];
event event;
event.element = menu;
event.name = "close";
notify(event);
menu->close();
};
game_type["onframe"] = [&scheduler](const game&, const sol::protected_function& callback)
{
return scheduler.add(callback, 0, false);
@ -874,7 +248,6 @@ namespace ui_scripting::lua
{
event_listener listener{};
listener.callback = callback;
listener.element = &ui_element;
listener.event = event;
listener.is_volatile = false;
@ -886,7 +259,6 @@ namespace ui_scripting::lua
{
event_listener listener{};
listener.callback = callback;
listener.element = &ui_element;
listener.event = event;
listener.is_volatile = true;
@ -991,49 +363,6 @@ namespace ui_scripting::lua
(0x71B970_b)(video.data(), 64, 0);
};
game_type[sol::meta_function::index] = [](const game&, const std::string& name)
{
return [name](const game&, const sol::this_state s, sol::variadic_args va)
{
arguments arguments{};
for (auto arg : va)
{
arguments.push_back(convert({s, arg}));
}
const auto values = call(name, arguments);
std::vector<sol::lua_value> returns;
for (const auto& value : values)
{
returns.push_back(convert(s, value));
}
return sol::as_returns(returns);
};
};
game_type["call"] = [](const game&, const sol::this_state s, const std::string& name, sol::variadic_args va)
{
arguments arguments{};
for (auto arg : va)
{
arguments.push_back(convert({s, arg}));
}
const auto values = call(name, arguments);
std::vector<sol::lua_value> returns;
for (const auto& value : values)
{
returns.push_back(convert(s, value));
}
return sol::as_returns(returns);
};
game_type["sharedset"] = [](const game&, const std::string& key, const std::string& value)
{
scripting::shared_table.access([key, value](scripting::shared_table_t& table)
@ -1116,7 +445,6 @@ namespace ui_scripting::lua
::scheduler::once([result, id]
{
event event;
event.element = &ui_element;
event.name = "http_request_done";
if (result.has_value())
@ -1129,7 +457,7 @@ namespace ui_scripting::lua
}
notify(event);
}, ::scheduler::pipeline::renderer);
}, ::scheduler::pipeline::lui);
}, ::scheduler::pipeline::async);
return id;
};
@ -1140,25 +468,50 @@ namespace ui_scripting::lua
const auto id = request_id++;
::scheduler::once([url, id, dest]()
{
const auto result = utils::http::get_data(url);
::scheduler::once([result, id, dest]
auto last_report = std::chrono::high_resolution_clock::now();
const auto result = utils::http::get_data(url, {}, [&last_report, id](size_t progress, size_t total, float speed)
{
event event;
event.element = &ui_element;
event.name = "http_request_done";
if (result.has_value())
const auto now = std::chrono::high_resolution_clock::now();
if (now - last_report < 100ms && progress < total)
{
const auto write = utils::io::write_file(dest, result.value(), false);
return;
}
last_report = now;
::scheduler::once([id, progress, total, speed]
{
event event;
event.name = "http_request_progress";
event.arguments = {id, static_cast<int>(progress), static_cast<int>(total), speed};
notify(event);
}, ::scheduler::pipeline::lui);
});
if (result.has_value())
{
const auto write = utils::io::write_file(dest, result.value(), false);
::scheduler::once([result, id, write]()
{
event event;
event.name = "http_request_done";
event.arguments = {id, true, write};
}
else
{
event.arguments = {id, false};
}
notify(event);
}, ::scheduler::pipeline::renderer);
notify(event);
}, ::scheduler::pipeline::lui);
}
else
{
::scheduler::once([result, id]()
{
event event;
event.name = "http_request_done";
event.arguments = {id, false};
notify(event);
}, ::scheduler::pipeline::lui);
}
}, ::scheduler::pipeline::async);
return id;
};
@ -1243,31 +596,6 @@ namespace ui_scripting::lua
}
);
for (const auto method : methods)
{
const auto name = method.first;
userdata_type[name] = [name](const userdata& userdata, const sol::this_state s, sol::variadic_args va)
{
arguments arguments{};
for (auto arg : va)
{
arguments.push_back(convert({s, arg}));
}
const auto values = call_method(userdata, name, arguments);
std::vector<sol::lua_value> returns;
for (const auto& value : values)
{
returns.push_back(convert(s, value));
}
return sol::as_returns(returns);
};
}
userdata_type[sol::meta_function::index] = [](const userdata& userdata, const sol::this_state s,
const std::string& name)
{
@ -1344,8 +672,6 @@ namespace ui_scripting::lua
state["LUI"] = state["luiglobals"]["LUI"];
state["Engine"] = state["luiglobals"]["Engine"];
state["Game"] = state["luiglobals"]["Game"];
state.script(animation_script);
}
}
@ -1365,8 +691,6 @@ namespace ui_scripting::lua
setup_io(this->state_);
setup_json(this->state_);
setup_vector_type(this->state_);
setup_element_type(this->state_, this->event_handler_, this->scheduler_);
setup_menu_type(this->state_, this->event_handler_, this->scheduler_);
setup_game_type(this->state_, this->event_handler_, this->scheduler_);
setup_lui_types(this->state_, this->event_handler_, this->scheduler_);

View File

@ -1,7 +1,6 @@
#pragma once
#include "../event.hpp"
#include "../menu.hpp"
#pragma warning(push)
#pragma warning(disable: 4702)
@ -21,11 +20,6 @@ namespace ui_scripting::lua
code
};
extern std::unordered_map<std::string, menu> menus;
extern std::vector<element*> elements;
extern element ui_element;
extern int mouse[2];
class context
{
public:

View File

@ -15,290 +15,27 @@ namespace ui_scripting::lua::engine
{
const auto updater_script = utils::nt::load_resource(LUI_UPDATER_MENU);
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)ceil(((float)value / screen_max[0]) * 1920.f);
}
int relative(int value)
{
return (int)ceil(((float)value / 1920.f) * screen_max[0]);
}
float relative(float value)
{
return ceil((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.hidden || (!menu.hidden && 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) || menu.second.ignoreevents)
{
continue;
}
for (const auto& child : menu.second.children)
{
if (child->hidden)
{
continue;
}
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]);
event event;
event.name = down
? "keydown"
: "keyup";
event.arguments = {key};
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};
engine::notify(event);
break;
}
}
engine::notify(event);
}
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)
{
if (mouse[0] == x && mouse[1] == y)
{
return;
}
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()
{
static std::vector<std::unique_ptr<context>> scripts{};
@ -327,93 +64,14 @@ namespace ui_scripting::lua::engine
{
get_scripts().push_back(std::make_unique<context>(code, script_type::code));
}
void render_menus()
{
check_resize();
for (auto& menu : menus)
{
if (is_menu_visible(menu.second))
{
menu.second.render();
}
}
}
void close_all_menus()
{
for (auto& menu : menus)
{
if (!is_menu_visible(menu.second))
{
continue;
}
event event;
event.element = &menu.second;
event.name = "close";
engine::notify(event);
menu.second.close();
}
}
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;
}
const auto menu = &menus[name];
event event;
event.element = menu;
event.name = "open";
engine::notify(event);
menu->open();
}
void close_menu(const std::string& name)
{
if (menus.find(name) == menus.end())
{
return;
}
const auto menu = &menus[name];
event event;
event.element = menu;
event.name = "close";
engine::notify(event);
menu->close();
}
void start()
{
clear_converted_functions();
close_all_menus();
get_scripts().clear();
clear_menus();
load_code(updater_script);
//load_code(updater_script);
load_scripts("ui_scripts/");
load_scripts("h2-mod/ui_scripts/");
@ -428,9 +86,7 @@ namespace ui_scripting::lua::engine
void stop()
{
clear_converted_functions();
close_all_menus();
get_scripts().clear();
clear_menus();
}
void ui_event(const std::string& type, const std::vector<int>& arguments)
@ -444,11 +100,6 @@ namespace ui_scripting::lua::engine
{
handle_char_event(arguments[0]);
}
if (type == "mousemove")
{
handle_mousemove_event(relative_mouse(arguments[0]), relative_mouse(arguments[1]));
}
}
void notify(const event& e)
@ -461,9 +112,6 @@ namespace ui_scripting::lua::engine
void run_frame()
{
check_resize();
render_menus();
for (auto& script : get_scripts())
{
script->run_frame();

View File

@ -7,9 +7,6 @@ namespace ui_scripting::lua::engine
void start();
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 notify(const event& e);
void run_frame();

View File

@ -17,9 +17,9 @@ namespace ui_scripting::lua
this->remove(handle);
};
event_listener_handle_type["endon"] = [this](const event_listener_handle& handle, const element* entity, const std::string& event)
event_listener_handle_type["endon"] = [this](const event_listener_handle& handle, const std::string& event)
{
this->add_endon_condition(handle, entity, event);
this->add_endon_condition(handle, event);
};
}
@ -35,7 +35,7 @@ namespace ui_scripting::lua
for (auto i = tasks.begin(); i != tasks.end();)
{
if (i->event != event.name || i->element != event.element)
if (i->event != event.name)
{
++i;
continue;
@ -78,8 +78,7 @@ namespace ui_scripting::lua
return {id};
}
void event_handler::add_endon_condition(const event_listener_handle& handle, const element* element,
const std::string& event)
void event_handler::add_endon_condition(const event_listener_handle& handle, const std::string& event)
{
auto merger = [&](task_list& tasks)
{
@ -87,7 +86,7 @@ namespace ui_scripting::lua
{
if (task.id == handle.id)
{
task.endon_conditions.emplace_back((uint64_t)element, event);
task.endon_conditions.emplace_back(event);
}
}
};
@ -150,7 +149,7 @@ namespace ui_scripting::lua
{
for (auto& condition : task.endon_conditions)
{
if (condition.first == (uint64_t)event.element && condition.second == event.name)
if (condition == event.name)
{
task.is_deleted = true;
break;

View File

@ -16,11 +16,10 @@ namespace ui_scripting::lua
{
public:
std::string event = {};
void* element{};
event_callback callback = {};
bool is_volatile = false;
bool is_deleted = false;
std::vector<std::pair<uint64_t, std::string>> endon_conditions{};
std::vector<std::string> endon_conditions{};
};
class event_handler final
@ -52,7 +51,7 @@ namespace ui_scripting::lua
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);
void add_endon_condition(const event_listener_handle& handle, const std::string& event);
event_arguments build_arguments(const event& event) const;
};

View File

@ -13,9 +13,9 @@ namespace ui_scripting::lua
this->remove(handle);
};
task_handle_type["endon"] = [this](const task_handle& handle, const element* element, const std::string& event)
task_handle_type["endon"] = [this](const task_handle& handle, const std::string& event)
{
this->add_endon_condition(handle, element, event);
this->add_endon_condition(handle, event);
};
}
@ -27,7 +27,7 @@ namespace ui_scripting::lua
{
for (auto& condition : task.endon_conditions)
{
if (condition.first == (uint64_t)event.element && condition.second == event.name)
if (condition == event.name)
{
task.is_deleted = true;
break;
@ -118,7 +118,7 @@ namespace ui_scripting::lua
return {id};
}
void scheduler::add_endon_condition(const task_handle& handle, const element* element, const std::string& event)
void scheduler::add_endon_condition(const task_handle& handle, const std::string& event)
{
auto merger = [&](task_list& tasks)
{
@ -126,7 +126,7 @@ namespace ui_scripting::lua
{
if (task.id == handle.id)
{
task.endon_conditions.emplace_back(element->id, event);
task.endon_conditions.emplace_back(event);
}
}
};

View File

@ -19,7 +19,7 @@ namespace ui_scripting::lua
std::chrono::milliseconds delay{};
bool is_volatile = false;
bool is_deleted = false;
std::vector<std::pair<uint64_t, std::string>> endon_conditions{};
std::vector<std::string> endon_conditions{};
};
class scheduler final
@ -46,7 +46,7 @@ namespace ui_scripting::lua
utils::concurrency::container<task_list, std::recursive_mutex> callbacks_;
std::atomic_int64_t current_task_id_ = 0;
void add_endon_condition(const task_handle& handle, const element* element, const std::string& event);
void add_endon_condition(const task_handle& handle, const std::string& event);
void remove(const task_handle& handle);
void merge_callbacks();

View File

@ -1,66 +0,0 @@
#include <std_include.hpp>
#include "menu.hpp"
#include "lua/engine.hpp"
#include "component/ui_scripting.hpp"
namespace ui_scripting
{
menu::menu()
{
}
void menu::add_child(element* el)
{
this->children.push_back(el);
}
void menu::open()
{
if (this->visible)
{
return;
}
this->cursor_was_enabled = *game::keyCatchers & 0x40;
if (this->cursor)
{
*game::keyCatchers |= 0x40;
}
this->visible = true;
}
void menu::close()
{
if (!this->visible)
{
return;
}
if (this->cursor && !this->cursor_was_enabled)
{
*game::keyCatchers &= ~0x40;
}
this->visible = false;
}
void menu::render()
{
if (this->cursor && !(*game::keyCatchers & 0x40))
{
this->visible = false;
return;
}
for (auto& element : this->children)
{
if (element->hidden)
{
continue;
}
element->render();
}
}
}

View File

@ -1,35 +0,0 @@
#pragma once
#include "game/game.hpp"
#include "element.hpp"
namespace ui_scripting
{
enum menu_type
{
normal,
overlay
};
class menu final
{
public:
menu();
bool visible = false;
bool hidden = false;
bool cursor = false;
bool ignoreevents = false;
bool cursor_was_enabled = false;
void open();
void close();
void add_child(element* el);
void render();
menu_type type = normal;
std::string overlay_menu;
std::vector<element*> children{};
};
}

View File

@ -10,19 +10,25 @@ namespace utils::http
{
struct progress_helper
{
const std::function<void(size_t)>* callback{};
const std::function<void(size_t, size_t, float)>* callback{};
std::exception_ptr exception{};
std::chrono::high_resolution_clock::time_point start{};
};
int progress_callback(void *clientp, const curl_off_t /*dltotal*/, const curl_off_t dlnow, const curl_off_t /*ultotal*/, const curl_off_t /*ulnow*/)
int progress_callback(void *clientp, const curl_off_t dltotal, const curl_off_t dlnow, const curl_off_t /*ultotal*/, const curl_off_t /*ulnow*/)
{
auto* helper = static_cast<progress_helper*>(clientp);
try
{
const auto now = std::chrono::high_resolution_clock::now();
const auto count = std::chrono::duration_cast<
std::chrono::milliseconds>(now - helper->start).count();
const auto speed = (static_cast<float>(dlnow) / static_cast<float>(count)) * 1000.f;
if (*helper->callback)
{
(*helper->callback)(dlnow);
(*helper->callback)(dlnow, dltotal, speed);
}
}
catch(...)
@ -44,7 +50,8 @@ namespace utils::http
}
}
std::optional<std::string> get_data(const std::string& url, const headers& headers, const std::function<void(size_t)>& callback)
std::optional<std::string> get_data(const std::string& url, const headers& headers,
const std::function<void(size_t, size_t, float)>& callback)
{
curl_slist* header_list = nullptr;
auto* curl = curl_easy_init();
@ -68,6 +75,7 @@ namespace utils::http
std::string buffer{};
progress_helper helper{};
helper.callback = &callback;
helper.start = std::chrono::high_resolution_clock::now();
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
curl_easy_setopt(curl, CURLOPT_URL, url.data());
@ -82,7 +90,7 @@ namespace utils::http
return {std::move(buffer)};
}
if(helper.exception)
if (helper.exception)
{
std::rethrow_exception(helper.exception);
}

View File

@ -8,6 +8,7 @@ namespace utils::http
{
using headers = std::unordered_map<std::string, std::string>;
std::optional<std::string> get_data(const std::string& url, const headers& headers = {}, const std::function<void(size_t)>& callback = {});
std::optional<std::string> get_data(const std::string& url, const headers& headers = {},
const std::function<void(size_t, size_t, float)>& callback = {});
std::future<std::optional<std::string>> get_data_async(const std::string& url, const headers& headers = {});
}