mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-20 04:30:12 +02:00
Quake 4 integrated with DoomRTX
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
// DeclLipSync.cpp
|
||||
//
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "../idLib/Lib.h"
|
||||
|
||||
/*
|
||||
===================
|
||||
rvDeclPlayerModel::SetLipSyncData
|
||||
===================
|
||||
*/
|
||||
void rvDeclLipSync::SetLipSyncData(const char* lsd, const char* lang) {
|
||||
if (!strchr(lsd, 37)) {
|
||||
mLipSyncData.Set(lsd, lang);
|
||||
return;
|
||||
}
|
||||
|
||||
common->Warning("SetLipSyncData: language %s for lipsync '%s' has invalid character %% in it", lsd, base->GetType());
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
rvDeclPlayerModel::Size
|
||||
===================
|
||||
*/
|
||||
size_t rvDeclLipSync::Size(void) const {
|
||||
return sizeof(rvDeclLipSync);
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
rvDeclPlayerModel::DefaultDefinition
|
||||
===================
|
||||
*/
|
||||
const char* rvDeclLipSync::DefaultDefinition() const {
|
||||
return "{ description \"<DEFAULTED>\" }";
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
rvDeclPlayerModel::FreeData
|
||||
===================
|
||||
*/
|
||||
bool rvDeclLipSync::Parse(const char* text, const int textLength) {
|
||||
idLexer src;
|
||||
idToken token, token2;
|
||||
|
||||
src.LoadMemory(text, textLength, GetFileName(), GetLineNum());
|
||||
src.SetFlags(DECL_LEXER_FLAGS);
|
||||
src.SkipUntilString("{");
|
||||
|
||||
while (1) {
|
||||
if (!src.ReadToken(&token)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!token.Icmp("}")) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (token == "visemes")
|
||||
{
|
||||
idToken lang;
|
||||
idToken data;
|
||||
|
||||
src.ReadToken(&lang);
|
||||
src.ReadToken(&data);
|
||||
|
||||
SetLipSyncData(lang.c_str(), data.c_str());
|
||||
continue;
|
||||
}
|
||||
else if (token == "hmm")
|
||||
{
|
||||
src.ReadToken(&token);
|
||||
mHMM = token;
|
||||
continue;
|
||||
}
|
||||
else if (token == "text")
|
||||
{
|
||||
src.ReadToken(&token);
|
||||
mTranscribeText = token;
|
||||
continue;
|
||||
}
|
||||
else if (token == "description")
|
||||
{
|
||||
src.ReadToken(&token);
|
||||
mDescription = token;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
src.Error("Invalid or unexpected token %s\n", token.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
rvDeclLipSync::FreeData
|
||||
===================
|
||||
*/
|
||||
void rvDeclLipSync::FreeData(void) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
|
||||
#ifndef __DECLLIPSYNC_H__
|
||||
#define __DECLLIPSYNC_H__
|
||||
|
||||
// A way of cross referencing strings and sound shaders
|
||||
// RAVEN BEGIN
|
||||
// jsinger: added to support serialization/deserialization of binary decls
|
||||
#ifdef RV_BINARYDECLS
|
||||
class rvDeclLipSync : public idDecl, public Serializable<'RDLS'>
|
||||
{
|
||||
public:
|
||||
virtual void Write(SerialOutputStream& stream) const;
|
||||
virtual void AddReferences() const;
|
||||
rvDeclLipSync(SerialInputStream& stream);
|
||||
#else
|
||||
class rvDeclLipSync : public idDecl
|
||||
{
|
||||
#endif
|
||||
// RAVEN END
|
||||
public:
|
||||
rvDeclLipSync(void) {}
|
||||
~rvDeclLipSync(void) {}
|
||||
|
||||
void SetDescription(const char* desc) { mDescription = desc; }
|
||||
const idStr& GetDescription(void) const { return(mDescription); }
|
||||
|
||||
void SetHMM(idStr& hmm) { mHMM = hmm; }
|
||||
const idStr& GetHMM(void) const { return(mHMM); }
|
||||
|
||||
void SetTranscribeText(const char* text) { mTranscribeText = text; }
|
||||
const char* GetTranscribeText(int langIndex = -1) const { return(common->GetLocalizedString(mTranscribeText, langIndex)); }
|
||||
const char* GetRawTranscribeText(void) const { return(mTranscribeText.c_str()); }
|
||||
|
||||
void SetLipSyncData(const char* lsd, const char* lang);
|
||||
const char* GetLipSyncData(int langIdx = -1) const;
|
||||
|
||||
virtual const char* DefaultDefinition(void) const;
|
||||
virtual bool Parse(const char* text, const int textLength) override;
|
||||
virtual void FreeData(void);
|
||||
//virtual bool RebuildTextSource( void );
|
||||
virtual size_t Size(void) const;
|
||||
|
||||
// scork: for detailed error-reporting
|
||||
//virtual bool Validate( const char *psText, int iTextLength, idStr &strReportTo ) const;
|
||||
|
||||
private:
|
||||
idStr mDescription;
|
||||
idStr mTranscribeText;
|
||||
idStr mHMM;
|
||||
idDict mLipSyncData;
|
||||
};
|
||||
|
||||
ID_INLINE const char* rvDeclLipSync::GetLipSyncData(int langIdx) const
|
||||
{
|
||||
//if( common->LanguageHasVO( langIdx ) )
|
||||
//{
|
||||
// return( mLipSyncData.GetString( common->GetLanguage( langIdx ) ) );
|
||||
//}
|
||||
|
||||
return(mLipSyncData.GetString("english"));
|
||||
}
|
||||
|
||||
class rvDeclLipSyncEdit
|
||||
{
|
||||
public:
|
||||
virtual ~rvDeclLipSyncEdit() {}
|
||||
virtual void SetLipSyncDescription(rvDeclLipSync* edit, const char* desc) = 0;
|
||||
virtual void SetLipSyncTranscribeText(rvDeclLipSync* edit, const char* text) = 0;
|
||||
virtual void SetLipSyncData(rvDeclLipSync* edit, const char* lsd, const char* lang) = 0;
|
||||
};
|
||||
|
||||
extern rvDeclLipSyncEdit* declLipSyncEdit;
|
||||
|
||||
#endif // __DECLLIPSYNC_H__
|
||||
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Quake 4 / Raven material type decl support
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../idLib/Lib.h"
|
||||
|
||||
idCVar mat_useHitMaterials(
|
||||
"mat_useHitMaterials",
|
||||
"1",
|
||||
CVAR_RENDERER | CVAR_BOOL,
|
||||
"use hit materials for ray/path tracing material lookup"
|
||||
);
|
||||
|
||||
idCVar mat_writeHitMaterials(
|
||||
"mat_writeHitMaterials",
|
||||
"0",
|
||||
CVAR_RENDERER | CVAR_BOOL,
|
||||
"write/debug hit material data"
|
||||
);
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclMatType::DefaultDefinition
|
||||
================
|
||||
*/
|
||||
const char* rvDeclMatType::DefaultDefinition(void) const {
|
||||
return "{ description \"<DEFAULTED>\" rgb 0,0,0 }";
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclMatType::FreeData
|
||||
================
|
||||
*/
|
||||
void rvDeclMatType::FreeData(void) {
|
||||
mDescription.Clear();
|
||||
*(ulong*)mTint = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclMatType::Size
|
||||
================
|
||||
*/
|
||||
size_t rvDeclMatType::Size(void) const {
|
||||
return sizeof(rvDeclMatType) + mDescription.Allocated();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclMatType::Parse
|
||||
================
|
||||
*/
|
||||
bool rvDeclMatType::Parse(const char* text, const int textLength, bool noCaching) {
|
||||
idLexer src;
|
||||
idToken token;
|
||||
|
||||
//parserLineNum = 1;
|
||||
|
||||
src.LoadMemory(text, textLength, GetFileName(), GetLineNum());
|
||||
src.SetFlags(
|
||||
LEXFL_NOSTRINGCONCAT |
|
||||
LEXFL_NOSTRINGESCAPECHARS |
|
||||
LEXFL_ALLOWPATHNAMES |
|
||||
LEXFL_ALLOWMULTICHARLITERALS |
|
||||
LEXFL_ALLOWBACKSLASHSTRINGCONCAT |
|
||||
LEXFL_NOFATALERRORS |
|
||||
LEXFL_ALLOWIPADDRESSES
|
||||
);
|
||||
|
||||
src.SkipUntilString("{");
|
||||
|
||||
if (!src.ReadToken(&token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (token.Icmp("}") != 0) {
|
||||
if (token.Icmp("rgb") == 0) {
|
||||
byte tint[4];
|
||||
|
||||
tint[0] = (byte)src.ParseInt();
|
||||
src.ExpectTokenString(",");
|
||||
|
||||
tint[1] = (byte)src.ParseInt();
|
||||
src.ExpectTokenString(",");
|
||||
|
||||
tint[2] = (byte)src.ParseInt();
|
||||
tint[3] = 0xFF;
|
||||
|
||||
SetTint(tint);
|
||||
}
|
||||
else if (token.Icmp("description") == 0) {
|
||||
if (!src.ReadToken(&token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mDescription = token;
|
||||
}
|
||||
else {
|
||||
src.Warning("rvDeclMatType::Parse: unknown token '%s'", token.c_str());
|
||||
}
|
||||
|
||||
if (!src.ReadToken(&token)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//parserLineNum = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclMatType::Validate
|
||||
================
|
||||
*/
|
||||
bool rvDeclMatType::Validate(const char* psText, int iTextLength, idStr& strReportTo) const {
|
||||
idLexer src;
|
||||
idToken token;
|
||||
|
||||
src.LoadMemory(psText, iTextLength, GetFileName(), GetLineNum());
|
||||
src.SetFlags(
|
||||
LEXFL_NOSTRINGCONCAT |
|
||||
LEXFL_NOSTRINGESCAPECHARS |
|
||||
LEXFL_ALLOWPATHNAMES |
|
||||
LEXFL_ALLOWMULTICHARLITERALS |
|
||||
LEXFL_ALLOWBACKSLASHSTRINGCONCAT |
|
||||
LEXFL_NOFATALERRORS |
|
||||
LEXFL_ALLOWIPADDRESSES
|
||||
);
|
||||
|
||||
if (!src.SkipUntilString("{")) {
|
||||
strReportTo += "Missing opening brace.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
while (src.ReadToken(&token)) {
|
||||
if (token.Icmp("}") == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (token.Icmp("rgb") == 0) {
|
||||
if (!src.ReadToken(&token)) {
|
||||
strReportTo += "rgb missing red value.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!src.ExpectTokenString(",")) {
|
||||
strReportTo += "rgb missing comma after red value.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!src.ReadToken(&token)) {
|
||||
strReportTo += "rgb missing green value.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!src.ExpectTokenString(",")) {
|
||||
strReportTo += "rgb missing comma after green value.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!src.ReadToken(&token)) {
|
||||
strReportTo += "rgb missing blue value.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token.Icmp("description") == 0) {
|
||||
if (!src.ReadToken(&token)) {
|
||||
strReportTo += "description missing string.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
strReportTo += va("Unknown token '%s'.\n", token.c_str());
|
||||
}
|
||||
|
||||
strReportTo += "Missing closing brace.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
MT_FindMaterialTypeByTint
|
||||
================
|
||||
*/
|
||||
const rvDeclMatType* MT_FindMaterialTypeByTint(unsigned long tint) {
|
||||
const int numMaterialTypes = declManager->GetNumDecls(DECL_MATERIALTYPE);
|
||||
|
||||
for (int i = 0; i < numMaterialTypes; i++) {
|
||||
const rvDeclMatType* matType = static_cast<const rvDeclMatType*>(
|
||||
declManager->DeclByIndex(DECL_MATERIALTYPE, i, true)
|
||||
);
|
||||
|
||||
if (matType == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (matType->GetTint() == (int)tint) {
|
||||
return matType;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
MT_FindMaterialTypeByClosestTint
|
||||
================
|
||||
*/
|
||||
const rvDeclMatType* MT_FindMaterialTypeByClosestTint(unsigned long tint) {
|
||||
const byte* wanted = reinterpret_cast<const byte*>(&tint);
|
||||
|
||||
const rvDeclMatType* bestMatType = NULL;
|
||||
int bestDist = 0x01000001;
|
||||
|
||||
const int numMaterialTypes = declManager->GetNumDecls(DECL_MATERIALTYPE);
|
||||
|
||||
for (int i = 0; i < numMaterialTypes; i++) {
|
||||
const rvDeclMatType* matType = static_cast<const rvDeclMatType*>(
|
||||
declManager->DeclByIndex(DECL_MATERIALTYPE, i, true)
|
||||
);
|
||||
|
||||
if (matType == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const int matTint = matType->GetTint();
|
||||
const byte* test = reinterpret_cast<const byte*>(&matTint);
|
||||
|
||||
const int dr = (int)test[0] - (int)wanted[0];
|
||||
const int dg = (int)test[1] - (int)wanted[1];
|
||||
const int db = (int)test[2] - (int)wanted[2];
|
||||
|
||||
const int dist = dr * dr + dg * dg + db * db;
|
||||
|
||||
if (dist < bestDist) {
|
||||
bestMatType = matType;
|
||||
bestDist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
return bestMatType;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
MT_GetMaterialTypeArray
|
||||
|
||||
Returns one byte per source image pixel.
|
||||
Each byte is the material type decl index.
|
||||
================
|
||||
*/
|
||||
byte* MT_GetMaterialTypeArray(idStr image, int& width, int& height) {
|
||||
idFile* hitFile = NULL;
|
||||
|
||||
if (mat_useHitMaterials.GetBool()) {
|
||||
image.SetFileExtension(".hit");
|
||||
|
||||
hitFile = fileSystem->OpenFileRead(image.c_str(), true);
|
||||
if (hitFile != NULL) {
|
||||
hitFile->Read(&height, sizeof(height));
|
||||
height = LittleLong(height);
|
||||
|
||||
hitFile->Read(&width, sizeof(width));
|
||||
width = LittleLong(width);
|
||||
|
||||
const int size = width * height;
|
||||
|
||||
byte* data = (byte*)Mem_ClearedAlloc(size);
|
||||
hitFile->Read(data, size);
|
||||
|
||||
fileSystem->CloseFile(hitFile);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
image.StripFileExtension();
|
||||
}
|
||||
|
||||
byte* pic = NULL;
|
||||
|
||||
renderSystem->LoadImage(image.c_str(), &pic, &width, &height, NULL, false);
|
||||
|
||||
if (pic == NULL) {
|
||||
common->Printf("Failed to load hit material image %s\n", image.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const int size = width * height;
|
||||
|
||||
byte* data = (byte*)malloc(size);
|
||||
byte* dst = data;
|
||||
byte* src = pic;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
const unsigned long color = *(unsigned long*)src;
|
||||
src += 4;
|
||||
|
||||
const rvDeclMatType* type = MT_FindMaterialTypeByTint(color);
|
||||
if (type == NULL) {
|
||||
type = MT_FindMaterialTypeByClosestTint(color);
|
||||
}
|
||||
|
||||
if (type != NULL) {
|
||||
*dst++ = (byte)type->Index();
|
||||
}
|
||||
else {
|
||||
*dst++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
free(pic);
|
||||
|
||||
if (mat_writeHitMaterials.GetBool()) {
|
||||
idStr hitImage = image;
|
||||
hitImage.SetFileExtension(".hit");
|
||||
|
||||
hitFile = fileSystem->OpenFileWrite(hitImage.c_str(), "fs_savepath");
|
||||
if (hitFile != NULL) {
|
||||
const int littleHeight = LittleLong(height);
|
||||
const int littleWidth = LittleLong(width);
|
||||
|
||||
hitFile->Write(&littleHeight, sizeof(littleHeight));
|
||||
hitFile->Write(&littleWidth, sizeof(littleWidth));
|
||||
hitFile->Write(data, size);
|
||||
|
||||
fileSystem->CloseFile(hitFile);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#ifdef RV_BINARYDECLS
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclMatType::rvDeclMatType
|
||||
================
|
||||
*/
|
||||
rvDeclMatType::rvDeclMatType(SerialInputStream& stream) {
|
||||
*(ulong*)mTint = 0;
|
||||
|
||||
stream.ReadString(mDescription);
|
||||
stream.Read(mTint, sizeof(mTint));
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclMatType::Write
|
||||
================
|
||||
*/
|
||||
void rvDeclMatType::Write(SerialOutputStream& stream) const {
|
||||
stream.WriteString(mDescription);
|
||||
stream.Write(mTint, sizeof(mTint));
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclMatType::AddReferences
|
||||
================
|
||||
*/
|
||||
void rvDeclMatType::AddReferences(void) const {
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
|
||||
#ifndef __DECLMATTYPE_H__
|
||||
#define __DECLMATTYPE_H__
|
||||
|
||||
// Defines a material type - such as concrete, metal, glass etc
|
||||
#ifdef RV_BINARYDECLS
|
||||
class rvDeclMatType : public idDecl, public Serializable<'RDMT'>
|
||||
{
|
||||
public:
|
||||
// jsinger: allow exporting of this decl type in a preparsed form
|
||||
virtual void Write(SerialOutputStream& stream) const;
|
||||
virtual void AddReferences() const;
|
||||
rvDeclMatType(SerialInputStream& stream);
|
||||
#else
|
||||
class rvDeclMatType : public idDecl
|
||||
{
|
||||
public:
|
||||
#endif
|
||||
rvDeclMatType(void) { *(ulong*)mTint = 0; }
|
||||
~rvDeclMatType(void) {}
|
||||
|
||||
void SetDescription(idStr& desc) { mDescription = desc; }
|
||||
const idStr& GetDescription(void) const { return(mDescription); }
|
||||
|
||||
void SetTint(byte tint[4]) { *(ulong*)mTint = *(ulong*)tint; }
|
||||
int GetTint(void) const { return(*(int*)mTint); }
|
||||
|
||||
float GetRed(void) const { return(mTint[0] / 255.0f); }
|
||||
float GetGreen(void) const { return(mTint[1] / 255.0f); }
|
||||
float GetBlue(void) const { return(mTint[2] / 255.0f); }
|
||||
|
||||
virtual const char* DefaultDefinition(void) const;
|
||||
virtual bool Parse(const char* text, const int textLength, bool noCaching);
|
||||
virtual void FreeData(void);
|
||||
virtual size_t Size(void) const;
|
||||
|
||||
// RAVEN BEGIN
|
||||
// jscott: to prevent a recursive crash
|
||||
virtual bool RebuildTextSource(void) { return(false); }
|
||||
// scork: for detailed error-reporting
|
||||
virtual bool Validate(const char* psText, int iTextLength, idStr& strReportTo) const;
|
||||
// RAVEN END
|
||||
|
||||
|
||||
private:
|
||||
|
||||
idStr mDescription;
|
||||
byte mTint[4];
|
||||
};
|
||||
|
||||
byte* MT_GetMaterialTypeArray(idStr image, int& width, int& height);
|
||||
|
||||
#endif // __DECLMATTYPE_H__
|
||||
@@ -0,0 +1,976 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Quake 4 / Raven playback decl support
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "DeclPlayback.h"
|
||||
|
||||
rvDeclPlaybackEdit* declPlaybackEdit = NULL;
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::rvDeclPlayback
|
||||
================
|
||||
*/
|
||||
rvDeclPlayback::rvDeclPlayback(void) {
|
||||
flags = 0;
|
||||
frameRate = 15.0f;
|
||||
duration = 0.0f;
|
||||
|
||||
origin.Zero();
|
||||
|
||||
bounds.Clear();
|
||||
|
||||
//points.SetGranularity(16);
|
||||
//angles.SetGranularity(16);
|
||||
//buttons.SetGranularity(16);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::~rvDeclPlayback
|
||||
================
|
||||
*/
|
||||
rvDeclPlayback::~rvDeclPlayback(void) {
|
||||
FreeData();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::DefaultDefinition
|
||||
================
|
||||
*/
|
||||
const char* rvDeclPlayback::DefaultDefinition(void) const {
|
||||
return "{ sequence { } data { } }";
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::FreeData
|
||||
================
|
||||
*/
|
||||
void rvDeclPlayback::FreeData(void) {
|
||||
points.Clear();
|
||||
angles.Clear();
|
||||
buttons.Clear();
|
||||
|
||||
flags = 0;
|
||||
frameRate = 15.0f;
|
||||
duration = 0.0f;
|
||||
|
||||
origin.Zero();
|
||||
bounds.Clear();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::Size
|
||||
================
|
||||
*/
|
||||
size_t rvDeclPlayback::Size(void) const {
|
||||
return sizeof(rvDeclPlayback) +
|
||||
points.GetNumValues() * sizeof(idVec3) +
|
||||
angles.GetNumValues() * sizeof(idAngles) +
|
||||
buttons.Num() * sizeof(rvButtonState);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::ParseSample
|
||||
================
|
||||
*/
|
||||
void rvDeclPlayback::ParseSample(idLexer* src, idVec3& pos, idAngles& ang) {
|
||||
idToken token;
|
||||
|
||||
if (!src->ReadToken(&token)) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (token.Icmp("}") != 0) {
|
||||
if (token.Icmp("pos") == 0) {
|
||||
pos.x = src->ParseFloat();
|
||||
src->ExpectTokenString(",");
|
||||
pos.y = src->ParseFloat();
|
||||
src->ExpectTokenString(",");
|
||||
pos.z = src->ParseFloat();
|
||||
|
||||
SetHasPositions(true);
|
||||
}
|
||||
else if (token.Icmp("ang") == 0) {
|
||||
ang.pitch = src->ParseFloat();
|
||||
src->ExpectTokenString(",");
|
||||
ang.yaw = src->ParseFloat();
|
||||
ang.roll = 0.0f;
|
||||
|
||||
SetHasAngles(true);
|
||||
}
|
||||
else if (token.Icmp("rotate") == 0) {
|
||||
ang.pitch = src->ParseFloat();
|
||||
src->ExpectTokenString(",");
|
||||
ang.yaw = src->ParseFloat();
|
||||
src->ExpectTokenString(",");
|
||||
ang.roll = src->ParseFloat();
|
||||
|
||||
SetHasAngles(true);
|
||||
}
|
||||
else if (token.Icmp("down") == 0 ||
|
||||
token.Icmp("up") == 0 ||
|
||||
token.Icmp("impulse") == 0) {
|
||||
src->ParseInt();
|
||||
}
|
||||
else {
|
||||
src->Warning("rvDeclPlayback::ParseSample: unknown token '%s'", token.c_str());
|
||||
}
|
||||
|
||||
if (!src->ReadToken(&token)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::ParseData
|
||||
================
|
||||
*/
|
||||
bool rvDeclPlayback::ParseData(idLexer* src) {
|
||||
idToken token;
|
||||
idVec3 pos;
|
||||
idAngles ang;
|
||||
float time;
|
||||
|
||||
time = 0.0f;
|
||||
pos.Zero();
|
||||
ang.Zero();
|
||||
|
||||
src->ExpectTokenString("{");
|
||||
|
||||
if (!src->ReadToken(&token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (token.Icmp("}") != 0) {
|
||||
if (token.Icmp("{") == 0) {
|
||||
ParseSample(src, pos, ang);
|
||||
|
||||
points.AddValue(time, pos);
|
||||
angles.AddValue(time, ang);
|
||||
|
||||
if (frameRate > 0.0f) {
|
||||
time += 1.0f / frameRate;
|
||||
}
|
||||
}
|
||||
|
||||
if (!src->ReadToken(&token)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
duration = time;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::ParseButton
|
||||
================
|
||||
*/
|
||||
void rvDeclPlayback::ParseButton(idLexer* src, byte& button, rvButtonState& state) {
|
||||
idToken token;
|
||||
float time;
|
||||
byte impulse;
|
||||
|
||||
impulse = 0;
|
||||
time = src->ParseFloat();
|
||||
|
||||
if (!src->ReadToken(&token)) {
|
||||
state.Init(time, button, impulse);
|
||||
return;
|
||||
}
|
||||
|
||||
while (token.Icmp("}") != 0) {
|
||||
if (token.Icmp("down") == 0) {
|
||||
button |= (byte)src->ParseInt();
|
||||
}
|
||||
else if (token.Icmp("up") == 0) {
|
||||
button &= ~(byte)src->ParseInt();
|
||||
}
|
||||
else if (token.Icmp("impulse") == 0) {
|
||||
impulse = (byte)src->ParseInt();
|
||||
}
|
||||
else {
|
||||
src->Warning("rvDeclPlayback::ParseButton: unknown token '%s'", token.c_str());
|
||||
}
|
||||
|
||||
if (!src->ReadToken(&token)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
state.Init(time, button, impulse);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::ParseButtons
|
||||
================
|
||||
*/
|
||||
bool rvDeclPlayback::ParseButtons(idLexer* src) {
|
||||
idToken token;
|
||||
byte button;
|
||||
rvButtonState state;
|
||||
|
||||
button = 0;
|
||||
|
||||
src->ExpectTokenString("{");
|
||||
|
||||
if (!src->ReadToken(&token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (token.Icmp("}") != 0) {
|
||||
if (token.Icmp("{") == 0) {
|
||||
ParseButton(src, button, state);
|
||||
buttons.Append(state);
|
||||
SetHasButtons(true);
|
||||
}
|
||||
|
||||
if (!src->ReadToken(&token)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::ParseSequence
|
||||
================
|
||||
*/
|
||||
bool rvDeclPlayback::ParseSequence(idLexer* src) {
|
||||
idToken token;
|
||||
|
||||
src->ExpectTokenString("sequence");
|
||||
src->ExpectTokenString("{");
|
||||
|
||||
if (!src->ReadToken(&token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (token.Icmp("}") != 0) {
|
||||
if (token.Icmp("origin") == 0) {
|
||||
origin.x = src->ParseFloat();
|
||||
src->ExpectTokenString(",");
|
||||
origin.y = src->ParseFloat();
|
||||
src->ExpectTokenString(",");
|
||||
origin.z = src->ParseFloat();
|
||||
}
|
||||
else if (token.Icmp("framerate") == 0 || token.Icmp("frameRate") == 0) {
|
||||
frameRate = src->ParseFloat();
|
||||
}
|
||||
else if (token.Icmp("destination") == 0) {
|
||||
idStr deprecated;
|
||||
src->ParseRestOfLine(deprecated);
|
||||
}
|
||||
else {
|
||||
src->Error("Invalid token %s in file %s.\n", token.c_str(), GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!src->ReadToken(&token)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::Parse
|
||||
================
|
||||
*/
|
||||
bool rvDeclPlayback::Parse(const char* text, const int textLength) {
|
||||
idLexer src;
|
||||
idToken token;
|
||||
|
||||
FreeData();
|
||||
|
||||
src.LoadMemory(text, textLength, GetFileName(), GetLineNum());
|
||||
src.SetFlags(
|
||||
LEXFL_NOSTRINGCONCAT |
|
||||
LEXFL_NOSTRINGESCAPECHARS |
|
||||
LEXFL_ALLOWPATHNAMES |
|
||||
LEXFL_ALLOWMULTICHARLITERALS |
|
||||
LEXFL_ALLOWBACKSLASHSTRINGCONCAT |
|
||||
LEXFL_NOFATALERRORS |
|
||||
LEXFL_ALLOWIPADDRESSES
|
||||
);
|
||||
|
||||
src.SkipUntilString("{");
|
||||
|
||||
if (!ParseSequence(&src)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!src.ReadToken(&token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (token.Icmp("}") != 0) {
|
||||
if (token.Icmp("data") == 0) {
|
||||
if (!ParseData(&src)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (token.Icmp("buttons") == 0) {
|
||||
if (!ParseButtons(&src)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
src.Warning("rvDeclPlayback::Parse: unknown token '%s'", token.c_str());
|
||||
}
|
||||
|
||||
if (!src.ReadToken(&token)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SetOrigin();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::WriteSequence
|
||||
================
|
||||
*/
|
||||
void rvDeclPlayback::WriteSequence(idFile_Memory& f) {
|
||||
f.WriteFloatString("\tsequence\n\t{\n");
|
||||
f.WriteFloatString("\t\torigin\t\t%.1f,%.1f,%.1f\n", origin.x, origin.y, origin.z);
|
||||
f.WriteFloatString("\t\tframeRate\t%.1f\n", frameRate);
|
||||
f.WriteFloatString("\t}\n");
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::WriteData
|
||||
================
|
||||
*/
|
||||
void rvDeclPlayback::WriteData(idFile_Memory& f) {
|
||||
idVec3 oldPos;
|
||||
idAngles oldAng;
|
||||
|
||||
oldPos.Zero();
|
||||
oldAng.Zero();
|
||||
|
||||
if ((points.GetNumValues() == 0 && angles.GetNumValues() == 0) || !(flags & (PBFL_GET_POSITION | PBFL_GET_ANGLES))) {
|
||||
return;
|
||||
}
|
||||
|
||||
f.WriteFloatString("\tdata\n\t{\n");
|
||||
|
||||
for (int i = 0; i < points.GetNumValues(); i++) {
|
||||
f.WriteFloatString("\t\t{ ");
|
||||
|
||||
if (flags & PBFL_GET_POSITION) {
|
||||
const idVec3& pos = points.GetValue(i);
|
||||
|
||||
if (i == 0 || idMath::Fabs(pos.x - oldPos.x) > 0.0625f ||
|
||||
idMath::Fabs(pos.y - oldPos.y) > 0.0625f ||
|
||||
idMath::Fabs(pos.z - oldPos.z) > 0.0625f) {
|
||||
f.WriteFloatString("pos %.1f,%.1f,%.1f ", pos.x, pos.y, pos.z);
|
||||
oldPos = pos;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & PBFL_GET_ANGLES) {
|
||||
const idAngles& ang = angles.GetValue(i);
|
||||
|
||||
if (i == 0 || idMath::Fabs(ang.pitch - oldAng.pitch) > 0.0625f ||
|
||||
idMath::Fabs(ang.yaw - oldAng.yaw) > 0.0625f ||
|
||||
idMath::Fabs(ang.roll - oldAng.roll) > 0.0625f) {
|
||||
if (ang.roll == 0.0f) {
|
||||
f.WriteFloatString("ang %.1f,%.1f ", ang.pitch, ang.yaw);
|
||||
}
|
||||
else {
|
||||
f.WriteFloatString("rotate %.1f,%.1f,%.1f ", ang.pitch, ang.yaw, ang.roll);
|
||||
}
|
||||
|
||||
oldAng = ang;
|
||||
}
|
||||
}
|
||||
|
||||
f.WriteFloatString("}\n");
|
||||
}
|
||||
|
||||
f.WriteFloatString("\t}\n");
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::WriteButtons
|
||||
================
|
||||
*/
|
||||
void rvDeclPlayback::WriteButtons(idFile_Memory& f) {
|
||||
byte oldState;
|
||||
|
||||
if (buttons.Num() == 0 || !(flags & PBFL_GET_BUTTONS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
oldState = 0;
|
||||
|
||||
f.WriteFloatString("\tbuttons\n\t{\n");
|
||||
|
||||
for (int i = 0; i < buttons.Num(); i++) {
|
||||
const rvButtonState& button = buttons[i];
|
||||
const byte changed = oldState ^ button.state;
|
||||
|
||||
if (changed == 0 && button.impulse == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
f.WriteFloatString("\t\t{ %.3g ", button.time);
|
||||
|
||||
if (changed != 0) {
|
||||
if (button.state & changed) {
|
||||
f.WriteFloatString("down %d ", button.state & changed);
|
||||
}
|
||||
|
||||
if (oldState & changed) {
|
||||
f.WriteFloatString("up %d ", oldState & changed);
|
||||
}
|
||||
|
||||
oldState = button.state;
|
||||
}
|
||||
|
||||
if (button.impulse != 0) {
|
||||
f.WriteFloatString("impulse %d ", button.impulse);
|
||||
}
|
||||
|
||||
f.WriteFloatString("}\n");
|
||||
}
|
||||
|
||||
f.WriteFloatString("\t}\n");
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::RebuildTextSource
|
||||
================
|
||||
*/
|
||||
bool rvDeclPlayback::RebuildTextSource(void) {
|
||||
#if 0
|
||||
idFile_Memory f;
|
||||
|
||||
f.WriteFloatString("\nplayback %s\n{\n", GetName());
|
||||
WriteSequence(f);
|
||||
WriteData(f);
|
||||
WriteButtons(f);
|
||||
f.WriteFloatString("}\n\n");
|
||||
|
||||
SetText(f.GetDataPtr());
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::Start
|
||||
================
|
||||
*/
|
||||
void rvDeclPlayback::Start(void) {
|
||||
origin.Zero();
|
||||
|
||||
bounds.Clear();
|
||||
|
||||
points.Clear();
|
||||
angles.Clear();
|
||||
buttons.Clear();
|
||||
|
||||
//points.SetGranularity(60);
|
||||
//angles.SetGranularity(60);
|
||||
//buttons.SetGranularity(60);
|
||||
|
||||
duration = 0.0f;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::SetOrigin
|
||||
================
|
||||
*/
|
||||
void rvDeclPlayback::SetOrigin(void) {
|
||||
if (points.GetNumValues() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const idVec3 first = points.GetValue(0);
|
||||
|
||||
origin += first;
|
||||
|
||||
bounds.Clear();
|
||||
|
||||
for (int i = 0; i < points.GetNumValues(); i++) {
|
||||
idVec3 p = points.GetValue(i);
|
||||
p -= first;
|
||||
|
||||
points.SetValue(i, p);
|
||||
bounds.AddPoint(p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::Copy
|
||||
================
|
||||
*/
|
||||
void rvDeclPlayback::Copy(rvDeclPlayback* pb) {
|
||||
flags = pb->flags & ~PBFL_ED_MASK;
|
||||
frameRate = pb->frameRate;
|
||||
duration = pb->duration;
|
||||
origin = pb->origin;
|
||||
bounds = pb->bounds;
|
||||
|
||||
points = pb->points;
|
||||
angles = pb->angles;
|
||||
buttons = pb->buttons;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::SetCurrentData
|
||||
================
|
||||
*/
|
||||
bool rvDeclPlayback::SetCurrentData(float localTime, int control, rvDeclPlaybackData* pbd) {
|
||||
if (control & PBFL_GET_POSITION) {
|
||||
points.AddValue(localTime, pbd->GetPosition());
|
||||
SetHasPositions(true);
|
||||
}
|
||||
|
||||
if (control & PBFL_GET_ANGLES) {
|
||||
angles.AddValue(localTime, pbd->GetAngles());
|
||||
SetHasAngles(true);
|
||||
}
|
||||
|
||||
if (control & PBFL_GET_BUTTONS) {
|
||||
rvButtonState state;
|
||||
state.Init(localTime, pbd->GetButtons(), pbd->GetImpulse());
|
||||
|
||||
buttons.Append(state);
|
||||
SetHasButtons(true);
|
||||
}
|
||||
|
||||
if (localTime > duration) {
|
||||
duration = localTime;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::GetCurrentOffset
|
||||
================
|
||||
*/
|
||||
bool rvDeclPlayback::GetCurrentOffset(float localTime, idVec3& pos) const {
|
||||
if (points.GetNumValues() <= 0) {
|
||||
pos.Zero();
|
||||
return false;
|
||||
}
|
||||
|
||||
pos = points.GetCurrentValue(localTime);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::GetCurrentAngles
|
||||
================
|
||||
*/
|
||||
bool rvDeclPlayback::GetCurrentAngles(float localTime, idAngles& ang) const {
|
||||
if (angles.GetNumValues() <= 0) {
|
||||
ang.Zero();
|
||||
return false;
|
||||
}
|
||||
|
||||
ang = angles.GetCurrentValue(localTime);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::GetCurrentData
|
||||
================
|
||||
*/
|
||||
bool rvDeclPlayback::GetCurrentData(int control, float localTime, float lastTime, rvDeclPlaybackData* pbd) const {
|
||||
byte changed;
|
||||
|
||||
if (pbd == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
changed = 0;
|
||||
|
||||
if (control & PBFL_GET_POSITION) {
|
||||
idVec3 offset;
|
||||
|
||||
if (GetCurrentOffset(localTime, offset)) {
|
||||
if (control & PBFL_RELATIVE_POSITION) {
|
||||
pbd->SetPosition(offset);
|
||||
}
|
||||
else {
|
||||
pbd->SetPosition(origin + offset);
|
||||
}
|
||||
|
||||
changed |= PBFL_GET_POSITION;
|
||||
}
|
||||
}
|
||||
|
||||
if (control & PBFL_GET_ANGLES) {
|
||||
idAngles currentAngles;
|
||||
|
||||
if (GetCurrentAngles(localTime, currentAngles)) {
|
||||
pbd->SetAngles(currentAngles);
|
||||
changed |= PBFL_GET_ANGLES;
|
||||
}
|
||||
}
|
||||
|
||||
if (control & PBFL_GET_VELOCITY) {
|
||||
idVec3 now;
|
||||
idVec3 prev;
|
||||
float delta;
|
||||
|
||||
delta = localTime - lastTime;
|
||||
if (delta <= 0.0f) {
|
||||
delta = 1.0f / Max(frameRate, 1.0f);
|
||||
}
|
||||
|
||||
if (GetCurrentOffset(localTime, now) && GetCurrentOffset(localTime - delta, prev)) {
|
||||
pbd->SetVelocity((now - prev) / delta);
|
||||
changed |= PBFL_GET_VELOCITY;
|
||||
}
|
||||
}
|
||||
|
||||
if (control & PBFL_GET_ACCELERATION) {
|
||||
idVec3 now;
|
||||
idVec3 prev;
|
||||
idVec3 prev2;
|
||||
float delta;
|
||||
|
||||
delta = localTime - lastTime;
|
||||
if (delta <= 0.0f) {
|
||||
delta = 1.0f / Max(frameRate, 1.0f);
|
||||
}
|
||||
|
||||
if (GetCurrentOffset(localTime, now) &&
|
||||
GetCurrentOffset(localTime - delta, prev) &&
|
||||
GetCurrentOffset(localTime - delta * 2.0f, prev2)) {
|
||||
const idVec3 vel0 = (now - prev) / delta;
|
||||
const idVec3 vel1 = (prev - prev2) / delta;
|
||||
|
||||
pbd->SetAcceleration((vel0 - vel1) / delta);
|
||||
changed |= PBFL_GET_ACCELERATION;
|
||||
}
|
||||
}
|
||||
|
||||
if (control & PBFL_GET_ANGLES_FROM_VEL) {
|
||||
const idVec3& vel = pbd->GetVelocity();
|
||||
|
||||
if (vel.LengthSqr() > 0.0001f) {
|
||||
pbd->SetAngles(vel.ToAngles());
|
||||
changed |= PBFL_GET_ANGLES;
|
||||
}
|
||||
}
|
||||
|
||||
if (control & PBFL_GET_BUTTONS) {
|
||||
byte currentButton;
|
||||
byte impulse;
|
||||
|
||||
currentButton = 0;
|
||||
impulse = 0;
|
||||
|
||||
for (int i = 0; i < buttons.Num(); i++) {
|
||||
const rvButtonState& state = buttons[i];
|
||||
|
||||
if (state.time > localTime) {
|
||||
break;
|
||||
}
|
||||
|
||||
currentButton = state.state;
|
||||
|
||||
if (state.time > lastTime && state.time <= localTime) {
|
||||
const byte previousButton = pbd->GetButtons();
|
||||
const byte down = state.state & ~previousButton;
|
||||
const byte up = previousButton & ~state.state;
|
||||
|
||||
if (down) {
|
||||
pbd->SetButtons(state.state);
|
||||
pbd->CallCallback(PBCB_BUTTON_DOWN, state.time);
|
||||
}
|
||||
|
||||
if (up) {
|
||||
pbd->SetButtons(state.state);
|
||||
pbd->CallCallback(PBCB_BUTTON_UP, state.time);
|
||||
}
|
||||
|
||||
if (state.impulse) {
|
||||
impulse = state.impulse;
|
||||
pbd->SetImpulse(impulse);
|
||||
pbd->CallCallback(PBCB_IMPULSE, state.time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pbd->SetButtons(currentButton);
|
||||
pbd->SetImpulse(impulse);
|
||||
|
||||
changed |= PBFL_GET_BUTTONS;
|
||||
}
|
||||
|
||||
pbd->SetChanged(changed);
|
||||
|
||||
return changed != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::Finish
|
||||
================
|
||||
*/
|
||||
bool rvDeclPlayback::Finish(float desiredDuration) {
|
||||
rvDeclPlayback temp;
|
||||
float speed;
|
||||
|
||||
SetOrigin();
|
||||
|
||||
temp.Copy(this);
|
||||
|
||||
FreeData();
|
||||
|
||||
flags = temp.flags;
|
||||
frameRate = temp.frameRate;
|
||||
origin = temp.origin;
|
||||
|
||||
if (desiredDuration >= 0.0f) {
|
||||
duration = desiredDuration;
|
||||
speed = temp.duration / Max(desiredDuration, 0.001f);
|
||||
}
|
||||
else {
|
||||
duration = temp.duration;
|
||||
speed = 1.0f;
|
||||
}
|
||||
|
||||
for (int i = 0; i < temp.buttons.Num(); i++) {
|
||||
const rvButtonState& src = temp.buttons[i];
|
||||
|
||||
if (i == 0 || src.state != temp.buttons[i - 1].state || src.impulse != 0) {
|
||||
rvButtonState dst;
|
||||
dst.Init(src.time / speed, src.state, src.impulse);
|
||||
buttons.Append(dst);
|
||||
}
|
||||
}
|
||||
|
||||
float oldTime = 0.0f;
|
||||
float newTime = 0.0f;
|
||||
const float step = 1.0f / Max(frameRate, 1.0f);
|
||||
|
||||
while (oldTime <= temp.duration) {
|
||||
rvDeclPlaybackData pbd;
|
||||
pbd.Init();
|
||||
|
||||
temp.GetCurrentData(PBFL_GET_POSITION | PBFL_GET_ANGLES, oldTime, 0.0f, &pbd);
|
||||
|
||||
points.AddValue(newTime, pbd.GetPosition() - origin);
|
||||
angles.AddValue(newTime, pbd.GetAngles());
|
||||
|
||||
oldTime += step * speed;
|
||||
newTime += step;
|
||||
}
|
||||
|
||||
//common->UpdateScreen();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::Validate
|
||||
================
|
||||
*/
|
||||
bool rvDeclPlayback::Validate(const char* psText, int iTextLength, idStr& strReportTo) const {
|
||||
idLexer src;
|
||||
idToken token;
|
||||
|
||||
src.LoadMemory(psText, iTextLength, GetFileName(), GetLineNum());
|
||||
src.SetFlags(
|
||||
LEXFL_NOSTRINGCONCAT |
|
||||
LEXFL_NOSTRINGESCAPECHARS |
|
||||
LEXFL_ALLOWPATHNAMES |
|
||||
LEXFL_ALLOWMULTICHARLITERALS |
|
||||
LEXFL_ALLOWBACKSLASHSTRINGCONCAT |
|
||||
LEXFL_NOFATALERRORS |
|
||||
LEXFL_ALLOWIPADDRESSES
|
||||
);
|
||||
|
||||
if (!src.SkipUntilString("{")) {
|
||||
strReportTo += "Missing opening brace.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!src.ReadToken(&token) || token.Icmp("sequence") != 0) {
|
||||
strReportTo += "Missing sequence block.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlaybackEditLocal
|
||||
================
|
||||
*/
|
||||
class rvDeclPlaybackEditLocal : public rvDeclPlaybackEdit {
|
||||
public:
|
||||
virtual bool Finish(rvDeclPlayback* edit, float desiredDuration) {
|
||||
return edit->Finish(desiredDuration);
|
||||
}
|
||||
|
||||
virtual void SetOrigin(rvDeclPlayback* edit) {
|
||||
edit->SetOrigin();
|
||||
}
|
||||
|
||||
virtual void SetOrigin(rvDeclPlayback* edit, idVec3& origin) {
|
||||
edit->SetOrigin(origin);
|
||||
}
|
||||
|
||||
virtual void Copy(rvDeclPlayback* edit, rvDeclPlayback* copy) {
|
||||
edit->Copy(copy);
|
||||
}
|
||||
};
|
||||
|
||||
static rvDeclPlaybackEditLocal declPlaybackEditLocal;
|
||||
|
||||
/*
|
||||
================
|
||||
DeclPlayback_Init
|
||||
================
|
||||
*/
|
||||
void DeclPlayback_Init(void) {
|
||||
declPlaybackEdit = &declPlaybackEditLocal;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
DeclPlayback_Shutdown
|
||||
================
|
||||
*/
|
||||
void DeclPlayback_Shutdown(void) {
|
||||
if (declPlaybackEdit == &declPlaybackEditLocal) {
|
||||
declPlaybackEdit = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RV_BINARYDECLS
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::rvDeclPlayback
|
||||
================
|
||||
*/
|
||||
rvDeclPlayback::rvDeclPlayback(SerialInputStream& stream) {
|
||||
flags = stream.ReadInt();
|
||||
frameRate = stream.ReadFloat();
|
||||
duration = stream.ReadFloat();
|
||||
|
||||
stream.ReadVec3(origin);
|
||||
stream.ReadBounds(bounds);
|
||||
|
||||
int count = stream.ReadInt();
|
||||
for (int i = 0; i < count; i++) {
|
||||
float t;
|
||||
idVec3 v;
|
||||
|
||||
t = stream.ReadFloat();
|
||||
stream.ReadVec3(v);
|
||||
|
||||
points.AddValue(t, v);
|
||||
}
|
||||
|
||||
count = stream.ReadInt();
|
||||
for (int i = 0; i < count; i++) {
|
||||
float t;
|
||||
idAngles a;
|
||||
|
||||
t = stream.ReadFloat();
|
||||
stream.ReadAngles(a);
|
||||
|
||||
angles.AddValue(t, a);
|
||||
}
|
||||
|
||||
count = stream.ReadInt();
|
||||
for (int i = 0; i < count; i++) {
|
||||
rvButtonState state;
|
||||
|
||||
state.time = stream.ReadFloat();
|
||||
state.state = stream.ReadByte();
|
||||
state.impulse = stream.ReadByte();
|
||||
|
||||
buttons.Append(state);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::Write
|
||||
================
|
||||
*/
|
||||
void rvDeclPlayback::Write(SerialOutputStream& stream) const {
|
||||
stream.WriteInt(flags);
|
||||
stream.WriteFloat(frameRate);
|
||||
stream.WriteFloat(duration);
|
||||
|
||||
stream.WriteVec3(origin);
|
||||
stream.WriteBounds(bounds);
|
||||
|
||||
stream.WriteInt(points.GetNumValues());
|
||||
for (int i = 0; i < points.GetNumValues(); i++) {
|
||||
stream.WriteFloat(points.GetTime(i));
|
||||
stream.WriteVec3(points.GetValue(i));
|
||||
}
|
||||
|
||||
stream.WriteInt(angles.GetNumValues());
|
||||
for (int i = 0; i < angles.GetNumValues(); i++) {
|
||||
stream.WriteFloat(angles.GetTime(i));
|
||||
stream.WriteAngles(angles.GetValue(i));
|
||||
}
|
||||
|
||||
stream.WriteInt(buttons.Num());
|
||||
for (int i = 0; i < buttons.Num(); i++) {
|
||||
stream.WriteFloat(buttons[i].time);
|
||||
stream.WriteByte(buttons[i].state);
|
||||
stream.WriteByte(buttons[i].impulse);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDeclPlayback::AddReferences
|
||||
================
|
||||
*/
|
||||
void rvDeclPlayback::AddReferences(void) const {
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,185 @@
|
||||
|
||||
#ifndef __DECLPLAYBACK_H__
|
||||
#define __DECLPLAYBACK_H__
|
||||
|
||||
// WARNING: These must stay mirrored in both Q4Monster.state
|
||||
#define PBFL_GET_POSITION BIT( 0 ) // Stored in playback file
|
||||
#define PBFL_GET_ANGLES BIT( 1 )
|
||||
#define PBFL_GET_BUTTONS BIT( 2 )
|
||||
|
||||
#define PBFL_GET_VELOCITY BIT( 4 ) // Derived from data
|
||||
#define PBFL_GET_ACCELERATION BIT( 5 )
|
||||
#define PBFL_GET_ANGLES_FROM_VEL BIT( 6 )
|
||||
|
||||
#define PBFL_AT_DEST BIT( 7 )
|
||||
#define PBFL_RELATIVE_POSITION BIT( 8 )
|
||||
|
||||
#define PBFL_ED_MODIFIED BIT( 29 )
|
||||
#define PBFL_ED_NEW BIT( 30 )
|
||||
#define PBFL_ED_CHECKEDIN BIT( 31 )
|
||||
|
||||
#define PBFL_ED_MASK ( PBFL_ED_MODIFIED | PBFL_ED_NEW | PBFL_ED_CHECKEDIN )
|
||||
|
||||
#define PBCB_NONE 0
|
||||
#define PBCB_BUTTON_DOWN 1
|
||||
#define PBCB_BUTTON_UP 2
|
||||
#define PBCB_IMPULSE 3
|
||||
|
||||
typedef void ( *pbCallback_t )( int type, float time, const void *data );
|
||||
|
||||
class rvDeclPlaybackData
|
||||
{
|
||||
public:
|
||||
void Init( void ) { entity = NULL; Callback = NULL; position.Zero(); velocity.Zero(); acceleration.Zero(); angles.Zero(); changed = 0; button = 0; impulse = 0; }
|
||||
|
||||
void SetPosition( const idVec3 &pos ) { position = pos; }
|
||||
void SetVelocity( const idVec3 &vel ) { velocity = vel; }
|
||||
void SetAcceleration( const idVec3 &accel ) { acceleration = accel; }
|
||||
void SetAngles( const idAngles &ang ) { angles = ang; }
|
||||
void SetChanged( const byte chg ) { changed = chg; }
|
||||
void SetButtons( const byte btn ) { button = btn; }
|
||||
void SetImpulse( const byte imp ) { impulse = imp; }
|
||||
|
||||
const idVec3 &GetPosition( void ) const { return( position ); }
|
||||
const idVec3 &GetVelocity( void ) const { return( velocity ); }
|
||||
const idVec3 &GetAcceleration( void ) const { return( acceleration ); }
|
||||
const idAngles &GetAngles( void ) const { return( angles ); }
|
||||
byte GetChanged( void ) const { return( changed ); }
|
||||
byte GetButtons( void ) const { return( button ); }
|
||||
byte GetImpulse( void ) const { return( impulse ); }
|
||||
|
||||
class idEntity *GetEntity( void ) const { return( entity ); }
|
||||
|
||||
void SetCallback( class idEntity *ent, pbCallback_t cb ) { entity = ent; Callback = cb; }
|
||||
void CallCallback( int type, float time ) { if( Callback ) { Callback( type, time, this ); } }
|
||||
private:
|
||||
class idEntity *entity;
|
||||
pbCallback_t Callback;
|
||||
|
||||
idVec3 position;
|
||||
idVec3 velocity;
|
||||
idVec3 acceleration;
|
||||
idAngles angles;
|
||||
byte changed;
|
||||
byte button;
|
||||
byte impulse;
|
||||
};
|
||||
|
||||
class rvButtonState
|
||||
{
|
||||
public:
|
||||
void Init( float t, byte b = 0, byte i = 0 ) { time = t; state = b; impulse = i; }
|
||||
|
||||
float time;
|
||||
byte state;
|
||||
byte impulse;
|
||||
};
|
||||
|
||||
#ifdef RV_BINARYDECLS
|
||||
class rvDeclPlayback : public idDecl, public Serializable<'RDP '>
|
||||
{
|
||||
public:
|
||||
// jsinger: allow exporting of this decl type in a preparsed form
|
||||
virtual void Write( SerialOutputStream &stream ) const;
|
||||
virtual void AddReferences() const;
|
||||
rvDeclPlayback( SerialInputStream &stream );
|
||||
#else
|
||||
class rvDeclPlayback : public idDecl
|
||||
{
|
||||
#endif
|
||||
public:
|
||||
rvDeclPlayback( void );
|
||||
~rvDeclPlayback( void );
|
||||
|
||||
void SetFlag( bool on, int flag ) { on ? flags |= flag : flags &= ~flag; }
|
||||
|
||||
bool GetHasPositions( void ) const { return( !!( flags & PBFL_GET_POSITION ) ); }
|
||||
bool GetHasAngles( void ) const { return( !!( flags & PBFL_GET_ANGLES ) ); }
|
||||
bool GetHasButtons( void ) const { return( !!( flags & PBFL_GET_BUTTONS ) ); }
|
||||
bool GetEditorModified( void ) const { return( !!( flags & PBFL_ED_MODIFIED ) ); }
|
||||
bool GetEditorNew( void ) const { return( !!( flags & PBFL_ED_NEW ) ); }
|
||||
bool GetEditorCheckedIn( void ) const { return( !!( flags & PBFL_ED_CHECKEDIN ) ); }
|
||||
|
||||
void SetHasPositions( bool pos ) { SetFlag( pos, PBFL_GET_POSITION ); }
|
||||
void SetHasAngles( bool ang ) { SetFlag( ang, PBFL_GET_ANGLES ); }
|
||||
void SetHasButtons( bool btn ) { SetFlag( btn, PBFL_GET_BUTTONS ); }
|
||||
void SetEditorModified( bool em ) { SetFlag( em, PBFL_ED_MODIFIED ); }
|
||||
void SetEditorNew( bool en ) { SetFlag( en, PBFL_ED_NEW ); }
|
||||
void SetEditorCheckedIn( bool eci ) { SetFlag( eci, PBFL_ED_CHECKEDIN ); }
|
||||
|
||||
int GetFlags( void ) const { return( flags ); }
|
||||
void SetFlags( int in ) { flags = in; }
|
||||
|
||||
float GetFrameRate( void ) const { return( frameRate ); }
|
||||
void SetFrameRate( float in ) { frameRate = in; }
|
||||
|
||||
idVec3 GetOrigin( void ) const { return( origin ); }
|
||||
void SetOrigin( idVec3 &in ) { origin = in; }
|
||||
|
||||
float GetDuration( void ) const { return( duration ); }
|
||||
void SetDuration( float dur ) { duration = dur; }
|
||||
|
||||
idBounds GetBounds( void ) const { return( bounds ); }
|
||||
|
||||
void ParseSample( idLexer *src, idVec3 &pos, idAngles &ang );
|
||||
void WriteData( idFile_Memory &f );
|
||||
void WriteButtons( idFile_Memory &f );
|
||||
void WriteSequence( idFile_Memory &f );
|
||||
|
||||
bool ParseData( idLexer *src );
|
||||
void ParseButton( idLexer *src, byte &button, rvButtonState &state );
|
||||
bool ParseSequence( idLexer *src );
|
||||
bool ParseButtons( idLexer *src );
|
||||
|
||||
void Copy( rvDeclPlayback *pb );
|
||||
void SetOrigin( void );
|
||||
void Start( void );
|
||||
bool Finish( float desiredDuration = -1.0f );
|
||||
|
||||
bool SetCurrentData( float localTime, int control, rvDeclPlaybackData *pbd );
|
||||
bool GetCurrentOffset( float localTime, idVec3 &pos ) const;
|
||||
bool GetCurrentAngles( float localTime, idAngles &ang ) const;
|
||||
bool GetCurrentData( int control, float localTime, float lastTime, rvDeclPlaybackData *pbd ) const;
|
||||
|
||||
virtual const char *DefaultDefinition( void ) const;
|
||||
virtual bool Parse( const char *text, const int textLength );
|
||||
virtual void FreeData( void );
|
||||
virtual bool RebuildTextSource( void );
|
||||
virtual size_t Size( void ) const;
|
||||
|
||||
// RAVEN BEGIN
|
||||
// scork: for detailed error-reporting
|
||||
virtual bool Validate( const char *psText, int iTextLength, idStr &strReportTo ) const;
|
||||
// RAVEN END
|
||||
|
||||
|
||||
idCurve_UniformCubicBSpline<idVec3> &GetPoints( void ) { return( points ); }
|
||||
idCurve_UniformCubicBSpline<idAngles> &GetAngles( void ) { return( angles ); }
|
||||
idList<rvButtonState> &GetButtons( void ) { return( buttons ); }
|
||||
|
||||
private:
|
||||
|
||||
int flags;
|
||||
float frameRate;
|
||||
float duration;
|
||||
idVec3 origin;
|
||||
idBounds bounds;
|
||||
|
||||
idCurve_UniformCubicBSpline<idVec3> points;
|
||||
idCurve_UniformCubicBSpline<idAngles> angles;
|
||||
idList<rvButtonState> buttons;
|
||||
};
|
||||
|
||||
class rvDeclPlaybackEdit
|
||||
{
|
||||
public:
|
||||
virtual ~rvDeclPlaybackEdit() {}
|
||||
virtual bool Finish( rvDeclPlayback *edit, float desiredDuration ) = 0;
|
||||
virtual void SetOrigin( rvDeclPlayback *edit ) = 0;
|
||||
virtual void SetOrigin( rvDeclPlayback *edit, idVec3 &origin ) = 0;
|
||||
virtual void Copy( rvDeclPlayback *edit, rvDeclPlayback *copy ) = 0;
|
||||
};
|
||||
|
||||
extern rvDeclPlaybackEdit *declPlaybackEdit;
|
||||
|
||||
#endif // __DECLPLAYBACK_H__
|
||||
@@ -0,0 +1,126 @@
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../idLib/Lib.h"
|
||||
|
||||
rvDeclPlayerModel::rvDeclPlayerModel() {
|
||||
FreeData();
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
rvDeclPlayerModel::Size
|
||||
===================
|
||||
*/
|
||||
size_t rvDeclPlayerModel::Size(void) const {
|
||||
return sizeof(rvDeclPlayerModel);
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
rvDeclPlayerModel::DefaultDefinition
|
||||
===================
|
||||
*/
|
||||
const char* rvDeclPlayerModel::DefaultDefinition() const {
|
||||
return "{\n\t\"model\"\t\"model_player_marine\"\n\t\"def_head\"\t\"char_marinehead_kane2_client\"\n\t\"def_head_ui\"\t\"char_marinehead_kane2_mp\"\n\t\"skin\"\t\"skins/multiplayer/marine\"\n}";
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
rvDeclPlayerModel::FreeData
|
||||
===================
|
||||
*/
|
||||
bool rvDeclPlayerModel::Parse(const char* text, const int textLength) {
|
||||
idLexer src;
|
||||
idToken token;
|
||||
|
||||
FreeData();
|
||||
|
||||
src.LoadMemory(text, textLength, GetFileName(), GetLineNum());
|
||||
src.SetFlags(DECL_LEXER_FLAGS);
|
||||
src.SkipUntilString("{");
|
||||
|
||||
while (1) {
|
||||
if (!src.ReadToken(&token)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!token.Icmp("}")) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!token.Icmp("head_offset")) {
|
||||
src.Parse1DMatrix(3, headOffset.ToFloatPtr());
|
||||
continue;
|
||||
}
|
||||
|
||||
idToken value;
|
||||
if (!src.ReadToken(&value)) {
|
||||
src.Error("Unexpected end of file parsing key '%s' in playerModel decl '%s'", token.c_str(), GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!token.Icmp("model")) {
|
||||
model = value;
|
||||
}
|
||||
else if (!token.Icmp("def_head") || !token.Icmp("head")) {
|
||||
head = value;
|
||||
}
|
||||
else if (!token.Icmp("def_head_ui") || !token.Icmp("ui_head")) {
|
||||
uiHead = value;
|
||||
}
|
||||
else if (!token.Icmp("skin")) {
|
||||
skin = value;
|
||||
}
|
||||
else if (!token.Icmp("team")) {
|
||||
team = value;
|
||||
}
|
||||
else if (!token.Icmp("description")) {
|
||||
description = value;
|
||||
}
|
||||
else if (!idStr::Cmpn(token.c_str(), "snd_", 4)) {
|
||||
sounds.Set(token.c_str(), value.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (model.Length() <= 0) {
|
||||
src.Error("playerModel decl '%s' without model declaration", GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!head.Length()) {
|
||||
head = uiHead;
|
||||
}
|
||||
|
||||
if (!uiHead.Length()) {
|
||||
uiHead = head;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
rvDeclPlayerModel::FreeData
|
||||
===================
|
||||
*/
|
||||
void rvDeclPlayerModel::FreeData(void) {
|
||||
model.Clear();
|
||||
head.Clear();
|
||||
headOffset.Zero();
|
||||
uiHead.Clear();
|
||||
team.Clear();
|
||||
skin.Clear();
|
||||
description.Clear();
|
||||
sounds.Clear();
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
rvDeclPlayerModel::DefaultDefinition
|
||||
===================
|
||||
*/
|
||||
void rvDeclPlayerModel::Print(void) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
//----------------------------------------------------------------
|
||||
// DeclPlayerModel.h
|
||||
//
|
||||
// Copyright 2002-2006 Raven Software
|
||||
//----------------------------------------------------------------
|
||||
|
||||
#ifndef __DECLPLAYERMODEL_H__
|
||||
#define __DECLPLAYERMODEL_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
rvDeclPlayerModel
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
class rvDeclPlayerModel : public idDecl {
|
||||
public:
|
||||
rvDeclPlayerModel();
|
||||
|
||||
idStr model;
|
||||
idStr head;
|
||||
idVec3 headOffset;
|
||||
idStr uiHead;
|
||||
idStr team;
|
||||
idStr skin;
|
||||
idStr description;
|
||||
idDict sounds;
|
||||
|
||||
virtual size_t Size( void ) const;
|
||||
virtual const char * DefaultDefinition() const;
|
||||
virtual bool Parse( const char *text, const int textLength );
|
||||
virtual void FreeData( void );
|
||||
virtual void Print( void );
|
||||
|
||||
virtual bool RebuildTextSource( void ) { return( false ); }
|
||||
//virtual bool Validate( const char *psText, int iTextLength, idStr &strReportTo ) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user