2019-05-15 14:52:37 +00:00
|
|
|
#include "common.h"
|
2019-06-12 18:07:37 +00:00
|
|
|
#include <rpskin.h>
|
2020-04-17 13:31:11 +00:00
|
|
|
|
2019-06-17 08:30:02 +00:00
|
|
|
#include "main.h"
|
2019-06-12 18:07:37 +00:00
|
|
|
#include "RwHelper.h"
|
|
|
|
#include "RpAnimBlend.h"
|
|
|
|
#include "AnimBlendClumpData.h"
|
2020-04-23 20:25:18 +00:00
|
|
|
#include "Bones.h"
|
2019-06-12 18:07:37 +00:00
|
|
|
#include "Directory.h"
|
|
|
|
#include "CutsceneMgr.h"
|
|
|
|
#include "Streaming.h"
|
2019-05-15 14:52:37 +00:00
|
|
|
#include "CutsceneHead.h"
|
2019-11-09 15:17:54 +00:00
|
|
|
#include "CdStream.h"
|
2019-06-12 18:07:37 +00:00
|
|
|
|
2020-11-11 08:42:30 +00:00
|
|
|
#ifdef GTA_PS2_STUFF
|
|
|
|
// this is a total hack to switch between PC and PS2 code
|
|
|
|
static bool lastLoadedSKA;
|
|
|
|
#endif
|
2019-06-12 18:07:37 +00:00
|
|
|
|
|
|
|
CCutsceneHead::CCutsceneHead(CObject *obj)
|
|
|
|
{
|
|
|
|
RpAtomic *atm;
|
|
|
|
|
|
|
|
assert(RwObjectGetType(obj->m_rwObject) == rpCLUMP);
|
2020-04-23 20:25:18 +00:00
|
|
|
#ifdef PED_SKIN
|
|
|
|
unk1 = 0;
|
|
|
|
bIsSkinned = false;
|
|
|
|
m_parentObject = (CCutsceneObject*)obj;
|
|
|
|
// Hide original head
|
|
|
|
if(IsClumpSkinned(obj->GetClump())){
|
|
|
|
m_parentObject->SetRenderHead(false);
|
|
|
|
bIsSkinned = true;
|
|
|
|
}else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
m_pHeadNode = RpAnimBlendClumpFindFrame((RpClump*)obj->m_rwObject, "Shead")->frame;
|
|
|
|
atm = (RpAtomic*)GetFirstObject(m_pHeadNode);
|
|
|
|
if(atm){
|
|
|
|
assert(RwObjectGetType((RwObject*)atm) == rpATOMIC);
|
|
|
|
RpAtomicSetFlags(atm, RpAtomicGetFlags(atm) & ~rpATOMICRENDER);
|
|
|
|
}
|
2019-06-12 18:07:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CCutsceneHead::CreateRwObject(void)
|
|
|
|
{
|
|
|
|
RpAtomic *atm;
|
|
|
|
|
|
|
|
CEntity::CreateRwObject();
|
|
|
|
assert(RwObjectGetType(m_rwObject) == rpCLUMP);
|
|
|
|
atm = GetFirstAtomic((RpClump*)m_rwObject);
|
|
|
|
RpSkinAtomicSetHAnimHierarchy(atm, RpHAnimFrameGetHierarchy(GetFirstChild(RpClumpGetFrame((RpClump*)m_rwObject))));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CCutsceneHead::DeleteRwObject(void)
|
|
|
|
{
|
|
|
|
CEntity::DeleteRwObject();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CCutsceneHead::ProcessControl(void)
|
|
|
|
{
|
|
|
|
RpAtomic *atm;
|
|
|
|
RpHAnimHierarchy *hier;
|
|
|
|
|
2020-04-23 20:25:18 +00:00
|
|
|
// android/xbox calls is at the end
|
2019-06-12 18:07:37 +00:00
|
|
|
CPhysical::ProcessControl();
|
|
|
|
|
2020-04-23 20:25:18 +00:00
|
|
|
#ifdef PED_SKIN
|
|
|
|
if(bIsSkinned){
|
|
|
|
UpdateRpHAnim();
|
|
|
|
UpdateRwFrame();
|
|
|
|
|
|
|
|
RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(m_parentObject->GetClump());
|
|
|
|
int idx = RpHAnimIDGetIndex(hier, BONE_head);
|
|
|
|
RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
|
|
|
|
if(RwV3dLength(&mat->pos) > 100.0f){
|
|
|
|
m_matrix.SetRotateY(PI/2);
|
|
|
|
m_matrix = CMatrix(mat) * m_matrix;
|
|
|
|
}
|
|
|
|
}else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
m_matrix.SetRotateY(PI/2);
|
|
|
|
m_matrix = CMatrix(RwFrameGetLTM(m_pHeadNode)) * m_matrix;
|
|
|
|
UpdateRwFrame(); // android/xbox don't call this
|
|
|
|
}
|
2019-06-12 18:07:37 +00:00
|
|
|
|
|
|
|
assert(RwObjectGetType(m_rwObject) == rpCLUMP);
|
|
|
|
atm = GetFirstAtomic((RpClump*)m_rwObject);
|
|
|
|
hier = RpSkinAtomicGetHAnimHierarchy(atm);
|
2020-11-11 08:42:30 +00:00
|
|
|
#ifdef GTA_PS2_STUFF
|
|
|
|
// PS2 only plays anims in cutscene, PC always plays anims
|
|
|
|
if(!lastLoadedSKA || CCutsceneMgr::IsRunning())
|
|
|
|
#endif
|
2019-06-12 18:07:37 +00:00
|
|
|
RpHAnimHierarchyAddAnimTime(hier, CTimer::GetTimeStepNonClipped()/50.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CCutsceneHead::Render(void)
|
|
|
|
{
|
|
|
|
RpAtomic *atm;
|
|
|
|
|
2020-04-23 20:25:18 +00:00
|
|
|
#ifdef PED_SKIN
|
|
|
|
if(bIsSkinned){
|
|
|
|
RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(m_parentObject->GetClump());
|
|
|
|
RpHAnimHierarchyUpdateMatrices(hier);
|
|
|
|
int idx = RpHAnimIDGetIndex(hier, BONE_head);
|
|
|
|
RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
|
|
|
|
if(RwV3dLength(&mat->pos) > 100.0f){
|
|
|
|
m_matrix.SetRotateY(PI/2);
|
|
|
|
m_matrix = CMatrix(mat) * m_matrix;
|
|
|
|
}
|
2020-05-12 07:44:50 +00:00
|
|
|
// This is head...it has no limbs
|
|
|
|
#ifndef FIX_BUGS
|
2020-04-23 20:25:18 +00:00
|
|
|
RenderLimb(BONE_Lhand);
|
|
|
|
RenderLimb(BONE_Rhand);
|
2020-05-12 07:44:50 +00:00
|
|
|
#endif
|
2020-04-23 20:25:18 +00:00
|
|
|
}else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
m_matrix.SetRotateY(PI/2);
|
|
|
|
m_matrix = CMatrix(RwFrameGetLTM(m_pHeadNode)) * m_matrix;
|
|
|
|
}
|
|
|
|
|
2019-06-12 18:07:37 +00:00
|
|
|
UpdateRwFrame();
|
|
|
|
|
|
|
|
assert(RwObjectGetType(m_rwObject) == rpCLUMP);
|
|
|
|
atm = GetFirstAtomic((RpClump*)m_rwObject);
|
|
|
|
RpHAnimHierarchyUpdateMatrices(RpSkinAtomicGetHAnimHierarchy(atm));
|
|
|
|
|
|
|
|
CObject::Render();
|
|
|
|
}
|
|
|
|
|
2020-04-23 20:25:18 +00:00
|
|
|
#ifdef PED_SKIN
|
|
|
|
void
|
|
|
|
CCutsceneHead::RenderLimb(int32 bone)
|
|
|
|
{
|
2020-05-12 07:44:50 +00:00
|
|
|
// It's not clear what this is...
|
|
|
|
// modelinfo for this object is not a ped so it also doesn't have any limbs
|
|
|
|
#ifndef FIX_BUGS
|
2020-04-23 20:25:18 +00:00
|
|
|
RpAtomic *atomic;
|
|
|
|
RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(m_parentObject->GetClump());
|
|
|
|
int idx = RpHAnimIDGetIndex(hier, bone);
|
|
|
|
RwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier);
|
2020-05-12 07:44:50 +00:00
|
|
|
CPedModelInfo *mi = (CPedModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
|
|
|
|
assert(mi->GetModelType() == MITYPE_PED);
|
2020-04-23 20:25:18 +00:00
|
|
|
switch(bone){
|
|
|
|
case BONE_Lhand:
|
|
|
|
atomic = mi->getLeftHand();
|
|
|
|
break;
|
|
|
|
case BONE_Rhand:
|
|
|
|
atomic = mi->getRightHand();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(atomic){
|
|
|
|
RwFrame *frame = RpAtomicGetFrame(atomic);
|
|
|
|
RwMatrixTransform(RwFrameGetMatrix(frame), &mats[idx], rwCOMBINEREPLACE);
|
|
|
|
RwFrameUpdateObjects(frame);
|
|
|
|
RpAtomicRender(atomic);
|
|
|
|
}
|
2020-05-12 07:44:50 +00:00
|
|
|
#endif
|
2020-04-23 20:25:18 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-06-12 18:07:37 +00:00
|
|
|
void
|
|
|
|
CCutsceneHead::PlayAnimation(const char *animName)
|
|
|
|
{
|
|
|
|
RpAtomic *atm;
|
|
|
|
RpHAnimHierarchy *hier;
|
|
|
|
RpHAnimAnimation *anim;
|
|
|
|
uint32 offset, size;
|
|
|
|
RwStream *stream;
|
|
|
|
|
2020-11-11 08:42:30 +00:00
|
|
|
#ifdef GTA_PS2_STUFF
|
|
|
|
lastLoadedSKA = false;
|
|
|
|
#endif
|
|
|
|
|
2019-06-12 18:07:37 +00:00
|
|
|
assert(RwObjectGetType(m_rwObject) == rpCLUMP);
|
|
|
|
atm = GetFirstAtomic((RpClump*)m_rwObject);
|
|
|
|
hier = RpSkinAtomicGetHAnimHierarchy(atm);
|
|
|
|
|
|
|
|
sprintf(gString, "%s.anm", animName);
|
|
|
|
|
|
|
|
if(CCutsceneMgr::ms_pCutsceneDir->FindItem(gString, offset, size)){
|
|
|
|
stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, "ANIM\\CUTS.IMG");
|
|
|
|
assert(stream);
|
|
|
|
|
2019-11-09 15:17:54 +00:00
|
|
|
CStreaming::MakeSpaceFor(size * CDSTREAM_SECTOR_SIZE);
|
2019-06-12 18:07:37 +00:00
|
|
|
CStreaming::ImGonnaUseStreamingMemory();
|
|
|
|
|
|
|
|
RwStreamSkip(stream, offset*2048);
|
|
|
|
if(RwStreamFindChunk(stream, rwID_HANIMANIMATION, nil, nil)){
|
|
|
|
anim = RpHAnimAnimationStreamRead(stream);
|
|
|
|
RpHAnimHierarchySetCurrentAnim(hier, anim);
|
|
|
|
}
|
|
|
|
|
|
|
|
CStreaming::IHaveUsedStreamingMemory();
|
|
|
|
|
|
|
|
RwStreamClose(stream, nil);
|
|
|
|
}
|
2020-11-11 08:42:30 +00:00
|
|
|
#ifdef GTA_PS2_STUFF
|
|
|
|
#ifdef LIBRW
|
|
|
|
else{
|
|
|
|
sprintf(gString, "%s.ska", animName);
|
|
|
|
|
|
|
|
if(CCutsceneMgr::ms_pCutsceneDir->FindItem(gString, offset, size)){
|
|
|
|
stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, "ANIM\\CUTS.IMG");
|
|
|
|
assert(stream);
|
|
|
|
|
|
|
|
CStreaming::MakeSpaceFor(size * CDSTREAM_SECTOR_SIZE);
|
|
|
|
CStreaming::ImGonnaUseStreamingMemory();
|
|
|
|
|
|
|
|
RwStreamSkip(stream, offset*2048);
|
|
|
|
anim = rw::Animation::streamReadLegacy(stream);
|
|
|
|
RpHAnimHierarchySetCurrentAnim(hier, anim);
|
|
|
|
|
|
|
|
CStreaming::IHaveUsedStreamingMemory();
|
|
|
|
|
|
|
|
RwStreamClose(stream, nil);
|
|
|
|
|
|
|
|
lastLoadedSKA = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
2019-06-12 18:07:37 +00:00
|
|
|
}
|