diff --git a/source/graphics/Model.cpp b/source/graphics/Model.cpp index 8e7f149637..33c5017ff8 100755 --- a/source/graphics/Model.cpp +++ b/source/graphics/Model.cpp @@ -205,7 +205,7 @@ void CModel::CalcAnimatedObjectBound(CSkeletonAnimDef* anim,CBound& result) ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // BuildAnimation: load raw animation frame animation from given file, and build a // animation specific to this model -CSkeletonAnim* CModel::BuildAnimation(const char* filename,float speed,double actionpos) +CSkeletonAnim* CModel::BuildAnimation(const char* filename,float speed,double actionpos,double actionpos2) { CSkeletonAnimDef* def=g_SkelAnimMan.GetAnimation(filename); if (!def) return 0; @@ -214,6 +214,7 @@ CSkeletonAnim* CModel::BuildAnimation(const char* filename,float speed,double ac anim->m_AnimDef=def; anim->m_Speed=speed; anim->m_ActionPos=(size_t)( actionpos * anim->m_AnimDef->GetDuration() ); + anim->m_ActionPos2=(size_t)( actionpos2 * anim->m_AnimDef->GetDuration() ); anim->m_ObjectBounds.SetEmpty(); InvalidateBounds(); diff --git a/source/graphics/Model.h b/source/graphics/Model.h index 8c60df0218..79b27b90b5 100755 --- a/source/graphics/Model.h +++ b/source/graphics/Model.h @@ -102,7 +102,7 @@ public: // load raw animation frame animation from given file, and build a // animation specific to this model - CSkeletonAnim* BuildAnimation(const char* filename,float speed, double actionpos); + CSkeletonAnim* BuildAnimation(const char* filename,float speed,double actionpos,double actionpos2); // add a prop to the model on the given point void AddProp(SPropPoint* point,CModel* model); diff --git a/source/graphics/ObjectBase.cpp b/source/graphics/ObjectBase.cpp index 7a252945fa..6b0fd24c9a 100644 --- a/source/graphics/ObjectBase.cpp +++ b/source/graphics/ObjectBase.cpp @@ -160,6 +160,7 @@ bool CObjectBase::Load(const char* filename) AT(name); AT(speed); AT(event); + AT(load); AT(attachpoint); AT(actor); AT(frequency); @@ -227,6 +228,13 @@ bool CObjectBase::Load(const char* filename) else if (anim.m_ActionPos > 100.0) anim.m_ActionPos = 1.0; else if (anim.m_ActionPos > 1.0) anim.m_ActionPos /= 100.0; } + else if (ae.Name == at_load) + { + anim.m_ActionPos2 = CStr(ae.Value).ToDouble(); + if (anim.m_ActionPos2 < 0.0) anim.m_ActionPos2 = 0.0; + else if (anim.m_ActionPos2 > 100.0) anim.m_ActionPos2 = 1.0; + else if (anim.m_ActionPos2 > 1.0) anim.m_ActionPos2 /= 100.0; + } else ; // unrecognised element } diff --git a/source/graphics/ObjectBase.h b/source/graphics/ObjectBase.h index da451836ab..974fbc6a4d 100644 --- a/source/graphics/ObjectBase.h +++ b/source/graphics/ObjectBase.h @@ -13,7 +13,7 @@ public: struct Anim { // constructor - Anim() : m_Speed(1), m_ActionPos( 0.0 ), m_AnimData(0) {} + Anim() : m_Speed(1), m_ActionPos( 0.0 ), m_ActionPos2( 0.0 ), m_AnimData(0) {} // name of the animation - "Idle", "Run", etc CStr m_AnimName; @@ -21,10 +21,11 @@ public: CStr m_FileName; // animation speed, as specified in XML actor file float m_Speed; - // fraction of the way through the animation that the interesting bit + // fraction of the way through the animation that the interesting bit(s) // happens (this is converted to an absolute time when the animation // data is loaded) double m_ActionPos; + double m_ActionPos2; // the animation data, specific to the this model CSkeletonAnim* m_AnimData; }; diff --git a/source/graphics/ObjectEntry.cpp b/source/graphics/ObjectEntry.cpp index 44503a0cb8..839b3a685b 100755 --- a/source/graphics/ObjectEntry.cpp +++ b/source/graphics/ObjectEntry.cpp @@ -144,7 +144,7 @@ bool CObjectEntry::BuildRandomVariant(CObjectBase::variation_key& vars, CObjectB if (m_Animations[t].m_FileName.Length() > 0) { const char* animfilename = m_Animations[t].m_FileName; - m_Animations[t].m_AnimData = m_Model->BuildAnimation(animfilename, m_Animations[t].m_Speed, m_Animations[t].m_ActionPos); + m_Animations[t].m_AnimData = m_Model->BuildAnimation(animfilename, m_Animations[t].m_Speed, m_Animations[t].m_ActionPos, m_Animations[t].m_ActionPos2); CStr AnimNameLC = m_Animations[t].m_AnimName.LowerCase(); diff --git a/source/graphics/SkeletonAnim.h b/source/graphics/SkeletonAnim.h index d0f8cde780..83fa511270 100755 --- a/source/graphics/SkeletonAnim.h +++ b/source/graphics/SkeletonAnim.h @@ -23,8 +23,9 @@ public: CSkeletonAnimDef* m_AnimDef; // speed at which this animation runs float m_Speed; - // time during the animation at which the interesting bit happens (msec) + // time(s) during the animation at which the interesting bit(s) happens (msec) size_t m_ActionPos; + size_t m_ActionPos2; // object space bounds of the model when this animation is applied to it CBound m_ObjectBounds; }; diff --git a/source/ps/scripting/JSInterface_VFS.cpp b/source/ps/scripting/JSInterface_VFS.cpp index 26f94b5781..bccb00222a 100644 --- a/source/ps/scripting/JSInterface_VFS.cpp +++ b/source/ps/scripting/JSInterface_VFS.cpp @@ -5,6 +5,7 @@ #include "lib/res/res.h" #include "scripting/ScriptingHost.h" #include "scripting/JSConversions.h" +#include "scripting/JSInterface_VFS.h" /* array = buildFileList(start_directory, bool recursive, string pattern) @@ -14,9 +15,6 @@ string = readFile(filename) array (of string) = readFileLines(filename) */ -#if 0 - - struct BuildFileListState { JSContext* cx; @@ -35,11 +33,16 @@ static void BuildFileListCB(const char* path, const vfsDirEnt* ent, void* contex { BuildFileListState* s = (BuildFileListState*)context; - jsval val = ToJSVal(ent->name); + CStr result = path; + /* result += CStr( ent->name ); */ + + jsval val = ToJSVal( result ); + JS_SetElement(s->cx, s->filename_array, s->cur_idx, &val); + s->cur_idx++; } -bool BuildFileList( JSContext* cx, uintN argc, jsval* argv, jsval* rval ) +JSBool JSI_VFS::BuildFileList( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval ) { // // get arguments @@ -74,12 +77,11 @@ bool BuildFileList( JSContext* cx, uintN argc, jsval* argv, jsval* rval ) BuildFileListState state(cx); VFSUtil::EnumDirEnts(path, filter, recursive, BuildFileListCB, &state); - *rval = ToJSVal( state.filename_array ); + *rval = OBJECT_TO_JSVAL( state.filename_array ); return( JS_TRUE ); } - -bool GetFileMTime( JSContext* cx, uintN argc, jsval* argv, jsval* rval ) +JSBool JSI_VFS::GetFileMTime( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval ) { assert( argc >= 1 ); CStr filename; @@ -87,15 +89,19 @@ bool GetFileMTime( JSContext* cx, uintN argc, jsval* argv, jsval* rval ) return( JS_FALSE ); struct stat s; + if( !vfs_exists( filename.c_str() ) ) + { + *rval = JSVAL_NULL; + return( JS_TRUE ); + } if(vfs_stat(filename.c_str(), &s) < 0) return( JS_FALSE ); - *rval = ToJSVal( s.st_mtime ); + *rval = ToJSVal( (double)s.st_mtime ); return( JS_TRUE ); } - -bool GetFileSize( JSContext* cx, uintN argc, jsval* argv, jsval* rval ) +JSBool JSI_VFS::GetFileSize( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval ) { assert( argc >= 1 ); CStr filename; @@ -103,15 +109,20 @@ bool GetFileSize( JSContext* cx, uintN argc, jsval* argv, jsval* rval ) return( JS_FALSE ); struct stat s; + if( !vfs_exists( filename.c_str() ) ) + { + *rval = JSVAL_NULL; + return( JS_TRUE ); + } if(vfs_stat(filename.c_str(), &s) < 0) return( JS_FALSE ); - *rval = ToJSVal( s.st_size ); + *rval = ToJSVal( (uint)s.st_size ); return( JS_TRUE ); } -bool ReadFile( JSContext* cx, uintN argc, jsval* argv, jsval* rval ) +JSBool JSI_VFS::ReadFile( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval ) { assert( argc >= 1 ); CStr filename; @@ -120,18 +131,22 @@ bool ReadFile( JSContext* cx, uintN argc, jsval* argv, jsval* rval ) void* p; size_t size; + if( !vfs_exists( filename.c_str() ) ) + { + *rval = JSVAL_NULL; + return( JS_TRUE ); + } Handle hm = vfs_load(filename.c_str(), p, size); if(hm <= 0) return( JS_FALSE ); CStr contents((const char*)p, size); mem_free_h(hm); - *rval = ToJSVal( contents ); + *rval = ToJSVal( CStr( contents ) ); return( JS_TRUE ); } - -bool ReadFileLines( JSContext* cx, uintN argc, jsval* argv, jsval* rval ) +JSBool JSI_VFS::ReadFileLines( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval ) { assert( argc >= 1 ); CStr filename; @@ -141,6 +156,11 @@ bool ReadFileLines( JSContext* cx, uintN argc, jsval* argv, jsval* rval ) // read file void* p; size_t size; + if( !vfs_exists( filename.c_str() ) ) + { + *rval = JSVAL_NULL; + return( JS_TRUE ); + } Handle hm = vfs_load(filename.c_str(), p, size); if(hm <= 0) return( JS_FALSE ); @@ -153,12 +173,10 @@ bool ReadFileLines( JSContext* cx, uintN argc, jsval* argv, jsval* rval ) std::string line; while(std::getline(ss, line)) { - jsval val = ToJSVal(line); + jsval val = ToJSVal( CStr( line ) ); JS_SetElement(cx, line_array, 0, &val); } - *rval = ToJSVal(line_array); + *rval = OBJECT_TO_JSVAL( line_array); return( JS_TRUE ); } - -#endif diff --git a/source/ps/scripting/JSInterface_VFS.h b/source/ps/scripting/JSInterface_VFS.h new file mode 100644 index 0000000000..1cee048612 --- /dev/null +++ b/source/ps/scripting/JSInterface_VFS.h @@ -0,0 +1,19 @@ +// JSInterface_VFS.h +// +// The JavaScript wrapper around useful snippets of the VFS + +#include "scripting/ScriptingHost.h" + +#ifndef JSI_VFS_INCLUDED +#define JSI_VFS_INCLUDED + +namespace JSI_VFS +{ + JSBool BuildFileList( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval ); + JSBool GetFileMTime( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval ); + JSBool GetFileSize( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval ); + JSBool ReadFile( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval ); + JSBool ReadFileLines( JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval ); +}; + +#endif diff --git a/source/scripting/JSConversions.cpp b/source/scripting/JSConversions.cpp index 3ed8f701f3..8ae2ab5e53 100755 --- a/source/scripting/JSConversions.cpp +++ b/source/scripting/JSConversions.cpp @@ -237,6 +237,31 @@ template<> jsval ToJSVal( CStrW& Native ) return( STRING_TO_JSVAL( JS_NewUCStringCopyZ( g_ScriptingHost.GetContext(), Native.utf16().c_str() ) ) ); } +// CStr/CStr8 + +template<> bool ToPrimitive( JSContext* cx, jsval v, CStr8& Storage ) +{ + try + { + Storage = g_ScriptingHost.ValueToString( v ); + } + catch( PSERROR_Scripting_ConversionFailed ) + { + return( false ); + } + return( true ); +} + +template<> jsval ToJSVal( const CStr8& Native ) +{ + return( STRING_TO_JSVAL( JS_NewStringCopyZ( g_ScriptingHost.GetContext(), Native.c_str() ) ) ); +} + +template<> jsval ToJSVal( CStr8& Native ) +{ + return( STRING_TO_JSVAL( JS_NewStringCopyZ( g_ScriptingHost.GetContext(), Native.c_str() ) ) ); +} + // jsval template<> jsval ToJSVal( const jsval& Native ) diff --git a/source/scripting/JSConversions.h b/source/scripting/JSConversions.h index d81a2a8f03..43247968cc 100755 --- a/source/scripting/JSConversions.h +++ b/source/scripting/JSConversions.h @@ -145,6 +145,11 @@ template<> bool ToPrimitive( JSContext* cx, jsval v, CStrW& Storage ); template<> jsval ToJSVal( const CStrW& Native ); template<> jsval ToJSVal( CStrW& Native ); +// CStr(8) +template<> bool ToPrimitive( JSContext* cx, jsval v, CStr8& Storage ); +template<> jsval ToJSVal( const CStr8& Native ); +template<> jsval ToJSVal( CStr8& Native ); + // jsval template<> jsval ToJSVal( const jsval& Native ); @@ -153,4 +158,25 @@ template<> jsval ToJSVal( const jsval& Native ); jsval JSParseString( const CStrW& String ); +/* MT: Maybe: +#define JSCOPY_CAST( For, Use ) \ + template<> bool ToPrimitive( JSContext* cx, jsval v, For& Storage ) \ + { \ + Use temp; \ + if( !ToPrimitive( cx, v, temp ) ) \ + return( false ); \ + Storage = (For)temp; \ + } \ + template<> jsval ToJSVal( const For& Native ) \ + { \ + Use temp = (Use)Native; \ + return( ToJSVal( temp ) ); \ + } \ + template<> jsval ToJSVal( For& Native ) \ + { \ + Use temp = (Use)Native; \ + return( ToJSVal( temp ) ); \ + } +*/ + #endif diff --git a/source/scripting/ScriptGlue.cpp b/source/scripting/ScriptGlue.cpp index 96d4fc4f3f..5d85f0a0b2 100755 --- a/source/scripting/ScriptGlue.cpp +++ b/source/scripting/ScriptGlue.cpp @@ -29,6 +29,7 @@ #include "scripting/JSInterface_Selection.h" #include "scripting/JSInterface_Camera.h" #include "scripting/JSInterface_Console.h" +#include "scripting/JSInterface_VFS.h" #include "scripting/JSConversions.h" #ifndef NO_GUI @@ -72,6 +73,13 @@ JSFunctionSpec ScriptFunctionTable[] = {"getFPS", getFPS, 0, 0, 0 }, {"buildTime", buildTime, 0, 0, 0 }, + // VFS: + {"buildFileList", JSI_VFS::BuildFileList, 1, 0, 0 }, + {"getFileMTime", JSI_VFS::GetFileMTime, 1, 0, 0 }, + {"getFileSize", JSI_VFS::GetFileSize, 1, 0, 0 }, + {"readFile", JSI_VFS::ReadFile, 1, 0, 0 }, + {"readFileLines", JSI_VFS::ReadFileLines, 1, 0, 0 }, + {"v3dist", v3dist, 2, 0, 0 }, {"exit", exitProgram, 0, 0, 0 },