From f03144a594c110af906926d4d2f8bd0e680f44b0 Mon Sep 17 00:00:00 2001 From: Mark Langen Date: Wed, 21 May 2025 22:51:54 -0700 Subject: [PATCH] Various progress --- src/SB/Core/x/xHud.cpp | 180 +++++++++++++++++++++++++++++++++++++++++ src/SB/Core/x/xHud.h | 18 ++++- 2 files changed, 196 insertions(+), 2 deletions(-) diff --git a/src/SB/Core/x/xHud.cpp b/src/SB/Core/x/xHud.cpp index 97db4b66d..c17501952 100644 --- a/src/SB/Core/x/xHud.cpp +++ b/src/SB/Core/x/xHud.cpp @@ -4,12 +4,16 @@ #include "xMath.h" #include "xMathInlines.h" #include "xstransvc.h" +#include "zGlobals.h" +#include "xHudText.h" #include "zEnt.h" #include #include +#define lengthof(x) (sizeof(x) / sizeof((x)[0])) + namespace xhud { @@ -329,8 +333,119 @@ namespace xhud } } + const struct + { + U8 widget_type; + U32 widget_size; + } known_types[] = { + // TODO: The second value should probably be sizeof(...) + {0x3a, 0x9c}, + {0x3c, 0x19c}, + {0x3b, 0x15c}, + {0x47, 0x17c}, + }; + + struct functor_disable + { + functor_disable(bool b) + { + destroy_widgets = b; + } + + void operator()(xhud::widget& widget) + { + widget.disable(); + if (destroy_widgets) + { + widget.destroy(); + } + } + + U8 destroy_widgets; + }; + + struct functor_update + { + functor_update(F32 dt) + { + delta_time = dt; + } + + void operator()(xhud::widget& widget) + { + if (widget.enabled()) + widget.update(delta_time); + } + + F32 delta_time; + }; + + template + void for_each(U8 widget_type, U32 type_size, F f) + { + U32 count = globals.sceneCur->baseCount[widget_type]; + U8* list = (U8*)globals.sceneCur->baseList[widget_type]; + for (int i = 0; i < count; ++i) + { + f(*(widget*)(list + i * type_size)); + } + } + + void render_one_model(xModelInstance& model, F32 alpha, const basic_rect& rect, const xVec3& from, const xVec3& to, const xMat4x3& frame) + { + xModelSetMaterialAlpha(&model, 255.0f * alpha + 0.5f); + xModelSetFrame(&model, &frame); + xModelRender2D(model, rect, from, to); + } + } // namespace + void widget::debug_render() + { + + } + + void widget::setup_all() + { + for (U32 i = 0; i < lengthof(known_types); ++i) + { + for_each(known_types[i].widget_type, known_types[i].widget_size, fp_setup); + } + } + + S32 widget::cb_dispatch(xBase*, xBase* target, U32, const F32*, xBase*) + { + // Target gets cast to some type we probably don't have decomped yet. + return 0; + } + + void widget::render_all() + { + debug_render(); + for (U32 i = 0; i < lengthof(known_types); ++i) + { + for_each(known_types[i].widget_type, known_types[i].widget_size, fp_render); + } + } + + void widget::update_all(F32 dt) + { + functor_update func(dt); + for (U32 i = 0; i < lengthof(known_types); ++i) + { + for_each(known_types[i].widget_type, known_types[i].widget_size, func); + } + } + + void widget::disable_all(bool st) + { + functor_disable func(st); + for (U32 i = 0; i < lengthof(known_types); ++i) + { + for_each(known_types[i].widget_type, known_types[i].widget_size, func); + } + } + void widget::add_motive(const motive& m) { motive_node* node = (motive_node*)motive_allocator()->alloc(); @@ -438,6 +553,71 @@ namespace xhud } } + bool shake_motive_update(widget& w, motive& m, F32 dt) + { + static const float mult[4] = {-1.0f, -1.0f, 1.0f, 1.0f}; + + *((U32*)&m.context) += 1; + U32 context = *((U32*)&m.context); + if (context > 0x32) + { + m.context = 0; + *m.value -= m.offset; + m.offset = 0.0f; + return false; + } + + F32 value = m.delta * mult[context & 0x3]; + if ((context & 0x3) == 0) + { + m.delta = m.delta * m.accel; + } + + *m.value += value; + m.offset += value; + + return true; + } + + bool delay_motive_update(widget& w, motive& m, F32 dt) + { + m.offset += dt; + if (m.max_offset - m.offset < 0.0f) + { + ((motive_proc*)m.context)(w, m, dt); + return false; + } + return true; + } + + void xhud::render_model(xModelInstance& model, const xhud::render_context& rc) + { + + basic_rect rect = { 0 }; + rect.x = rc.loc.x; + rect.y = rc.loc.y; + rect.w = rc.size.x; + rect.h = rc.size.y; + + xVec3 vecA = {0, 0, 1}; + xVec3 vecB = {0, 0, -rc.loc.z}; + + xMat4x3 matrix; + xMat3x3Euler(&matrix, rc.rot.x, rc.rot.y, rc.rot.z); + matrix.right *= (1.0f + rc.loc.z); + matrix.up *= (1.0f + rc.loc.z); + matrix.at *= 0.0099999998f; + matrix.pos.z = 0.0f; + matrix.pos.y = 0.0f; + matrix.pos.x = 0.0f; + matrix.flags = 0; + + for (xModelInstance* cur = &model; cur; cur = cur->Next) + { + render_one_model(*cur, rc.a, rect, vecA, vecB, matrix); + } + } + void __deadstripped_xHud() { // "%d" was used in a deadstripped function. This function forces it to be used. diff --git a/src/SB/Core/x/xHud.h b/src/SB/Core/x/xHud.h index 9b6b015ba..916c5cf73 100644 --- a/src/SB/Core/x/xHud.h +++ b/src/SB/Core/x/xHud.h @@ -98,6 +98,7 @@ namespace xhud static void setup_all(); static void update_all(F32 dt); static void render_all(); + static void debug_render(); static void init_base(xBase&, const xBaseAsset&, unsigned long); static S32 cb_dispatch(xBase*, xBase*, U32, const F32*, xBase*); @@ -143,6 +144,8 @@ namespace xhud static block_allocator* motive_allocator(); }; + typedef bool (motive_proc)(widget&, motive&, F32); + struct motive { F32* value; @@ -151,7 +154,7 @@ namespace xhud F32 max_offset; F32 offset; F32 accel; - bool (*fp_update)(widget&, motive&, F32); + motive_proc* fp_update; void* context; U8 inverse; @@ -166,7 +169,17 @@ namespace xhud this->fp_update = fp_update; this->context = context; } - motive(const motive& other); + motive(const motive& other) + { + value = other.value; + delta = other.delta; + start_delta = other.start_delta; + max_offset = other.max_offset; + offset = other.offset; + accel = other.accel; + fp_update = other.fp_update; + context = other.context; + } bool update(widget& w, F32 dt) { @@ -198,6 +211,7 @@ namespace xhud bool linear_motive_update(widget& w, motive& m, F32); bool accelerate_motive_update(widget& w, motive& m, F32); + bool shake_motive_update(widget& w, motive& m, F32); bool delay_motive_update(widget& w, motive& m, F32); xModelInstance* load_model(U32);