|
|
//=============================================================================
//
//========= Copyright Valve Corporation, All rights reserved. ============//
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
// Converts from any one DMX file format to another
// Can also output SMD or a QCI header from DMX input
//
//=============================================================================
#ifndef DMXEDIT_H
#define DMXEDIT_H
// Valve includes
#include "movieobjects/dmemesh.h"
#include "tier1/utlstring.h"
#include "tier1/utlvector.h"
#include "tier1/UtlStringMap.h"
// Lua includes
#include <lua.h>
class CDmxEditProxy;
//=============================================================================
// CDmxEdit declaration
//=============================================================================
class CDmxEdit { public: void SetScriptFilename( const char *pFilename );
class delta : public CUtlString { public: delta() {}; delta( const char *pString ) : CUtlString( pString ) {} delta( const CUtlString &string ) : CUtlString( string ) {} };
class CFalloffType { public: CFalloffType( CDmeMesh::Falloff_t falloffType ) : m_falloffType( falloffType ) { }
CDmeMesh::Falloff_t StringToFalloff( const char *pFalloffTypeString ) { if ( !Q_strnicmp( pFalloffTypeString, "L", 1 ) ) return CDmeMesh::LINEAR;
if ( !Q_strnicmp( pFalloffTypeString, "ST", 2 ) ) return CDmeMesh::STRAIGHT;
if ( !Q_strnicmp( pFalloffTypeString, "B", 1 ) ) return CDmeMesh::BELL;
if ( !Q_strnicmp( pFalloffTypeString, "SM", 2 ) ) return CDmeMesh::SMOOTH;
if ( !Q_strnicmp( pFalloffTypeString, "SP", 2 ) ) return CDmeMesh::SPIKE;
if ( !Q_strnicmp( pFalloffTypeString, "D", 1 ) ) return CDmeMesh::DOME;
Msg( "// ERROR: Can't Figure Out Which Falloff Type Is Meant By \"%s\", Assuming STRAIGHT\n", pFalloffTypeString );
return CDmeMesh::STRAIGHT; }
CFalloffType( const char *pFalloffTypeString ) : m_falloffType( StringToFalloff( pFalloffTypeString ) ) { }
CDmeMesh::Falloff_t operator()() const { return m_falloffType; }
operator char *() const { switch ( m_falloffType ) { case CDmeMesh::LINEAR: return "STRAIGHT"; case CDmeMesh::BELL: return "BELL"; case CDmeMesh::SPIKE: return "SPIKE"; case CDmeMesh::DOME: return "DOME"; default: break; }
return "STRAIGHT"; }
protected: const CDmeMesh::Falloff_t m_falloffType; };
static const CFalloffType STRAIGHT; static const CFalloffType LINEAR; static const CFalloffType BELL; static const CFalloffType SMOOTH; static const CFalloffType SPIKE; static const CFalloffType DOME;
class CSelectOp { public: enum SelectOp_t { kAdd, kSubtract, kToggle, kIntersect, kReplace };
CSelectOp( SelectOp_t selectOp ) : m_selectOp( selectOp ) { }
SelectOp_t StringToSelectOp( const char *pSelectOpString ) { if ( !Q_strnicmp( pSelectOpString, "A", 1 ) ) return kAdd;
if ( !Q_strnicmp( pSelectOpString, "S", 1 ) ) return kSubtract;
if ( !Q_strnicmp( pSelectOpString, "T", 1 ) ) return kToggle;
if ( !Q_strnicmp( pSelectOpString, "I", 1 ) ) return kIntersect;
if ( !Q_strnicmp( pSelectOpString, "R", 1 ) ) return kReplace;
Msg( "// ERROR: Can't Figure Out Which Select Operation Type Is Meant By \"%s\", Assuming REPLACE\n", pSelectOpString );
return kReplace; }
CSelectOp( const char *pSelectOp ) : m_selectOp( StringToSelectOp( pSelectOp ) ) { }
SelectOp_t operator()() const { return m_selectOp; }
operator char *() const { switch ( m_selectOp ) { case kAdd: return "ADD"; case kSubtract: return "SUBTRACT"; case kToggle: return "TOGGLE"; case kIntersect: return "INTERSECT"; default: break; }
return "REPLACE"; }
protected: const SelectOp_t m_selectOp; };
static const CSelectOp ADD; static const CSelectOp SUBTRACT; static const CSelectOp TOGGLE; static const CSelectOp INTERSECT; static const CSelectOp REPLACE;
class CSelectType { public: enum Select_t { kNone, kAll, kDelta };
CSelectType( Select_t selectType ) : m_selectType( selectType ) { }
Select_t SelectTypeStringToType( const char *pSelectString ) { if ( !Q_stricmp( pSelectString, "NONE" ) ) return kNone;
if ( !Q_stricmp( pSelectString, "ALL" ) ) return kAll;
return kDelta; }
CSelectType( const char *pSelectTypeString ) : m_selectType( SelectTypeStringToType( pSelectTypeString ) ) { }
Select_t operator()() const { return m_selectType; }
operator char *() const { switch ( m_selectType ) { case kNone: return "NONE"; case kAll: return "ALL"; default: break; }
return "DELTA"; }
protected: const Select_t m_selectType; };
static const CSelectType ALL; static const CSelectType NONE;
//=============================================================================
//
//=============================================================================
class CObjType { public: enum Obj_t { kAbsolute, kRelative };
CObjType( Obj_t objType ) : m_objType( objType ) { }
CObjType &operator=( const CObjType &rhs ) { m_objType = rhs.m_objType; return *this; }
Obj_t ObjTypeStringToType( const char *pObjString ) { if ( pObjString && ( *pObjString == 'r' || *pObjString == 'R' ) ) return kRelative;
return kAbsolute; }
CObjType( const char *pObjTypeString ) : m_objType( ObjTypeStringToType( pObjTypeString ) ) { }
Obj_t operator()() const { return m_objType; }
operator char *() const { switch ( m_objType ) { case kRelative: return "RELATIVE"; default: break; }
return "ABSOLUTE"; }
protected: Obj_t m_objType; };
static const CObjType ABSOLUTE; static const CObjType RELATIVE;
//=============================================================================
//
//=============================================================================
class CDistanceType { public: CDistanceType( CDmeMesh::Distance_t distanceType ) : m_distanceType( distanceType ) { }
CDmeMesh::Distance_t DistanceTypeStringToType( const char *pDistanceTypeString ) { if ( pDistanceTypeString && ( *pDistanceTypeString == 'a' || *pDistanceTypeString == 'A' ) ) return CDmeMesh::DIST_ABSOLUTE;
if ( pDistanceTypeString && ( *pDistanceTypeString == 'r' || *pDistanceTypeString == 'R' ) ) return CDmeMesh::DIST_RELATIVE;
return CDmeMesh::DIST_DEFAULT; }
CDistanceType( const char *pDistanceTypeString ) : m_distanceType( DistanceTypeStringToType( pDistanceTypeString ) ) { }
CDmeMesh::Distance_t operator()() const { return m_distanceType; }
operator char *() const { switch ( m_distanceType ) { case CDmeMesh::DIST_ABSOLUTE: return "ABSOLUTE"; case CDmeMesh::DIST_RELATIVE: return "RELATIVE"; default: break; }
return "DEFAULT"; }
protected: CDmeMesh::Distance_t m_distanceType; };
static const CDistanceType DIST_ABSOLUTE; static const CDistanceType DIST_RELATIVE; static const CDistanceType DIST_DEFAULT;
class CAxisType { public: enum Axis_t { kXAxis, kYAxis, kZAxis };
CAxisType( Axis_t axisType ) : m_axisType( axisType ) { }
Axis_t AxisTypeStringToType( const char *pAxisString ) { if ( pAxisString && ( *pAxisString == 'y' || *pAxisString == 'Y' ) ) return kYAxis;
if ( pAxisString && ( *pAxisString == 'z' || *pAxisString == 'Z' ) ) return kZAxis;
return kXAxis; }
CAxisType( const char *pAxisTypeString ) : m_axisType( AxisTypeStringToType( pAxisTypeString ) ) { }
Axis_t operator()() const { return m_axisType; }
operator char *() const { switch ( m_axisType ) { case kYAxis: return "YAXIS"; case kZAxis: return "ZAXIS"; default: break; }
return "XAXIS"; }
protected: const Axis_t m_axisType; };
static const CAxisType XAXIS; static const CAxisType YAXIS; static const CAxisType ZAXIS;
class CHalfType { public: enum Half_t { kLeft, kRight };
CHalfType( Half_t halfType ) : m_halfType( halfType ) { }
Half_t HalfTypeStringToType( const char *pHalfString ) { if ( pHalfString && ( *pHalfString == 'l' || *pHalfString == 'L' ) ) return kLeft;
if ( pHalfString && ( *pHalfString == 'r' || *pHalfString == 'R' ) ) return kRight;
return kLeft; }
CHalfType( const char *pHalfTypeString ) : m_halfType( HalfTypeStringToType( pHalfTypeString ) ) { }
Half_t operator()() const { return m_halfType; }
operator char *() const { switch ( m_halfType ) { case kLeft: return "LEFT"; case kRight: return "RIGHT"; default: break; }
return "LEFT"; }
protected: const Half_t m_halfType; };
static const CHalfType LEFT; static const CHalfType RIGHT;
CDmxEdit();
virtual ~CDmxEdit() {};
bool Load( const char *pFilename, const CObjType &loadType = ABSOLUTE );
bool Import( const char *pFilename, const char *pParentName = NULL );
operator bool() const { return m_pMesh != NULL; }
void DoIt();
bool ListDeltas();
int DeltaCount();
const char *DeltaName( int nDeltaIndex );
void Unload();
bool ImportComboRules( const char *pFilename, bool bOverwrite = true, bool bPurgeDeltas = true );
bool ResetState();
bool SetState( const char *pDeltaName );
bool Select( const char *selectString, CDmeSingleIndexedComponent *pPassedSelection = NULL, CDmeMesh *pPassedMesh = NULL );
bool Select( const CSelectType &selectType, CDmeSingleIndexedComponent *pPassedSelection = NULL, CDmeMesh *pPassedMesh = NULL );
bool Select( const CSelectOp &selectOp, const char *pSelectTypeString, CDmeSingleIndexedComponent *pPassedSelection = NULL, CDmeMesh *pPassedMesh = NULL );
bool Select( const CSelectOp &selectOp, const CSelectType &selectType, CDmeSingleIndexedComponent *pPassedSelection = NULL, CDmeMesh *pPassedMesh = NULL );
bool SelectHalf( const CSelectOp &selectOp, const CHalfType &halfType, CDmeSingleIndexedComponent *pPassedSelection = NULL, CDmeMesh *pPassedMesh = NULL );
bool SelectHalf( const CHalfType &halfType, CDmeSingleIndexedComponent *pPassedSelection = NULL, CDmeMesh *pPassedMesh = NULL );
bool GrowSelection( int nSize = 1 );
bool ShrinkSelection( int nSize = 1 );
enum AddType { kRaw, kCorrected };
bool Add( AddType addType, const CDmxEditProxy &e, float weight = 1.0f, float featherDistance = 0.0f, const CFalloffType &falloffType = STRAIGHT, const CDistanceType &distanceType = DIST_DEFAULT );
bool Add( const CDmxEditProxy &e, float weight = 1.0f, float featherDistance = 0.0f, const CFalloffType &falloffType = STRAIGHT, const CDistanceType &distanceType = DIST_DEFAULT ) { return Add( kRaw, e, weight, featherDistance, falloffType, distanceType ); }
bool Add( AddType addType, const char *pDeltaName, float weight = 1.0f, float featherDistance = 0.0f, const CFalloffType &falloffType = STRAIGHT, const CDistanceType &distanceType = DIST_DEFAULT );
bool Add( const char *pDeltaName, float weight = 1.0f, float featherDistance = 0.0f, const CFalloffType &falloffType = STRAIGHT, const CDistanceType &distanceType = DIST_DEFAULT ) { return Add( kRaw, pDeltaName, weight, featherDistance, falloffType, distanceType ); }
bool Interp( const CDmxEditProxy &e, float weight = 1.0f, float featherDistance = 0.0f, const CFalloffType &falloffType = STRAIGHT, const CDistanceType &distanceType = DIST_DEFAULT );
bool Interp( const char *pDeltaName, float weight = 1.0f, float featherDistance = 0.0f, const CFalloffType &falloffType = STRAIGHT, const CDistanceType &distanceType = DIST_DEFAULT );
bool SaveDelta( const char *pDeltaName );
bool DeleteDelta( const delta &d );
bool Save( const char *pFilename, const CObjType &saveType = ABSOLUTE, const char *pDeltaName = NULL );
bool Save() { return Save( m_filename ); }
void CleanupWork();
void CreateWork(); bool Merge( const char *pInFilename, const char *pOutFilename );
bool RemapMaterial( int nMaterialIndex, const char *pNewMaterialName );
bool RemapMaterial( const char *pOldMaterialName, const char *pNewMaterialName );
bool RemoveFacesWithMaterial( const char *pMaterialName );
bool RemoveFacesWithMoreThanNVerts( int nVertexCount );
bool Mirror( CAxisType = XAXIS );
bool ComputeNormals();
bool CreateDeltasFromPresets( const char *pPresetFilename, bool bDeleteNonPresetDeltas = true, const CUtlVector< CUtlString > *pPurgeAllButThese = NULL, const char *pExpressionFilename = NULL );
bool CachePreset( const char *pPresetFilename, const char *pExpressionFilename = NULL );
bool ClearPresetCache();
bool CreateDeltasFromCachedPresets( bool bDeleteNonPresetDeltas = true, const CUtlVector< CUtlString > *pPurgeAllButThese = NULL ) const;
bool CreateExpressionFileFromPresets( const char *pPresetFilename, const char *pExpressionFilename );
bool CreateExpressionFilesFromCachedPresets() const;
bool ComputeWrinkles( bool bOverwrite );
bool ComputeWrinkle( const char *pDeltaName, float scale, const char *pOperation );
bool Scale( float sx, float sy, float sz );
bool SetDistanceType( const CDistanceType &distanceType );
bool Translate( Vector t, float featherDistance = 0.0f, const CFalloffType &falloffType = STRAIGHT, const CDistanceType &distanceType = DIST_DEFAULT, CDmeMesh *pPassedMesh = NULL, CDmeVertexData *pPassedBase = NULL, CDmeSingleIndexedComponent *pPassedSelection = NULL );
bool Translate( Vector t, float featherDistance, const CFalloffType &falloffType = STRAIGHT ) { return Translate( t, featherDistance, falloffType, m_distanceType ); }
bool Rotate( Vector r, Vector o, float featherDistance = 0.0f, const CFalloffType &falloffType = STRAIGHT, const CDistanceType &passedDistanceType = DIST_DEFAULT, CDmeMesh *pPassedMesh = NULL, CDmeVertexData *pPassedBase = NULL, CDmeSingleIndexedComponent *pPassedSelection = NULL );
bool FixPresetFile( const char *pPresetFilename );
bool GroupControls( const char *pGroupName, CUtlVector< const char * > &rawControlNames );
bool ReorderControls( CUtlVector< CUtlString > &controlNames );
bool AddDominationRule( CUtlVector< CUtlString > &dominators, CUtlVector< CUtlString > &supressed );
bool SetStereoControl( const char *pControlName, bool bStereo );
bool SetEyelidControl( const char *pControlName, bool bEyelid );
float MaxDeltaDistance( const char *pDeltaName );
float DeltaRadius( const char *pDeltaName );
float SelectionRadius();
bool SetWrinkleScale( const char *pControlName, const char *pRawControlName, float flScale );
bool ErrorState() { return m_errorState; }
void Error( PRINTF_FORMAT_STRING const tchar *pMsgFormat, ... );
const CUtlString &SetFuncString( lua_State *pLuaState );
const CUtlString &GetFuncString() const { return m_funcString; }
int GetLineNumber() const { return m_lineNo; }
const CUtlString &GetSourceFile() const { return m_sourceFile; }
const CUtlString &GetErrorString() const { return m_errorString; }
int LuaOk( lua_State *pLuaState ) { Msg( "// %s\n", GetFuncString().Get() );
lua_pushboolean( pLuaState, true ); return 1; }
int LuaError( lua_State *pLuaState ) { if ( GetLineNumber() >= 0 ) { Error( "// ERROR: %s:%d: %s - %s\n", GetSourceFile().Get(), GetLineNumber(), GetFuncString().Get(), GetErrorString().Get() ); } else { Error( "// ERROR: %s - %s\n", GetFuncString().Get(), GetErrorString().Get() ); }
lua_pushboolean( pLuaState, false ); return 1; }
int LuaError( lua_State *pLuaState, PRINTF_FORMAT_STRING const char *pFormat, ... ) { char tmpBuf[ 4096 ];
va_list marker;
va_start( marker, pFormat ); #ifdef _WIN32
int len = _vsnprintf( tmpBuf, sizeof( tmpBuf ) - 1, pFormat, marker ); #elif LINUX
int len = vsnprintf( tmpBuf, sizeof( tmpBuf ) - 1, pFormat, marker ); #else
#error "define vsnprintf type."
#endif
va_end( marker );
// Len < 0 represents an overflow
if( len < 0 ) { len = sizeof( tmpBuf ) - 1; tmpBuf[sizeof( tmpBuf ) - 1] = 0; }
if ( GetLineNumber() >= 0 ) { Error( "// ERROR: %s:%d: %s - %s\n", GetSourceFile().Get(), GetLineNumber(), GetFuncString().Get(), tmpBuf ); } else { Error( "// ERROR: %s - %s\n", GetFuncString().Get(), tmpBuf ); }
lua_pushboolean( pLuaState, false ); return 1; }
void LuaWarning( PRINTF_FORMAT_STRING const char *pFormat, ... ) { char tmpBuf[ 4096 ];
va_list marker;
va_start( marker, pFormat ); #ifdef _WIN32
int len = _vsnprintf( tmpBuf, sizeof( tmpBuf ) - 1, pFormat, marker ); #elif LINUX
int len = vsnprintf( tmpBuf, sizeof( tmpBuf ) - 1, pFormat, marker ); #else
#error "define vsnprintf type."
#endif
va_end( marker );
// Len < 0 represents an overflow
if( len < 0 ) { len = sizeof( tmpBuf ) - 1; tmpBuf[sizeof( tmpBuf ) - 1] = 0; }
if ( GetLineNumber() >= 0 ) { Warning( "// WARNING: %s:%d: %s - %s\n", GetSourceFile().Get(), GetLineNumber(), GetFuncString().Get(), tmpBuf ); } else { Warning( "// WARNING: %s - %s\n", GetFuncString().Get(), tmpBuf ); } }
bool SetErrorString( PRINTF_FORMAT_STRING const char *pFormat, ... ) { char tmpBuf[ 4096 ];
va_list marker;
va_start( marker, pFormat ); #ifdef _WIN32
int len = _vsnprintf( tmpBuf, sizeof( tmpBuf ) - 1, pFormat, marker ); #elif LINUX
int len = vsnprintf( tmpBuf, sizeof( tmpBuf ) - 1, pFormat, marker ); #else
#error "define vsnprintf type."
#endif
va_end( marker );
// Len < 0 represents an overflow
if( len < 0 ) { len = sizeof( tmpBuf ) - 1; tmpBuf[sizeof( tmpBuf ) - 1] = 0; }
m_errorString = tmpBuf;
return false; }
protected: CUtlString m_filename; CDmElement *m_pRoot; CDmeMesh *m_pMesh; CDmeSingleIndexedComponent *m_pCurrentSelection; bool m_errorState; CDistanceType m_distanceType;
CUtlStringMap< CUtlString > m_presetCache;
CUtlString m_scriptFilename;
bool Select( CDmeVertexDeltaData *pDelta, CDmeSingleIndexedComponent *pPassedSelection = NULL, CDmeMesh *pPassedMesh = NULL );
bool Select( const CSelectOp &selectOp, CDmeSingleIndexedComponent *pOriginal, const CDmeSingleIndexedComponent *pNew );
bool Select( const CSelectOp &selectOp, CDmeVertexDeltaData *pDelta, CDmeSingleIndexedComponent *pPassedSelection = NULL, CDmeMesh *pPassedMesh = NULL );
void ImportCombinationControls( CDmeCombinationOperator *pSrcComboOp, CDmeCombinationOperator *pDstComboOp, bool bOverwrite );
void ImportDominationRules( CDmeCombinationOperator *pDestComboOp, CDmeCombinationOperator *pSrcComboOp, bool bOverwrite );
CDmeMesh *GetMesh( CDmeMesh *pPassedMesh ) { return pPassedMesh ? pPassedMesh : m_pMesh; }
void SetErrorState() { m_errorState = true; }
void ResetErrorState() { m_errorState = false; }
CDmeSingleIndexedComponent *GetSelection( CDmeSingleIndexedComponent *pPassedSelection ) { return pPassedSelection ? pPassedSelection : m_pCurrentSelection; }
CDmeVertexDeltaData *FindDeltaState( const char *pDeltaName, const CDmeMesh *pPassedMesh = NULL ) const { const CDmeMesh *pMesh = pPassedMesh ? pPassedMesh : m_pMesh; if ( !pMesh ) return NULL;
return pMesh->FindDeltaState( pDeltaName ); }
CDmeVertexData *GetBindState( const CDmeMesh *pPassedMesh = NULL ) const { const CDmeMesh *pMesh = pPassedMesh ? pPassedMesh : m_pMesh; if ( !pMesh ) return NULL;
return pMesh->FindBaseState( "bind" ); }
void GetFuncArg( lua_State *pLuaState, int nIndex, CUtlString &funcString );
CUtlString m_funcString;
int m_lineNo;
CUtlString m_sourceFile;
CUtlString m_errorString;
void UpdateMakefile( CDmElement *pRoot ); void AddExportTags( CDmElement *pRoot, const char *pFilename ); void RemoveExportTags( CDmElement *pRoot, const char *pExportTagsName ); };
//=============================================================================
//
//=============================================================================
typedef int ( * LuaFunc_t ) ( lua_State * );
//=============================================================================
//
//=============================================================================
struct LuaFunc_s { LuaFunc_s( const char *pName, LuaFunc_t pFunc, const char *pProto, const char *pDoc ) : m_pFuncName( pName ) , m_pFunc( pFunc ) , m_pFuncPrototype( pProto ) , m_pFuncDesc( pDoc ) { m_pNextFunc = s_pFirstFunc; s_pFirstFunc = this; }
const char *m_pFuncName; LuaFunc_t m_pFunc; const char *m_pFuncPrototype; const char *m_pFuncDesc;
static LuaFunc_s *s_pFirstFunc; LuaFunc_s *m_pNextFunc;
static CDmxEdit m_dmxEdit; };
//-----------------------------------------------------------------------------
// Macro to install a valve lua command
//
// Use like this:
//
// LUA_COMMAND( blah, "blah prototype", "blah documentation" )
// {
// // ... blah implementation ...
// // ... Function is passed single struct of lua_State *pLuaState ...
// // ... Function returns an int ...
//
// // Example usage:
//
// const char *pArg = luaL_checkstring( pLuaState, 1 );
// return 0;
// }
//-----------------------------------------------------------------------------
#define LUA_COMMAND( _name, _proto, _doc ) \
static int _name##_luaFunc( lua_State *pLuaState ); \ static LuaFunc_s _name##_LuaFunc_s( #_name, _name##_luaFunc, _proto, _doc ); \ static int _name##_luaFunc( lua_State *pLuaState )
//=============================================================================
//
//=============================================================================
class CDmxEditLua { public: CDmxEditLua();
bool DoIt( const char *pFilename );
void SetVar( const CUtlString &var, const CUtlString &val );
void SetGame( const CUtlString &game );
static int FileExists( lua_State *pLuaState );
protected: lua_State *m_pLuaState; };
//=============================================================================
//
//=============================================================================
class CDmxEditProxy { public: CDmxEditProxy( CDmxEdit &dmxEdit ) : m_dmxEdit( dmxEdit ) {}
CDmxEditProxy &operator=( const char *pFilename ) { m_dmxEdit.Load( pFilename ); return *this; }
operator bool() const { m_dmxEdit; }
protected: CDmxEdit &m_dmxEdit; };
#endif // DMXEDIT_H
|