Decompile and hook mouse wheel input processing

This commit is contained in:
Marijn van der Werf 2018-06-13 15:12:51 +02:00
parent b2111d8582
commit da329a08de
6 changed files with 253 additions and 0 deletions

View File

@ -66,6 +66,7 @@
<ClCompile Include="openloco.cpp" />
<ClCompile Include="gui.cpp" />
<ClCompile Include="windows\constructionwnd.cpp" />
<ClCompile Include="windows\map.cpp" />
<ClCompile Include="windows\promptbrowsewnd.cpp" />
<ClCompile Include="windows\promptokcancelwnd.cpp" />
<ClCompile Include="windows\stationwnd.cpp" />

View File

@ -32,4 +32,15 @@ namespace openloco::ui::scrollview
*output_scroll_area = (scroll_part)regs.cx;
*scroll_id = regs.edx;
}
// 0x004CA1ED
void update_thumbs(window* window, widget_index widgetIndex)
{
registers regs;
regs.esi = (uintptr_t)window;
regs.ebx = window->get_scroll_data_index(widgetIndex) * sizeof(scroll_area_t);
regs.edi = (uintptr_t)&window->widgets[widgetIndex];
call(0x4CA1ED, regs);
}
}

View File

@ -30,4 +30,5 @@ namespace openloco::ui::scrollview
int16_t* output_y,
scroll_part* output_scroll_area,
int32_t* scroll_id);
void update_thumbs(window* window, widget_index widgetIndex);
}

View File

@ -2,8 +2,11 @@
#include "companymgr.h"
#include "console.h"
#include "graphics/colours.h"
#include "input.h"
#include "interop/interop.hpp"
#include "tutorial.h"
#include "ui.h"
#include "ui/scrollview.h"
#include <algorithm>
using namespace openloco::interop;
@ -245,6 +248,16 @@ namespace openloco::ui::windowmgr
close_topmost();
regs = backup;
return 0;
});
register_hook(
0x004C6202,
[](registers& regs) -> uint8_t {
registers backup = regs;
all_wheel_input();
regs = backup;
return 0;
});
}
@ -799,4 +812,216 @@ namespace openloco::ui::windowmgr
break;
}
}
static loco_global<int32_t, 0x00525330> _cursorWheel;
static void window_scroll_wheel_input(ui::window *window, widget_index widgetIndex, int wheel)
{
int scrollIndex = window->get_scroll_data_index(widgetIndex);
scroll_area_t* scroll = &window->scroll_areas[scrollIndex];
ui::widget_t* widget = &window->widgets[widgetIndex];
if (window->scroll_areas[scrollIndex].flags & 0b10000)
{
int size = widget->bottom - widget->top - 1;
if (scroll->flags & 0b1)
size -= 11;
size = std::max(0, scroll->v_bottom - size);
scroll->v_top = std::clamp(scroll->v_top + wheel, 0, size);
}
else if (window->scroll_areas[scrollIndex].flags & 0b1)
{
int size = widget->right - widget->left - 1;
if (scroll->flags & 0b10000)
size -= 11;
size = std::max(0, scroll->h_right - size);
scroll->h_left = std::clamp(scroll->h_left + wheel, 0, size);
}
ui::scrollview::update_thumbs(window, widgetIndex);
invalidate_widget(window->type, window->number, widgetIndex);
}
// 0x004C628E
static bool window_wheel_input(window* window, int wheel)
{
int widgetIndex = -1;
int scrollIndex = -1;
for (widget_t* widget = window->widgets; widget->type != widget_type::end; widget++)
{
widgetIndex++;
if (widget->type != widget_type::scrollview)
continue;
scrollIndex++;
if (window->scroll_areas[scrollIndex].flags & 0b10001)
{
window_scroll_wheel_input(window, widgetIndex, wheel);
return true;
}
}
return false;
}
// TODO: Move
static void sub_45EFDB(ui::window* window)
{
registers regs;
regs.esi = (uintptr_t)window;
call(0x0045EFDB, regs);
}
// TODO: Move
static void sub_45F015(ui::window* window)
{
registers regs;
regs.esi = (uintptr_t)window;
call(0x0045F015, regs);
}
// TODO: Move
static void sub_45F04F(ui::window* window)
{
registers regs;
regs.esi = (uintptr_t)window;
call(0x0045F04F, regs);
}
// TODO: Move
static void sub_45F0ED(ui::window* window)
{
registers regs;
regs.esi = (uintptr_t)window;
call(0x0045F0ED, regs);
}
// TODO: Move
static void sub_49771C()
{
// Might have something to do with town labels
call(0x0049771C);
}
// TODO: Move
static void sub_48DDC3()
{
// Might have something to do with station labels
call(0x0048DDC3);
}
void all_wheel_input()
{
int wheel = 0;
while (true)
{
_cursorWheel -= 120;
if (_cursorWheel < 0)
{
_cursorWheel += 120;
break;
}
wheel -= 17;
}
while (true)
{
_cursorWheel += 120;
if (_cursorWheel > 0)
{
_cursorWheel -= 120;
break;
}
wheel += 17;
}
if (tutorial::state() != tutorial::tutorial_state::none)
return;
if (input::has_flag(input::input_flags::flag5))
{
if (openloco::is_title_mode())
return;
auto main = windowmgr::get_main();
if (main != nullptr)
{
if (wheel > 0)
{
sub_45F04F(main);
}
else if (wheel < 0)
{
sub_45F0ED(main);
}
sub_49771C();
sub_48DDC3();
windows::map_center_on_view_point();
}
return;
}
int32_t x = addr<0x0113E72C, int32_t>();
int32_t y = addr<0x0113E730, int32_t>();
auto window = find_at(x, y);
if (window != nullptr)
{
if (window->type == window_type::main)
{
if (openloco::is_title_mode())
return;
if (wheel > 0)
{
sub_45F015(window);
}
else if (wheel < 0)
{
sub_45EFDB(window);
}
sub_49771C();
sub_48DDC3();
return;
}
else
{
auto widgetIndex = window->find_widget_at(x, y);
if (widgetIndex != -1)
{
if (window->widgets[widgetIndex].type == widget_type::scrollview)
{
auto scrollIndex = window->get_scroll_data_index(widgetIndex);
if (window->scroll_areas[scrollIndex].flags & 0b10001)
{
window_scroll_wheel_input(window, widgetIndex, wheel);
return;
}
}
if (window_wheel_input(window, wheel))
{
return;
}
}
}
}
for (ui::window* w = _windows_end - 1; w >= _windows; w--)
{
if (window_wheel_input(w, wheel))
{
return;
}
}
}
}

View File

@ -101,6 +101,7 @@ namespace openloco::ui::windowmgr
void sub_4CEE0B(window* self);
void sub_4B93A5(uint16_t arg);
void close_topmost();
void all_wheel_input();
}
namespace openloco::ui::windows
@ -119,6 +120,7 @@ namespace openloco::ui::windows
bool prompt_browse(browse_type type, char* path, const char* filter, const char* title);
bool prompt_ok_cancel(string_id okButtonStringId);
void map_center_on_view_point();
}
namespace openloco::ui::textinput

View File

@ -0,0 +1,13 @@
#include "../interop/interop.hpp"
#include "../windowmgr.h"
using namespace openloco::interop;
namespace openloco::ui::windows
{
// 0x0046B5C0
void map_center_on_view_point()
{
call(0x0046B5C0);
}
}