Decompile widget drawing
This commit is contained in:
parent
1e7a6e60ec
commit
8f8ab7ca13
|
@ -0,0 +1,24 @@
|
|||
#include "../interop/interop.hpp"
|
||||
#include "colours.h"
|
||||
#include <cassert>
|
||||
|
||||
using namespace openloco::interop;
|
||||
|
||||
namespace openloco::colour
|
||||
{
|
||||
|
||||
loco_global<uint8_t[32][8], 0x01136BA0> _colour_map_a;
|
||||
loco_global<uint8_t[32][8], 0x01136C98> _colour_map_b;
|
||||
|
||||
uint8_t get_shade(colour_t colour, uint8_t shade)
|
||||
{
|
||||
assert(colour <= 31);
|
||||
|
||||
if (shade < 8)
|
||||
{
|
||||
return _colour_map_a[colour][shade];
|
||||
}
|
||||
|
||||
return _colour_map_b[colour][shade - 8];
|
||||
}
|
||||
}
|
|
@ -52,5 +52,7 @@ namespace openloco
|
|||
{
|
||||
return c & ~translucent_flag;
|
||||
}
|
||||
|
||||
uint8_t get_shade(colour_t colour, uint8_t shade);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,6 +139,33 @@ namespace openloco::gfx
|
|||
clear(dpi, fill);
|
||||
}
|
||||
|
||||
// 0x004957C4
|
||||
int16_t clip_string(int16_t width, char* string)
|
||||
{
|
||||
|
||||
registers regs;
|
||||
regs.di = width;
|
||||
regs.esi = (int32_t)string;
|
||||
call(0x004957C4, regs);
|
||||
return regs.cx;
|
||||
}
|
||||
|
||||
void draw_string(
|
||||
drawpixelinfo_t& dpi,
|
||||
int16_t x,
|
||||
int16_t y,
|
||||
uint8_t colour,
|
||||
const char* string)
|
||||
{
|
||||
registers regs;
|
||||
regs.cx = x;
|
||||
regs.dx = y;
|
||||
regs.al = colour;
|
||||
regs.edi = (int32_t)&dpi;
|
||||
regs.esi = (int32_t)string;
|
||||
call(0x00451025, regs);
|
||||
}
|
||||
|
||||
// 0x00494B3F
|
||||
// al: colour
|
||||
// bx: string id
|
||||
|
@ -192,6 +219,26 @@ namespace openloco::gfx
|
|||
call(0x00494BBF, regs);
|
||||
}
|
||||
|
||||
void draw_string_centred_clipped(
|
||||
drawpixelinfo_t& dpi,
|
||||
int16_t x,
|
||||
int16_t y,
|
||||
int16_t width,
|
||||
uint8_t colour,
|
||||
string_id stringId,
|
||||
const char* args)
|
||||
{
|
||||
registers regs;
|
||||
regs.edi = (int32_t)&dpi;
|
||||
regs.esi = (int32_t)args;
|
||||
regs.ebx = stringId;
|
||||
regs.cx = x;
|
||||
regs.dx = y;
|
||||
regs.al = colour;
|
||||
regs.bp = width;
|
||||
call(0x00494C36, regs);
|
||||
}
|
||||
|
||||
// 0x004474BA
|
||||
static void draw_rect_impl(gfx::drawpixelinfo_t* dpi, int16_t left, int16_t top, int16_t right, int16_t bottom, uint32_t color)
|
||||
{
|
||||
|
@ -205,12 +252,30 @@ namespace openloco::gfx
|
|||
call(0x004474BA, regs);
|
||||
}
|
||||
|
||||
void fill_rect(gfx::drawpixelinfo_t* dpi, int16_t left, int16_t top, int16_t right, int16_t bottom, uint32_t color)
|
||||
{
|
||||
draw_rect_impl(dpi, left, top, right, bottom, color);
|
||||
}
|
||||
|
||||
void draw_rect(gfx::drawpixelinfo_t* dpi, int16_t x, int16_t y, uint16_t dx, uint16_t dy, uint32_t color)
|
||||
{
|
||||
// This makes the function signature more like a drawing application
|
||||
draw_rect_impl(dpi, x, y, x + dx - 1, y + dy - 1, color);
|
||||
}
|
||||
|
||||
void fill_rect_inset(gfx::drawpixelinfo_t* dpi, int16_t left, int16_t top, int16_t right, int16_t bottom, uint32_t color, uint8_t flags)
|
||||
{
|
||||
registers regs;
|
||||
regs.ax = left;
|
||||
regs.bx = right;
|
||||
regs.cx = top;
|
||||
regs.dx = bottom;
|
||||
regs.ebp = color;
|
||||
regs.edi = (uint32_t)dpi;
|
||||
regs.si = flags;
|
||||
call(0x004C58C7, regs);
|
||||
}
|
||||
|
||||
// 0x004CD406
|
||||
void invalidate_screen()
|
||||
{
|
||||
|
@ -227,4 +292,47 @@ namespace openloco::gfx
|
|||
regs.bp = bottom;
|
||||
call(0x004C5C69, regs);
|
||||
}
|
||||
|
||||
void draw_image(gfx::drawpixelinfo_t* dpi, int16_t x, int16_t y, uint32_t image)
|
||||
{
|
||||
registers regs;
|
||||
regs.cx = x;
|
||||
regs.dx = y;
|
||||
regs.ebx = image;
|
||||
regs.edi = (uint32_t)dpi;
|
||||
call(0x00448C79, regs);
|
||||
}
|
||||
|
||||
loco_global<uint8_t*, 0x0050B860> _50B860;
|
||||
loco_global<uint32_t, 0x00E04324> _E04324;
|
||||
|
||||
void draw_image_solid(gfx::drawpixelinfo_t* dpi, int16_t x, int16_t y, uint32_t image, uint8_t palette_index)
|
||||
{
|
||||
uint8_t palette[256];
|
||||
memset(palette, palette_index, 256);
|
||||
palette[0] = 0;
|
||||
|
||||
_50B860 = palette;
|
||||
_E04324 = 0x20000000;
|
||||
registers regs;
|
||||
regs.cx = x;
|
||||
regs.dx = y;
|
||||
regs.ebx = image;
|
||||
regs.edi = (uint32_t)dpi;
|
||||
call(0x00448D90, regs);
|
||||
}
|
||||
|
||||
bool clip_drawpixelinfo(gfx::drawpixelinfo_t** dst, gfx::drawpixelinfo_t* src, int16_t x, int16_t y, int16_t width, int16_t height)
|
||||
{
|
||||
registers regs;
|
||||
regs.ax = x;
|
||||
regs.bx = width;
|
||||
regs.edi = (int32_t)src;
|
||||
regs.dx = height;
|
||||
regs.cx = y;
|
||||
call(0x4cec50, regs);
|
||||
*dst = (gfx::drawpixelinfo_t*)regs.edi;
|
||||
|
||||
return *dst != nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,6 +69,16 @@ namespace openloco::gfx
|
|||
void load_g1();
|
||||
void clear(drawpixelinfo_t& dpi, uint32_t fill);
|
||||
void clear_single(drawpixelinfo_t& dpi, uint8_t paletteId);
|
||||
|
||||
int16_t clip_string(int16_t width, char* string);
|
||||
|
||||
void draw_string(
|
||||
drawpixelinfo_t& dpi,
|
||||
int16_t x,
|
||||
int16_t y,
|
||||
uint8_t colour,
|
||||
const char* string);
|
||||
|
||||
void draw_string_494B3F(
|
||||
drawpixelinfo_t& dpi,
|
||||
int16_t x,
|
||||
|
@ -84,7 +94,22 @@ namespace openloco::gfx
|
|||
uint8_t colour,
|
||||
string_id stringId,
|
||||
const void* args);
|
||||
void draw_string_centred_clipped(
|
||||
drawpixelinfo_t& dpi,
|
||||
int16_t x,
|
||||
int16_t y,
|
||||
int16_t width,
|
||||
uint8_t colour,
|
||||
string_id stringId,
|
||||
const char* args);
|
||||
|
||||
void fill_rect(gfx::drawpixelinfo_t* dpi, int16_t left, int16_t top, int16_t right, int16_t bottom, uint32_t color);
|
||||
void draw_rect(gfx::drawpixelinfo_t* dpi, int16_t x, int16_t y, uint16_t dx, uint16_t dy, uint32_t color);
|
||||
void fill_rect_inset(gfx::drawpixelinfo_t* dpi, int16_t left, int16_t top, int16_t right, int16_t bottom, uint32_t color, uint8_t flags);
|
||||
void draw_image(gfx::drawpixelinfo_t* dpi, int16_t x, int16_t y, uint32_t image);
|
||||
void draw_image_solid(gfx::drawpixelinfo_t* dpi, int16_t x, int16_t y, uint32_t image, uint8_t palette_index);
|
||||
void invalidate_screen();
|
||||
void set_dirty_blocks(int32_t left, int32_t top, int32_t right, int32_t bottom);
|
||||
|
||||
bool clip_drawpixelinfo(gfx::drawpixelinfo_t** dst, gfx::drawpixelinfo_t* src, int16_t x, int16_t y, int16_t width, int16_t height);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ using namespace openloco::interop;
|
|||
namespace openloco::gui
|
||||
{
|
||||
|
||||
loco_global<openloco::ui::widget[64], 0x00509c20> _mainWindowWidgets;
|
||||
loco_global<openloco::ui::widget_t[64], 0x00509c20> _mainWindowWidgets;
|
||||
|
||||
// 0x00438A6C
|
||||
void init()
|
||||
|
@ -60,7 +60,7 @@ namespace openloco::gui
|
|||
92,
|
||||
ui::window_flags::flag_1 | ui::window_flags::flag_4 | ui::window_flags::flag_5 | ui::window_flags::flag_6,
|
||||
(void*)0x004f9ec8);
|
||||
window->widgets = (ui::widget*)0x00509df4;
|
||||
window->widgets = (ui::widget_t*)0x00509df4;
|
||||
window->enabled_widgets = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5);
|
||||
|
||||
windowmgr::init_scroll_widgets(window);
|
||||
|
@ -77,7 +77,7 @@ namespace openloco::gui
|
|||
28,
|
||||
ui::window_flags::flag_1 | ui::window_flags::flag_4 | ui::window_flags::flag_5 | ui::window_flags::flag_6,
|
||||
(void*)0x004f9f3c);
|
||||
window->widgets = (ui::widget*)0x00509e58;
|
||||
window->widgets = (ui::widget_t*)0x00509e58;
|
||||
window->enabled_widgets = (1 << 0);
|
||||
|
||||
windowmgr::init_scroll_widgets(window);
|
||||
|
@ -93,7 +93,7 @@ namespace openloco::gui
|
|||
170,
|
||||
ui::window_flags::flag_1,
|
||||
(void*)0x004f9fb0);
|
||||
window->widgets = (ui::widget*)0x00509e6c;
|
||||
window->widgets = (ui::widget_t*)0x00509e6c;
|
||||
window->enabled_widgets = (1 << 0);
|
||||
|
||||
windowmgr::init_scroll_widgets(window);
|
||||
|
@ -115,7 +115,7 @@ namespace openloco::gui
|
|||
28,
|
||||
ui::window_flags::flag_1 | ui::window_flags::flag_4 | ui::window_flags::flag_5,
|
||||
(void*)0x4fa180);
|
||||
window->widgets = (ui::widget*)0x509c34;
|
||||
window->widgets = (ui::widget_t*)0x509c34;
|
||||
window->enabled_widgets = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12);
|
||||
windowmgr::init_scroll_widgets(window);
|
||||
|
||||
|
@ -136,7 +136,7 @@ namespace openloco::gui
|
|||
27,
|
||||
ui::window_flags::flag_1 | ui::window_flags::flag_4 | ui::window_flags::flag_5,
|
||||
(void*)0x4fa024);
|
||||
window->widgets = (ui::widget*)0x509d08;
|
||||
window->widgets = (ui::widget_t*)0x509d08;
|
||||
window->enabled_widgets = (1 << 2) | (1 << 3) | (1 << 4);
|
||||
window->var_854 = 0;
|
||||
windowmgr::init_scroll_widgets(window);
|
||||
|
@ -155,7 +155,7 @@ namespace openloco::gui
|
|||
27,
|
||||
ui::window_flags::flag_1 | ui::window_flags::flag_4 | ui::window_flags::flag_5,
|
||||
(void*)0x4fa098);
|
||||
window->widgets = (ui::widget*)0x509d5c;
|
||||
window->widgets = (ui::widget_t*)0x509d5c;
|
||||
window->enabled_widgets = (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7);
|
||||
window->var_854 = 0;
|
||||
window->var_856 = 0;
|
||||
|
@ -178,7 +178,7 @@ namespace openloco::gui
|
|||
27,
|
||||
ui::window_flags::flag_1 | ui::window_flags::flag_4 | ui::window_flags::flag_5,
|
||||
(void*)0x4fa10c);
|
||||
window->widgets = (ui::widget*)0x509de0;
|
||||
window->widgets = (ui::widget_t*)0x509de0;
|
||||
windowmgr::init_scroll_widgets(window);
|
||||
|
||||
if (skin != nullptr)
|
||||
|
|
|
@ -654,6 +654,15 @@ void openloco::interop::register_hooks()
|
|||
return 0;
|
||||
});
|
||||
|
||||
register_hook(
|
||||
0x004CA4DF,
|
||||
[](registers& regs) FORCE_ALIGN_ARG_POINTER -> uint8_t {
|
||||
auto window = (ui::window*)regs.esi;
|
||||
auto dpi = (gfx::drawpixelinfo_t*)regs.edi;
|
||||
window->draw(dpi);
|
||||
return 0;
|
||||
});
|
||||
|
||||
ui::tooltip::register_hooks();
|
||||
|
||||
register_hook(
|
||||
|
|
|
@ -11,4 +11,13 @@ namespace openloco::stringmgr
|
|||
{
|
||||
return _strings[id];
|
||||
}
|
||||
|
||||
void format_string(char* buffer, string_id id, void* args)
|
||||
{
|
||||
registers regs;
|
||||
regs.eax = id;
|
||||
regs.edi = (uint32_t)buffer;
|
||||
regs.ecx = (uint32_t)args;
|
||||
call(0x004958C6, regs);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,5 @@ namespace openloco
|
|||
namespace openloco::stringmgr
|
||||
{
|
||||
const char* get_string(string_id id);
|
||||
void format_string(char* buffer, string_id id, void* args);
|
||||
}
|
||||
|
|
|
@ -48,12 +48,14 @@
|
|||
</ClCompile>
|
||||
<ClCompile Include="viewportmgr.cpp" />
|
||||
<ClCompile Include="window.cpp" />
|
||||
<ClCompile Include="widget.cpp" />
|
||||
<ClCompile Include="intro.cpp" />
|
||||
<ClCompile Include="objects\objectmgr.cpp" />
|
||||
<ClCompile Include="scenariomgr.cpp" />
|
||||
<ClCompile Include="tutorial.cpp" />
|
||||
<ClCompile Include="windowmgr.cpp" />
|
||||
<ClCompile Include="graphics\gfx.cpp" />
|
||||
<ClCompile Include="graphics\colour.cpp" />
|
||||
<ClCompile Include="ui.cpp" />
|
||||
<ClCompile Include="progressbar.cpp" />
|
||||
<ClCompile Include="interop\hook.cpp" />
|
||||
|
|
|
@ -0,0 +1,604 @@
|
|||
#include "widget.h"
|
||||
#include "graphics/colours.h"
|
||||
#include "input.h"
|
||||
#include "interop/interop.hpp"
|
||||
#include "window.h"
|
||||
#include <cassert>
|
||||
|
||||
using namespace openloco::interop;
|
||||
|
||||
namespace openloco::ui::widget
|
||||
{
|
||||
|
||||
static loco_global<int32_t, 0x112C876> _currentFontSpriteBase;
|
||||
static loco_global<char[512], 0x0112CC04> stringFormatBuffer;
|
||||
static loco_global<char[1], 0x112C826> _commonFormatArgs;
|
||||
|
||||
static loco_global<char[2], 0x005045F8> _strCheckmark;
|
||||
|
||||
void draw_11_c(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint8_t colour, bool disabled, int16_t x, int16_t y, string_id string);
|
||||
void draw_14(gfx::drawpixelinfo_t* dpi, widget_t* widget, uint8_t colour, bool disabled, int16_t x, int16_t y, string_id string);
|
||||
|
||||
static void sub_4CF3EB(const gfx::drawpixelinfo_t* dpi, const window* window, const widget_t* widget, int16_t x, int16_t y, uint8_t colour, int16_t width)
|
||||
{
|
||||
registers regs;
|
||||
regs.eax = colour;
|
||||
regs.bx = width;
|
||||
regs.cx = x;
|
||||
regs.dx = y;
|
||||
regs.esi = (uint32_t)window;
|
||||
regs.edi = (uint32_t)dpi;
|
||||
regs.ebp = (uint32_t)widget;
|
||||
call(0x004CF3EB, regs);
|
||||
}
|
||||
|
||||
// 0x004CAB8E
|
||||
static void draw_resize_handle(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint8_t colour)
|
||||
{
|
||||
if (!(window->flags & window_flags::resizable))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (window->min_height == window->max_height || window->min_width == window->max_width)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t x = widget->right + window->x - 18;
|
||||
int16_t y = widget->bottom + window->y - 18;
|
||||
uint32_t image = 0x20000000 | 2305 | (colour << 19);
|
||||
gfx::draw_image(dpi, x, y, image);
|
||||
}
|
||||
|
||||
void sub_4CADE8(gfx::drawpixelinfo_t* dpi, const window* window, const widget_t* widget, uint8_t colour, bool enabled, bool disabled, bool activated)
|
||||
{
|
||||
int16_t x = widget->left + window->x;
|
||||
int16_t y = widget->top + window->y;
|
||||
uint32_t image = widget->image;
|
||||
|
||||
if (widget->type == widget_type::wt_6 || widget->type == widget_type::wt_7 || widget->type == widget_type::wt_8 || widget->type == widget_type::wt_4)
|
||||
{
|
||||
if (activated)
|
||||
{
|
||||
// TODO: remove image addition
|
||||
image++;
|
||||
}
|
||||
}
|
||||
|
||||
if (disabled)
|
||||
{
|
||||
if (image & (1 << 31))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
image &= 0x7FFFF;
|
||||
uint8_t c;
|
||||
if (colour & openloco::colour::translucent_flag)
|
||||
{
|
||||
c = openloco::colour::get_shade(colour & 0x7F, 4);
|
||||
gfx::draw_image_solid(dpi, x + 1, y + 1, image, c);
|
||||
c = openloco::colour::get_shade(colour & 0x7F, 2);
|
||||
gfx::draw_image_solid(dpi, x, y, image, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
c = openloco::colour::get_shade(colour & 0x7F, 6);
|
||||
gfx::draw_image_solid(dpi, x + 1, y + 1, image, c);
|
||||
c = openloco::colour::get_shade(colour & 0x7F, 4);
|
||||
gfx::draw_image_solid(dpi, x, y, image, c);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (image & (1 << 31))
|
||||
{
|
||||
// 0x4CAE5F
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if (image & (1 << 30))
|
||||
{
|
||||
image |= colour << 19;
|
||||
}
|
||||
|
||||
gfx::draw_image(dpi, x, y, image);
|
||||
}
|
||||
|
||||
// 0x004CAB58
|
||||
void draw_1(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour)
|
||||
{
|
||||
gfx::fill_rect_inset(dpi, window->x + widget->left, window->y + widget->top, window->x + widget->right, window->y + widget->bottom, colour, flags);
|
||||
|
||||
draw_resize_handle(dpi, window, widget, colour);
|
||||
}
|
||||
|
||||
// 0x004CAAB9
|
||||
void draw_2(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour)
|
||||
{
|
||||
gfx::drawpixelinfo_t* clipped = nullptr;
|
||||
if (gfx::clip_drawpixelinfo(&clipped, dpi, widget->left + window->x, widget->top + window->y, widget->right - widget->left, 41))
|
||||
{
|
||||
uint32_t image;
|
||||
if (window->flags & window_flags::flag_11)
|
||||
{
|
||||
image = 0x20000000 | 2322 | ((colour & 0x7F) << 19);
|
||||
}
|
||||
else
|
||||
{
|
||||
image = 0x20000000 | 2323 | ((colour & 0x7F) << 19);
|
||||
}
|
||||
gfx::draw_image(clipped, 0, 0, image);
|
||||
}
|
||||
|
||||
uint8_t shade;
|
||||
if (window->flags & window_flags::flag_11)
|
||||
{
|
||||
shade = openloco::colour::get_shade(colour, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
shade = openloco::colour::get_shade(colour, 1);
|
||||
}
|
||||
|
||||
gfx::fill_rect(
|
||||
dpi,
|
||||
window->x + widget->right,
|
||||
window->y + widget->top,
|
||||
window->x + widget->right,
|
||||
window->y + widget->top + 40,
|
||||
shade);
|
||||
|
||||
draw_resize_handle(dpi, window, widget, colour);
|
||||
}
|
||||
|
||||
void draw_3(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool enabled, bool disabled, bool activated)
|
||||
{
|
||||
int16_t top, left, bottom, right;
|
||||
top = window->y + widget->top;
|
||||
left = window->x + widget->left;
|
||||
right = window->x + widget->right;
|
||||
bottom = window->y + widget->bottom;
|
||||
|
||||
if (activated)
|
||||
{
|
||||
flags |= 0x20;
|
||||
}
|
||||
|
||||
if (widget->content == -2)
|
||||
{
|
||||
flags |= 0x10;
|
||||
gfx::fill_rect_inset(dpi, left, top, right, bottom, colour, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
if (window->flags & window_flags::flag_6)
|
||||
{
|
||||
gfx::fill_rect(dpi, left, top, right, bottom, 0x2000000 | 52);
|
||||
}
|
||||
|
||||
gfx::fill_rect_inset(dpi, left, top, right, bottom, colour, flags);
|
||||
|
||||
if (widget->content == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sub_4CADE8(dpi, window, widget, colour, enabled, disabled, activated);
|
||||
}
|
||||
|
||||
// 0x004CABFE
|
||||
void draw_5(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool enabled, bool disabled, bool activated)
|
||||
{
|
||||
if (widget->content == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!disabled)
|
||||
{
|
||||
widget::sub_4CADE8(dpi, window, widget, colour, enabled, disabled, activated);
|
||||
return;
|
||||
}
|
||||
|
||||
if (widget->type == widget_type::wt_8)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (widget->type != widget_type::wt_7)
|
||||
{
|
||||
widget::sub_4CADE8(dpi, window, widget, colour, enabled, disabled, activated);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Remove image addition
|
||||
uint32_t image = widget->image + 2;
|
||||
|
||||
if (image & (1 << 30))
|
||||
{
|
||||
image |= colour << 19;
|
||||
}
|
||||
|
||||
gfx::draw_image(dpi, window->x + widget->left, window->y + widget->top, image);
|
||||
}
|
||||
|
||||
// 0x004CACD4
|
||||
void draw_9(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool enabled, bool disabled, bool activated, bool hovered)
|
||||
{
|
||||
if (!disabled && hovered)
|
||||
{
|
||||
// TODO: Fix mixed windows
|
||||
widget::draw_3(dpi, window, widget, flags, colour, enabled, disabled, activated);
|
||||
return;
|
||||
}
|
||||
|
||||
int l = widget->left + window->x;
|
||||
int t = widget->top + window->y;
|
||||
int r = widget->right + window->x;
|
||||
int b = widget->bottom + window->y;
|
||||
|
||||
if (activated)
|
||||
{
|
||||
flags |= 0x20;
|
||||
if (widget->content == -2)
|
||||
{
|
||||
// 0x004CABE8
|
||||
|
||||
flags |= 0x10;
|
||||
gfx::fill_rect_inset(dpi, l, t, r, b, colour, flags);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
gfx::fill_rect_inset(dpi, l, t, r, b, colour, flags);
|
||||
}
|
||||
|
||||
if (widget->content == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
widget::sub_4CADE8(dpi, window, widget, colour, enabled, disabled, activated);
|
||||
}
|
||||
|
||||
// 0x004CAC5F
|
||||
void draw_10(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool enabled, bool disabled, bool activated, bool hovered)
|
||||
{
|
||||
if (widget->content == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t image = widget->image;
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
// TODO: Remove image addition
|
||||
image += 2;
|
||||
|
||||
if (!activated)
|
||||
{
|
||||
image -= 1;
|
||||
|
||||
if (!hovered)
|
||||
{
|
||||
image -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (image & (1 << 30))
|
||||
{
|
||||
image |= colour << 19;
|
||||
}
|
||||
|
||||
gfx::draw_image(dpi, window->x + widget->left, window->y + widget->top, image);
|
||||
}
|
||||
|
||||
// 0x004CB164
|
||||
void draw_11_a(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool enabled, bool disabled, bool activated)
|
||||
{
|
||||
int left = window->x + widget->left;
|
||||
int right = window->x + widget->right;
|
||||
int top = window->y + widget->top;
|
||||
int bottom = window->y + widget->bottom;
|
||||
|
||||
if (activated)
|
||||
{
|
||||
flags |= 0x20;
|
||||
}
|
||||
|
||||
gfx::fill_rect_inset(dpi, left, top, right, bottom, colour, flags);
|
||||
}
|
||||
|
||||
// 0x004CB1BE
|
||||
void draw_13(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool enabled, bool disabled, bool activated)
|
||||
{
|
||||
if (widget->content == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t x = window->x + widget->left;
|
||||
int16_t y = window->y + std::max<int16_t>(widget->top, (widget->top + widget->bottom) / 2 - 5);
|
||||
string_id string = widget->text;
|
||||
|
||||
// TODO: Refactor out widget_t type check
|
||||
if (widget->type == widget_type::wt_12)
|
||||
{
|
||||
if (activated)
|
||||
{
|
||||
// TODO: Remove string addition
|
||||
string++;
|
||||
}
|
||||
}
|
||||
|
||||
if (widget->type == widget_type::wt_14)
|
||||
{
|
||||
draw_14(dpi, widget, colour, disabled, x, y, string);
|
||||
}
|
||||
else
|
||||
{
|
||||
draw_11_c(dpi, window, widget, colour, disabled, x, y, string);
|
||||
}
|
||||
}
|
||||
|
||||
// 0x004CB21D
|
||||
void draw_11_c(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint8_t colour, bool disabled, int16_t x, int16_t y, string_id string)
|
||||
{
|
||||
colour &= 0x7F;
|
||||
if (disabled)
|
||||
{
|
||||
colour |= 0x40;
|
||||
}
|
||||
|
||||
int16_t centreX = window->x + (widget->left + widget->right + 1) / 2 - 1;
|
||||
int16_t width = widget->right - widget->left - 2;
|
||||
gfx::draw_string_centred_clipped(*dpi, centreX, y, width, colour, string, _commonFormatArgs);
|
||||
}
|
||||
|
||||
// 0x004CB263
|
||||
void draw_14(gfx::drawpixelinfo_t* dpi, widget_t* widget, uint8_t colour, bool disabled, int16_t x, int16_t y, string_id string)
|
||||
{
|
||||
x = x + 1;
|
||||
|
||||
colour &= 0x7F;
|
||||
if (disabled)
|
||||
{
|
||||
colour |= 0x40;
|
||||
}
|
||||
|
||||
int width = widget->right - widget->left - 2;
|
||||
gfx::draw_string_494BBF(*dpi, x, y, width, colour, string, _commonFormatArgs);
|
||||
}
|
||||
|
||||
// 0x4CB2D6
|
||||
void draw_15(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool disabled)
|
||||
{
|
||||
if (widget->content < 0)
|
||||
{
|
||||
// FIXME: Probably wrong check, but I couldn't think of another meaning
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t c = 0xFD;
|
||||
if (disabled)
|
||||
{
|
||||
c = colour | 0x40;
|
||||
}
|
||||
|
||||
draw_string_494B3F(*dpi, window->x + widget->left + 1, window->y + widget->top, c, widget->text, _commonFormatArgs);
|
||||
}
|
||||
|
||||
// 0x4CB29C
|
||||
void draw_17(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour)
|
||||
{
|
||||
gfx::fill_rect_inset(dpi, window->x + widget->left, window->y + widget->top, window->x + widget->right, window->y + widget->bottom, colour, flags | 0x60);
|
||||
}
|
||||
|
||||
// 0x004CA6AE
|
||||
void draw_22_caption(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour)
|
||||
{
|
||||
int left = window->x + widget->left;
|
||||
int right = window->x + widget->right;
|
||||
int top = window->y + widget->top;
|
||||
int bottom = window->y + widget->bottom;
|
||||
gfx::fill_rect_inset(dpi, left, top, right, bottom, colour, flags | 0x60);
|
||||
gfx::fill_rect(dpi, left + 1, top + 1, right - 1, bottom - 1, 0x2000000 | 46);
|
||||
|
||||
int16_t width = widget->right - widget->left - 4 - 10;
|
||||
int16_t y = widget->top + window->y + 1;
|
||||
int16_t x = widget->left + window->x + 2 + (width / 2);
|
||||
|
||||
gfx::draw_string_centred_clipped(*dpi, x, y, width, colour::white | 0x20, widget->text, _commonFormatArgs);
|
||||
}
|
||||
|
||||
// 0x004CA750
|
||||
void draw_23_caption(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour)
|
||||
{
|
||||
stringFormatBuffer[0] = (char)144;
|
||||
stringmgr::format_string(&stringFormatBuffer[1], widget->text, _commonFormatArgs);
|
||||
|
||||
int16_t width = widget->right - widget->left - 4 - 14;
|
||||
int16_t x = widget->left + window->x + 2 + (width / 2);
|
||||
|
||||
_currentFontSpriteBase = 224;
|
||||
width = gfx::clip_string(width - 8, stringFormatBuffer);
|
||||
|
||||
x -= width / 2;
|
||||
int16_t y = window->y + widget->top + 1;
|
||||
|
||||
sub_4CF3EB(dpi, window, widget, x, y, colour, width);
|
||||
|
||||
gfx::draw_string(*dpi, x, y, colour::black, stringFormatBuffer);
|
||||
}
|
||||
|
||||
// 0x004CA7F6
|
||||
void draw_24_caption(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour)
|
||||
{
|
||||
stringFormatBuffer[0] = (char)13;
|
||||
stringmgr::format_string(&stringFormatBuffer[1], widget->text, _commonFormatArgs);
|
||||
|
||||
int16_t x = widget->left + window->x + 2;
|
||||
int16_t width = widget->right - widget->left - 4 - 14;
|
||||
x = x + (width / 2);
|
||||
|
||||
_currentFontSpriteBase = 224;
|
||||
int16_t stringWidth = gfx::clip_string(width - 8, stringFormatBuffer);
|
||||
x -= (stringWidth - 1) / 2;
|
||||
|
||||
gfx::draw_string(*dpi, x, window->y + widget->top + 1, 0x20, stringFormatBuffer);
|
||||
}
|
||||
|
||||
// 0x004CA88B
|
||||
void draw_25_caption(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour)
|
||||
{
|
||||
stringFormatBuffer[0] = (char)146;
|
||||
stringmgr::format_string(&stringFormatBuffer[1], widget->text, _commonFormatArgs);
|
||||
|
||||
int16_t x = widget->left + window->x + 2;
|
||||
int16_t width = widget->right - widget->left - 4 - 14;
|
||||
x = x + (width / 2);
|
||||
|
||||
_currentFontSpriteBase = 224;
|
||||
int16_t stringWidth = gfx::clip_string(width - 8, stringFormatBuffer);
|
||||
x -= (stringWidth - 1) / 2;
|
||||
|
||||
gfx::draw_string(*dpi, x, window->y + widget->top + 1, 0x20, stringFormatBuffer);
|
||||
}
|
||||
|
||||
// 0x004CB31C
|
||||
void draw_26(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool enabled, bool disabled, bool activated, bool hovered, int16_t scrollview_index)
|
||||
{
|
||||
uint16_t left = window->x + widget->left;
|
||||
uint16_t top = window->y + widget->top;
|
||||
uint16_t right = window->x + widget->right;
|
||||
uint16_t bottom = window->y + widget->bottom;
|
||||
|
||||
gfx::fill_rect_inset(dpi, left, top, right, bottom, colour, flags | 0x60);
|
||||
|
||||
left++;
|
||||
top++;
|
||||
right--;
|
||||
bottom--;
|
||||
|
||||
ui::scroll_area_t* scroll_area = &window->scroll_areas[scrollview_index];
|
||||
|
||||
_currentFontSpriteBase = 224;
|
||||
if (scroll_area->flags & (1 << 0))
|
||||
{
|
||||
// draw horizontal scrollbar
|
||||
bottom -= 11;
|
||||
}
|
||||
|
||||
if (scroll_area->flags & (1 << 4))
|
||||
{
|
||||
// draw vertical scrollbar
|
||||
right -= 11;
|
||||
}
|
||||
|
||||
gfx::drawpixelinfo_t cropped = *dpi;
|
||||
bottom++;
|
||||
right++;
|
||||
|
||||
if (left > cropped.x)
|
||||
{
|
||||
int offset = left - cropped.x;
|
||||
cropped.width -= offset;
|
||||
cropped.x = left;
|
||||
cropped.pitch += offset;
|
||||
|
||||
cropped.bits += offset;
|
||||
}
|
||||
|
||||
int16_t bp = cropped.x + cropped.width - right;
|
||||
if (bp > 0)
|
||||
{
|
||||
cropped.width -= bp;
|
||||
cropped.pitch += bp;
|
||||
}
|
||||
|
||||
if (top > cropped.y)
|
||||
{
|
||||
int offset = top - cropped.y;
|
||||
cropped.height -= offset;
|
||||
cropped.y = top;
|
||||
|
||||
int aex = (cropped.pitch + cropped.width) * offset;
|
||||
cropped.bits += aex;
|
||||
}
|
||||
|
||||
bp = cropped.y + cropped.height - bottom;
|
||||
if (bp > 0)
|
||||
{
|
||||
cropped.height -= bp;
|
||||
}
|
||||
|
||||
if (cropped.width > 0 && cropped.height > 0)
|
||||
{
|
||||
cropped.x -= left - scroll_area->h_left;
|
||||
cropped.y -= top - scroll_area->v_top;
|
||||
|
||||
{
|
||||
registers regs;
|
||||
regs.ax = scrollview_index;
|
||||
regs.esi = (int32_t)window;
|
||||
regs.edi = (int32_t)&cropped;
|
||||
call(window->event_handlers->event_28, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 0x004CB00B
|
||||
void draw_27_checkbox(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool enabled, bool disabled, bool activated)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
gfx::fill_rect_inset(
|
||||
dpi,
|
||||
window->x + widget->left,
|
||||
window->y + widget->top,
|
||||
window->x + widget->left + 9,
|
||||
window->y + widget->bottom - 1,
|
||||
colour,
|
||||
flags | 0x60);
|
||||
}
|
||||
|
||||
if (activated)
|
||||
{
|
||||
_currentFontSpriteBase = 224;
|
||||
gfx::draw_string(*dpi, window->x + widget->left, window->y + widget->top, colour & 0x7F, _strCheckmark);
|
||||
}
|
||||
}
|
||||
|
||||
// 0x004CB080
|
||||
void draw_27_label(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool disabled)
|
||||
{
|
||||
if (widget->content == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
colour &= 0x7F;
|
||||
|
||||
if (disabled)
|
||||
{
|
||||
colour |= 0x40;
|
||||
}
|
||||
|
||||
gfx::draw_string_494B3F(*dpi, window->x + widget->left + 14, window->y + widget->top, colour, widget->text, _commonFormatArgs);
|
||||
}
|
||||
|
||||
// 0x004CA679
|
||||
void draw_29(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget)
|
||||
{
|
||||
int left = window->x + widget->left;
|
||||
int right = window->x + widget->right;
|
||||
int top = window->y + widget->top;
|
||||
int bottom = window->y + widget->bottom;
|
||||
gfx::fill_rect(dpi, left, top, right, bottom, colour::get_shade(colour::black, 5));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include "graphics/gfx.h"
|
||||
#include "localisation/stringmgr.h"
|
||||
#include "window.h"
|
||||
#include <cstdint>
|
||||
|
||||
namespace openloco::ui::widget
|
||||
{
|
||||
void sub_4CADE8(gfx::drawpixelinfo_t* dpi, const window* window, const widget_t* widget, uint8_t colour, bool enabled, bool disabled, bool activated);
|
||||
|
||||
void draw_1(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour);
|
||||
void draw_2(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour);
|
||||
void draw_3(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool enabled, bool disabled, bool activated);
|
||||
|
||||
void draw_5(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool enabled, bool disabled, bool activated);
|
||||
|
||||
void draw_9(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool enabled, bool disabled, bool activated, bool hovered);
|
||||
void draw_10(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool enabled, bool disabled, bool activated, bool hovered);
|
||||
|
||||
void draw_11_a(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool enabled, bool disabled, bool activated);
|
||||
void draw_13(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool enabled, bool disabled, bool activated);
|
||||
|
||||
void draw_15(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool disabled);
|
||||
|
||||
void draw_17(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour);
|
||||
|
||||
void draw_22_caption(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour);
|
||||
void draw_23_caption(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour);
|
||||
void draw_24_caption(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour);
|
||||
void draw_25_caption(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour);
|
||||
void draw_26(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool enabled, bool disabled, bool activated, bool hovered, int16_t scrollview_index);
|
||||
void draw_27_checkbox(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool enabled, bool disabled, bool activated);
|
||||
void draw_27_label(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget, uint16_t flags, uint8_t colour, bool disabled);
|
||||
|
||||
void draw_29(gfx::drawpixelinfo_t* dpi, window* window, widget_t* widget);
|
||||
}
|
|
@ -1,53 +1,251 @@
|
|||
#include "window.h"
|
||||
#include "console.h"
|
||||
#include "graphics/colours.h"
|
||||
#include "input.h"
|
||||
#include "interop/interop.hpp"
|
||||
#include "widget.h"
|
||||
#include <cassert>
|
||||
#include <cinttypes>
|
||||
|
||||
using namespace openloco;
|
||||
using namespace openloco::interop;
|
||||
using namespace openloco::ui;
|
||||
|
||||
template<typename T>
|
||||
static bool is_interop_event(T e)
|
||||
namespace openloco::ui
|
||||
{
|
||||
return (uint32_t)e < 0x004D7000;
|
||||
}
|
||||
|
||||
// 0x004CA4BD
|
||||
void window::invalidate()
|
||||
{
|
||||
registers regs;
|
||||
regs.esi = (int32_t)this;
|
||||
call(0x004CA4BD, regs);
|
||||
}
|
||||
|
||||
void window::sub_4CA17F()
|
||||
{
|
||||
registers regs;
|
||||
regs.esi = (int32_t)this;
|
||||
call(0x004CA17F, regs);
|
||||
}
|
||||
|
||||
bool window::call_tooltip(int16_t widget_index)
|
||||
{
|
||||
registers regs;
|
||||
regs.ax = widget_index;
|
||||
regs.esi = (int32_t)this;
|
||||
call((int32_t)this->event_handlers->tooltip, regs);
|
||||
return regs.ax != (int16_t)string_ids::null;
|
||||
}
|
||||
|
||||
void window::call_prepare_draw()
|
||||
{
|
||||
if (event_handlers->prepare_draw != nullptr)
|
||||
template<typename T>
|
||||
static bool is_interop_event(T e)
|
||||
{
|
||||
if (is_interop_event(event_handlers->prepare_draw))
|
||||
return (uint32_t)e < 0x004D7000;
|
||||
}
|
||||
|
||||
// 0x004CA4BD
|
||||
void window::invalidate()
|
||||
{
|
||||
registers regs;
|
||||
regs.esi = (int32_t)this;
|
||||
call(0x004CA4BD, regs);
|
||||
}
|
||||
|
||||
void window::sub_4CA17F()
|
||||
{
|
||||
registers regs;
|
||||
regs.esi = (int32_t)this;
|
||||
call(0x004CA17F, regs);
|
||||
}
|
||||
|
||||
bool window::call_tooltip(int16_t widget_index)
|
||||
{
|
||||
registers regs;
|
||||
regs.ax = widget_index;
|
||||
regs.esi = (int32_t)this;
|
||||
call((int32_t)this->event_handlers->tooltip, regs);
|
||||
return regs.ax != (int16_t)string_ids::null;
|
||||
}
|
||||
|
||||
void window::call_prepare_draw()
|
||||
{
|
||||
if (event_handlers->prepare_draw != nullptr)
|
||||
{
|
||||
registers regs;
|
||||
regs.esi = (int32_t)this;
|
||||
call((int32_t)this->event_handlers->prepare_draw, regs);
|
||||
if (is_interop_event(event_handlers->prepare_draw))
|
||||
{
|
||||
registers regs;
|
||||
regs.esi = (int32_t)this;
|
||||
call((int32_t)this->event_handlers->prepare_draw, regs);
|
||||
}
|
||||
else
|
||||
{
|
||||
event_handlers->prepare_draw(this);
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
// 0x004CA4DF
|
||||
void window::draw(gfx::drawpixelinfo_t* dpi)
|
||||
{
|
||||
if ((this->flags & window_flags::flag_4) && !(this->flags & window_flags::flag_5))
|
||||
{
|
||||
event_handlers->prepare_draw(this);
|
||||
gfx::fill_rect(dpi, this->x, this->y, this->x + this->width - 1, this->y + this->height - 1, 0x2000000 | 52);
|
||||
}
|
||||
|
||||
uint64_t pressed_widget = 0;
|
||||
if (input::state() == input::input_state::dropdown_active || input::state() == input::input_state::widget_pressed)
|
||||
{
|
||||
if (this->type == addr<0x0052336F, window_type>() && this->number == addr<0x00523370, uint16_t>())
|
||||
{
|
||||
if (input::has_flag((input::input_flags)(1 << 0)))
|
||||
{
|
||||
pressed_widget = 1u << addr<0x00523372, uint32_t>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t tool_widget = 0;
|
||||
if (this->type == addr<0x00523392, window_type>() && this->number == addr<0x00523390, uint16_t>())
|
||||
{
|
||||
tool_widget = 1u << addr<0x00523394, uint32_t>();
|
||||
}
|
||||
|
||||
uint64_t hovered_widget = 0;
|
||||
if (this->type == addr<0x005233A8, window_type>() && this->number == addr<0x005233AA, uint16_t>())
|
||||
{
|
||||
hovered_widget = 1u << addr<0x005233AC, uint16_t>();
|
||||
}
|
||||
|
||||
int scrollviewIndex = 0;
|
||||
for (int widgetIndex = 0; widgetIndex < 64; widgetIndex++)
|
||||
{
|
||||
auto widget = &this->widgets[widgetIndex];
|
||||
auto type = (widget_type)widget->type;
|
||||
|
||||
if (type == widget_type::end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((this->flags & window_flags::flag_5) == 0)
|
||||
{
|
||||
// Check if widget is outside the draw region
|
||||
if (this->x + widget->left >= dpi->x + dpi->width && this->x + widget->right < dpi->x)
|
||||
{
|
||||
if (this->y + widget->top >= dpi->y + dpi->height && this->y + widget->bottom < dpi->y)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t flags = 0;
|
||||
if (widget->colour == 0 && this->flags & window_flags::flag_11)
|
||||
{
|
||||
flags = 0x80;
|
||||
}
|
||||
|
||||
uint8_t colour = this->colours[widget->colour];
|
||||
|
||||
bool enabled = (this->enabled_widgets & (1 << widgetIndex)) != 0;
|
||||
bool disabled = (this->disabled_widgets & (1 << widgetIndex)) != 0;
|
||||
bool activated = (this->activated_widgets & (1 << widgetIndex)) != 0;
|
||||
activated |= (pressed_widget & (1 << widgetIndex)) != 0;
|
||||
activated |= (tool_widget & (1 << widgetIndex)) != 0;
|
||||
bool hovered = (hovered_widget & (1 << widgetIndex)) != 0;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case widget_type::none:
|
||||
case widget_type::end:
|
||||
break;
|
||||
|
||||
case widget_type::panel:
|
||||
widget::draw_1(dpi, this, widget, flags, colour);
|
||||
break;
|
||||
|
||||
case widget_type::frame:
|
||||
widget::draw_2(dpi, this, widget, flags, colour);
|
||||
break;
|
||||
|
||||
case widget_type::wt_3:
|
||||
widget::draw_3(dpi, this, widget, flags, colour, enabled, disabled, activated);
|
||||
break;
|
||||
|
||||
case widget_type::wt_4:
|
||||
assert(false); // Unused
|
||||
break;
|
||||
|
||||
case widget_type::wt_5:
|
||||
case widget_type::wt_6:
|
||||
case widget_type::wt_7:
|
||||
case widget_type::wt_8:
|
||||
widget::draw_5(dpi, this, widget, flags, colour, enabled, disabled, activated);
|
||||
break;
|
||||
|
||||
case widget_type::wt_9:
|
||||
widget::draw_9(dpi, this, widget, flags, colour, enabled, disabled, activated, hovered);
|
||||
break;
|
||||
|
||||
case widget_type::wt_10:
|
||||
widget::draw_10(dpi, this, widget, flags, colour, enabled, disabled, activated, hovered);
|
||||
break;
|
||||
|
||||
case widget_type::wt_11:
|
||||
case widget_type::wt_12:
|
||||
case widget_type::wt_14:
|
||||
if (type == widget_type::wt_12)
|
||||
{
|
||||
assert(false); // Unused
|
||||
}
|
||||
widget::draw_11_a(dpi, this, widget, flags, colour, enabled, disabled, activated);
|
||||
widget::draw_13(dpi, this, widget, flags, colour, enabled, disabled, activated);
|
||||
break;
|
||||
|
||||
case widget_type::wt_13:
|
||||
widget::draw_13(dpi, this, widget, flags, colour, enabled, disabled, activated);
|
||||
break;
|
||||
|
||||
case widget_type::wt_15:
|
||||
case widget_type::wt_16:
|
||||
assert(false); // Unused
|
||||
break;
|
||||
|
||||
case widget_type::wt_17:
|
||||
case widget_type::wt_18:
|
||||
case widget_type::wt_19:
|
||||
widget::draw_17(dpi, this, widget, flags, colour);
|
||||
widget::draw_15(dpi, this, widget, flags, colour, disabled);
|
||||
break;
|
||||
|
||||
case widget_type::wt_20:
|
||||
case widget_type::wt_21:
|
||||
assert(false); // Unused
|
||||
break;
|
||||
|
||||
case widget_type::caption_22:
|
||||
widget::draw_22_caption(dpi, this, widget, flags, colour);
|
||||
break;
|
||||
|
||||
case widget_type::caption_23:
|
||||
widget::draw_23_caption(dpi, this, widget, flags, colour);
|
||||
break;
|
||||
|
||||
case widget_type::caption_24:
|
||||
widget::draw_24_caption(dpi, this, widget, flags, colour);
|
||||
break;
|
||||
|
||||
case widget_type::caption_25:
|
||||
widget::draw_25_caption(dpi, this, widget, flags, colour);
|
||||
break;
|
||||
|
||||
case widget_type::scrollview:
|
||||
widget::draw_26(dpi, this, widget, flags, colour, enabled, disabled, activated, hovered, scrollviewIndex);
|
||||
scrollviewIndex++;
|
||||
break;
|
||||
|
||||
case widget_type::checkbox:
|
||||
widget::draw_27_checkbox(dpi, this, widget, flags, colour, enabled, disabled, activated);
|
||||
widget::draw_27_label(dpi, this, widget, flags, colour, disabled);
|
||||
break;
|
||||
|
||||
case widget_type::wt_28:
|
||||
assert(false); // Unused
|
||||
widget::draw_27_label(dpi, this, widget, flags, colour, disabled);
|
||||
break;
|
||||
|
||||
case widget_type::wt_29:
|
||||
assert(false); // Unused
|
||||
widget::draw_29(dpi, this, widget);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->flags & window_flags::white_border_mask)
|
||||
{
|
||||
gfx::fill_rect_inset(
|
||||
dpi,
|
||||
this->x,
|
||||
this->y,
|
||||
this->x + this->width - 1,
|
||||
this->y + this->height - 1,
|
||||
colour::white,
|
||||
0x10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,37 +7,88 @@
|
|||
namespace openloco::ui
|
||||
{
|
||||
enum class window_type : uint8_t;
|
||||
enum class widget_type : uint8_t;
|
||||
struct window;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct widget
|
||||
struct widget_t
|
||||
{
|
||||
uint8_t type; // 0x00
|
||||
uint8_t colour; // 0x01
|
||||
int16_t left; // 0x02
|
||||
int16_t right; // 0x04
|
||||
int16_t top; // 0x06
|
||||
int16_t bottom; // 0x08
|
||||
widget_type type; // 0x00
|
||||
uint8_t colour; // 0x01
|
||||
int16_t left; // 0x02
|
||||
int16_t right; // 0x04
|
||||
int16_t top; // 0x06
|
||||
int16_t bottom; // 0x08
|
||||
union
|
||||
{
|
||||
uint32_t image;
|
||||
string_id text;
|
||||
uint32_t content;
|
||||
int32_t content;
|
||||
};
|
||||
string_id tooltip; // 0x0E
|
||||
};
|
||||
|
||||
enum class widget_type : uint8_t
|
||||
{
|
||||
none = 0,
|
||||
panel = 1,
|
||||
frame = 2,
|
||||
wt_3,
|
||||
wt_4,
|
||||
wt_5,
|
||||
wt_6,
|
||||
wt_7,
|
||||
wt_8,
|
||||
wt_9,
|
||||
wt_10,
|
||||
wt_11,
|
||||
wt_12,
|
||||
wt_13,
|
||||
wt_14,
|
||||
wt_15,
|
||||
wt_16,
|
||||
wt_17,
|
||||
wt_18,
|
||||
wt_19,
|
||||
wt_20,
|
||||
wt_21,
|
||||
caption_22,
|
||||
caption_23,
|
||||
caption_24,
|
||||
caption_25,
|
||||
scrollview = 26,
|
||||
checkbox = 27,
|
||||
wt_28,
|
||||
wt_29,
|
||||
end = 30,
|
||||
};
|
||||
|
||||
struct scroll_area_t
|
||||
{
|
||||
uint16_t flags; // 0x00
|
||||
uint16_t h_left; // 0x02
|
||||
uint16_t h_right; // 0x04
|
||||
uint16_t h_thumb_left; // 0x06
|
||||
uint16_t h_thumb_right; // 0x08
|
||||
uint16_t v_top; // 0x0A
|
||||
uint16_t v_bottom; // 0x0C
|
||||
uint16_t v_thumb_top; // 0x0E
|
||||
uint16_t v_thumb_bottom; // 0x10
|
||||
};
|
||||
|
||||
namespace window_flags
|
||||
{
|
||||
constexpr uint16_t flag_0 = 1 << 0;
|
||||
constexpr uint16_t flag_1 = 1 << 1;
|
||||
constexpr uint16_t flag_4 = 1 << 4;
|
||||
constexpr uint16_t flag_5 = 1 << 5;
|
||||
constexpr uint16_t flag_6 = 1 << 6;
|
||||
constexpr uint16_t flag_7 = 1 << 7;
|
||||
constexpr uint16_t flag_9 = 1 << 9;
|
||||
constexpr uint16_t flag_12 = 1 << 12;
|
||||
constexpr uint32_t flag_0 = 1 << 0;
|
||||
constexpr uint32_t flag_1 = 1 << 1;
|
||||
constexpr uint32_t flag_4 = 1 << 4;
|
||||
constexpr uint32_t flag_5 = 1 << 5;
|
||||
constexpr uint32_t flag_6 = 1 << 6;
|
||||
constexpr uint32_t flag_7 = 1 << 7;
|
||||
constexpr uint32_t resizable = 1 << 9;
|
||||
constexpr uint32_t flag_11 = 1 << 11;
|
||||
constexpr uint32_t flag_12 = 1 << 12;
|
||||
constexpr uint32_t white_border_mask = (1 << 17) | (1 << 18);
|
||||
}
|
||||
|
||||
struct window_event_list
|
||||
|
@ -114,20 +165,23 @@ namespace openloco::ui
|
|||
window_event_list* event_handlers; // 0x00
|
||||
ui::viewport* viewport; // 0x04
|
||||
uint8_t pad_08[0x04]; // 0x08
|
||||
uint32_t enabled_widgets; // 0x0C
|
||||
uint8_t pad_10[0x2C - 0x10];
|
||||
widget* widgets; // 0x2C
|
||||
uint16_t x; // 0x30
|
||||
uint16_t y; // 0x32
|
||||
uint16_t width; // 0x34
|
||||
uint16_t height; // 0x36
|
||||
uint16_t min_width; // 0x38
|
||||
uint16_t max_width; // 0x3a
|
||||
uint16_t min_height; // 0x3c
|
||||
uint16_t max_height; // 0x3e
|
||||
uint16_t number;
|
||||
uint32_t flags;
|
||||
uint8_t pad_46[0x83E - 0x46];
|
||||
uint64_t enabled_widgets; // 0x0C
|
||||
uint64_t disabled_widgets; // 0x14
|
||||
uint64_t activated_widgets; // 0x1C
|
||||
uint8_t pad_24[0x2C - 0x24];
|
||||
widget_t* widgets; // 0x2C
|
||||
uint16_t x; // 0x30
|
||||
uint16_t y; // 0x32
|
||||
uint16_t width; // 0x34
|
||||
uint16_t height; // 0x36
|
||||
uint16_t min_width; // 0x38
|
||||
uint16_t max_width; // 0x3a
|
||||
uint16_t min_height; // 0x3c
|
||||
uint16_t max_height; // 0x3e
|
||||
uint16_t number; // 0x40
|
||||
uint32_t flags; // 0x42
|
||||
scroll_area_t scroll_areas[3]; // 0x46
|
||||
uint8_t pad_7C[0x83E - 0x7C];
|
||||
uint16_t var_83E;
|
||||
uint8_t pad_840[0x846 - 0x840];
|
||||
uint16_t var_846;
|
||||
|
@ -154,6 +208,7 @@ namespace openloco::ui
|
|||
|
||||
void invalidate();
|
||||
void sub_4CA17F();
|
||||
void draw(openloco::gfx::drawpixelinfo_t* dpi);
|
||||
|
||||
bool call_tooltip(int16_t widget_index); // 23
|
||||
void call_prepare_draw(); // 26
|
||||
|
|
|
@ -85,10 +85,10 @@ namespace openloco::ui::windows
|
|||
utility::strcpy_safe(_text_input_buffer, baseName.c_str());
|
||||
|
||||
sub_446A93();
|
||||
auto window = windowmgr::create_window_centred(window_type::prompt_browse, 500, 380, ui::window_flags::flag_1 | ui::window_flags::flag_9 | ui::window_flags::flag_12, (void*)0x004FB308);
|
||||
auto window = windowmgr::create_window_centred(window_type::prompt_browse, 500, 380, ui::window_flags::flag_1 | ui::window_flags::resizable | ui::window_flags::flag_12, (void*)0x004FB308);
|
||||
if (window != nullptr)
|
||||
{
|
||||
window->widgets = (widget*)0x0050AD58;
|
||||
window->widgets = (widget_t*)0x0050AD58;
|
||||
window->enabled_widgets = (1 << 2) | (1 << 4) | (1 << 6);
|
||||
window->sub_4CA17F();
|
||||
addr<0x01136FA2, int16_t>() = -1;
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace openloco::ui::windows
|
|||
auto window = windowmgr::create_window_centred(window_type::prompt_ok_cancel, 280, 92, ui::window_flags::flag_12 | ui::window_flags::flag_1, (void*)0x004FB37C);
|
||||
if (window != nullptr)
|
||||
{
|
||||
window->widgets = (widget*)0x0050AE00;
|
||||
window->widgets = (widget_t*)0x0050AE00;
|
||||
window->enabled_widgets = (1 << 2) | (1 << 3) | (1 << 4);
|
||||
window->sub_4CA17F();
|
||||
window->colours[0] = colour::translucent(colour::salmon_pink);
|
||||
|
|
|
@ -9,8 +9,8 @@ using namespace openloco::interop;
|
|||
|
||||
namespace openloco::ui::windows
|
||||
{
|
||||
static widget widgets[] = {
|
||||
{ 0x1E, 0, 0, 0, 0, 0, { 0 }, 0 }
|
||||
static widget_t widgets[] = {
|
||||
{ widget_type::end, 0, 0, 0, 0, 0, { 0 }, 0 }
|
||||
};
|
||||
|
||||
static ui::window_event_list _events;
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace openloco::ui::tooltip
|
|||
static loco_global<int16_t, 0x00523384> _523384;
|
||||
static loco_global<uint16_t, 0x0052338C> _tooltipNotShownTicks;
|
||||
|
||||
static loco_global<ui::widget[1], 0x005234CC> _widgets;
|
||||
static loco_global<ui::widget_t[1], 0x005234CC> _widgets;
|
||||
|
||||
static loco_global<int32_t, 0x112C876> gCurrentFontSpriteBase;
|
||||
static loco_global<char[512], 0x0112CC04> byte_112CC04;
|
||||
|
|
Loading…
Reference in New Issue