Skip to content

Commit

Permalink
Fixed mouse scrolling
Browse files Browse the repository at this point in the history
  • Loading branch information
twist84 committed Sep 14, 2024
1 parent 207c4df commit d5810a6
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 88 deletions.
4 changes: 2 additions & 2 deletions game/source/input/input_windows.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ struct mouse_state
c_flags<e_mouse_button, byte, k_mouse_button_count> raw_flags;
long relative_x;
long relative_y;
long wheel_delta; // += TEST_FLAGS(usButtonFlags, RI_MOUSE_WHEEL) ? usButtonData : 0
short wheel_delta; // += TEST_FLAGS(usButtonFlags, RI_MOUSE_WHEEL) ? usButtonData : 0
};
static_assert(sizeof(mouse_state) == 0x2C);

Expand Down Expand Up @@ -449,7 +449,7 @@ struct s_input_globals
// sub_511AF0
long mouse_relative_x; // 1
long mouse_relative_y; // 1
long mouse_wheel_delta; // 120, WHEEL_DELTA
short mouse_wheel_delta; // 120, WHEEL_DELTA
long mouse_x_ticks; // 1
long mouse_y_ticks; // 1
long mouse_wheel_ticks; // 1
Expand Down
51 changes: 51 additions & 0 deletions game/source/interface/c_gui_list_widget.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,66 @@
#include "interface/c_gui_list_widget.hpp"

//.text:00B14FD0 ; public: virtual s_runtime_core_widget_definition* c_gui_list_widget::get_core_definition()

c_gui_data* c_gui_list_widget::get_data()
{
return DECLFUNC(0x00B14FE0, c_gui_data*, __thiscall, c_gui_list_widget*)(this);
}

//.text:00B15020 ; public: virtual long c_gui_list_widget::get_datasource_index()
//.text:00B15060 ; public: long c_gui_list_widget::get_element_handle_from_list_item_index(long)
//.text:00B150E0 ; public: long c_gui_list_widget::get_focused_element_handle()
//.text:00B15160 ; public: long c_gui_list_widget::get_focused_item_index()
//.text:00B15170 ; public: long c_gui_list_widget::get_item_count(bool)
//.text:00B151C0 ;

long c_gui_list_widget::get_scroll_position()
{
return DECLFUNC(0x00B15250, long, __thiscall, c_gui_list_widget*)(this);
}

long c_gui_list_widget::get_selectable_item_count()
{
return DECLFUNC(0x00B15260, long, __thiscall, c_gui_list_widget*)(this);
}

//.text:00B152C0 ;
//.text:00B15390 ;
//.text:00B15450 ; private: bool c_gui_list_widget::handle_grid_tab(c_gui_list_item_widget*, e_event_type)
//.text:00B156B0 ; public: virtual bool c_gui_list_widget::handle_tab(c_controller_input_message const*)
//.text:00B157F0 ; private: bool c_gui_list_widget::handle_tab_direction(c_gui_list_item_widget*, c_gui_list_widget::e_list_scroll_direction)
//.text:00B15B70 ; private: bool c_gui_list_widget::handle_tab_to_list_item(c_gui_list_item_widget*, c_gui_list_item_widget*)
//.text:00B15BA0 ; public: virtual void c_gui_list_widget::initialize(s_list_widget_block const*)
//.text:00B15C20 ; public: bool c_gui_list_widget::invoke_submenu(long, long, bool)
//.text:00B15CD0 ; public: bool c_gui_list_widget::invoke_submenu(s_list_widget_block const*, long, bool)
//.text:00B15EA0 ; public: bool c_gui_list_widget::is_submenu_that_needs_disposal() const
//.text:00B15EB0 ; public: bool c_gui_list_widget::list_has_more_elements_following()
//.text:00B15F40 ; public: bool c_gui_list_widget::list_has_more_elements_preceeding()
//.text:00B15FB0 ;
//.text:00B15FC0 ; public: void c_gui_list_widget::mark_as_submenu(bool)
//.text:00B15FD0 ; private: void c_gui_list_widget::offset_horizontal_list_item_indicators()
//.text:00B16130 ; public: virtual void c_gui_list_widget::post_initialize()
//.text:00B16140 ;
//.text:00B16150 ;
//.text:00B16160 ; private: void c_gui_list_widget::set_datasource_name(long)
//.text:00B16170 ; public: bool c_gui_list_widget::set_focused_datasource_element_from_value(long, long, bool)
//.text:00B16230 ; public: bool c_gui_list_widget::set_focused_element_handle(long, bool)

bool c_gui_list_widget::set_focused_item_index(long focused_item_index, bool a2)
{
return DECLFUNC(0x00B162E0, bool, __thiscall, c_gui_list_widget*, long, bool)(this, focused_item_index, a2);
}

void c_gui_list_widget::set_scroll_position(long scroll_position)
{
DECLFUNC(0x00B16440, void, __thiscall, c_gui_list_widget*, long)(this, scroll_position);
}

//.text:00B16490 ;
//.text:00B164F0 ;
//.text:00B16510 ; public: virtual void c_gui_list_widget::update(dword)
//.text:00B165D0 ; private: void __cdecl c_gui_list_widget::update_indicator_bitmap_widget_animation_states()

void c_gui_list_widget::set_selectable_item_cap_count(long selectable_item_cap_count)
{
m_selectable_item_cap_count = selectable_item_cap_count;
Expand Down
3 changes: 3 additions & 0 deletions game/source/interface/c_gui_list_widget.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ struct c_gui_list_widget :
{
public:
c_gui_data* get_data();
long get_scroll_position();
long get_selectable_item_count();
bool set_focused_item_index(long focused_item_index, bool a2);
void set_scroll_position(long scroll_position);
void set_selectable_item_cap_count(long selectable_item_cap_count);

//protected:
Expand Down
146 changes: 72 additions & 74 deletions game/source/interface/user_interface_mouse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,9 @@
#define WIDGET_GET_FIRST_CHILD(WIDGET) (WIDGET)->m_children.__unknown0
#define WIDGET_GET_NEXT_CHILD(WIDGET) (WIDGET)->m_next.__unknown0

HOOK_DECLARE_CALL(0x00A84F49, user_interface_mouse_update); // replacing `user_interface_messaging_update` nullsub

s_user_interface_mouse_globals user_interface_mouse_globals{};
point2d global_cursor_position{};

void __cdecl user_interface_mouse_update()
void user_interface_mouse_update()
{
if (g_windows_params.created_window_handle != GetForegroundWindow())
return;
Expand Down Expand Up @@ -50,19 +47,19 @@ void __cdecl user_interface_mouse_update()

void widget_bounds_from_window_bounds(real_rectangle2d const* window_bounds, real_rectangle2d* widget_bounds)
{
vector2d aspect_ratio_scale = interface_get_aspect_ratio_scaling();

real bounds_width = window_bounds->x1 - window_bounds->x0;
real bounds_height = window_bounds->y1 - window_bounds->y0;
real normalized_width = real(bounds_width / real(c_rasterizer::render_globals.resolution_width));
real normalized_height = real(bounds_height / real(c_rasterizer::render_globals.resolution_height));
real adjusted_x = real(bounds_width / 2) + window_bounds->x0;
real adjusted_y = real(bounds_height / 2) + window_bounds->y0;

widget_bounds->x0 = adjusted_x + (aspect_ratio_scale.i * (widget_bounds->x0 * normalized_width));
widget_bounds->x1 = adjusted_x + (aspect_ratio_scale.i * (widget_bounds->x1 * normalized_width));
widget_bounds->y0 = adjusted_y + (aspect_ratio_scale.j * (widget_bounds->y0 * normalized_height));
widget_bounds->y1 = adjusted_y + (aspect_ratio_scale.j * (widget_bounds->y1 * normalized_height));
vector2d aspect_ratio_scaling = interface_get_aspect_ratio_scaling();

real bounds_x = window_bounds->x1 - window_bounds->x0;
real bounds_y = window_bounds->y1 - window_bounds->y0;
real adjusted_x = real(bounds_x / 2) + window_bounds->x0;
real adjusted_y = real(bounds_y / 2) + window_bounds->y0;
real normalized_x = real(bounds_x / real(c_rasterizer::render_globals.resolution_width));
real normalized_y = real(bounds_y / real(c_rasterizer::render_globals.resolution_height));

widget_bounds->x0 = ((widget_bounds->x0 * normalized_x) * aspect_ratio_scaling.i) + adjusted_x;
widget_bounds->x1 = ((widget_bounds->x1 * normalized_x) * aspect_ratio_scaling.i) + adjusted_x;
widget_bounds->y0 = ((widget_bounds->y0 * normalized_y) * aspect_ratio_scaling.j) + adjusted_y;
widget_bounds->y1 = ((widget_bounds->y1 * normalized_y) * aspect_ratio_scaling.j) + adjusted_y;
}

void user_interface_mouse_update_tracking()
Expand All @@ -80,10 +77,10 @@ void user_interface_mouse_update_tracking()
GetCursorPos(&cursor_position);
ScreenToClient(g_windows_params.created_window_handle, &cursor_position);

long x_delta = abs(cursor_position.x - global_cursor_position.x);
long y_delta = abs(cursor_position.y - global_cursor_position.y);
global_cursor_position.x = cursor_position.x;
global_cursor_position.y = cursor_position.y;
long x_delta = abs(cursor_position.x - user_interface_mouse_globals.update_cursor_position.x);
long y_delta = abs(cursor_position.y - user_interface_mouse_globals.update_cursor_position.y);
user_interface_mouse_globals.update_cursor_position.x = cursor_position.x;
user_interface_mouse_globals.update_cursor_position.y = cursor_position.y;

static real mouse_move_delta = 0.0f;
mouse_move_delta += ((real(y_delta * y_delta + x_delta * x_delta) * 1.0f) / 60.0f);
Expand Down Expand Up @@ -114,14 +111,55 @@ void user_interface_mouse_update_internal()
user_interface_mouse_globals.window_bounds.y0 = y;
user_interface_mouse_globals.window_bounds.y1 = height - y;

user_interface_mouse_globals.last_window_mouse_coords = user_interface_mouse_globals.window_cursor_position;
user_interface_mouse_globals.window_cursor_position.x = real(global_cursor_position.x);
user_interface_mouse_globals.window_cursor_position.y = real(global_cursor_position.y);
user_interface_mouse_globals.last_window_cursor_position = user_interface_mouse_globals.window_cursor_position;
user_interface_mouse_globals.window_cursor_position.x = real(user_interface_mouse_globals.update_cursor_position.x);
user_interface_mouse_globals.window_cursor_position.y = real(user_interface_mouse_globals.update_cursor_position.y);

user_interface_mouse_globals.left_button_frames_down = input_mouse_frames_down(_mouse_button_left_click, _input_type_ui);
user_interface_mouse_globals.right_button_frames_down = input_mouse_frames_down(_mouse_button_right_click, _input_type_ui);

user_interface_mouse_globals.mouse_wheel_delta = input_globals.raw_mouse_state.wheel_delta;
}

void user_interface_mouse_compute_widget_bounds(c_gui_widget* widget, real_rectangle2d* accumulated_bounds, bool(*child_filter)(c_gui_widget const*))
{
real_rectangle2d bounds{};
for (c_gui_widget* child_widget = WIDGET_GET_FIRST_CHILD(widget);
child_widget;
child_widget = WIDGET_GET_NEXT_CHILD(child_widget))
{
if (child_filter(child_widget))
{
csmemset(&bounds, 0, sizeof(bounds));
child_widget->get_current_bounds(&bounds);

if (accumulated_bounds->x0 > bounds.x0 || accumulated_bounds->x0 == 0.0f)
accumulated_bounds->x0 = bounds.x0;

if (bounds.x1 > accumulated_bounds->x1 || accumulated_bounds->x1 == 0.0f)
accumulated_bounds->x1 = bounds.x1;

if (accumulated_bounds->y0 > bounds.y0 || accumulated_bounds->y0 == 0.0f)
accumulated_bounds->y0 = bounds.y0;

user_interface_mouse_globals.left_button_down_ticks = input_mouse_frames_down(_mouse_button_left_click, _input_type_ui);
user_interface_mouse_globals.right_button_down_ticks = input_mouse_frames_down(_mouse_button_right_click, _input_type_ui);
if (bounds.y1 > accumulated_bounds->y1 || accumulated_bounds->y1 == 0.0f)
accumulated_bounds->y1 = bounds.y1;
}
}
}

user_interface_mouse_globals.mouse_wheel_delta = (short)input_globals.raw_mouse_state.wheel_delta;
void user_interface_mouse_compute_list_item_bounds(c_gui_list_item_widget* list_item_widget, real_rectangle2d* bounds)
{
user_interface_mouse_compute_widget_bounds(list_item_widget, bounds, [](c_gui_widget const* widget) -> bool { return widget->m_visible && widget->m_type == _gui_widget_type_bitmap; });

real_point2d anchor_position{};
anchor_position.x = list_item_widget->m_full_animation_state.__unknown48.x;
anchor_position.y = list_item_widget->m_full_animation_state.__unknown48.y;

bounds->x0 += anchor_position.x;
bounds->x1 += anchor_position.x;
bounds->y0 += anchor_position.y;
bounds->y1 += anchor_position.y;
}

bool user_interface_mouse_handle_spinner_list_widget_focus(c_gui_screen_widget* screen_widget, c_gui_list_widget* list_widget)
Expand All @@ -136,7 +174,7 @@ bool user_interface_mouse_handle_spinner_list_widget_focus(c_gui_screen_widget*
if (!list_widget->get_parent_list_item())
return false;

if (user_interface_mouse_globals.left_button_down_ticks == 1)
if (user_interface_mouse_globals.left_button_frames_down == 1)
event_manager_button_pressed(user_interface_mouse_globals.controller_index, _button_action_a);

c_gui_data* data = screen_widget->get_data(list_widget->m_datasource_name.get_value(), NULL);
Expand Down Expand Up @@ -169,7 +207,7 @@ void user_interface_mouse_handle_scroll_list_widget(c_gui_screen_widget* screen_
s_runtime_list_widget_definition* definition = (s_runtime_list_widget_definition*)list_widget->get_core_definition();
if (list_widget->m_scroll_position != NONE)
{
long scroll_position = scroll_amount + list_widget->m_scroll_position;
long scroll_position = list_widget->m_scroll_position + scroll_amount;

if (scroll_position > current_item_count - definition->items.count)
scroll_position = current_item_count - definition->items.count;
Expand All @@ -186,47 +224,6 @@ void user_interface_mouse_handle_scroll_list_widget(c_gui_screen_widget* screen_
}
}

void user_interface_mouse_compute_widget_bounds(c_gui_widget* widget, real_rectangle2d* accumulated_bounds, bool(*child_filter)(c_gui_widget const*))
{
real_rectangle2d bounds{};
for (c_gui_widget* child_widget = WIDGET_GET_FIRST_CHILD(widget);
child_widget;
child_widget = WIDGET_GET_NEXT_CHILD(child_widget))
{
if (child_filter(child_widget))
{
csmemset(&bounds, 0, sizeof(bounds));
child_widget->get_current_bounds(&bounds);

if (accumulated_bounds->x0 > bounds.x0 || accumulated_bounds->x0 == 0.0f)
accumulated_bounds->x0 = bounds.x0;

if (bounds.x1 > accumulated_bounds->x1 || accumulated_bounds->x1 == 0.0f)
accumulated_bounds->x1 = bounds.x1;

if (accumulated_bounds->y0 > bounds.y0 || accumulated_bounds->y0 == 0.0f)
accumulated_bounds->y0 = bounds.y0;

if (bounds.y1 > accumulated_bounds->y1 || accumulated_bounds->y1 == 0.0f)
accumulated_bounds->y1 = bounds.y1;
}
}
}

void user_interface_mouse_compute_list_item_bounds(c_gui_list_item_widget* list_item_widget, real_rectangle2d* bounds)
{
user_interface_mouse_compute_widget_bounds(list_item_widget, bounds, [](c_gui_widget const* widget) -> bool { return widget->m_visible && widget->m_type == _gui_widget_type_bitmap; });

real_point2d anchor_position{};
anchor_position.x = list_item_widget->m_full_animation_state.__unknown48.x;
anchor_position.y = list_item_widget->m_full_animation_state.__unknown48.y;

bounds->x0 += anchor_position.x;
bounds->x1 += anchor_position.x;
bounds->y0 += anchor_position.y;
bounds->y1 += anchor_position.y;
}

bool user_interface_mouse_handle_list_widget(c_gui_screen_widget* screen_widget, c_gui_list_widget* list_widget)
{
for (c_gui_list_item_widget* list_item_widget = (c_gui_list_item_widget*)list_widget->get_first_child_widget_by_type(_gui_widget_type_list_item);
Expand Down Expand Up @@ -264,7 +261,7 @@ bool user_interface_mouse_handle_list_widget(c_gui_screen_widget* screen_widget,

REFERENCE_DECLARE(offset_pointer(screen_widget, 0x68), dword, v20);
bool v19 = v20 >> 3 || v20 >> 5;
if (user_interface_mouse_globals.left_button_down_ticks == 1 && list_item_widget == focused_widget && !v19)
if (user_interface_mouse_globals.left_button_frames_down == 1 && list_item_widget == focused_widget && !v19)
{
user_interface_mouse_globals.last_focused_widget = list_item_widget;
event_manager_button_pressed(user_interface_mouse_globals.controller_index, _button_action_a);
Expand Down Expand Up @@ -311,7 +308,7 @@ bool user_interface_mouse_handle_list_widgets(c_gui_screen_widget* screen_widget

bool user_interface_mouse_handle_screen_widget(c_gui_screen_widget* screen_widget)
{
if (user_interface_mouse_globals.right_button_down_ticks == 1)
if (user_interface_mouse_globals.right_button_frames_down == 1)
{
event_manager_button_pressed(user_interface_mouse_globals.controller_index, _button_action_b);
return true;
Expand All @@ -331,9 +328,10 @@ bool user_interface_mouse_handle_screen_widget(c_gui_screen_widget* screen_widge
}
}

if (screen_widget->m_name != user_interface_mouse_globals.last_screen_widget_name)
static c_string_id last_screen_widget_name{};
if (screen_widget->m_name != last_screen_widget_name)
{
user_interface_mouse_globals.last_screen_widget_name = screen_widget->m_name;
last_screen_widget_name = screen_widget->m_name;
user_interface_mouse_globals.list_item_selected_dirty = true;
}

Expand Down
18 changes: 8 additions & 10 deletions game/source/interface/user_interface_mouse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,31 @@ struct s_user_interface_mouse_globals
e_controller_index controller_index;
real_rectangle2d window_bounds;
real_point2d window_cursor_position;
real_point2d last_window_mouse_coords;
real_point2d last_window_cursor_position;
point2d update_cursor_position;
byte mouse_move_ticks;
byte left_button_down_ticks;
byte right_button_down_ticks;
byte left_button_frames_down;
byte right_button_frames_down;
short mouse_wheel_delta;
void* last_focused_widget;
c_string_id last_screen_widget_name;
bool list_item_selected_dirty;
};
static_assert(sizeof(s_user_interface_mouse_globals) == 0x38);
static_assert(sizeof(s_user_interface_mouse_globals) == 0x3C);

extern s_user_interface_mouse_globals user_interface_mouse_globals;
extern point2d global_cursor_position;

struct c_gui_widget;
struct c_gui_list_item_widget;
struct c_gui_list_widget;
struct c_gui_screen_widget;

extern void __cdecl user_interface_mouse_update();

extern void user_interface_mouse_update();
extern void user_interface_mouse_update_tracking();
extern void user_interface_mouse_update_internal();
extern bool user_interface_mouse_handle_spinner_list_widget_focus(c_gui_screen_widget* screen_widget, c_gui_list_widget* list_widget);
extern void user_interface_mouse_handle_scroll_list_widget(c_gui_screen_widget* screen_widget, c_gui_list_widget* list_widget, long scroll_amount);
extern void user_interface_mouse_compute_widget_bounds(c_gui_widget* widget, real_rectangle2d* accumulated_bounds, bool(*child_filter)(c_gui_widget const*));
extern void user_interface_mouse_compute_list_item_bounds(c_gui_list_item_widget* list_item_widget, real_rectangle2d* bounds);
extern bool user_interface_mouse_handle_spinner_list_widget_focus(c_gui_screen_widget* screen_widget, c_gui_list_widget* list_widget);
extern void user_interface_mouse_handle_scroll_list_widget(c_gui_screen_widget* screen_widget, c_gui_list_widget* list_widget, long scroll_amount);
extern bool user_interface_mouse_handle_list_widget(c_gui_screen_widget* screen_widget, c_gui_list_widget* list_widget);
extern bool user_interface_mouse_handle_list_widgets(c_gui_screen_widget* screen_widget, c_gui_widget* parent_widget);
extern bool user_interface_mouse_handle_screen_widget(c_gui_screen_widget* screen_widget);
Expand Down
4 changes: 2 additions & 2 deletions game/source/shell/shell_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,9 +393,9 @@ void __cdecl WndProc_HandleMouse(UINT Msg, WPARAM wParam, LPARAM lParam)
case WM_MBUTTONDOWN: HANDLE_MOUSE_BUTTON(type_down, button_middle_click);
case WM_MBUTTONUP: HANDLE_MOUSE_BUTTON(type_up, button_middle_click);
case WM_MOUSEWHEEL:
input_globals.raw_mouse_state.wheel_delta += GET_WHEEL_DELTA_WPARAM(wParam);
mouse.mouse_type = _mouse_type_wheel;
mouse.wheel_delta = GET_WHEEL_DELTA_WPARAM(wParam);
input_globals.raw_mouse_state.wheel_delta += mouse.wheel_delta;
mouse.wheel_delta = input_globals.raw_mouse_state.wheel_delta;
break;
case WM_XBUTTONDOWN:
if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) HANDLE_MOUSE_BUTTON(type_down, button_4);
Expand Down

0 comments on commit d5810a6

Please sign in to comment.