summaryrefslogtreecommitdiffstats
path: root/tools/statepropbuilder/apps/spbuilder/code/sp/engine
diff options
context:
space:
mode:
Diffstat (limited to 'tools/statepropbuilder/apps/spbuilder/code/sp/engine')
-rw-r--r--tools/statepropbuilder/apps/spbuilder/code/sp/engine/aicollisionsolveragent.cpp59
-rw-r--r--tools/statepropbuilder/apps/spbuilder/code/sp/engine/aicollisionsolveragent.hpp43
-rw-r--r--tools/statepropbuilder/apps/spbuilder/code/sp/engine/context.cpp792
-rw-r--r--tools/statepropbuilder/apps/spbuilder/code/sp/engine/context.hpp119
-rw-r--r--tools/statepropbuilder/apps/spbuilder/code/sp/engine/dllmain.cpp43
-rw-r--r--tools/statepropbuilder/apps/spbuilder/code/sp/engine/platform.cpp94
-rw-r--r--tools/statepropbuilder/apps/spbuilder/code/sp/engine/stateprop.cpp445
-rw-r--r--tools/statepropbuilder/apps/spbuilder/code/sp/engine/stateprop.hpp120
-rw-r--r--tools/statepropbuilder/apps/spbuilder/code/sp/engine/statepropdata.cpp509
-rw-r--r--tools/statepropbuilder/apps/spbuilder/code/sp/engine/statepropdata.hpp139
-rw-r--r--tools/statepropbuilder/apps/spbuilder/code/sp/engine/statepropdatatypes.hpp45
-rw-r--r--tools/statepropbuilder/apps/spbuilder/code/sp/engine/workspace.cpp879
-rw-r--r--tools/statepropbuilder/apps/spbuilder/code/sp/engine/workspace.hpp67
13 files changed, 3354 insertions, 0 deletions
diff --git a/tools/statepropbuilder/apps/spbuilder/code/sp/engine/aicollisionsolveragent.cpp b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/aicollisionsolveragent.cpp
new file mode 100644
index 0000000..2c10a5b
--- /dev/null
+++ b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/aicollisionsolveragent.cpp
@@ -0,0 +1,59 @@
+
+
+#include "aicollisionsolveragent.hpp"
+#include "simcollision/collisionanalyserdata.hpp"
+
+AICollisionSolverAgent::AICollisionSolverAgent()
+{
+ EnableCollisionAnalyser();
+}
+
+AICollisionSolverAgent::~AICollisionSolverAgent()
+{
+ DisableCollisionAnalyser();
+}
+
+
+// =======================================================
+// PRE_COLLISION_EVENT
+//
+sim::Solving_Answer AICollisionSolverAgent::PreCollisionEvent(sim::Collision& inCollision, int inPass)
+{
+ return sim::Solving_Continue;
+}
+
+
+// =======================================================
+// COLLISION_EVENT
+//
+sim::Solving_Answer AICollisionSolverAgent::CollisionEvent(
+ sim::SimState* inSimStateA, int indexA,
+ sim::SimState* inSimStateB, int indexB,
+ const rmt::Vector& inPos, float inDvN, float inDvT)
+{
+
+ return sim::Solving_Continue;
+}
+
+
+// =======================================================
+// TEST_IMPULSE
+//
+sim::Solving_Answer AICollisionSolverAgent::TestImpulse(rmt::Vector& mImpulse,
+ sim::Collision& inCollision)
+{
+ sim::SimState* inSimStateA = inCollision.mCollisionObjectA->GetSimState();
+ sim::SimState* inSimStateB = inCollision.mCollisionObjectB->GetSimState();
+
+ return sim::Solving_Continue;
+}
+
+// =======================================================
+// END_OBJECT_COLLISION
+//
+sim::Solving_Answer AICollisionSolverAgent::EndObjectCollision(
+ sim::SimState* inSimState,
+ int inIndex)
+{
+ return sim::Solving_Continue;
+} \ No newline at end of file
diff --git a/tools/statepropbuilder/apps/spbuilder/code/sp/engine/aicollisionsolveragent.hpp b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/aicollisionsolveragent.hpp
new file mode 100644
index 0000000..10097a8
--- /dev/null
+++ b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/aicollisionsolveragent.hpp
@@ -0,0 +1,43 @@
+#ifndef _AICOLLISIONSOLVERAGENT_HPP_
+#define _AICOLLISIONSOLVERAGENT_HPP_
+
+#include "simcommon/tlist.hpp"
+#include "simcollision/impulsebasedcollisionsolver.hpp"
+#include "simcollision/collisionanalyser.hpp"
+#include "simcollision/collisionanalyserdata.hpp"
+
+class AICollisionSolverAgent
+: public sim::CollisionSolverAgent
+{
+public:
+ AICollisionSolverAgent();
+ ~AICollisionSolverAgent();
+
+ //
+ // this method is called at the beginning before anything is done with the collision
+ // returning Solving_Aborted would cause the collision to be ignored.
+ //
+ sim::Solving_Answer PreCollisionEvent(sim::Collision& inCollision, int inPass);
+
+ //
+ // this method allows to trigger sounds, animation and modify the objects state.
+ //
+ sim::Solving_Answer CollisionEvent( sim::SimState* inSimStateA, int indexA,
+ sim::SimState* inSimStateB, int indexB,
+ const rmt::Vector& inPos, float inDvN, float inDvT);
+
+ //
+ // this is called everytime an impulse is computed, before it gets added to the objects
+ //
+ sim::Solving_Answer TestImpulse(rmt::Vector& mImpulse, sim::Collision& inCollision);
+
+ //
+ // the impulse has been added to the object's cache, testing that cache tells
+ // the consequence of adding the cache to the object's state. It is also a good
+ // time for adding the cache of the root node of an articulated object to its
+ // virtual center of mass.
+ //
+ sim::Solving_Answer EndObjectCollision(sim::SimState* inSimState, int inIndex);
+};
+
+#endif \ No newline at end of file
diff --git a/tools/statepropbuilder/apps/spbuilder/code/sp/engine/context.cpp b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/context.cpp
new file mode 100644
index 0000000..f994e0d
--- /dev/null
+++ b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/context.cpp
@@ -0,0 +1,792 @@
+/*
+ * sp/engine/context.cpp
+ */
+
+
+#include <SP/engine/workspace.hpp>
+#include <SP/engine/context.hpp>
+#include <SP/interface/context.hpp>
+
+
+//#include <SP/engine/project.hpp>
+//#include <choreo/load.hpp>
+
+#include <p3d/context.hpp>
+#include <p3d/utility.hpp>
+#include <p3d/view.hpp>
+#include <p3d/directionallight.hpp>
+#include <p3d/pointcamera.hpp>
+#include <p3d/geometry.hpp>
+#include <p3d/anim/drawablepose.hpp>
+#include <radload/radload.hpp>
+
+#include <radtime.hpp>
+#include <radplatform.hpp>
+
+#include <shlwapi.h>
+
+#include <typeinfo>
+
+
+#ifdef RAD_DEBUG
+static const char* pddiDLL = "pddidx8d.dll";
+#endif
+
+#ifdef RAD_TUNE
+static const char* pddiDLL = "pddidx8t.dll";
+#endif
+
+#ifdef RAD_RELEASE
+static const char* pddiDLL = "pddidx8r.dll";
+#endif
+
+
+// global SPContext reference
+SPContext* g_SPContext = 0;
+
+extern Workspace* g_Workspace;
+
+
+//---------------------------------------------------------------------------
+// class SPContext - implementation
+//---------------------------------------------------------------------------
+
+SPContext::SPContext(HWND hwnd):
+ m_HWnd(hwnd),
+
+ m_Context(0),
+ m_View(0),
+ m_Camera(0),
+ m_Light(0),
+ m_Shader(0),
+
+ m_CurrentTime(-1.0f),
+ m_FPSIndex(0),
+ m_SimRate(1.0f),
+
+ m_MouseCapture(0),
+ m_MouseX(0),
+ m_MouseY(0),
+
+ m_IsCameraLocked(false)
+{
+ memset(m_FPS, 0, sizeof(m_FPS));
+}
+
+SPContext::~SPContext()
+{
+ tRefCounted::Release(m_Shader);
+ tRefCounted::Release(m_Light);
+ tRefCounted::Release(m_Camera);
+ tRefCounted::Release(m_View);
+}
+
+bool SPContext::Open()
+{
+ // p3d context init
+ RECT wndRect;
+ GetWindowRect(m_HWnd, &wndRect);
+
+ tContextInitData init;
+ init.hwnd = m_HWnd;
+ init.displayMode = PDDI_DISPLAY_WINDOW;
+ init.bufferMask = PDDI_BUFFER_COLOUR | PDDI_BUFFER_DEPTH;
+ int wndWidth = wndRect.right - wndRect.left;
+ int wndHeight = wndRect.bottom - wndRect.top;
+ init.xsize = wndWidth;
+ init.ysize = wndHeight;
+ init.bpp = 32;
+ strcpy(init.PDDIlib, pddiDLL);
+
+ //p3d::platform->SetActiveContext(0);
+ m_Context = p3d::platform->CreateContext(&init);
+ if (m_Context == 0)
+ return false;
+
+ p3d::platform->SetActiveContext(m_Context);
+
+ // Call into PDDI to enable Z-buffering.
+ p3d::pddi->EnableZBuffer(true);
+
+
+ radLoadInitialize();
+
+ // This call installs chunk handlers for all the primary chunk types that
+ // Pure3D supports. This includes textures, materials, geometries, and the
+ // like.
+ p3d::InstallDefaultLoaders();
+
+ // install default choreo loaders
+ //choreo::InstallDefaultLoaders();
+
+ // p3d view init
+ m_View = new tView;
+ m_View->AddRef();
+
+ m_View->SetBackgroundColour(tColour(64, 64, 128));
+ m_View->SetAmbientLight(tColour(40, 40, 40));
+
+ // p3d light init
+ m_Light = new tDirectionalLight;
+ m_Light->AddRef();
+
+ m_Light->SetDirection(0.0f, 0.0f, 1.0f);
+ m_Light->SetColour(tColour(255, 255, 255));
+ m_View->AddLight(m_Light);
+
+ // p3d camera init
+ m_Camera = new tPointCamera;
+ m_Camera->AddRef();
+ m_Camera->SetNearPlane(0.01f);
+ m_Camera->SetFarPlane(5000.0f);
+ m_Camera->SetFOV(rmt::DegToRadian(90.0f), (float)wndWidth / (float)wndHeight);
+ m_View->SetCamera(m_Camera);
+
+ m_CameraTarget.Clear();
+ m_CameraRotateX = rmt::DegToRadian(-45.0f);
+ m_CameraRotateY = 0.0f;
+ m_CameraDistance = 5.0f;
+
+ // pddi shader
+ m_Shader = p3d::device->NewShader("simple");
+ m_Shader->AddRef();
+ m_Shader->SetInt(PDDI_SP_ISLIT, 0);
+
+ // workspace create
+ if (g_Workspace == 0)
+ {
+ g_Workspace = new Workspace;
+ g_Workspace->AddRef();
+ }
+
+ return true;
+}
+
+bool SPContext::Close()
+{
+ // p3d release stuff
+ tRefCounted::Release(m_Shader);
+ tRefCounted::Release(m_Light);
+ tRefCounted::Release(m_Camera);
+ tRefCounted::Release(m_View);
+
+ // p3d context destroy
+ if (m_Context != 0)
+ {
+ p3d::platform->DestroyContext(m_Context);
+ m_Context = 0;
+ }
+
+ radLoadTerminate();
+
+ return true;
+}
+
+bool SPContext::ViewResize(int w, int h)
+{
+ if (w <= 0)
+ w = 1;
+ if (h <= 0)
+ h = 1;
+
+ RECT wndRect;
+ GetWindowRect(m_HWnd, &wndRect);
+ int wndWidth = wndRect.right - wndRect.left;
+ if (wndWidth <= 0)
+ wndWidth = 1;
+ int wndHeight = wndRect.bottom - wndRect.top;
+ if (wndHeight <= 0)
+ wndHeight = 1;
+
+ if (w > wndWidth)
+ w = wndWidth;
+ if (h > wndHeight)
+ h = wndHeight;
+
+ m_View->SetWindow(0.0f, 0.0f, (float)w / (float)wndWidth, (float)h / (float)wndHeight);
+ m_Camera->SetFOV(rmt::DegToRadian(90.0f), (float)w / (float)h);
+
+ return true;
+}
+
+bool SPContext::Advance()
+{
+ // do time
+ float deltaTime;
+ {
+ float newTime = (float)radTimeGetMilliseconds() / 1000.0f;
+
+ if (m_CurrentTime < 0.0f)
+ {
+ deltaTime = 0.0f;
+ m_CurrentTime = newTime;
+ }
+ else
+ {
+ deltaTime = newTime - m_CurrentTime;
+
+ if (deltaTime < 0.0f)
+ {
+ deltaTime = 0.0f;
+ }
+ else
+ {
+ m_CurrentTime = newTime;
+ }
+
+ // for debugging
+ if (deltaTime > 1.0f)
+ {
+ deltaTime = 1.0f / 60.0f;
+ }
+ else
+ {
+ // do fps
+ m_FPS[m_FPSIndex] = deltaTime;
+ m_FPSIndex = (m_FPSIndex + 1) % MAX_FPS_COUNT;
+ }
+ }
+ }
+
+ float simDeltaTime = m_SimRate * deltaTime;
+ if ( g_Workspace )
+ {
+ g_Workspace->Advance(simDeltaTime * 1000.0f);
+ }
+
+ // update camera & light
+ {
+ /*if (m_IsCameraLocked)
+ {
+ rmt::Vector desiredTarget = m_CVPuppet->GetCameraTarget();
+
+ rmt::Vector delta = desiredTarget;
+ delta.Sub(m_CameraTarget);
+ float mag = delta.NormalizeSafe();
+
+ static const float cameraSpeed = 1.5f; // m/s
+ float maxMag = cameraSpeed * deltaTime * mag;
+ if (mag > maxMag)
+ {
+ mag = maxMag;
+ }
+
+ delta.Scale(mag);
+ m_CameraTarget.Add(delta);
+ m_CameraTarget.x = desiredTarget.x;
+ m_CameraTarget.z = desiredTarget.z;
+ }*/
+
+ m_Camera->SetTarget(m_CameraTarget);
+ rmt::Matrix mY;
+ mY.FillRotateY(m_CameraRotateY);
+ rmt::Matrix mX;
+ mX.FillRotateX(m_CameraRotateX);
+ rmt::Vector cameraPos(0.0f, 0.0f, m_CameraDistance);
+ cameraPos.Rotate(mX);
+ cameraPos.Rotate(mY);
+ cameraPos.Add(m_CameraTarget);
+ m_Camera->SetPosition(cameraPos);
+
+ rmt::Vector lightDir;
+ lightDir = m_CameraTarget;
+ lightDir.Sub(cameraPos);
+ m_Light->SetDirection(lightDir);
+ }
+
+ //return rc;
+ return true;
+}
+
+bool SPContext::Display()
+{
+ m_Context->BeginFrame();
+ m_View->BeginRender();
+
+ // render game context
+ if ( g_Workspace )
+ {
+ g_Workspace->Display(m_Context);
+ }
+
+ // draw origin
+ {
+ rmt::Matrix m;
+ m.Identity();
+ DrawAxes(m, 0.5f);
+ }
+
+ m_View->EndRender();
+ m_Context->EndFrame();
+
+ //return rc;
+ return true;
+}
+
+void SPContext::DrawAxes(const rmt::Matrix& m, float radius)
+{
+ rmt::Vector oldVtx[4] =
+ {
+ rmt::Vector(0,0,0),
+ rmt::Vector(radius,0,0),
+ rmt::Vector(0,radius,0),
+ rmt::Vector(0,0,radius)
+ };
+ rmt::Vector newVtx[4];
+ m.Transform(4, oldVtx, newVtx);
+
+ pddiPrimStream* stream = p3d::pddi->BeginPrims(m_Shader, PDDI_PRIM_LINES, PDDI_V_C , 6);
+
+ stream->Vertex((pddiVector*)newVtx, pddiColour(255,0,0));
+ stream->Vertex((pddiVector*)(newVtx + 1), pddiColour(255,0,0));
+
+ stream->Vertex((pddiVector*)newVtx, pddiColour(0,255,0));
+ stream->Vertex((pddiVector*)(newVtx + 2), pddiColour(0,255,0));
+
+ stream->Vertex((pddiVector*)newVtx, pddiColour(0,0,255));
+ stream->Vertex((pddiVector*)(newVtx + 3), pddiColour(0,0,255));
+
+ p3d::pddi->EndPrims(stream);
+}
+
+void SPContext::DrawLine(const rmt::Vector& a, const rmt::Vector& b, tColour c)
+{
+ pddiPrimStream* stream = p3d::pddi->BeginPrims(m_Shader, PDDI_PRIM_LINES, PDDI_V_C , 2 );
+ stream->Vertex((pddiVector*)(&a), c);
+ stream->Vertex((pddiVector*)(&b), c);
+ p3d::pddi->EndPrims(stream);
+}
+
+void SPContext::RenderPose(tPose* pose)
+{
+ pose->Evaluate();
+
+ int i;
+ int startJoint = 0;
+ for (i = startJoint; i < pose->GetNumJoint(); ++i)
+ {
+ tPose::Joint* joint = pose->GetJoint(i);
+ tPose::Joint* parent = joint->parent;
+
+ if (parent != 0)
+ {
+ DrawLine(parent->worldMatrix.Row(3), joint->worldMatrix.Row(3), tColour(255,255,255));
+ DrawAxes(parent->worldMatrix, 0.02f);
+ }
+ }
+}
+
+void SPContext::MouseDown(int button, int shift, int x, int y)
+{
+ if (m_MouseCapture == 0)
+ {
+ SetCapture(m_HWnd);
+ m_MouseCapture = 1;
+ }
+
+ m_MouseX = x;
+ m_MouseY = y;
+}
+
+void SPContext::MouseMove(int button, int shift, int x, int y)
+{
+ if (m_MouseCapture == 0)
+ return;
+ if (GetCapture() != m_HWnd)
+ return;
+
+ int dx = x - m_MouseX;
+ int dy = y - m_MouseY;
+ m_MouseX = x;
+ m_MouseY = y;
+
+ if ((button & MK_LBUTTON) != 0)
+ {
+ if ((button & MK_MBUTTON) != 0)
+ {
+ CameraZoom(dx * 10);
+ }
+ else
+ {
+ CameraRotate(dx, dy);
+ }
+ }
+ else if ((button & MK_MBUTTON) != 0)
+ {
+ CameraPan(dx, dy);
+ }
+}
+
+void SPContext::MouseUp(int button, int shift, int x, int y)
+{
+ MouseMove(button, shift, x, y);
+
+ if (m_MouseCapture == 0)
+ return;
+
+ ReleaseCapture();
+ m_MouseCapture = 0;
+}
+
+void SPContext::MouseWheel(int scroll)
+{
+ CameraZoom(scroll);
+}
+
+void SPContext::CameraPan(int dx, int dy)
+{
+ RECT wndRect;
+ GetWindowRect(m_HWnd, &wndRect);
+
+ rmt::Vector v((float)-dx / (float)(wndRect.right - wndRect.left),
+ (float)dy / (float)(wndRect.bottom - wndRect.top), 0.0f);
+ rmt::Vector a, b;
+ m_Camera->ViewToWorld(v, &a, &b);
+ b.Sub(a);
+ b.NormalizeSafe();
+ b.Scale(m_CameraDistance - m_Camera->GetNearPlane());
+ b.Add(a);
+ m_CameraTarget = b;
+}
+
+void SPContext::CameraZoom(int dz)
+{
+ m_CameraDistance += ((float)-dz * 0.001f * m_CameraDistance);
+
+ if (m_CameraDistance < 0.1f)
+ {
+ m_CameraDistance = 0.1f;
+ }
+}
+
+void SPContext::CameraRotate(int dx, int dy)
+{
+ m_CameraRotateX += ((float)-dy * 0.01f);
+
+ if (m_CameraRotateX > rmt::DegToRadian(89.9f))
+ {
+ m_CameraRotateX = rmt::DegToRadian(89.9f);
+ }
+
+ if (m_CameraRotateX < rmt::DegToRadian(-89.9f))
+ {
+ m_CameraRotateX = rmt::DegToRadian(-89.9f);
+ }
+
+ m_CameraRotateY += ((float)dx * 0.01f);
+}
+
+float SPContext::SimulationGetFPS() const
+{
+ float fps = 0.0f;
+
+ for (int i = 0; i < MAX_FPS_COUNT; ++i)
+ {
+ fps += m_FPS[i];
+ }
+
+ fps /= (float)MAX_FPS_COUNT;
+
+ if (!rmt::Epsilon(fps, 0.0f))
+ {
+ fps = 1.0f / fps;
+ }
+
+ return fps;
+}
+
+void SPContext::SimulationSetRate(float simRate)
+{
+ m_SimRate = simRate;
+
+ if (m_SimRate < 0.0f)
+ {
+ m_SimRate = 0.0f;
+ }
+}
+
+bool SPContext::GetEntityName(tEntity* entity, char* name, int maxLen)
+{
+ if (maxLen > 0)
+ {
+ name[0] = 0;
+ }
+
+ if (entity == 0)
+ return false;
+
+ if (entity->GetName() != 0)
+ {
+ _snprintf(name, maxLen, "%s", entity->GetName());
+ }
+ else
+ {
+ _snprintf(name, maxLen, "0x%016I64x", entity->GetUID());
+ }
+
+ if (maxLen > 0)
+ {
+ name[maxLen - 1] = 0;
+ }
+
+ return true;
+}
+
+void SPContext::InventoryClear()
+{
+ if (m_Context != 0)
+ {
+ m_Context->GetInventory()->RemoveAllElements();
+ }
+}
+
+int SPContext::InventoryGetEntityCount() const
+{
+ if (m_Context == 0)
+ return 0;
+
+ int entityCount = 0;
+ /*
+ for (int s = 0; s < m_Context->GetInventory()->GetSectionCount(); ++s)
+ {
+ entityCount += m_Context->GetInventory()->GetSectionByIndex(s)->GetElementCount();
+ }
+ */
+
+ return entityCount;
+}
+
+bool SPContext::InventoryGetEntityName(int index,
+ char* name, int nameLen,
+ char* type, int typeLen) const
+{
+ int entityCount = 0;
+
+ /*
+ for (int s = 0; s < m_Context->GetInventory()->GetSectionCount(); ++s)
+ {
+ tEntityTable::RawIterator itor(m_Context->GetInventory()->GetSectionByIndex(s));
+
+ tEntity* obj = itor.First();
+ while (obj)
+ {
+ if (entityCount == index)
+ {
+ GetEntityName(obj, name, nameLen);
+ _snprintf(type, typeLen, "%s", typeid(*obj).name());
+ type[typeLen - 1] = '\0';
+
+ return true;
+ }
+
+ ++entityCount;
+ obj = itor.Next();
+ }
+ }
+ */
+
+ return false;
+}
+
+void SPContext::SetBackgroundColour(int r , int g , int b )
+{
+ m_View->SetBackgroundColour( tColour( r , g , b ) );
+}
+
+
+//---------------------------------------------------------------------------
+// SPContext - DLL interface
+//---------------------------------------------------------------------------
+
+int SP_CALLCONV SPContextOpen(HWND hwnd)
+{
+ P3DASSERT(g_SPContext == 0);
+ if (g_SPContext != 0)
+ return -1;
+
+ g_SPContext = new SPContext(hwnd);
+ if (!g_SPContext->Open())
+ {
+ delete g_SPContext;
+ g_SPContext = 0;
+ return -1;
+ }
+
+ return 1;
+}
+
+int SP_CALLCONV SPContextClose()
+{
+ if (g_SPContext == 0)
+ return 0;
+
+ if (!g_SPContext->Close())
+ {
+ delete g_SPContext;
+ g_SPContext = 0;
+ return -1;
+ }
+
+ delete g_SPContext;
+ g_SPContext = 0;
+ return 1;
+}
+
+int SP_CALLCONV SPContextViewResize(int w, int h)
+{
+ if (g_SPContext == 0)
+ return -1;
+
+ g_SPContext->ViewResize(w, h);
+ return 1;
+}
+
+int SP_CALLCONV SPContextIsPDDIStatsEnabled()
+{
+ if (p3d::pddi == 0)
+ return -1;
+ return p3d::pddi->IsStatsOverlayEnabled();
+}
+
+int SP_CALLCONV SPContextSetIsPDDIStatsEnabled(int statsEnabled)
+{
+ if (p3d::pddi == 0)
+ return -1;
+ p3d::pddi->EnableStatsOverlay(statsEnabled != 0);
+ return 1;
+}
+
+int SP_CALLCONV SPContextAdvance()
+{
+ if (g_SPContext == 0)
+ return -1;
+
+ return g_SPContext->Advance();
+}
+
+int SP_CALLCONV SPContextDisplay()
+{
+ if (g_SPContext == 0)
+ return -1;
+
+ return g_SPContext->Display();
+}
+
+int SP_CALLCONV SPContextMouseDown(int button, int shift, int x, int y)
+{
+ if (g_SPContext == 0)
+ return -1;
+
+ g_SPContext->MouseDown(button, shift, x, y);
+ return 0;
+}
+
+int SP_CALLCONV SPContextMouseMove(int button, int shift, int x, int y)
+{
+ if (g_SPContext == 0)
+ return -1;
+
+ g_SPContext->MouseMove(button, shift, x, y);
+ return 0;
+}
+
+int SP_CALLCONV SPContextMouseUp(int button, int shift, int x, int y)
+{
+ if (g_SPContext == 0)
+ return -1;
+
+ g_SPContext->MouseUp(button, shift, x, y);
+ return 0;
+}
+
+int SP_CALLCONV SPContextMouseWheel(int scroll)
+{
+ if (g_SPContext == 0)
+ return -1;
+
+ g_SPContext->MouseWheel(scroll);
+ return 0;
+}
+
+float SP_CALLCONV SPSimulationGetFPS()
+{
+ if (g_SPContext == 0)
+ return 0.0f;
+
+ return g_SPContext->SimulationGetFPS();
+}
+
+float SP_CALLCONV SPSimulationGetRate()
+{
+ if (g_SPContext == 0)
+ return 0.0f;
+
+ return g_SPContext->SimulationGetRate();
+}
+
+int SP_CALLCONV SPSimulationSetRate(float rate)
+{
+ if (g_SPContext == 0)
+ return -1;
+
+ g_SPContext->SimulationSetRate(rate);
+ return 0;
+}
+
+int SP_CALLCONV SPContextGetCameraLock()
+{
+ if (g_SPContext == 0)
+ return -1;
+
+ return g_SPContext->IsCameraLocked();
+}
+
+int SP_CALLCONV SPContextSetCameraLock(int cameraLock)
+{
+ if (g_SPContext == 0)
+ return -1;
+
+ g_SPContext->SetIsCameraLocked(cameraLock != 0);
+ return 0;
+}
+
+int SP_CALLCONV SPInventoryClear()
+{
+ if (g_SPContext == 0)
+ return -1;
+
+ g_SPContext->InventoryClear();
+ return 0;
+}
+
+int SP_CALLCONV SPInventoryGetEntityCount()
+{
+ if (g_SPContext == 0)
+ return -1;
+
+ return g_SPContext->InventoryGetEntityCount();
+}
+
+int SP_CALLCONV SPInventoryGetEntityName(int index, char* name, int nameLen, char* type, int typeLen)
+{
+ if (g_SPContext == 0)
+ return -1;
+
+ if (!g_SPContext->InventoryGetEntityName(index, name, nameLen, type, typeLen))
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+int SP_CALLCONV SPSetBackgroundColour( int r , int g , int b )
+{
+ if (g_SPContext == 0)
+ return 0;
+
+ g_SPContext->SetBackgroundColour( r , g , b );
+ return 1;
+}
+
+// End of file.
diff --git a/tools/statepropbuilder/apps/spbuilder/code/sp/engine/context.hpp b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/context.hpp
new file mode 100644
index 0000000..faf88c0
--- /dev/null
+++ b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/context.hpp
@@ -0,0 +1,119 @@
+/*
+ * sp/engine/context.hpp
+ */
+
+
+#ifndef SP_ENGINE_CONTEXT_HPP
+#define SP_ENGINE_CONTEXT_HPP
+
+
+#define WIN32_LEAN_AND_MEAN
+#define WIN32_EXTRA_LEAN
+#include <windows.h>
+
+#include <radmath/radmath.hpp>
+#include <p3d/p3dtypes.hpp>
+
+
+class tEntity;
+class tContext;
+class tView;
+class tPointCamera;
+class tDirectionalLight;
+class tPose;
+class pddiShader;
+
+
+//---------------------------------------------------------------------------
+// class SPContext
+//---------------------------------------------------------------------------
+
+class SPContext
+{
+public:
+
+ enum
+ {
+ MAX_FPS_COUNT = 10
+ };
+
+ SPContext(HWND hwnd);
+ virtual ~SPContext();
+
+ tContext* GetContext()
+ { return m_Context; }
+
+ bool Open();
+ bool Close();
+
+ bool ViewResize(int w, int h);
+
+ bool Advance();
+ bool Display();
+
+ void MouseDown(int button, int shift, int x, int y);
+ void MouseMove(int button, int shift, int x, int y);
+ void MouseUp(int button, int shift, int x, int y);
+ void MouseWheel(int scroll);
+
+ float SimulationGetFPS() const;
+ float SimulationGetRate() const
+ { return m_SimRate; }
+ void SimulationSetRate(float simRate);
+
+ bool IsCameraLocked() const
+ { return m_IsCameraLocked; }
+ void SetIsCameraLocked(bool cameraLock)
+ { m_IsCameraLocked = cameraLock; }
+ tPointCamera* GetCamera() const
+ { return m_Camera; }
+
+ static bool GetEntityName(tEntity* entity, char* name, int maxLen);
+
+ void InventoryClear();
+ int InventoryGetEntityCount() const;
+ bool InventoryGetEntityName(int index,
+ char* name, int nameLen,
+ char* type, int typeLen) const;
+
+ void RenderPose(tPose* pose);
+ void DrawAxes(const rmt::Matrix& m, float radius);
+ void DrawLine(const rmt::Vector& a, const rmt::Vector& b, tColour c);
+
+ void SetBackgroundColour( int r , int g , int b );
+
+private:
+
+ void CameraPan(int dx, int dy);
+ void CameraZoom(int dz);
+ void CameraRotate(int dx, int dy);
+
+ HWND m_HWnd;
+
+ tContext* m_Context;
+ tView* m_View;
+ tPointCamera* m_Camera;
+ tDirectionalLight* m_Light;
+ pddiShader* m_Shader;
+
+ float m_CurrentTime;
+ float m_FPS[MAX_FPS_COUNT];
+ int m_FPSIndex;
+ float m_SimRate;
+
+ rmt::Vector m_CameraTarget;
+ float m_CameraRotateX;
+ float m_CameraRotateY;
+ float m_CameraDistance;
+ bool m_IsCameraLocked;
+
+ int m_MouseCapture;
+ int m_MouseX;
+ int m_MouseY;
+};
+
+
+extern SPContext* g_SPContext;
+
+
+#endif // SP_ENGINE_CONTEXT_HPP
diff --git a/tools/statepropbuilder/apps/spbuilder/code/sp/engine/dllmain.cpp b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/dllmain.cpp
new file mode 100644
index 0000000..5d2df57
--- /dev/null
+++ b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/dllmain.cpp
@@ -0,0 +1,43 @@
+/*
+ * fightviewer/code/engine/dllmain.cpp
+ */
+
+
+#include <windows.h>
+
+
+HINSTANCE SPHInstance = 0;
+
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,
+ DWORD reason,
+ LPVOID reserved)
+{
+ SPHInstance = hinstDLL;
+
+ // Perform actions based on the reason for calling.
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ // Initialize once for each new process.
+ // Return FALSE to fail DLL load.
+ break;
+
+ case DLL_THREAD_ATTACH:
+ // Do thread-specific initialization.
+ break;
+
+ case DLL_THREAD_DETACH:
+ // Do thread-specific cleanup.
+ break;
+
+ case DLL_PROCESS_DETACH:
+ // Perform any necessary cleanup.
+ break;
+ }
+
+ return TRUE;
+}
+
+
+// End of file.
diff --git a/tools/statepropbuilder/apps/spbuilder/code/sp/engine/platform.cpp b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/platform.cpp
new file mode 100644
index 0000000..c27a39e
--- /dev/null
+++ b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/platform.cpp
@@ -0,0 +1,94 @@
+/*
+ * sp/engine/platform.cpp
+ */
+
+
+#include <sp/interface/platform.hpp>
+
+#include <radmemory.hpp>
+#include <radplatform.hpp>
+#include <radtime.hpp>
+#include <radfile.hpp>
+#include <radthread.hpp>
+
+#include <p3d/utility.hpp>
+
+
+extern HINSTANCE SPHInstance;
+
+//---------------------------------------------------------------------------
+// SPPlatform - DLL interface
+//---------------------------------------------------------------------------
+
+int SP_CALLCONV SPPlatformOpen(HWND hwnd)
+{
+ // ftt thread init
+ radThreadInitialize();
+
+ // ftt memory init
+ radMemoryInitialize();
+
+ // ftt platform init
+ radPlatformInitialize(hwnd, SPHInstance);
+
+ // ftt time init
+ radTimeInitialize();
+
+ // ftt file init
+ radFileInitialize();
+
+ // p3d platform init
+ tPlatform* platform = tPlatform::Create(SPHInstance);
+ if (platform == 0)
+ return -1;
+
+ // game project create
+ /*
+ if (g_SPProject == 0)
+ {
+ g_SPProject = SP_PROC_NEWPROJECT();
+ P3DASSERT(g_SPProject != 0);
+ if (g_SPProject == 0)
+ return -1;
+ g_SPProject->AddRef();
+ g_SPProject->ProjectInit();
+ }
+ */
+
+ return 0;
+}
+
+int SP_CALLCONV SPPlatformClose()
+{
+ // destroy game project
+ //tRefCounted::Release(g_SPProject);
+
+ // destroy workspace
+ //tRefCounted::Release(g_SPWorkspace);
+
+ // p3d platform destroy
+ if (p3d::platform != 0)
+ {
+ tPlatform::Destroy(p3d::platform);
+ }
+
+ // ftt file destroy
+ radFileTerminate();
+
+ // ftt time destroy
+ radTimeTerminate();
+
+ // ftt platform destroy
+ radPlatformTerminate();
+
+ // ftt memory destroy
+ radMemoryTerminate();
+
+ // ftt thread destroy
+ radThreadTerminate();
+
+ return 0;
+}
+
+
+// End of file.
diff --git a/tools/statepropbuilder/apps/spbuilder/code/sp/engine/stateprop.cpp b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/stateprop.cpp
new file mode 100644
index 0000000..cbfa84d
--- /dev/null
+++ b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/stateprop.cpp
@@ -0,0 +1,445 @@
+#include <p3d/utility.hpp>
+#include <p3d/matrixstack.hpp>
+#include <p3d/anim/multicontroller.hpp>
+#include <p3d/anim/compositedrawable.hpp>
+#include <p3d/anim/animatedobject.hpp>
+#include <p3d/anim/animate.hpp>
+
+#include <toollib/chunks16/inc/tlStatePropChunk.hpp>
+#include <toollib/inc/tlFile.hpp>
+#include <toollib/inc/tlFileByteStream.hpp>
+
+#include "stateprop.hpp"
+#include "statepropdata.hpp"
+
+CStateProp* CStateProp::CreateCStateProp( CStatePropData* statePropData , unsigned int state )
+{
+ tAnimatedObjectFactory* objectFactory = statePropData->m_ObjectFactory;
+
+ if ( !objectFactory )
+ {
+ objectFactory = p3d::find<tAnimatedObjectFactory>( statePropData->m_FactoryName );
+ if ( objectFactory )
+ {
+ statePropData->m_ObjectFactory = objectFactory;
+ statePropData->m_ObjectFactory->AddRef();
+ }
+ }
+
+ if ( objectFactory )
+ {
+ tAnimatedObject* animatedObject = objectFactory->CreateObject(NULL);
+ CStateProp* stateProp = new CStateProp( animatedObject , statePropData , state );
+ return stateProp;
+ }
+
+ return NULL;
+}
+
+CStateProp::CStateProp( tAnimatedObject* animatedObject , CStatePropData* statePropData , unsigned int state ) :
+ m_StatePropData( NULL ),
+ m_AnimatedObject( NULL ),
+ m_BaseFrameController( NULL ),
+ m_StatePropListener( NULL ),
+ m_CurrentState( state )
+{
+ //set state data
+ P3DASSERT( statePropData );
+ m_StatePropData = statePropData;
+ m_StatePropData->AddRef();
+
+ //set animated object
+ P3DASSERT( animatedObject );
+ m_AnimatedObject = animatedObject;
+ m_AnimatedObject->AddRef();
+
+ //base frame controller is run in milliseconds (ie the 1 is the timer)
+ m_BaseFrameController = new tMultiController(0 , 1000.f);
+ m_BaseFrameController->AddRef();
+ m_BaseFrameController->Reset();
+
+ //initilize transform
+ rmt::Matrix identity;
+ identity.Identity();
+ SetTransformationMatrix( identity );
+
+ //initialize the state
+ SetState( state );
+}
+
+CStateProp::~CStateProp()
+{
+ if ( m_BaseFrameController )
+ m_BaseFrameController->Release();
+ if ( m_StatePropData )
+ m_StatePropData->Release();
+ if ( m_AnimatedObject )
+ m_AnimatedObject->Release();
+}
+
+void CStateProp::Update( float dt )
+{
+ unsigned int i;
+
+ float lastFrame = m_BaseFrameController->GetFrame();
+ m_BaseFrameController->Advance( dt );
+ float newFrame = m_BaseFrameController->GetFrame();
+
+ //Check out transition
+ TransitionData tansdata = m_StatePropData->GetTransitionData( m_CurrentState );
+ if ( tansdata.autoTransition )
+ {
+ if (tansdata.onFrame >= lastFrame && tansdata.onFrame < newFrame)
+ {
+ SetState( tansdata.toState );
+ }
+ }
+
+ //Check callback events
+ if ( m_StatePropListener )
+ {
+ for ( i = 0; i < m_StatePropData->GetNumberOfCallbacks( m_CurrentState ); i++ )
+ {
+ CallbackData callbackData = m_StatePropData->GetCallbackData( m_CurrentState , i );
+ if ( callbackData.onFrame >= lastFrame && callbackData.onFrame < newFrame)
+ {
+ m_StatePropListener->RecieveEvent( callbackData.callbackID , this );
+ }
+ }
+ }
+
+ //update frame controllers
+ unsigned int numFrameControllers = GetNumberOfFrameControllers();
+ for ( i = 0; i < numFrameControllers; i++ )
+ {
+ FrameControllerData fcData = m_StatePropData->GetFrameControllerData( m_CurrentState , i );
+
+ //if we need to update
+ if ( fcData.minFrame != fcData.maxFrame )
+ {
+ tFrameController* fc = GetFrameControllerByIndex( i );
+
+ //if the min frame is greater than the max frame then reverse the update
+ if ( fcData.minFrame > fcData.maxFrame )
+ {
+ fc->Advance( -dt , false );
+ }
+ else
+ {
+ fc->Advance( dt , false );
+ }
+
+ if ( fcData.isCyclic && fcData.numberOfCycles > 0 )
+ {
+ unsigned int currentNumberOfCycles = fc->LastFrameReached();
+ if ( currentNumberOfCycles >= fcData.numberOfCycles )
+ {
+ fc->SetCycleMode( FORCE_NON_CYCLIC );
+ fc->SetFrame( fcData.maxFrame );
+ }
+ }
+ }
+ }
+}
+
+void CStateProp::Render()
+{
+ p3d::stack->Push();
+ p3d::stack->Multiply( m_Transform );
+
+ m_AnimatedObject->Display();
+
+ p3d::stack->Pop();
+}
+
+void CStateProp::UpdateFrameControllersForRender()
+{
+ unsigned int numFrameControllers = GetNumberOfFrameControllers();
+ for ( unsigned int i = 0; i < numFrameControllers; i++ )
+ {
+ GetFrameControllerByIndex( i )->Advance( 0.f , true );
+ }
+}
+
+unsigned int CStateProp::GetState()
+{
+ return m_CurrentState;
+}
+
+void CStateProp::NextState()
+{
+ if ( m_CurrentState + 1 >= m_StatePropData->GetNumberOfStates() )
+ {
+ SetState( 0 );
+ }
+ else
+ {
+ SetState( m_CurrentState + 1 );
+ }
+}
+
+void CStateProp::PrevState()
+{
+ if ( m_CurrentState - 1 < 0 )
+ {
+ SetState( m_StatePropData->GetNumberOfStates() - 1 );
+ }
+ else
+ {
+ SetState( m_CurrentState - 1 );
+ }
+}
+
+void CStateProp::SetState( unsigned int state )
+{
+ if ( state < m_StatePropData->GetNumberOfStates() && state >= 0 )
+ {
+ m_CurrentState = state;
+ }
+
+ m_BaseFrameController->SetFrame(0.f);
+
+ unsigned int i;
+
+ //reset the FC for new state
+ unsigned int numFrameControllers = GetNumberOfFrameControllers();
+ for ( i = 0; i < numFrameControllers; i++ )
+ {
+ FrameControllerData frameControllerData = m_StatePropData->GetFrameControllerData( m_CurrentState , i );
+ tFrameController* fc = GetFrameControllerByIndex(i);
+
+ //if we are holding a frame over from last state dont reset
+ if ( !frameControllerData.holdFrame )
+ {
+ //Reset() MUST come first or it will trounce frame ranges etc...
+ fc->Reset();
+ }
+ fc->SetRelativeSpeed( frameControllerData.relativeSpeed );
+ fc->SetCycleMode( (frameControllerData.isCyclic == 1) ? FORCE_CYCLIC : FORCE_NON_CYCLIC );
+ if ( frameControllerData.minFrame > frameControllerData.maxFrame )
+ {
+ fc->SetFrameRange( frameControllerData.maxFrame , frameControllerData.minFrame );
+ }
+ else
+ {
+ fc->SetFrameRange( frameControllerData.minFrame , frameControllerData.maxFrame );
+ }
+
+ if ( !frameControllerData.holdFrame )
+ {
+ fc->SetFrame( frameControllerData.minFrame );
+ }
+ }
+
+ //Set visibility for new state
+ unsigned int numElements = m_AnimatedObject->GetBaseObject()->GetNumDrawableElement();
+ for ( i = 0; i < numElements; i++ )
+ {
+ tCompositeDrawable::DrawableElement* de = GetDrawableElement(i);
+
+ de->SetLockVisibility(false);
+ VisibilityData visibilityData = m_StatePropData->GetVisibilityData( m_CurrentState , i );
+ bool visible = visibilityData.isVisible == 1;
+ de->SetVisibility( visible );
+
+ //lock visibility if visiblility if false
+ de->SetLockVisibility(!visible);
+ }
+}
+
+void CStateProp::OnEvent( unsigned int eventID )
+{
+ unsigned int i;
+ unsigned int numEvents = m_StatePropData->GetNumberOfEvents( m_CurrentState );
+ for ( i = 0; i < numEvents; i++ )
+ {
+ EventData eventData = m_StatePropData->GetEventData( m_CurrentState , i );
+ if ( eventData.eventID == eventID )
+ {
+ SetState( eventData.toState );
+ }
+ }
+}
+
+void CStateProp::UpdateOnDataEdit()
+{
+ //Update without reseting the current frame or current state info
+ unsigned int i;
+
+ //update frame controllers
+ unsigned int numFrameControllers = GetNumberOfFrameControllers();
+ for ( i = 0; i < numFrameControllers; i++ )
+ {
+ FrameControllerData frameControllerData = m_StatePropData->GetFrameControllerData( m_CurrentState , i );
+ tFrameController* fc = GetFrameControllerByIndex(i);
+ float frame = fc->GetFrame();
+ fc->Reset();
+ fc->SetRelativeSpeed( frameControllerData.relativeSpeed );
+ fc->SetCycleMode( (frameControllerData.isCyclic == 1) ? FORCE_CYCLIC : FORCE_NON_CYCLIC );
+ if ( frameControllerData.minFrame > frameControllerData.maxFrame )
+ {
+ fc->SetFrameRange( frameControllerData.maxFrame , frameControllerData.minFrame );
+ }
+ else
+ {
+ fc->SetFrameRange( frameControllerData.minFrame , frameControllerData.maxFrame );
+ }
+
+ fc->SetFrame( frame );
+ }
+
+ //set visibilites
+ unsigned int numDrawableElements = GetNumberOfDrawableElements();
+ for ( i = 0; i < numDrawableElements; i++ )
+ {
+ tCompositeDrawable::DrawableElement* de = GetDrawableElement(i);
+
+ de->SetLockVisibility(false);
+ VisibilityData visibilityData = m_StatePropData->GetVisibilityData( m_CurrentState , i );
+ bool visible = visibilityData.isVisible == 1;
+ de->SetVisibility( visible );
+
+ //lock visibility if visiblility if false
+ de->SetLockVisibility(!visible);
+ }
+}
+
+float CStateProp::GetBaseFrameControllerFrame()
+{
+ return m_BaseFrameController->GetFrame();
+}
+
+CStatePropData* CStateProp::GetCStatePropData()
+{
+ return m_StatePropData;
+}
+
+unsigned int CStateProp::GetNumberOfFrameControllers()
+{
+ return m_AnimatedObject->GetCurrentAnimation()->GetNumFrameControllers();
+}
+
+tFrameController* CStateProp::GetFrameControllerByIndex( unsigned int i )
+{
+ return m_AnimatedObject->GetCurrentAnimation()->GetFrameControllerByIndex(i);
+}
+
+unsigned int CStateProp::GetNumberOfDrawableElements()
+{
+ return m_AnimatedObject->GetBaseObject()->GetNumDrawableElement();
+}
+
+tCompositeDrawable::DrawableElement* CStateProp::GetDrawableElement( unsigned int i )
+{
+ return m_AnimatedObject->GetBaseObject()->GetDrawableElement( i );
+}
+
+const char* CStateProp::GetDrawableName( unsigned int i )
+{
+ return m_AnimatedObject->GetBaseObject()->GetDrawableElement( i )->GetDrawable()->GetName();
+}
+
+const char* CStateProp::GetPropName( )
+{
+ return GetName();
+}
+
+//Export the CStatePropData
+void CStateProp::ExportChunk( const char* filename )
+{
+ //create the outchunk data chunk
+ tlDataChunk* outchunk = new tlDataChunk;
+
+ //create smart prop chunk
+ char buf[256];
+ tlStatePropChunk* statepropchunk = new tlStatePropChunk;
+
+ //version one has extra floats and ints
+ statepropchunk->SetVersion( 1 );
+
+ statepropchunk->SetName( m_StatePropData->GetName() );
+ statepropchunk->SetObjectFactoryName( m_StatePropData->GetName() );
+ statepropchunk->SetNumStates( m_StatePropData->GetNumberOfStates() );
+
+ unsigned int state;
+ int j;
+ //create state subchunks
+ for ( state = 0; state < m_StatePropData->GetNumberOfStates(); state++ )
+ {
+ tlStatePropStateDataChunk* statechunk = new tlStatePropStateDataChunk;
+ sprintf(buf, "state%i", state );
+ statechunk->SetName( buf );
+ TransitionData tData = m_StatePropData->GetTransitionData( state );
+ statechunk->SetAutoTransition( tData.autoTransition );
+ statechunk->SetOutFrame( tData.onFrame );
+ statechunk->SetOutState( tData.toState );
+
+ int numDrawables = GetNumberOfDrawableElements();
+ statechunk->SetNumDrawables( numDrawables );
+ for ( j = 0; j < numDrawables; j++ )
+ {
+ tlStatePropVisibilitiesDataChunk* visibilitychunk = new tlStatePropVisibilitiesDataChunk;
+ VisibilityData vData = m_StatePropData->GetVisibilityData( state , j );
+ visibilitychunk->SetName( GetDrawableElement(j)->GetDrawable()->GetName() );
+ visibilitychunk->SetVisible( vData.isVisible );
+ statechunk->AppendSubChunk( visibilitychunk );
+ }
+
+ int numFrameControllers = GetNumberOfFrameControllers();
+ statechunk->SetNumFrameControllers( numFrameControllers );
+ for ( j = 0; j < numFrameControllers; j++ )
+ {
+ tlStatePropFrameControllerDataChunk* framecontrollerchunk = new tlStatePropFrameControllerDataChunk;
+ FrameControllerData fData = m_StatePropData->GetFrameControllerData( state , j );
+ framecontrollerchunk->SetName( GetFrameControllerByIndex(j)->GetName() );
+ framecontrollerchunk->SetCyclic( fData.isCyclic );
+ framecontrollerchunk->SetMinFrame( fData.minFrame );
+ framecontrollerchunk->SetMaxFrame( fData.maxFrame );
+ framecontrollerchunk->SetRelativeSpeed( fData.relativeSpeed );
+ framecontrollerchunk->SetHoldFrame( fData.holdFrame );
+ framecontrollerchunk->SetNumberOfCycles( fData.numberOfCycles );
+ statechunk->AppendSubChunk( framecontrollerchunk );
+ }
+
+ int numEvents = m_StatePropData->GetNumberOfEvents( state );
+ statechunk->SetNumEvents( numEvents );
+ for ( j = 0; j < numEvents; j++ )
+ {
+ tlStatePropEventDataChunk* eventdatachunk = new tlStatePropEventDataChunk;
+ EventData eData = m_StatePropData->GetEventData( state , j );
+ eventdatachunk->SetName( eData.eventName );
+ eventdatachunk->SetState( eData.toState );
+ eventdatachunk->SetEventEnum( eData.eventID );
+ statechunk->AppendSubChunk( eventdatachunk );
+ }
+
+ int numCallbacks = m_StatePropData->GetNumberOfCallbacks( state );
+ statechunk->SetNumCallbacks( numCallbacks );
+ for ( j = 0; j < numCallbacks; j++ )
+ {
+ tlStatePropCallbackDataChunk* callbackChunk = new tlStatePropCallbackDataChunk;
+ CallbackData cData = m_StatePropData->GetCallbackData( state , j );
+ callbackChunk->SetName( cData.callbackName );
+ callbackChunk->SetOnFrame( cData.onFrame );
+ callbackChunk->SetEventEnum( cData.callbackID );
+ statechunk->AppendSubChunk( callbackChunk );
+ }
+
+ //append the sate chunk
+ statepropchunk->AppendSubChunk( statechunk );
+ }
+
+ outchunk->AppendSubChunk( statepropchunk );
+
+ // create the new output file
+ tlFile output(new tlFileByteStream(filename,omWRITE), tlFile::CHUNK32);
+
+ if(!output.IsOpen())
+ {
+ printf("Could not open %s for writing\n", filename);
+ return ;
+ }
+
+ outchunk->Write(&output);
+ output.Close();
+} \ No newline at end of file
diff --git a/tools/statepropbuilder/apps/spbuilder/code/sp/engine/stateprop.hpp b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/stateprop.hpp
new file mode 100644
index 0000000..c72b76b
--- /dev/null
+++ b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/stateprop.hpp
@@ -0,0 +1,120 @@
+#ifndef _STATEPROP_HPP_
+#define _STATEPROP_HPP_
+
+#include "radmath/radmath.hpp"
+
+//=============================================================================
+// Forward Class/Struct Declarations
+//=============================================================================
+
+class tFrameController;
+class tAnimatedObject;
+class CStatePropData;
+class CStateProp;
+class tCompositeDrawable;
+
+
+//=============================================================================
+// Class Declarations
+// PropListener
+//=============================================================================
+
+class CStatePropListener : public tRefCounted
+{
+public:
+ virtual void RecieveEvent( int event , CStateProp* stateProp ) = 0;
+};
+
+//=============================================================================
+// Definitions
+//=============================================================================
+
+
+//=============================================================================
+// Class Declarations
+// CStateProp
+//=============================================================================
+class CStateProp : public tEntity
+{
+public:
+
+ static CStateProp* CreateCStateProp( CStatePropData* statePropData , unsigned int state );
+
+ CStateProp( tAnimatedObject* animatedObject , CStatePropData* statePropData , unsigned int state = 0 );
+ ~CStateProp();
+
+ //Per frame update
+ void Update( float dt );
+
+ //Render
+ void Render();
+
+ //call before render
+ void UpdateFrameControllersForRender();
+
+ unsigned int GetState();
+ void SetState( unsigned int state );
+ void NextState();
+ void PrevState();
+
+ void OnEvent( unsigned int eventID );
+
+ void SetTransformationMatrix( const rmt::Matrix &tm);
+ const rmt::Matrix& GetTransformationMatrix() const;
+
+ void SetPosition( const rmt::Vector& pos );
+ const rmt::Vector& GetPosition() const;
+
+ //Get State Prop Data
+ CStatePropData* GetCStatePropData();
+
+ // Update for new data
+ void UpdateOnDataEdit();
+
+ //accessors
+ float GetBaseFrameControllerFrame();
+ unsigned int GetNumberOfFrameControllers();
+ tFrameController* GetFrameControllerByIndex( unsigned int i );
+ unsigned int GetNumberOfDrawableElements();
+ tCompositeDrawable::DrawableElement* GetDrawableElement( unsigned int i );
+ const char* GetDrawableName( unsigned int i );
+ const char* GetPropName();
+
+ //Export the SmartPropData
+ void ExportChunk( const char* filename );
+
+
+private:
+
+ // Orientation and location
+ rmt::Matrix m_Transform;
+
+ //Private members
+ CStatePropData* m_StatePropData;
+ tAnimatedObject* m_AnimatedObject;
+ tFrameController* m_BaseFrameController;
+ unsigned int m_CurrentState;
+
+ CStatePropListener* m_StatePropListener;
+};
+
+
+inline void CStateProp::SetPosition( const rmt::Vector& pos )
+{
+ m_Transform.FillTranslate( pos );
+}
+inline const rmt::Vector& CStateProp::GetPosition() const
+{
+ return const_cast< RadicalMathLibrary::Matrix & >( m_Transform ).Row(3);
+}
+
+inline void CStateProp::SetTransformationMatrix(const rmt::Matrix& tmx)
+{
+ m_Transform = tmx;
+}
+inline const rmt::Matrix& CStateProp::GetTransformationMatrix() const
+{
+ return m_Transform;
+}
+
+#endif //_STATEPROP_HPP_ \ No newline at end of file
diff --git a/tools/statepropbuilder/apps/spbuilder/code/sp/engine/statepropdata.cpp b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/statepropdata.cpp
new file mode 100644
index 0000000..eb88194
--- /dev/null
+++ b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/statepropdata.cpp
@@ -0,0 +1,509 @@
+#include <string.h>
+#include <p3d/utility.hpp>
+#include <p3d/anim/animatedobject.hpp>
+#include <constants/chunkids.hpp>
+#include <p3d/chunkfile.hpp>
+
+#include "statepropdata.hpp"
+
+//=============================================================================
+// Class Declarations
+// Prop
+//=============================================================================
+
+CStatePropData::CStatePropData( tAnimatedObjectFactory* factory ) :
+ tEntity(),
+ m_NumStates(1)
+{
+ P3DASSERT ( factory );
+ m_ObjectFactory = factory;
+ m_ObjectFactory->AddRef();
+ SetName( m_ObjectFactory->GetName() );
+
+ ResetData();
+}
+
+CStatePropData::CStatePropData( ) :
+ tEntity(),
+ m_NumStates(1),
+ m_ObjectFactory( NULL )
+{
+ ResetData();
+}
+
+CStatePropData::~CStatePropData()
+{
+ m_ObjectFactory->Release();
+}
+
+//=============================================================================
+//State Data
+//=============================================================================
+
+//Get
+unsigned int CStatePropData::GetNumberOfStates()
+{
+ return m_NumStates;
+}
+StateData CStatePropData::GetStateData( unsigned int state )
+{
+ return m_StateData[ state ];
+}
+
+//Set
+void CStatePropData::InsertState( unsigned int state )
+{
+ if ( m_NumStates >= MAX_STATES - 1)
+ return;
+
+ //increase the number of states and copy all the data up a state
+ m_NumStates++;
+
+ unsigned int i , j;
+ for ( i = m_NumStates - 1; i > state + 1; i-- )
+ {
+ //transition data for each state
+ m_StateData[i].transitionData.autoTransition = m_StateData[i-1].transitionData.autoTransition;
+ m_StateData[i].transitionData.onFrame = m_StateData[i-1].transitionData.onFrame;
+ m_StateData[i].transitionData.toState = m_StateData[i-1].transitionData.toState;
+
+ //visibility data for each drawable in each state
+ for (j = 0; j < MAX_VISIBILITIES; j++ )
+ {
+ m_StateData[i].visibilityData[j].isVisible = m_StateData[i-1].visibilityData[j].isVisible;
+ }
+
+ //framecontroller data in each state
+ for (j = 0; j < MAX_FRAMECONTROLLERS; j++ )
+ {
+ m_StateData[i].frameControllerData[j].isCyclic = m_StateData[i-1].frameControllerData[j].isCyclic;
+ m_StateData[i].frameControllerData[j].maxFrame = m_StateData[i-1].frameControllerData[j].maxFrame;
+ m_StateData[i].frameControllerData[j].minFrame = m_StateData[i-1].frameControllerData[j].minFrame;
+ m_StateData[i].frameControllerData[j].relativeSpeed = m_StateData[i-1].frameControllerData[j].relativeSpeed;
+ m_StateData[i].frameControllerData[j].holdFrame = m_StateData[i-1].frameControllerData[j].holdFrame;
+ m_StateData[i].frameControllerData[j].numberOfCycles = m_StateData[i-1].frameControllerData[j].numberOfCycles;
+ }
+
+ //event data for each state
+ m_StateData[i].numEvents = m_StateData[i-1].numEvents;
+ m_StateData[i].numCallbacks = m_StateData[i-1].numCallbacks;
+ for (j = 0; j < MAX_EVENTS; j++ )
+ {
+ strcpy( m_StateData[i].eventData[j].eventName , m_StateData[i-1].eventData[j].eventName );
+ m_StateData[i].eventData[j].toState = m_StateData[i-1].eventData[j].toState;
+ m_StateData[i].eventData[j].eventID = m_StateData[i-1].eventData[j].eventID;
+
+ strcpy( m_StateData[i].callbackData[j].callbackName , m_StateData[i-1].callbackData[j].callbackName );
+ m_StateData[i].callbackData[j].onFrame = m_StateData[i-1].callbackData[j].onFrame;
+ m_StateData[i].callbackData[j].callbackID = m_StateData[i-1].callbackData[j].callbackID;
+ }
+ }
+
+ //Initialize the newly added state
+
+ //transition data for each state
+ m_StateData[state + 1].transitionData.autoTransition = 0;
+ m_StateData[state + 1].transitionData.onFrame = 0.f;
+ m_StateData[state + 1].transitionData.toState = 0;
+
+ //visibility data for each drawable in each state
+ for (j = 0; j < MAX_VISIBILITIES; j++ )
+ {
+ m_StateData[state + 1].visibilityData[j].isVisible = 1;
+ }
+
+ //framecontroller data in each state
+ for (j = 0; j < MAX_FRAMECONTROLLERS; j++ )
+ {
+ m_StateData[state + 1].frameControllerData[j].isCyclic = 0;
+ m_StateData[state + 1].frameControllerData[j].maxFrame = 0.f;
+ m_StateData[state + 1].frameControllerData[j].minFrame = 0.f;
+ m_StateData[state + 1].frameControllerData[j].relativeSpeed = 1.f;
+ m_StateData[state + 1].frameControllerData[j].holdFrame = 0;
+ m_StateData[state + 1].frameControllerData[j].numberOfCycles = 0;
+ }
+
+ //event data for each state
+ m_StateData[state + 1].numEvents = 0;
+ m_StateData[state + 1].numCallbacks = 0;
+}
+
+void CStatePropData::DeleteState( unsigned int state )
+{
+ if ( m_NumStates == 1 )
+ {
+ ResetData();
+ return;
+ }
+
+ int i;
+ int j;
+
+ for ( i = state; i < m_NumStates - 1; i++ )
+ {
+ //transition data for each state
+ m_StateData[i].transitionData.autoTransition = m_StateData[i+1].transitionData.autoTransition;
+ m_StateData[i].transitionData.onFrame = m_StateData[i+1].transitionData.onFrame;
+ m_StateData[i].transitionData.toState = m_StateData[i+1].transitionData.toState;
+
+ //visibility data for each drawable in each state
+ for (j = 0; j < MAX_VISIBILITIES; j++ )
+ {
+ m_StateData[i].visibilityData[j].isVisible = m_StateData[i+1].visibilityData[j].isVisible;
+ }
+
+ //framecontroller data in each state
+ for (j = 0; j < MAX_FRAMECONTROLLERS; j++ )
+ {
+ m_StateData[i].frameControllerData[j].isCyclic = m_StateData[i+1].frameControllerData[j].isCyclic;
+ m_StateData[i].frameControllerData[j].maxFrame = m_StateData[i+1].frameControllerData[j].maxFrame;
+ m_StateData[i].frameControllerData[j].minFrame = m_StateData[i+1].frameControllerData[j].minFrame;
+ m_StateData[i].frameControllerData[j].relativeSpeed = m_StateData[i+1].frameControllerData[j].relativeSpeed;
+ m_StateData[i].frameControllerData[j].holdFrame = m_StateData[i+1].frameControllerData[j].holdFrame;
+ m_StateData[i].frameControllerData[j].numberOfCycles = m_StateData[i+1].frameControllerData[j].numberOfCycles;
+ }
+
+ //event data for each state
+ m_StateData[i].numEvents = m_StateData[i+1].numEvents;
+ m_StateData[i].numCallbacks = m_StateData[i+1].numCallbacks;
+ for (j = 0; j < MAX_EVENTS; j++ )
+ {
+ strcpy( m_StateData[i].eventData[j].eventName , m_StateData[i+1].eventData[j].eventName );
+ m_StateData[i].eventData[j].toState = m_StateData[i+1].eventData[j].toState;
+ m_StateData[i].eventData[j].eventID = m_StateData[i+1].eventData[j].eventID;
+
+ strcpy( m_StateData[i].callbackData[j].callbackName , m_StateData[i+1].callbackData[j].callbackName );
+ m_StateData[i].callbackData[j].onFrame = m_StateData[i+1].callbackData[j].onFrame;
+ m_StateData[i].callbackData[j].callbackID = m_StateData[i+1].callbackData[j].callbackID;
+ }
+ }
+
+ m_NumStates--;
+}
+
+//=============================================================================
+//Transition Data
+//=============================================================================
+
+//Get
+TransitionData CStatePropData::GetTransitionData( int state )
+{
+ return m_StateData[state].transitionData;
+}
+
+//Set
+void CStatePropData::SetAutoTransition( int state, bool b )
+{
+ m_StateData[state].transitionData.autoTransition = b;
+}
+void CStatePropData::SetAutoTransitionOnFrame( int state, float onFrame )
+{
+ m_StateData[state].transitionData.onFrame = onFrame;
+}
+void CStatePropData::SetAutoTransitionToState( int state, int toState )
+{
+ m_StateData[state].transitionData.toState = toState;
+}
+
+//=============================================================================
+//Visibility Data
+//=============================================================================
+
+//Get
+VisibilityData CStatePropData::GetVisibilityData( int state , int index)
+{
+ return ( m_StateData[state].visibilityData[index] );
+}
+
+//Set
+void CStatePropData::SetVisible( int state , int index , bool b )
+{
+ m_StateData[state].visibilityData[index].isVisible = b;
+}
+void CStatePropData::SetAllVisibilities( int state , bool b )
+{
+ for ( int i = 0; i < MAX_VISIBILITIES; i++ )
+ {
+ m_StateData[state].visibilityData[i].isVisible = b;
+ }
+}
+void CStatePropData::ShowAll(int state)
+{
+ SetAllVisibilities( state , true );
+}
+void CStatePropData::HideAll(int state)
+{
+ SetAllVisibilities( state , false );
+}
+
+//=============================================================================
+//Frame controller data
+//=============================================================================
+
+//Get
+FrameControllerData CStatePropData::GetFrameControllerData( int state, int fc )
+{
+ return m_StateData[state].frameControllerData[fc];
+}
+
+//Set
+void CStatePropData::SetCyclic( int state ,int fc, bool isCyclic )
+{
+ m_StateData[state].frameControllerData[fc].isCyclic = isCyclic;
+}
+void CStatePropData::SetRelativeSpeed( int state ,int fc, float speed )
+{
+ m_StateData[state].frameControllerData[fc].relativeSpeed = speed;
+}
+void CStatePropData::SetFrameRange( int state , int fc, float min, float max )
+{
+ m_StateData[state].frameControllerData[fc].minFrame = min;
+ m_StateData[state].frameControllerData[fc].maxFrame = max;
+}
+void CStatePropData::SetHoldFrame( int state , int fc , bool holdFrame )
+{
+ m_StateData[state].frameControllerData[fc].holdFrame = holdFrame;
+}
+void CStatePropData::SetNumberOfCycles( int state , int fc , unsigned int numberOfCycles )
+{
+ m_StateData[state].frameControllerData[fc].numberOfCycles = numberOfCycles;
+}
+
+
+//=============================================================================
+//Event data
+//=============================================================================
+
+//Get
+unsigned int CStatePropData::GetNumberOfEvents( int state )
+{
+ return m_StateData[state].numEvents;
+}
+EventData CStatePropData::GetEventData( int state , int eventindex )
+{
+ return m_StateData[state].eventData[eventindex];
+}
+
+//Set
+void CStatePropData::AddEvent( const char* event , int eventEnum , int toState , int fromState )
+{
+ int n_events = m_StateData[fromState].numEvents;
+
+ strcpy( m_StateData[fromState].eventData[n_events].eventName , event );
+ m_StateData[fromState].eventData[n_events].toState = toState;
+ m_StateData[fromState].eventData[n_events].eventID = eventEnum;
+
+ m_StateData[fromState].numEvents = n_events + 1;
+}
+void CStatePropData::EditEvent( int state, int EventIndex, char* eventName, int eventID , int toState )
+{
+ strcpy( m_StateData[state].eventData[EventIndex].eventName , eventName );
+ m_StateData[state].eventData[EventIndex].toState = toState;
+ m_StateData[state].eventData[EventIndex].eventID = eventID;
+}
+void CStatePropData::DeleteEvent( int state , int index )
+{
+ int numEvents = m_StateData[state].numEvents;
+ for ( int i = index; i < numEvents - 1; i++ )
+ {
+ strcpy( m_StateData[state].eventData[i].eventName , m_StateData[state].eventData[i+1].eventName );
+ m_StateData[state].eventData[i].toState = m_StateData[state].eventData[i+1].toState;
+ m_StateData[state].eventData[i].eventID = m_StateData[state].eventData[i+1].eventID;
+ }
+
+ strcpy( m_StateData[state].eventData[numEvents - 1].eventName , "" );
+ m_StateData[state].eventData[numEvents - 1].toState = 0;
+ m_StateData[state].eventData[numEvents - 1].eventID = 0;
+
+ m_StateData[state].numEvents = numEvents - 1;
+}
+
+//=============================================================================
+//Callback Data
+//=============================================================================
+
+//Get
+unsigned int CStatePropData::GetNumberOfCallbacks( int state )
+{
+ return m_StateData[state].numCallbacks;
+}
+CallbackData CStatePropData::GetCallbackData( int state , int eventindex )
+{
+ return m_StateData[state].callbackData[eventindex];
+}
+
+//Set
+void CStatePropData::AddCallback( int state , const char* callback , int callbackID , float onFrame )
+{
+ int n_callbacks = m_StateData[state].numCallbacks;
+
+ strcpy( m_StateData[state].callbackData[n_callbacks].callbackName , callback );
+ m_StateData[state].callbackData[n_callbacks].onFrame = onFrame;
+ m_StateData[state].callbackData[n_callbacks].callbackID = callbackID;
+
+ m_StateData[state].numCallbacks = n_callbacks + 1;
+}
+void CStatePropData::EditCallback( int state, int CBIndex, char* callbackname, int callbackID , float onFrame )
+{
+ strcpy( m_StateData[state].callbackData[CBIndex].callbackName , callbackname );
+ m_StateData[state].callbackData[CBIndex].onFrame = onFrame;
+ m_StateData[state].callbackData[CBIndex].callbackID = callbackID;
+}
+void CStatePropData::DeleteCallback( int state , int index )
+{
+ int numCallbacks = m_StateData[state].numCallbacks;
+ for ( int i = index; i < numCallbacks - 1; i++ )
+ {
+ strcpy( m_StateData[state].callbackData[i].callbackName , m_StateData[state].callbackData[i+1].callbackName );
+ m_StateData[state].callbackData[i].onFrame = m_StateData[state].callbackData[i+1].onFrame;
+ m_StateData[state].callbackData[i].callbackID = m_StateData[state].callbackData[i+1].callbackID;
+ }
+
+ strcpy( m_StateData[state].callbackData[numCallbacks - 1].callbackName , "" );
+ m_StateData[state].callbackData[numCallbacks - 1].onFrame = 0.f;
+ m_StateData[state].callbackData[numCallbacks - 1].callbackID = 0;
+
+ m_StateData[state].numCallbacks = numCallbacks - 1;
+}
+
+
+
+//=============================================================================
+//Utility
+//=============================================================================
+void CStatePropData::ResetData()
+{
+ unsigned int state;
+ unsigned int j;
+
+ for ( state = 0; state < MAX_STATES; state++ )
+ {
+ //transition data
+ m_StateData[state].transitionData.autoTransition = 0;
+ m_StateData[state].transitionData.onFrame = 0.f;
+ m_StateData[state].transitionData.toState = 0;
+
+ //framecontrollers
+ for ( j = 0; j < MAX_FRAMECONTROLLERS; j++ )
+ {
+ m_StateData[state].frameControllerData[j].isCyclic = false;
+ m_StateData[state].frameControllerData[j].minFrame = 0.f;
+ m_StateData[state].frameControllerData[j].maxFrame = 0.f;
+ m_StateData[state].frameControllerData[j].relativeSpeed = 1.f;
+ m_StateData[state].frameControllerData[j].holdFrame = 0;
+ m_StateData[state].frameControllerData[j].numberOfCycles = 0;
+
+ }
+
+ //visibilites
+ for ( j = 0; j < MAX_VISIBILITIES; j++ )
+ {
+ m_StateData[state].visibilityData[j].isVisible = true;
+ }
+
+ //events && callbacks
+ m_StateData[state].numEvents = 0;
+ m_StateData[state].numCallbacks = 0;
+ for ( j = 0; j < MAX_EVENTS; j++ )
+ {
+ strcpy( m_StateData[state].eventData[j].eventName , "" );
+ m_StateData[state].eventData[j].toState = 0;
+ m_StateData[state].eventData[j].eventID = 0;
+
+ strcpy( m_StateData[state].callbackData[j].callbackName , "" );
+ m_StateData[state].callbackData[j].onFrame = 0.f;
+ m_StateData[state].callbackData[j].callbackID = 0;
+ }
+ }
+}
+
+
+
+//=============================================================================
+// Class Declarations
+// PropLoader
+//=============================================================================
+CStatePropDataLoader::CStatePropDataLoader() :
+ tSimpleChunkHandler(StateProp::STATEPROP)
+{
+}
+
+//-------------------------------------------------------------------------
+tEntity* CStatePropDataLoader::LoadObject(tChunkFile* f, tEntityStore* store)
+{
+ unsigned int version = f->GetLong();
+
+ CStatePropData* statePropData = new CStatePropData();
+ statePropData->ResetData();
+
+ char buf[256];
+
+ f->GetPString(buf);
+ statePropData->SetName(buf);
+
+ strcpy( statePropData->m_FactoryName , f->GetPString(buf) );
+ statePropData->m_ObjectFactory = p3d::find<tAnimatedObjectFactory>(store, statePropData->m_FactoryName);
+ if ( statePropData->m_ObjectFactory )
+ {
+ statePropData->m_ObjectFactory->AddRef();
+ }
+
+ statePropData->m_NumStates = f->GetLong();
+
+ for ( int currState = 0; currState < statePropData->m_NumStates; currState++ )
+ {
+ f->BeginChunk();
+
+ f->GetPString(buf);
+ statePropData->m_StateData[currState].transitionData.autoTransition = ( f->GetLong() != 0 );
+ statePropData->m_StateData[currState].transitionData.toState = f->GetLong();
+ int numDrawables = f->GetLong();
+ int numFrameControllers = f->GetLong();
+ statePropData->m_StateData[currState].numEvents = f->GetLong();
+ statePropData->m_StateData[currState].numCallbacks = f->GetLong();
+ statePropData->m_StateData[currState].transitionData.onFrame = f->GetFloat();
+
+ for ( int currDrawable=0; currDrawable < numDrawables; currDrawable++ )
+ {
+ f->BeginChunk();
+ f->GetPString(buf);
+ statePropData->m_StateData[currState].visibilityData[currDrawable].isVisible = ( f->GetLong() != 0 );
+ f->EndChunk();
+ }
+
+ for ( int currFrameController=0; currFrameController < numFrameControllers; currFrameController++ )
+ {
+ f->BeginChunk();
+ f->GetPString(buf);
+ statePropData->m_StateData[currState].frameControllerData[currFrameController].isCyclic = ( f->GetLong() != 0 );
+ statePropData->m_StateData[currState].frameControllerData[currFrameController].numberOfCycles = f->GetLong();
+ statePropData->m_StateData[currState].frameControllerData[currFrameController].holdFrame = ( f->GetLong() != 0 );
+ statePropData->m_StateData[currState].frameControllerData[currFrameController].minFrame = f->GetFloat();
+ statePropData->m_StateData[currState].frameControllerData[currFrameController].maxFrame = f->GetFloat();
+ statePropData->m_StateData[currState].frameControllerData[currFrameController].relativeSpeed = f->GetFloat();
+ f->EndChunk();
+ }
+
+ for ( unsigned int currEvent=0; currEvent < statePropData->m_StateData[currState].numEvents; currEvent++ )
+ {
+ f->BeginChunk();
+ strcpy( statePropData->m_StateData[currState].eventData[currEvent].eventName , f->GetPString(buf) );
+ statePropData->m_StateData[currState].eventData[currEvent].toState = f->GetLong();
+ statePropData->m_StateData[currState].eventData[currEvent].eventID = f->GetLong();
+ f->EndChunk();
+ }
+
+ for ( unsigned int currCallback=0; currCallback < statePropData->m_StateData[currState].numCallbacks; currCallback++ )
+ {
+ f->BeginChunk();
+ strcpy( statePropData->m_StateData[currState].callbackData[currCallback].callbackName , f->GetPString(buf) );
+ statePropData->m_StateData[currState].callbackData[currCallback].callbackID = f->GetLong();
+ statePropData->m_StateData[currState].callbackData[currCallback].onFrame = f->GetFloat();
+ f->EndChunk();
+ }
+
+ f->EndChunk();
+ }
+
+ return statePropData;
+} \ No newline at end of file
diff --git a/tools/statepropbuilder/apps/spbuilder/code/sp/engine/statepropdata.hpp b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/statepropdata.hpp
new file mode 100644
index 0000000..f6cf691
--- /dev/null
+++ b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/statepropdata.hpp
@@ -0,0 +1,139 @@
+#ifndef _STATEPROPDATA_HPP_
+#define _STATEPROPDATA_HPP_
+
+
+#include <radmath/radmath.hpp>
+#include <p3d/loadmanager.hpp>
+
+#include "statepropdatatypes.hpp"
+
+//=============================================================================
+// Forward Class/Struct Declarations
+//=============================================================================
+
+class CStateProp;
+class tAnimatedObjectFactory;
+class CStatePropDataLoader;
+
+//=============================================================================
+// Definitions
+//=============================================================================
+#define MAX_STATES 50
+#define MAX_FRAMECONTROLLERS 250
+#define MAX_VISIBILITIES 250
+#define MAX_EVENTS 50
+
+//State data
+struct StateData
+{
+ TransitionData transitionData;
+ VisibilityData visibilityData[MAX_VISIBILITIES];
+ FrameControllerData frameControllerData[MAX_FRAMECONTROLLERS];
+ EventData eventData[MAX_EVENTS];
+ CallbackData callbackData[MAX_EVENTS];
+
+ unsigned int numEvents;
+ unsigned int numCallbacks;
+};
+
+//=============================================================================
+// Class Declarations
+// Prop
+//=============================================================================
+
+class CStatePropData : public tEntity
+{
+
+public:
+
+ friend class CStateProp;
+ friend class CStatePropDataLoader;
+
+ CStatePropData( tAnimatedObjectFactory* factory );
+ CStatePropData();
+ ~CStatePropData();
+
+ // State Data =====================================================================================
+ //Get
+ unsigned int GetNumberOfStates();
+ StateData GetStateData( unsigned int state );
+ //Set
+ void InsertState( unsigned int state );
+ void DeleteState( unsigned int state );
+
+ //Transition Data ==================================================================================
+ //Get
+ TransitionData GetTransitionData( int state );
+ //Set
+ void SetAutoTransition( int state, bool b );
+ void SetAutoTransitionOnFrame( int state, float onFrame );
+ void SetAutoTransitionToState( int state, int toState );
+
+ //Visibility Data ==================================================================================
+ //Get
+ VisibilityData GetVisibilityData( int state , int index);
+ //Set
+ void SetVisible( int state , int index , bool b );
+ void SetAllVisibilities( int state , bool b );
+ void ShowAll(int state);
+ void HideAll(int state);
+
+ //Frame Controller Data =============================================================================
+ //Get
+ FrameControllerData GetFrameControllerData( int state, int fc );
+ //Set
+ void SetCyclic( int state ,int fc, bool isCyclic );
+ void SetRelativeSpeed( int state ,int fc, float speed );
+ void SetFrameRange( int state ,int fc, float min, float max );
+ void SetHoldFrame( int state , int fc , bool holdFrame );
+ void SetNumberOfCycles( int state , int fc , unsigned int numberOfCycles );
+
+ //Event Data ========================================================================================
+ //Get
+ unsigned int GetNumberOfEvents( int state );
+ EventData GetEventData( int state , int eventindex );
+ //Set
+ void AddEvent( const char* event , int eventEnum , int toState , int fromState );
+ void EditEvent( int state, int EventIndex, char* eventName, int eventEnum , int toState );
+ void DeleteEvent( int fromState , int index );
+
+ //Callback Data ======================================================================================
+ //Get
+ unsigned int GetNumberOfCallbacks( int state );
+ CallbackData GetCallbackData( int state , int eventindex );
+ //Set
+ void AddCallback( int state , const char* event , int eventEnum , float frame );
+ void EditCallback( int state, int CBIndex, char* eventname, int eventEnum , float frame );
+ void DeleteCallback( int state , int index );
+
+private:
+
+ //reset the prop data
+ void ResetData();
+
+ //animated object factory
+ char m_FactoryName[64];
+ tAnimatedObjectFactory* m_ObjectFactory;
+
+ //total number of states
+ int m_NumStates;
+ StateData m_StateData[MAX_STATES];
+
+};
+
+
+//=============================================================================
+// Class Declarations
+// PropLoader
+//=============================================================================
+class CStatePropDataLoader : public tSimpleChunkHandler
+{
+public:
+ CStatePropDataLoader();
+ tEntity* LoadObject(tChunkFile* file, tEntityStore* store);
+
+protected:
+ ~CStatePropDataLoader() {};
+};
+
+#endif //_STATEPROPDATA_HPP_
diff --git a/tools/statepropbuilder/apps/spbuilder/code/sp/engine/statepropdatatypes.hpp b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/statepropdatatypes.hpp
new file mode 100644
index 0000000..4d035af
--- /dev/null
+++ b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/statepropdatatypes.hpp
@@ -0,0 +1,45 @@
+#ifndef _STATEPROPDATATYPES_HPP_
+#define _STATEPROPDATATYPES_HPP_
+
+//Transition data
+struct TransitionData
+{
+ unsigned int autoTransition;
+ unsigned int toState;
+ float onFrame;
+};
+
+//Visibility data
+struct VisibilityData
+{
+ unsigned int isVisible;
+};
+
+//Frame controller data
+struct FrameControllerData
+{
+ unsigned int isCyclic;
+ unsigned int numberOfCycles;
+ unsigned int holdFrame;
+ float minFrame;
+ float maxFrame;
+ float relativeSpeed;
+};
+
+//Event data
+struct EventData
+{
+ char eventName[64];
+ unsigned int eventID;
+ unsigned int toState;
+};
+
+//Callback data
+struct CallbackData
+{
+ char callbackName[64];
+ unsigned int callbackID;
+ float onFrame;
+};
+
+#endif //_STATEPROPDATATYPES_HPP_
diff --git a/tools/statepropbuilder/apps/spbuilder/code/sp/engine/workspace.cpp b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/workspace.cpp
new file mode 100644
index 0000000..2d31863
--- /dev/null
+++ b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/workspace.cpp
@@ -0,0 +1,879 @@
+/*===========================================================================
+Workspace.cpp - Pure3D testbed
+
+
+ Copyright (c) 1995-1999 Radical Entertainment, Inc.
+ All rights reserved.
+===========================================================================*/
+#include <windows.h>
+
+#include <assert.h>
+#include <string.h>
+#include <typeinfo.h>
+#include <ctype.h> //for isdigit
+#include <stdlib.h> //for atoi
+
+#include <p3d/pure3d.hpp>
+#include <p3d/anim/animatedobject.hpp>
+#include <p3d/anim/poseanimation.hpp>
+#include <p3d/anim/skeleton.hpp>
+#include <p3d/geometry.hpp>
+#include <p3d/anim/polyskin.hpp>
+#include <p3d/utility.hpp>
+#include <p3d/drawable.hpp>
+
+#include <simcommon/simutility.hpp>
+#include <simcommon/simenvironment.hpp> // for SimUnits
+#include <simcommon/simulatedobject.hpp>
+#include <simcollision/collisionmanager.hpp>
+#include <simcollision/collisiondisplay.hpp>
+#include <simcollision/proximitydetection.hpp>
+
+#include <sp/interface.hpp>
+#include "workspace.hpp"
+
+#include "stateprop.hpp"
+#include "statepropdata.hpp"
+
+void RegisterExtraChunks(void)
+{ //do nothing
+}
+
+bool g_DrawCollision = true;
+bool g_IsPaused = false;
+bool g_DebugPhysicsDisplay = false;
+float g_TotalTime_sec = 0.f;
+
+const char c_StatePropExtension[] = "_spdata.p3d";
+
+
+Workspace* g_Workspace = NULL;
+CStateProp* g_CStateProp = NULL;
+
+template <class T> class TemplateIterator : public ViewerIterator
+{
+public:
+ TemplateIterator(T* t)
+ {
+ iterator = t;
+ current = iterator->First();
+ }
+
+ ~TemplateIterator()
+ {
+ delete iterator;
+ }
+
+ tEntity* First(void)
+ {
+ current = iterator->First();
+
+ return current;
+ }
+
+ tEntity* Current(void)
+ {
+ if(!current)
+ current = iterator->First();
+
+ return current;
+ }
+
+ tEntity* Next(bool loop = false)
+ {
+ current = iterator->Next();
+ if(loop && !current)
+ current = iterator->First();
+ return current;
+ }
+
+ tEntity* Prev(void)
+ {
+ current = iterator->Prev();
+ if(!current)
+ current = iterator->Last();
+ return current;
+
+ }
+
+private:
+ T* iterator;
+ tEntity* current;
+};
+
+class DrawIterator : public tInventory::Iterator<tDrawable> {};
+class ObjectFactoryIterator : public tInventory::Iterator<tAnimatedObjectFactory> {};
+class CStatePropDataIterator : public tInventory::Iterator<CStatePropData> {};
+
+
+//Get allocated memory
+unsigned int GetAllocatedMemory()
+{
+ // on windows can't rely on the total physical memory so we must walk over
+ // each heap and accumulate all the memory allocated in it. there is stack
+ // overhead too but that should be minimal.
+ HANDLE heaps[128];
+
+ int numHeaps = GetProcessHeaps(sizeof(heaps)/sizeof(heaps[0]), heaps);
+ if(numHeaps > sizeof(heaps)/sizeof(heaps[0]))
+ {
+ numHeaps = sizeof(heaps)/sizeof(heaps[0]);
+ }
+
+ unsigned int total = 0;
+ int i;
+ for(i=0; i<numHeaps; i++)
+ {
+ PROCESS_HEAP_ENTRY heapEntry;
+
+ heapEntry.lpData = NULL;
+ if(!HeapLock(heaps[i]))
+ {
+ //HC_DEBUGPRINT(("could not lock heap %d", i));
+ continue;
+ }
+ while(HeapWalk(heaps[i], &heapEntry))
+ {
+ if(heapEntry.wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE)
+ {
+ // don't count non-committed pages as some of pure3d seems to
+ // mmap or allocate large ranges that never actually get paged
+ // in
+ //total += heapEntry.cbData;
+ }
+ else
+ {
+ total += heapEntry.cbData;
+ }
+ }
+ HeapUnlock(heaps[i]);
+ }
+
+ return total;
+}
+
+//-------------------------------------------------------------------
+// Workspace class
+// derive from Testbed.
+//
+//-------------------------------------------------------------------
+
+Workspace::Workspace() :
+ m_CStateProp(NULL),
+ m_CollisionManager(NULL),
+ m_CollisionSolver(NULL),
+ m_DrawableFloor(NULL),
+ m_SimStateFloor(NULL)
+{
+ sim::InstallSimLoaders();
+
+ //draw outlines for debug render
+ sim::SetDrawVolumeMethod( sim::DrawVolumeShape );
+
+ Init();
+}
+
+
+Workspace::~Workspace()
+{
+ ResetAll();
+
+ if ( m_CStateProp )
+ m_CStateProp->Release();
+
+ p3d::loadManager->RemoveAllHandlers(); // should be in testbed
+}
+
+void Workspace::Init()
+{
+ // get path to exe
+ GetModuleFileName(NULL, m_Path, sizeof(m_Path) - 1);
+ m_Path[ strlen(m_Path) - 13 ] = '\0';
+
+ m_DrawableIterator = new TemplateIterator<DrawIterator>(new DrawIterator);
+ m_ObjectFactoryIterator = new TemplateIterator<ObjectFactoryIterator>(new ObjectFactoryIterator);
+ m_CStatePropDataIterator = new TemplateIterator<CStatePropDataIterator>(new CStatePropDataIterator);
+
+ // install loader for Prop
+ tP3DFileHandler* p3d = p3d::loadManager->GetP3DHandler();
+ if(p3d)
+ {
+ p3d->AddHandler( new CStatePropDataLoader );
+ }
+
+ if (!sim::SimUnits::UnitSet())
+ {
+ sim::InitializeSimulation( sim::MetersUnits );
+ }
+
+ if (!m_CollisionManager)
+ {
+ float MAX_UPDATEAI_TIME_ms = 1000.0f*1.0f/30.0f; // 30 fps
+ //sim::SimulatedObject::SetMaxTimeStep(MAX_UPDATEAI_TIME_ms/1000.0f);
+ float collisionDistanceCGS = 2.0f; // cm
+ m_CollisionManager = sim::CollisionManager::GetInstance();
+ m_CollisionManager->AddRef();
+ sim::SimEnvironment* simEnvironment = sim::SimEnvironment::GetDefaultSimEnvironment();
+ simEnvironment->SetCollisionDistanceCGS(collisionDistanceCGS);
+ m_CollisionManager->SetCollisionManagerAttributes( sim::CM_DetectAll | sim::CM_SolveAll );
+
+ P3DASSERT(m_CollisionSolver == NULL);
+ m_CollisionSolver = new AICollisionSolverAgent();
+ m_CollisionSolver->AddRef();
+ m_CollisionManager->GetImpulseBasedCollisionSolver()->SetCollisionSolverAgent(m_CollisionSolver);
+ }
+}
+
+void Workspace::LoadFloor( const char* p3dfilename )
+{
+ if ( m_DrawableFloor )
+ m_DrawableFloor->Release();
+
+ if ( m_SimStateFloor )
+ m_SimStateFloor->Release();
+
+ //check that a data file exist
+ FILE* p = fopen( p3dfilename , "r" );
+ if ( p )
+ {
+ p3d::inventory->RemoveAllElements();
+
+ (void) p3d::load(p3dfilename);
+
+ m_DrawableFloor = p3d::find<tDrawable>("floorShape");
+ if ( m_DrawableFloor )
+ m_DrawableFloor->AddRef();
+
+ fclose(p);
+ }
+}
+
+void Workspace::ResetAll(bool emptyInventory)
+{
+ if (emptyInventory)
+ {
+ delete m_DrawableIterator;
+ delete m_ObjectFactoryIterator;
+ delete m_CStatePropDataIterator;
+
+ p3d::inventory->RemoveAllElements();
+ }
+
+ ResetProp();
+
+
+ if ( m_CollisionSolver )
+ {
+ m_CollisionSolver->Release();
+ m_CollisionSolver = NULL;
+ }
+
+ if ( m_CollisionManager )
+ {
+ m_CollisionManager->ResetAll();
+ m_CollisionManager->Release();
+ m_CollisionManager = NULL;
+ }
+
+ this->Init();
+}
+
+void Workspace::Advance(float dt_ms)
+{
+ g_TotalTime_sec += dt_ms / 1000.f;
+ float inDt_Sec = dt_ms / 1000.f;
+
+ if ( !g_IsPaused )
+ {
+ if ( m_CStateProp )
+ {
+ m_CStateProp->Update(dt_ms);
+ }
+ if ( m_CollisionManager )
+ {
+ m_CollisionManager->Update( inDt_Sec , g_TotalTime_sec );
+ }
+ }
+}
+
+void Workspace::Display(tContext* context)
+{
+ if ( m_DrawableFloor )
+ {
+ m_DrawableFloor->Display();
+ }
+
+ if ( m_CStateProp )
+ {
+ m_CStateProp->UpdateFrameControllersForRender();
+ m_CStateProp->Render();
+ }
+
+ if ( g_DrawCollision )
+ {
+ sim::DisplayCollisionObjects(sim::CollisionManager::GetInstance());
+ }
+}
+
+void Workspace::ResetProp()
+{
+ if ( m_CStateProp )
+ {
+ m_CStateProp->Release();
+ }
+
+ m_CStateProp = NULL;
+ g_CStateProp = NULL;
+}
+
+int Workspace::Load( const char* name )
+{
+ ResetAll();
+
+ (void) p3d::load(name);
+
+ //Search for object factories
+ m_ObjectFactoryIterator->First();
+ m_CStatePropDataIterator->First();
+
+ if ( m_ObjectFactoryIterator->Current() && m_CStatePropDataIterator->Current() )
+ {
+ //if we have an objectfactory and a prop we are good (1 file with all chunks)
+ CStatePropData* statePropData = ((CStatePropData*)m_CStatePropDataIterator->Current());
+ m_CStateProp = CStateProp::CreateCStateProp( statePropData , 0 );
+ m_CStateProp->AddRef();
+ }
+ else if( m_ObjectFactoryIterator->Current() )
+ {
+ //if we just have the factory we need the file with the prop data so load it
+ char buf[256];
+ memcpy( buf , name , strlen(name) - strlen(".p3d") );
+ buf[strlen(name) - strlen(".p3d")] = '\0';
+ strcat(buf , c_StatePropExtension );
+
+ //check that a data file exist
+ FILE* p = fopen( buf , "r" );
+ if ( p )
+ {
+ (void) p3d::load(buf);
+
+ m_CStatePropDataIterator->First();
+ if ( m_CStatePropDataIterator->Current() )
+ {
+ //if we have an objectfactory and a prop we are good (1 file with all chunks)
+ CStatePropData* statePropData = ((CStatePropData*)m_CStatePropDataIterator->Current());
+ m_CStateProp = CStateProp::CreateCStateProp( statePropData , 0 );
+ m_CStateProp->AddRef();
+ }
+ fclose(p);
+ }
+ else
+ {
+ //Create a new prop
+ CStatePropData* statePropData = new CStatePropData( (tAnimatedObjectFactory*)m_ObjectFactoryIterator->Current() );
+ if ( statePropData )
+ {
+ m_CStateProp = CStateProp::CreateCStateProp( statePropData , 0 );
+ m_CStateProp->AddRef();
+ }
+ }
+ }
+ else if( m_CStatePropDataIterator->Current() )
+ {
+ //if we just have the prop we need the file with the factory
+ char buf[256];
+ memcpy( buf , name , strlen(name) - strlen(c_StatePropExtension) );
+ buf[strlen(name) - strlen(c_StatePropExtension)] = '\0';
+ strcat(buf , ".p3d");
+
+ //check that a data file exist
+ FILE* p = fopen( buf , "r" );
+ if ( p )
+ {
+ (void) p3d::load(buf);
+
+ m_ObjectFactoryIterator->First();
+ if ( m_ObjectFactoryIterator->Current() )
+ {
+ CStatePropData* statePropData = ((CStatePropData*)m_CStatePropDataIterator->Current());
+ m_CStateProp = CStateProp::CreateCStateProp( statePropData , 0 );
+ m_CStateProp->AddRef();
+ }
+ fclose(p);
+ }
+ else
+ {
+ //no file associated with this prop data...
+ ResetAll();
+ }
+ }
+
+ if ( m_CStateProp )
+ {
+ g_CStateProp = m_CStateProp;
+ }
+ else
+ {
+ g_CStateProp = NULL;
+ }
+
+
+ return 1;
+}
+
+
+//=============================================================================
+// CStateProp - DLL interface
+//=============================================================================
+//Load a pure3D file with art for the background===============================
+int SP_CALLCONV SPLoadBackground( const char* filename )
+{
+ if ( g_Workspace )
+ {
+ g_Workspace->LoadFloor( filename );
+ return 1;
+ }
+ return 0;
+}
+
+//Load pure3D file ============================================================
+int SP_CALLCONV SPLoad( const char* filename )
+{
+ if ( g_Workspace )
+ {
+ g_Workspace->Load( filename );
+ return 1;
+ }
+ return 0;
+}
+
+//Export the SmartPropData ====================================================
+int SP_CALLCONV SPExportStatePropData( const char* filename )
+{
+ if ( g_CStateProp )
+ {
+ char buf[256];
+ memcpy( buf , filename , strlen(filename) - strlen(".p3d") );
+ buf[strlen(filename) - strlen(".p3d")] = '\0';
+ strcat( buf , c_StatePropExtension );
+ g_CStateProp->ExportChunk( buf );
+ return 1;
+ }
+ return 0;
+}
+
+//Display collision ==========================================================
+int SP_CALLCONV SPShowCollision( int show )
+{
+ g_DrawCollision = ( show == 1 );
+ return 1;
+}
+
+//Prop name ===================================================================
+const char* SP_CALLCONV SPGetPropName()
+{
+ if ( g_CStateProp )
+ {
+ return g_CStateProp->GetCStatePropData()->GetName();
+ }
+ return NULL;
+}
+
+//advance ====================================================================
+int SP_CALLCONV SPPause( bool b )
+{
+ g_IsPaused = b;
+ return 1;
+}
+int SP_CALLCONV SPAdvanceOneFrame()
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->Update( 100.f );
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPBackOneFrame()
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->Update( -100.f );
+ return 1;
+ }
+ return 0;
+}
+
+// State Data =================================================================
+unsigned int SP_CALLCONV SPGetNumberOfStates()
+{
+ if ( g_CStateProp )
+ {
+ return g_CStateProp->GetCStatePropData()->GetNumberOfStates();
+ }
+ return 0;
+}
+
+int SP_CALLCONV SPInsertState( unsigned int state )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->InsertState( state );
+ g_CStateProp->UpdateOnDataEdit();
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPDeleteState( unsigned int state )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->DeleteState( state );
+ g_CStateProp->UpdateOnDataEdit();
+ return 1;
+ }
+ return 0;
+}
+
+int SP_CALLCONV SPGetCurrentState()
+{
+ if ( g_CStateProp )
+ {
+ return g_CStateProp->GetState();
+ }
+ return 0;
+}
+int SP_CALLCONV SPNextState()
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->NextState();
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPPrevState()
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->PrevState();
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPSetState( unsigned int state )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->SetState( state );
+ return 1;
+ }
+ return 0;
+}
+
+//Transition Data =============================================================
+bool SP_CALLCONV SPGetTransitionData( int state , TransitionData* transitionData )
+{
+ if ( g_CStateProp )
+ {
+ transitionData->autoTransition = g_CStateProp->GetCStatePropData()->GetTransitionData( state ).autoTransition;
+ transitionData->onFrame = g_CStateProp->GetCStatePropData()->GetTransitionData( state ).onFrame;
+ transitionData->toState = g_CStateProp->GetCStatePropData()->GetTransitionData( state ).toState;
+ return true;
+ }
+ return false;
+}
+int SP_CALLCONV SPSetAutoTransition( int state, bool b )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->SetAutoTransition( state , b );
+ g_CStateProp->UpdateOnDataEdit();
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPSetAutoTransitionOnFrame( int state, float onFrame )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->SetAutoTransitionOnFrame( state , onFrame );
+ g_CStateProp->UpdateOnDataEdit();
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPSetAutoTransitionToState( int state, int toState )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->SetAutoTransitionToState( state , toState );
+ g_CStateProp->UpdateOnDataEdit();
+ return 1;
+ }
+ return 0;
+}
+
+//Visibility Data =============================================================
+bool SP_CALLCONV SPGetVisibilityData( int state , int index , VisibilityData* visibilityData )
+{
+ if ( g_CStateProp )
+ {
+ visibilityData->isVisible = g_CStateProp->GetCStatePropData()->GetVisibilityData( state , index ).isVisible;
+ return true;
+ }
+ return false;
+}
+int SP_CALLCONV SPSetVisible( int state , int index , bool b )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->SetVisible( state , index , b );
+ g_CStateProp->UpdateOnDataEdit();
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPSetAllVisibilities( int state , bool b )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->SetAllVisibilities( state , b );
+ g_CStateProp->UpdateOnDataEdit();
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPShowAll(int state)
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->ShowAll( state );
+ g_CStateProp->UpdateOnDataEdit();
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPHideAll(int state)
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->HideAll( state );
+ g_CStateProp->UpdateOnDataEdit();
+ return 1;
+ }
+ return 0;
+}
+
+SP_IMPORT int SP_CALLCONV SPGetNumDrawables()
+{
+ if ( g_CStateProp )
+ {
+ return g_CStateProp->GetNumberOfDrawableElements();
+ }
+ return 0;
+}
+
+const char* SP_CALLCONV SPGetDrawableName( int index )
+{
+ if ( g_CStateProp )
+ {
+ return g_CStateProp->GetDrawableName( index );
+ }
+ return NULL;
+}
+
+//Frame Controller Data =======================================================
+bool SPGetFrameControllerData( int state, int fc , FrameControllerData* fcData )
+{
+ if ( g_CStateProp )
+ {
+ fcData->holdFrame = g_CStateProp->GetCStatePropData()->GetFrameControllerData( state , fc ).holdFrame;
+ fcData->isCyclic = g_CStateProp->GetCStatePropData()->GetFrameControllerData( state , fc ).isCyclic;
+ fcData->maxFrame = g_CStateProp->GetCStatePropData()->GetFrameControllerData( state , fc ).maxFrame;
+ fcData->minFrame = g_CStateProp->GetCStatePropData()->GetFrameControllerData( state , fc ).minFrame;
+ fcData->numberOfCycles = g_CStateProp->GetCStatePropData()->GetFrameControllerData( state , fc ).numberOfCycles;
+ fcData->relativeSpeed = g_CStateProp->GetCStatePropData()->GetFrameControllerData( state , fc ).relativeSpeed;
+ return true;
+ }
+ return false;
+}
+int SP_CALLCONV SPSetCyclic( int state ,int fc, bool isCyclic )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->SetCyclic( state , fc , isCyclic );
+ g_CStateProp->UpdateOnDataEdit();
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPSetRelativeSpeed( int state ,int fc, float speed )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->SetRelativeSpeed( state , fc , speed );
+ g_CStateProp->UpdateOnDataEdit();
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPSetFrameRange( int state ,int fc, float min, float max )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->SetFrameRange( state , fc , min , max );
+ g_CStateProp->UpdateOnDataEdit();
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPSetHoldFrame( int state , int fc , bool holdFrame )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->SetHoldFrame( state , fc , holdFrame );
+ g_CStateProp->UpdateOnDataEdit();
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPSetNumberOfCycles( int state , int fc , unsigned int numberOfCycles )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->SetNumberOfCycles( state , fc , numberOfCycles );
+ return 1;
+ }
+ return 0;
+}
+
+int SP_CALLCONV SPGetNumFrameControllers()
+{
+ if ( g_CStateProp )
+ {
+ return g_CStateProp->GetNumberOfFrameControllers();
+ }
+ return 0;
+}
+float SP_CALLCONV SPGetBaseFrameControllerFrame()
+{
+ if ( g_CStateProp )
+ {
+ return g_CStateProp->GetBaseFrameControllerFrame();
+ }
+ return 0.f;
+}
+float SP_CALLCONV SPGetFrameControllerFrame( int index )
+{
+ if ( g_CStateProp )
+ {
+ return g_CStateProp->GetFrameControllerByIndex( index )->GetFrame();
+ }
+ return 0.f;
+}
+const char* SP_CALLCONV SPGetFrameControllerName( int index )
+{
+ if ( g_CStateProp )
+ {
+ return g_CStateProp->GetFrameControllerByIndex( index )->GetName();
+ }
+ return NULL;
+}
+
+//Event Data ==================================================================
+unsigned int SP_CALLCONV SPGetNumberOfEvents( int state )
+{
+ if ( g_CStateProp )
+ {
+ return g_CStateProp->GetCStatePropData()->GetNumberOfEvents( state );
+ }
+ return 0;
+}
+bool SP_CALLCONV SPGetEventData( int state , int eventindex , EventData *eventData)
+{
+ if ( g_CStateProp )
+ {
+ EventData ed = g_CStateProp->GetCStatePropData()->GetEventData( state , eventindex );
+ eventData->eventID = ed.eventID;
+ strcpy( eventData->eventName , ed.eventName );
+ eventData->toState = ed.toState;
+ return true;
+ }
+ return false;
+}
+int SP_CALLCONV SPAddEvent( const char* event , int eventEnum , int toState , int fromState )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->AddEvent( event , eventEnum , toState , fromState );
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPEditEvent( int state, int EventIndex, char* eventName, int eventEnum , int toState )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->EditEvent( state , EventIndex , eventName , eventEnum , toState );
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPDeleteEvent( int fromState , int index )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->DeleteEvent( fromState , index );
+ return 1;
+ }
+ return 0;
+}
+
+//Callback Data ===============================================================
+unsigned int SP_CALLCONV SPGetNumberOfCallbacks( int state )
+{
+ if ( g_CStateProp )
+ {
+ return g_CStateProp->GetCStatePropData()->GetNumberOfCallbacks( state );
+ }
+ return 0;
+}
+bool SP_CALLCONV SPGetCallbackData( int state , int index , CallbackData* callbackData )
+{
+ if ( g_CStateProp )
+ {
+ callbackData->callbackID = g_CStateProp->GetCStatePropData()->GetCallbackData( state , index ).callbackID;
+ strcpy( callbackData->callbackName , g_CStateProp->GetCStatePropData()->GetCallbackData( state , index ).callbackName );
+ callbackData->onFrame = g_CStateProp->GetCStatePropData()->GetCallbackData( state , index ).onFrame;
+ return true;
+ }
+ return false;
+}
+int SP_CALLCONV SPAddCallback( int state , const char* event , int eventEnum , float frame )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->AddCallback( state , event , eventEnum , frame );
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPEditCallback( int state, int CBIndex, char* eventname, int eventEnum , float frame )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->EditCallback( state , CBIndex , eventname , eventEnum , frame );
+ return 1;
+ }
+ return 0;
+}
+int SP_CALLCONV SPDeleteCallback( int state , int index )
+{
+ if ( g_CStateProp )
+ {
+ g_CStateProp->GetCStatePropData()->DeleteCallback( state , index );
+ return 1;
+ }
+ return 0;
+} \ No newline at end of file
diff --git a/tools/statepropbuilder/apps/spbuilder/code/sp/engine/workspace.hpp b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/workspace.hpp
new file mode 100644
index 0000000..e476ebf
--- /dev/null
+++ b/tools/statepropbuilder/apps/spbuilder/code/sp/engine/workspace.hpp
@@ -0,0 +1,67 @@
+#ifndef _WORKSPACE_HPP_
+#define _WORKSPACE_HPP_
+
+#include <radmath/radmath.hpp>
+#include <simcollision/collisionmanager.hpp>
+
+#include "aicollisionsolveragent.hpp"
+
+class CStateProp;
+class tDrawable;
+
+//=============================================================================
+// Class Declarations
+// ViewerIterator
+//=============================================================================
+class ViewerIterator
+{
+public:
+ virtual ~ViewerIterator() {}
+ virtual tEntity* Current(void) = 0;
+ virtual tEntity* Next(bool loop = false) = 0;
+ virtual tEntity* Prev(void) = 0;
+ virtual tEntity* First(void) = 0;
+};
+
+
+//=============================================================================
+// Class Declarations
+// Workspace
+//=============================================================================
+class Workspace : public tRefCounted
+{
+public:
+ Workspace();
+ ~Workspace();
+
+ void Init();
+ void ResetAll( bool emptyInventory = true );
+ void Advance(float dt_ms);
+ void Display(tContext* context);
+
+ int Load( const char* name );
+ int Pause(bool b);
+
+ void LoadFloor( const char* p3dfilename );
+
+private:
+
+ void ResetProp();
+ CStateProp* m_CStateProp;
+
+ AICollisionSolverAgent *m_CollisionSolver;
+ sim::CollisionManager* m_CollisionManager;
+
+ ViewerIterator* m_DrawableIterator;
+ ViewerIterator* m_ObjectFactoryIterator;
+ ViewerIterator* m_CStatePropDataIterator;
+
+ tDrawable* m_DrawableFloor;
+ sim::SimState* m_SimStateFloor;
+
+ char m_Path[256];
+};
+
+
+
+#endif