Skip to content
Merged

xHud #566

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 180 additions & 0 deletions src/SB/Core/x/xHud.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@
#include "xMath.h"
#include "xMathInlines.h"
#include "xstransvc.h"
#include "zGlobals.h"
#include "xHudText.h"

#include "zEnt.h"

#include <new>
#include <types.h>

#define lengthof(x) (sizeof(x) / sizeof((x)[0]))

namespace xhud
{

Expand Down Expand Up @@ -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 <class F>
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<F32>& 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();
Expand Down Expand Up @@ -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<F32> 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.
Expand Down
18 changes: 16 additions & 2 deletions src/SB/Core/x/xHud.h
Original file line number Diff line number Diff line change
Expand Up @@ -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*);
Expand Down Expand Up @@ -143,6 +144,8 @@ namespace xhud
static block_allocator* motive_allocator();
};

typedef bool (motive_proc)(widget&, motive&, F32);

struct motive
{
F32* value;
Expand All @@ -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;

Expand All @@ -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)
{
Expand Down Expand Up @@ -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);
Expand Down