Skip to content
Merged
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
- Fix script attachments breaking existing model callbacks (used by a…
…ttachable items like headlamps)

- Moved update of hud item visbox to CHudItem and disabled it by default (uncomment in HudItem.h if there's a need for it)
- Force update bones and visbox of script attachment models when bone visibility is changed
  • Loading branch information
xr-lucy committed Jul 26, 2025
commit bd61747210ada4a020ca5cc7b6ec25a9beaf5ddb
55 changes: 17 additions & 38 deletions src/xrGame/GameObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -854,26 +854,18 @@ script_attachment* CGameObject::add_attachment(LPCSTR name, script_attachment* a
{
R_ASSERT(att);
remove_child(name, true);
m_script_attachments.emplace(mk_pair(name, att));

if (!Visual()->dcast_PKinematics()->GetUpdateCallback())
{
Visual()->dcast_PKinematics()->SetUpdateCallback(update_visbox);
Visual()->dcast_PKinematics()->SetUpdateCallbackParam(this);
}

CHudItem* obj = smart_cast<CHudItem*>(this);
if (obj)
if (!m_script_attachments.size())
{
IKinematics* k = obj->HudItemData()->m_model;
add_visual_callback(update_visbox);

if (!k->GetUpdateCallback())
{
k->SetUpdateCallback(update_visbox_hud);
k->SetUpdateCallbackParam(obj);
}
#ifdef ATTACHMENT_HUD_VISBOX
CHudItem* hud = smart_cast<CHudItem*>(this);
if (hud) hud->add_visual_callback(update_visbox_hud);
#endif
}

m_script_attachments.emplace(mk_pair(name, att));
return att;
}

Expand Down Expand Up @@ -902,23 +894,12 @@ void CGameObject::remove_child(LPCSTR name, bool destroy)

if (!m_script_attachments.size())
{
if (Visual()->dcast_PKinematics()->GetUpdateCallbackParam() == this)
{
Visual()->dcast_PKinematics()->SetUpdateCallback(nullptr);
Visual()->dcast_PKinematics()->SetUpdateCallbackParam(nullptr);
}

CHudItem* obj = smart_cast<CHudItem*>(this);
if (obj)
{
IKinematics* k = obj->HudItemData()->m_model;
remove_visual_callback(update_visbox);

if (k->GetUpdateCallbackParam() == obj)
{
k->SetUpdateCallback(nullptr);
k->SetUpdateCallbackParam(nullptr);
}
}
#ifdef ATTACHMENT_HUD_VISBOX
CHudItem* hud = smart_cast<CHudItem*>(this);
if (hud) hud->remove_visual_callback(update_visbox_hud);
#endif
}
}

Expand Down Expand Up @@ -1005,22 +986,20 @@ BOOL CGameObject::TestServerFlag(u32 Flag) const

void CGameObject::add_visual_callback(visual_callback* callback)
{
VERIFY(smart_cast<IKinematics*>(Visual()));
if (!smart_cast<IKinematics*>(Visual())) return;
CALLBACK_VECTOR_IT I = std::find(visual_callbacks().begin(), visual_callbacks().end(), callback);
VERIFY(I == visual_callbacks().end());

if (I != visual_callbacks().end()) return;
if (m_visual_callback.empty()) SetKinematicsCallback(true);
// smart_cast<IKinematics*>(Visual())->Callback(VisualCallback,this);
m_visual_callback.push_back(callback);
}

void CGameObject::remove_visual_callback(visual_callback* callback)
{
if (!smart_cast<IKinematics*>(Visual())) return;
CALLBACK_VECTOR_IT I = std::find(m_visual_callback.begin(), m_visual_callback.end(), callback);
VERIFY(I != m_visual_callback.end());
if (I == m_visual_callback.end()) return;
m_visual_callback.erase(I);
if (m_visual_callback.empty()) SetKinematicsCallback(false);
// smart_cast<IKinematics*>(Visual())->Callback(0,0);
}

void CGameObject::SetKinematicsCallback(bool set)
Expand All @@ -1030,7 +1009,7 @@ void CGameObject::SetKinematicsCallback(bool set)
smart_cast<IKinematics*>(Visual())->Callback(VisualCallback, this);
else
smart_cast<IKinematics*>(Visual())->Callback(0, 0);
};
}

void VisualCallback(IKinematics* tpKinematics)
{
Expand Down
40 changes: 40 additions & 0 deletions src/xrGame/HudItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1205,3 +1205,43 @@ CAnonHudItem::~CAnonHudItem() { }
void CAnonHudItem::UpdateXForm() { }

void CAnonHudItem::on_renderable_Render() { }

#ifdef ATTACHMENT_HUD_VISBOX
void VisualCallbackHud(IKinematics* tpKinematics)
{
CHudItem* game_object = static_cast<CHudItem*>((tpKinematics->GetUpdateCallbackParam()));
VERIFY(game_object);

CHudItem::HUD_CALLBACK_VECTOR_IT I = game_object->visual_callbacks().begin();
CHudItem::HUD_CALLBACK_VECTOR_IT E = game_object->visual_callbacks().end();
for (; I != E; ++I)
(*I)(tpKinematics);
}

void CHudItem::add_visual_callback(hud_visual_callback* callback)
{
if (!HudItemData()->m_model) return;
HUD_CALLBACK_VECTOR_IT I = std::find(visual_callbacks().begin(), visual_callbacks().end(), callback);
if (I != visual_callbacks().end()) return;
if (m_visual_callback.empty()) SetKinematicsCallback(true);
m_visual_callback.push_back(callback);
}

void CHudItem::remove_visual_callback(hud_visual_callback* callback)
{
if (!HudItemData()->m_model) return;
HUD_CALLBACK_VECTOR_IT I = std::find(m_visual_callback.begin(), m_visual_callback.end(), callback);
if (I == m_visual_callback.end()) return;
m_visual_callback.erase(I);
if (m_visual_callback.empty()) SetKinematicsCallback(false);
}

void CHudItem::SetKinematicsCallback(bool set)
{
if (!HudItemData()->m_model) return;
if (set)
HudItemData()->m_model->Callback(VisualCallbackHud, this);
else
HudItemData()->m_model->Callback(0, 0);
}
#endif
20 changes: 20 additions & 0 deletions src/xrGame/HudItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class CUIWindow;
#define ORIGIN_OFFSET 0.04f, 0.04f, 0.04f, 0.02f
#define ORIGIN_OFFSET_AIM 0.015f, 0.015f, 0.01f, 0.005f

// Lucy: Uncomment if there ever is a use for correct visbox on HUD models
// #define ATTACHMENT_HUD_VISBOX

struct attachable_hud_item;
class motion_marks;

Expand Down Expand Up @@ -301,6 +304,23 @@ class CHudItem : public CHUDState
SPickParam& GetPick() { return PP; };
collide::rq_result& GetRQ() { return GetPick().result; };
float GetRQVis() { return PP.power; };

#ifdef ATTACHMENT_HUD_VISBOX
typedef void __stdcall hud_visual_callback(IKinematics*);
typedef svector<hud_visual_callback*, 6> HUD_CALLBACK_VECTOR;
typedef HUD_CALLBACK_VECTOR::iterator HUD_CALLBACK_VECTOR_IT;

HUD_CALLBACK_VECTOR m_visual_callback;

void add_visual_callback(hud_visual_callback* callback);
void remove_visual_callback(hud_visual_callback* callback);
void SetKinematicsCallback(bool set);

IC HUD_CALLBACK_VECTOR& visual_callbacks()
{
return (m_visual_callback);
}
#endif
};

class CAnonHudItem : public CHudItem
Expand Down
3 changes: 3 additions & 0 deletions src/xrGame/script_attachment_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,9 @@ void script_attachment::SetBoneVisible(u16 bone_id, bool bVisibility, bool bRecu
bool bVisibleNow = m_kinematics->LL_GetBoneVisible(bone_id);
if (bVisibleNow != bVisibility)
m_kinematics->LL_SetBoneVisible(bone_id, bVisibility, TRUE);

m_kinematics->CalculateBones_Invalidate();
m_kinematics->CalculateBones(TRUE);
}
}

Expand Down
Loading