mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-13 03:33:48 +00:00
Merge branch 'development' into ConvexProxies
This commit is contained in:
commit
bb30de04f7
2803 changed files with 195958 additions and 224299 deletions
|
|
@ -206,11 +206,11 @@ void AccumulationVolume::buildSilhouette( const SceneCameraState& cameraState, V
|
|||
|
||||
if( mTransformDirty )
|
||||
{
|
||||
const U32 numPoints = mPolyhedron.getNumPoints();
|
||||
const U32 numPolyPoints = mPolyhedron.getNumPoints();
|
||||
const PolyhedronType::PointType* points = getPolyhedron().getPoints();
|
||||
|
||||
mWSPoints.setSize( numPoints );
|
||||
for( U32 i = 0; i < numPoints; ++ i )
|
||||
mWSPoints.setSize(numPolyPoints);
|
||||
for( U32 i = 0; i < numPolyPoints; ++ i )
|
||||
{
|
||||
Point3F p = points[ i ];
|
||||
p.convolve( getScale() );
|
||||
|
|
|
|||
|
|
@ -418,7 +418,7 @@ void AIClient::onAdd( const char *nameSpace ) {
|
|||
/**
|
||||
* Sets the move speed for an AI object
|
||||
*/
|
||||
DefineConsoleMethod( AIClient, setMoveSpeed, void, (F32 speed), , "ai.setMoveSpeed( float );" )
|
||||
DefineEngineMethod( AIClient, setMoveSpeed, void, (F32 speed), , "ai.setMoveSpeed( float );" )
|
||||
{
|
||||
AIClient *ai = static_cast<AIClient *>( object );
|
||||
ai->setMoveSpeed( speed );
|
||||
|
|
@ -427,7 +427,7 @@ DefineConsoleMethod( AIClient, setMoveSpeed, void, (F32 speed), , "ai.setMoveSpe
|
|||
/**
|
||||
* Stops all AI movement, halt!
|
||||
*/
|
||||
DefineConsoleMethod( AIClient, stop, void, (),, "ai.stop();" )
|
||||
DefineEngineMethod( AIClient, stop, void, (),, "ai.stop();" )
|
||||
{
|
||||
AIClient *ai = static_cast<AIClient *>( object );
|
||||
ai->setMoveMode( AIClient::ModeStop );
|
||||
|
|
@ -436,7 +436,7 @@ DefineConsoleMethod( AIClient, stop, void, (),, "ai.stop();" )
|
|||
/**
|
||||
* Tells the AI to aim at the location provided
|
||||
*/
|
||||
DefineConsoleMethod( AIClient, setAimLocation, void, (Point3F v), , "ai.setAimLocation( x y z );" )
|
||||
DefineEngineMethod( AIClient, setAimLocation, void, (Point3F v), , "ai.setAimLocation( x y z );" )
|
||||
{
|
||||
AIClient *ai = static_cast<AIClient *>( object );
|
||||
|
||||
|
|
@ -446,7 +446,7 @@ DefineConsoleMethod( AIClient, setAimLocation, void, (Point3F v), , "ai.setAimLo
|
|||
/**
|
||||
* Tells the AI to move to the location provided
|
||||
*/
|
||||
DefineConsoleMethod( AIClient, setMoveDestination, void, (Point3F v), , "ai.setMoveDestination( x y z );" )
|
||||
DefineEngineMethod( AIClient, setMoveDestination, void, (Point3F v), , "ai.setMoveDestination( x y z );" )
|
||||
{
|
||||
AIClient *ai = static_cast<AIClient *>( object );
|
||||
|
||||
|
|
@ -456,7 +456,7 @@ DefineConsoleMethod( AIClient, setMoveDestination, void, (Point3F v), , "ai.setM
|
|||
/**
|
||||
* Returns the point the AI is aiming at
|
||||
*/
|
||||
DefineConsoleMethod( AIClient, getAimLocation, Point3F, (),, "ai.getAimLocation();" )
|
||||
DefineEngineMethod( AIClient, getAimLocation, Point3F, (),, "ai.getAimLocation();" )
|
||||
{
|
||||
AIClient *ai = static_cast<AIClient *>( object );
|
||||
return ai->getAimLocation();
|
||||
|
|
@ -465,7 +465,7 @@ DefineConsoleMethod( AIClient, getAimLocation, Point3F, (),, "ai.getAimLocation(
|
|||
/**
|
||||
* Returns the point the AI is set to move to
|
||||
*/
|
||||
DefineConsoleMethod( AIClient, getMoveDestination, Point3F, (),, "ai.getMoveDestination();" )
|
||||
DefineEngineMethod( AIClient, getMoveDestination, Point3F, (),, "ai.getMoveDestination();" )
|
||||
{
|
||||
AIClient *ai = static_cast<AIClient *>( object );
|
||||
return ai->getMoveDestination();
|
||||
|
|
@ -474,7 +474,7 @@ DefineConsoleMethod( AIClient, getMoveDestination, Point3F, (),, "ai.getMoveDest
|
|||
/**
|
||||
* Sets the bots target object
|
||||
*/
|
||||
DefineConsoleMethod( AIClient, setTargetObject, void, (const char * objName), , "ai.setTargetObject( obj );" )
|
||||
DefineEngineMethod( AIClient, setTargetObject, void, (const char * objName), , "ai.setTargetObject( obj );" )
|
||||
{
|
||||
AIClient *ai = static_cast<AIClient *>( object );
|
||||
|
||||
|
|
@ -489,7 +489,7 @@ DefineConsoleMethod( AIClient, setTargetObject, void, (const char * objName), ,
|
|||
/**
|
||||
* Gets the object the AI is targeting
|
||||
*/
|
||||
DefineConsoleMethod( AIClient, getTargetObject, S32, (),, "ai.getTargetObject();" )
|
||||
DefineEngineMethod( AIClient, getTargetObject, S32, (),, "ai.getTargetObject();" )
|
||||
{
|
||||
AIClient *ai = static_cast<AIClient *>( object );
|
||||
|
||||
|
|
@ -499,7 +499,7 @@ DefineConsoleMethod( AIClient, getTargetObject, S32, (),, "ai.getTargetObject();
|
|||
/**
|
||||
* Tells the bot the mission is cycling
|
||||
*/
|
||||
DefineConsoleMethod( AIClient, missionCycleCleanup, void, (),, "ai.missionCycleCleanup();" )
|
||||
DefineEngineMethod( AIClient, missionCycleCleanup, void, (),, "ai.missionCycleCleanup();" )
|
||||
{
|
||||
AIClient *ai = static_cast<AIClient*>( object );
|
||||
ai->missionCycleCleanup();
|
||||
|
|
@ -508,7 +508,7 @@ DefineConsoleMethod( AIClient, missionCycleCleanup, void, (),, "ai.missionCycleC
|
|||
/**
|
||||
* Sets the AI to run mode
|
||||
*/
|
||||
DefineConsoleMethod( AIClient, move, void, (),, "ai.move();" )
|
||||
DefineEngineMethod( AIClient, move, void, (),, "ai.move();" )
|
||||
{
|
||||
AIClient *ai = static_cast<AIClient *>( object );
|
||||
ai->setMoveMode( AIClient::ModeMove );
|
||||
|
|
@ -517,7 +517,7 @@ DefineConsoleMethod( AIClient, move, void, (),, "ai.move();" )
|
|||
/**
|
||||
* Gets the AI's location in the world
|
||||
*/
|
||||
DefineConsoleMethod( AIClient, getLocation, Point3F, (),, "ai.getLocation();" )
|
||||
DefineEngineMethod( AIClient, getLocation, Point3F, (),, "ai.getLocation();" )
|
||||
{
|
||||
AIClient *ai = static_cast<AIClient *>( object );
|
||||
return ai->getLocation();
|
||||
|
|
@ -526,7 +526,7 @@ DefineConsoleMethod( AIClient, getLocation, Point3F, (),, "ai.getLocation();" )
|
|||
/**
|
||||
* Adds an AI Player to the game
|
||||
*/
|
||||
DefineConsoleFunction( aiAddPlayer, S32, (const char * name, const char * ns), (""), "'playerName'[, 'AIClassType'] );")
|
||||
DefineEngineFunction( aiAddPlayer, S32, (const char * name, const char * ns), (""), "'playerName'[, 'AIClassType'] );")
|
||||
{
|
||||
// Create the player
|
||||
AIClient *aiPlayer = new AIClient();
|
||||
|
|
@ -559,7 +559,7 @@ DefineConsoleFunction( aiAddPlayer, S32, (const char * name, const char * ns), (
|
|||
/**
|
||||
* Tells the AI to move forward 100 units...TEST FXN
|
||||
*/
|
||||
DefineConsoleMethod( AIClient, moveForward, void, (),, "ai.moveForward();" )
|
||||
DefineEngineMethod( AIClient, moveForward, void, (),, "ai.moveForward();" )
|
||||
{
|
||||
|
||||
AIClient *ai = static_cast<AIClient *>( object );
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ static inline F32 moveClamp(F32 v)
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
/// Construct and connect an AI connection object
|
||||
ConsoleFunction(aiConnect, S32 , 2, 20, "(...)"
|
||||
DefineEngineStringlyVariadicFunction(aiConnect, S32 , 2, 20, "(...)"
|
||||
"@brief Creates a new AIConnection, and passes arguments to its onConnect script callback.\n\n"
|
||||
"@returns The newly created AIConnection\n"
|
||||
"@see GameConnection for parameter information\n"
|
||||
|
|
@ -160,7 +160,7 @@ ConsoleFunction(aiConnect, S32 , 2, 20, "(...)"
|
|||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
DefineConsoleMethod(AIConnection, setMove, void, (const char * field, F32 value), ,"(string field, float value)"
|
||||
DefineEngineMethod(AIConnection, setMove, void, (const char * field, F32 value), ,"(string field, float value)"
|
||||
"Set a field on the current move.\n\n"
|
||||
"@param field One of {'x','y','z','yaw','pitch','roll'}\n"
|
||||
"@param value Value to set field to.")
|
||||
|
|
@ -190,7 +190,7 @@ DefineConsoleMethod(AIConnection, setMove, void, (const char * field, F32 value)
|
|||
object->setMove(&move);
|
||||
}
|
||||
|
||||
DefineConsoleMethod(AIConnection,getMove,F32, (const char * field), ,"(string field)"
|
||||
DefineEngineMethod(AIConnection,getMove,F32, (const char * field), ,"(string field)"
|
||||
"Get the given field of a move.\n\n"
|
||||
"@param field One of {'x','y','z','yaw','pitch','roll'}\n"
|
||||
"@returns The requested field on the current move.")
|
||||
|
|
@ -212,7 +212,7 @@ DefineConsoleMethod(AIConnection,getMove,F32, (const char * field), ,"(string fi
|
|||
}
|
||||
|
||||
|
||||
DefineConsoleMethod(AIConnection,setFreeLook,void,(bool isFreeLook), ,"(bool isFreeLook)"
|
||||
DefineEngineMethod(AIConnection,setFreeLook,void,(bool isFreeLook), ,"(bool isFreeLook)"
|
||||
"Enable/disable freelook on the current move.")
|
||||
{
|
||||
Move move = object->getMove();
|
||||
|
|
@ -220,7 +220,7 @@ DefineConsoleMethod(AIConnection,setFreeLook,void,(bool isFreeLook), ,"(bool isF
|
|||
object->setMove(&move);
|
||||
}
|
||||
|
||||
DefineConsoleMethod(AIConnection, getFreeLook, bool, (), ,"getFreeLook()"
|
||||
DefineEngineMethod(AIConnection, getFreeLook, bool, (), ,"getFreeLook()"
|
||||
"Is freelook on for the current move?")
|
||||
{
|
||||
return object->getMove().freeLook;
|
||||
|
|
@ -229,7 +229,7 @@ DefineConsoleMethod(AIConnection, getFreeLook, bool, (), ,"getFreeLook()"
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineConsoleMethod(AIConnection,setTrigger,void, (S32 idx, bool set), ,"(int trigger, bool set)"
|
||||
DefineEngineMethod(AIConnection,setTrigger,void, (S32 idx, bool set), ,"(int trigger, bool set)"
|
||||
"Set a trigger.")
|
||||
{
|
||||
if (idx >= 0 && idx < MaxTriggerKeys)
|
||||
|
|
@ -240,7 +240,7 @@ DefineConsoleMethod(AIConnection,setTrigger,void, (S32 idx, bool set), ,"(int tr
|
|||
}
|
||||
}
|
||||
|
||||
DefineConsoleMethod(AIConnection,getTrigger,bool, (S32 idx), ,"(int trigger)"
|
||||
DefineEngineMethod(AIConnection,getTrigger,bool, (S32 idx), ,"(int trigger)"
|
||||
"Is the given trigger set?")
|
||||
{
|
||||
if (idx >= 0 && idx < MaxTriggerKeys)
|
||||
|
|
@ -251,7 +251,7 @@ DefineConsoleMethod(AIConnection,getTrigger,bool, (S32 idx), ,"(int trigger)"
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineConsoleMethod(AIConnection,getAddress,const char*,(), ,"")
|
||||
DefineEngineMethod(AIConnection,getAddress,const char*,(), ,"")
|
||||
{
|
||||
// Override the netConnection method to return to indicate
|
||||
// this is an ai connection.
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/aiPlayer.h"
|
||||
|
||||
|
|
@ -97,6 +102,9 @@ AIPlayer::AIPlayer()
|
|||
mMoveSlowdown = true;
|
||||
mMoveState = ModeStop;
|
||||
|
||||
// This new member saves the movement state of the AI so that
|
||||
// it can be restored after a substituted animation is finished.
|
||||
mMoveState_saved = -1;
|
||||
mAimObject = 0;
|
||||
mAimLocationSet = false;
|
||||
mTargetInLOS = false;
|
||||
|
|
@ -547,23 +555,27 @@ bool AIPlayer::getAIMove(Move *movePtr)
|
|||
mMoveState = ModeMove;
|
||||
}
|
||||
|
||||
if (mMoveStuckTestCountdown > 0)
|
||||
--mMoveStuckTestCountdown;
|
||||
else
|
||||
{
|
||||
// We should check to see if we are stuck...
|
||||
F32 locationDelta = (location - mLastLocation).len();
|
||||
// Don't check for ai stuckness if animation during
|
||||
// an anim-clip effect override.
|
||||
if (mDamageState == Enabled && !(anim_clip_flags & ANIM_OVERRIDDEN) && !isAnimationLocked()) {
|
||||
if (mMoveStuckTestCountdown > 0)
|
||||
--mMoveStuckTestCountdown;
|
||||
else
|
||||
{
|
||||
// We should check to see if we are stuck...
|
||||
F32 locationDelta = (location - mLastLocation).len();
|
||||
if (locationDelta < mMoveStuckTolerance && mDamageState == Enabled)
|
||||
{
|
||||
// If we are slowing down, then it's likely that our location delta will be less than
|
||||
// our move stuck tolerance. Because we can be both slowing and stuck
|
||||
// we should TRY to check if we've moved. This could use better detection.
|
||||
if ( mMoveState != ModeSlowing || locationDelta == 0 )
|
||||
{
|
||||
mMoveState = ModeStuck;
|
||||
onStuck();
|
||||
}
|
||||
}
|
||||
{
|
||||
mMoveState = ModeStuck;
|
||||
onStuck();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -626,6 +638,7 @@ bool AIPlayer::getAIMove(Move *movePtr)
|
|||
}
|
||||
#endif // TORQUE_NAVIGATION_ENABLED
|
||||
|
||||
if (!(anim_clip_flags & ANIM_OVERRIDDEN) && !isAnimationLocked())
|
||||
mLastLocation = location;
|
||||
|
||||
return true;
|
||||
|
|
@ -1238,7 +1251,7 @@ ConsoleDocFragment _setAimObject(
|
|||
"void setAimObject(GameBase targetObject, Point3F offset);"
|
||||
);
|
||||
|
||||
DefineConsoleMethod( AIPlayer, setAimObject, void, ( const char * objName, Point3F offset ), (Point3F::Zero), "( GameBase obj, [Point3F offset] )"
|
||||
DefineEngineMethod( AIPlayer, setAimObject, void, ( const char * objName, Point3F offset ), (Point3F::Zero), "( GameBase obj, [Point3F offset] )"
|
||||
"Sets the bot's target object. Optionally set an offset from target location."
|
||||
"@hide")
|
||||
{
|
||||
|
|
@ -1415,6 +1428,47 @@ DefineEngineMethod( AIPlayer, clearMoveTriggers, void, ( ),,
|
|||
object->clearMoveTriggers();
|
||||
}
|
||||
|
||||
// These changes coordinate with anim-clip mods to parent class, Player.
|
||||
|
||||
// New method, restartMove(), restores the AIPlayer to its normal move-state
|
||||
// following animation overrides from AFX. The tag argument is used to match
|
||||
// the latest override and prevents interruption of overlapping animation
|
||||
// overrides. See related anim-clip changes in Player.[h,cc].
|
||||
void AIPlayer::restartMove(U32 tag)
|
||||
{
|
||||
if (tag != 0 && tag == last_anim_tag)
|
||||
{
|
||||
if (mMoveState_saved != -1)
|
||||
{
|
||||
mMoveState = (MoveState) mMoveState_saved;
|
||||
mMoveState_saved = -1;
|
||||
}
|
||||
|
||||
bool is_death_anim = ((anim_clip_flags & IS_DEATH_ANIM) != 0);
|
||||
|
||||
last_anim_tag = 0;
|
||||
anim_clip_flags &= ~(ANIM_OVERRIDDEN | IS_DEATH_ANIM);
|
||||
|
||||
if (mDamageState != Enabled)
|
||||
{
|
||||
if (!is_death_anim)
|
||||
{
|
||||
// this is a bit hardwired and desperate,
|
||||
// but if he's dead he needs to look like it.
|
||||
setActionThread("death10", false, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// New method, saveMoveState(), stores the current movement state
|
||||
// so that it can be restored when restartMove() is called.
|
||||
void AIPlayer::saveMoveState()
|
||||
{
|
||||
if (mMoveState_saved == -1)
|
||||
mMoveState_saved = (S32) mMoveState;
|
||||
}
|
||||
|
||||
F32 AIPlayer::getTargetDistance(GameBase* target, bool _checkEnabled)
|
||||
{
|
||||
if (!isServerObject()) return false;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _AIPLAYER_H_
|
||||
#define _AIPLAYER_H_
|
||||
|
||||
|
|
@ -225,6 +230,18 @@ public:
|
|||
|
||||
/// @}
|
||||
#endif // TORQUE_NAVIGATION_ENABLED
|
||||
// New method, restartMove(), restores the AIPlayer to its normal move-state
|
||||
// following animation overrides from AFX. The tag argument is used to match
|
||||
// the latest override and prevents interruption of overlapping animation
|
||||
// overrides.
|
||||
// New method, saveMoveState(), stores the current movement state
|
||||
// so that it can be restored when restartMove() is called.
|
||||
// See related anim-clip changes in Player.[h,cc].
|
||||
private:
|
||||
S32 mMoveState_saved;
|
||||
public:
|
||||
void restartMove(U32 tag);
|
||||
void saveMoveState();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ ConsoleSetType(TypeComponentAssetPtr)
|
|||
if (pAssetPtr == NULL)
|
||||
{
|
||||
// No, so fail.
|
||||
//Con::warnf("(TypeTextureAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
//Con::warnf("(TypeComponentAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -85,24 +85,20 @@ ConsoleSetType(TypeComponentAssetPtr)
|
|||
}
|
||||
|
||||
// Warn.
|
||||
Con::warnf("(TypeTextureAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
Con::warnf("(TypeComponentAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ComponentAsset::ComponentAsset() :
|
||||
mpOwningAssetManager(NULL),
|
||||
mAssetInitialized(false),
|
||||
mAcquireReferenceCount(0)
|
||||
ComponentAsset::ComponentAsset()
|
||||
{
|
||||
// Generate an asset definition.
|
||||
mpAssetDefinition = new AssetDefinition();
|
||||
mComponentName = StringTable->EmptyString();
|
||||
mComponentClass = StringTable->EmptyString();
|
||||
mFriendlyName = StringTable->EmptyString();
|
||||
mComponentType = StringTable->EmptyString();
|
||||
mDescription = StringTable->EmptyString();
|
||||
|
||||
mComponentName = StringTable->lookup("");
|
||||
mComponentClass = StringTable->lookup("");
|
||||
mFriendlyName = StringTable->lookup("");
|
||||
mComponentType = StringTable->lookup("");
|
||||
mDescription = StringTable->lookup("");
|
||||
mScriptFile = StringTable->EmptyString();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -127,6 +123,8 @@ void ComponentAsset::initPersistFields()
|
|||
addField("friendlyName", TypeString, Offset(mFriendlyName, ComponentAsset), "The human-readble name for the component.");
|
||||
addField("componentType", TypeString, Offset(mComponentType, ComponentAsset), "The category of the component for organizing in the editor.");
|
||||
addField("description", TypeString, Offset(mDescription, ComponentAsset), "Simple description of the component.");
|
||||
|
||||
addField("scriptFile", TypeString, Offset(mScriptFile, ComponentAsset), "A script file with additional scripted functionality for this component.");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -135,4 +133,16 @@ void ComponentAsset::copyTo(SimObject* object)
|
|||
{
|
||||
// Call to parent.
|
||||
Parent::copyTo(object);
|
||||
}
|
||||
|
||||
void ComponentAsset::initializeAsset()
|
||||
{
|
||||
if(Platform::isFile(mScriptFile))
|
||||
Con::executeFile(mScriptFile, false, false);
|
||||
}
|
||||
|
||||
void ComponentAsset::onAssetRefresh()
|
||||
{
|
||||
if (Platform::isFile(mScriptFile))
|
||||
Con::executeFile(mScriptFile, false, false);
|
||||
}
|
||||
|
|
@ -44,17 +44,14 @@ class ComponentAsset : public AssetBase
|
|||
{
|
||||
typedef AssetBase Parent;
|
||||
|
||||
AssetManager* mpOwningAssetManager;
|
||||
bool mAssetInitialized;
|
||||
AssetDefinition* mpAssetDefinition;
|
||||
U32 mAcquireReferenceCount;
|
||||
|
||||
StringTableEntry mComponentName;
|
||||
StringTableEntry mComponentClass;
|
||||
StringTableEntry mFriendlyName;
|
||||
StringTableEntry mComponentType;
|
||||
StringTableEntry mDescription;
|
||||
|
||||
StringTableEntry mScriptFile;
|
||||
|
||||
public:
|
||||
ComponentAsset();
|
||||
virtual ~ComponentAsset();
|
||||
|
|
@ -69,12 +66,20 @@ public:
|
|||
StringTableEntry getComponentName() { return mComponentName; }
|
||||
StringTableEntry getComponentClass() { return mComponentClass; }
|
||||
StringTableEntry getFriendlyName() { return mFriendlyName; }
|
||||
StringTableEntry getFriendlyType() { return mComponentType; }
|
||||
StringTableEntry getComponentType() { return mComponentType; }
|
||||
StringTableEntry getDescription() { return mDescription; }
|
||||
|
||||
void setComponentName(StringTableEntry name) { mComponentName = name; }
|
||||
void setComponentClass(StringTableEntry name) { mComponentClass = name; }
|
||||
void setFriendlyName(StringTableEntry name) { mFriendlyName = name; }
|
||||
void setComponentType(StringTableEntry typeName) { mComponentType = typeName; }
|
||||
void setDescription(StringTableEntry description) { mDescription = description; }
|
||||
|
||||
AssetDefinition* getAssetDefinition() { return mpAssetDefinition; }
|
||||
|
||||
protected:
|
||||
virtual void initializeAsset(void) {}
|
||||
virtual void onAssetRefresh(void) {}
|
||||
virtual void initializeAsset(void);
|
||||
virtual void onAssetRefresh(void);
|
||||
};
|
||||
|
||||
DefineConsoleType(TypeComponentAssetPtr, ComponentAsset)
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ ConsoleSetType(TypeExampleAssetPtr)
|
|||
if (pAssetPtr == NULL)
|
||||
{
|
||||
// No, so fail.
|
||||
//Con::warnf("(TypeTextureAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
//Con::warnf("(TypeExampleAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -85,18 +85,13 @@ ConsoleSetType(TypeExampleAssetPtr)
|
|||
}
|
||||
|
||||
// Warn.
|
||||
Con::warnf("(TypeTextureAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
Con::warnf("(TypeExampleAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ExampleAsset::ExampleAsset() :
|
||||
mpOwningAssetManager(NULL),
|
||||
mAssetInitialized(false),
|
||||
mAcquireReferenceCount(0)
|
||||
ExampleAsset::ExampleAsset()
|
||||
{
|
||||
// Generate an asset definition.
|
||||
mpAssetDefinition = new AssetDefinition();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -43,11 +43,6 @@ class ExampleAsset : public AssetBase
|
|||
{
|
||||
typedef AssetBase Parent;
|
||||
|
||||
AssetManager* mpOwningAssetManager;
|
||||
bool mAssetInitialized;
|
||||
AssetDefinition* mpAssetDefinition;
|
||||
U32 mAcquireReferenceCount;
|
||||
|
||||
public:
|
||||
ExampleAsset();
|
||||
virtual ~ExampleAsset();
|
||||
|
|
|
|||
222
Engine/source/T3D/assets/GUIAsset.cpp
Normal file
222
Engine/source/T3D/assets/GUIAsset.cpp
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef GUI_ASSET_H
|
||||
#include "GUIAsset.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_MANAGER_H_
|
||||
#include "assets/assetManager.h"
|
||||
#endif
|
||||
|
||||
#ifndef _CONSOLETYPES_H_
|
||||
#include "console/consoleTypes.h"
|
||||
#endif
|
||||
|
||||
#ifndef _TAML_
|
||||
#include "persistence/taml/taml.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_PTR_H_
|
||||
#include "assets/assetPtr.h"
|
||||
#endif
|
||||
|
||||
// Debug Profiling.
|
||||
#include "platform/profiler.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(GUIAsset);
|
||||
|
||||
ConsoleType(GUIAssetPtr, TypeGUIAssetPtr, GUIAsset, ASSET_ID_FIELD_PREFIX)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleGetType(TypeGUIAssetPtr)
|
||||
{
|
||||
// Fetch asset Id.
|
||||
return (*((AssetPtr<GUIAsset>*)dptr)).getAssetId();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleSetType(TypeGUIAssetPtr)
|
||||
{
|
||||
// Was a single argument specified?
|
||||
if (argc == 1)
|
||||
{
|
||||
// Yes, so fetch field value.
|
||||
const char* pFieldValue = argv[0];
|
||||
|
||||
// Fetch asset pointer.
|
||||
AssetPtr<GUIAsset>* pAssetPtr = dynamic_cast<AssetPtr<GUIAsset>*>((AssetPtrBase*)(dptr));
|
||||
|
||||
// Is the asset pointer the correct type?
|
||||
if (pAssetPtr == NULL)
|
||||
{
|
||||
// No, so fail.
|
||||
//Con::warnf("(TypeGUIAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set asset.
|
||||
pAssetPtr->setAssetId(pFieldValue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Warn.
|
||||
Con::warnf("(TypeGUIAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GUIAsset::GUIAsset()
|
||||
{
|
||||
mScriptFilePath = StringTable->EmptyString();
|
||||
mGUIFilePath = StringTable->EmptyString();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GUIAsset::~GUIAsset()
|
||||
{
|
||||
// If the asset manager does not own the asset then we own the
|
||||
// asset definition so delete it.
|
||||
if (!getOwned())
|
||||
delete mpAssetDefinition;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GUIAsset::initPersistFields()
|
||||
{
|
||||
// Call parent.
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("scriptFilePath", TypeString, Offset(mScriptFilePath, GUIAsset), "Path to the script file for the gui");
|
||||
addField("GUIFilePath", TypeString, Offset(mGUIFilePath, GUIAsset), "Path to the gui file");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void GUIAsset::copyTo(SimObject* object)
|
||||
{
|
||||
// Call to parent.
|
||||
Parent::copyTo(object);
|
||||
}
|
||||
|
||||
void GUIAsset::initializeAsset()
|
||||
{
|
||||
if (Platform::isFile(mGUIFilePath))
|
||||
Con::executeFile(mGUIFilePath, false, false);
|
||||
|
||||
if (Platform::isFile(mScriptFilePath))
|
||||
Con::executeFile(mScriptFilePath, false, false);
|
||||
}
|
||||
|
||||
void GUIAsset::onAssetRefresh()
|
||||
{
|
||||
if (Platform::isFile(mGUIFilePath))
|
||||
Con::executeFile(mGUIFilePath, false, false);
|
||||
|
||||
if (Platform::isFile(mScriptFilePath))
|
||||
Con::executeFile(mScriptFilePath, false, false);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorTypeAssetId
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorTypeGUIAssetPtr);
|
||||
|
||||
ConsoleDocClass(GuiInspectorTypeGUIAssetPtr,
|
||||
"@brief Inspector field type for GUI Asset Objects\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
void GuiInspectorTypeGUIAssetPtr::consoleInit()
|
||||
{
|
||||
Parent::consoleInit();
|
||||
|
||||
ConsoleBaseType::getType(TypeGUIAssetPtr)->setInspectorFieldType("GuiInspectorTypeGUIAssetPtr");
|
||||
}
|
||||
|
||||
GuiControl* GuiInspectorTypeGUIAssetPtr::constructEditControl()
|
||||
{
|
||||
// Create base filename edit controls
|
||||
GuiControl *retCtrl = Parent::constructEditControl();
|
||||
if (retCtrl == NULL)
|
||||
return retCtrl;
|
||||
|
||||
// Change filespec
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"GUIAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
|
||||
mInspector->getComponentGroupTargetId(), mCaption);
|
||||
mBrowseButton->setField("Command", szBuffer);
|
||||
|
||||
// Create "Open in ShapeEditor" button
|
||||
mSMEdButton = new GuiBitmapButtonCtrl();
|
||||
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "echo(\"Game Object Editor not implemented yet!\");", retCtrl->getId());
|
||||
mSMEdButton->setField("Command", szBuffer);
|
||||
|
||||
char bitmapName[512] = "tools/worldEditor/images/toolbar/shape-editor";
|
||||
mSMEdButton->setBitmap(bitmapName);
|
||||
|
||||
mSMEdButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
|
||||
mSMEdButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
|
||||
mSMEdButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
|
||||
mSMEdButton->setDataField(StringTable->insert("tooltip"), NULL, "Open this file in the State Machine Editor");
|
||||
|
||||
mSMEdButton->registerObject();
|
||||
addObject(mSMEdButton);
|
||||
|
||||
return retCtrl;
|
||||
}
|
||||
|
||||
bool GuiInspectorTypeGUIAssetPtr::updateRects()
|
||||
{
|
||||
S32 dividerPos, dividerMargin;
|
||||
mInspector->getDivider(dividerPos, dividerMargin);
|
||||
Point2I fieldExtent = getExtent();
|
||||
Point2I fieldPos = getPosition();
|
||||
|
||||
mCaptionRect.set(0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y);
|
||||
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y);
|
||||
|
||||
bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
|
||||
if (mBrowseButton != NULL)
|
||||
{
|
||||
mBrowseRect.set(fieldExtent.x - 32, 2, 14, fieldExtent.y - 4);
|
||||
resized |= mBrowseButton->resize(mBrowseRect.point, mBrowseRect.extent);
|
||||
}
|
||||
|
||||
if (mSMEdButton != NULL)
|
||||
{
|
||||
RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4);
|
||||
resized |= mSMEdButton->resize(shapeEdRect.point, shapeEdRect.extent);
|
||||
}
|
||||
|
||||
return resized;
|
||||
}
|
||||
89
Engine/source/T3D/assets/GUIAsset.h
Normal file
89
Engine/source/T3D/assets/GUIAsset.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#pragma once
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef GUI_ASSET_H
|
||||
#define GUI_ASSET_H
|
||||
|
||||
#ifndef _ASSET_BASE_H_
|
||||
#include "assets/assetBase.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_DEFINITION_H_
|
||||
#include "assets/assetDefinition.h"
|
||||
#endif
|
||||
|
||||
#ifndef _STRINGUNIT_H_
|
||||
#include "string/stringUnit.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_FIELD_TYPES_H_
|
||||
#include "assets/assetFieldTypes.h"
|
||||
#endif
|
||||
|
||||
#include "gui/editor/guiInspectorTypes.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class GUIAsset : public AssetBase
|
||||
{
|
||||
typedef AssetBase Parent;
|
||||
|
||||
StringTableEntry mScriptFilePath;
|
||||
StringTableEntry mGUIFilePath;
|
||||
|
||||
public:
|
||||
GUIAsset();
|
||||
virtual ~GUIAsset();
|
||||
|
||||
/// Engine.
|
||||
static void initPersistFields();
|
||||
virtual void copyTo(SimObject* object);
|
||||
|
||||
/// Declare Console Object.
|
||||
DECLARE_CONOBJECT(GUIAsset);
|
||||
|
||||
protected:
|
||||
virtual void initializeAsset(void);
|
||||
virtual void onAssetRefresh(void);
|
||||
};
|
||||
|
||||
DefineConsoleType(TypeGUIAssetPtr, GUIAsset)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeAssetId GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeGUIAssetPtr : public GuiInspectorTypeFileName
|
||||
{
|
||||
typedef GuiInspectorTypeFileName Parent;
|
||||
public:
|
||||
|
||||
GuiBitmapButtonCtrl *mSMEdButton;
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeGUIAssetPtr);
|
||||
static void consoleInit();
|
||||
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual bool updateRects();
|
||||
};
|
||||
|
||||
#endif // _ASSET_BASE_H_
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ ConsoleSetType(TypeGameObjectAssetPtr)
|
|||
if (pAssetPtr == NULL)
|
||||
{
|
||||
// No, so fail.
|
||||
//Con::warnf("(TypeTextureAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
//Con::warnf("(TypeGameObjectAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -85,19 +85,13 @@ ConsoleSetType(TypeGameObjectAssetPtr)
|
|||
}
|
||||
|
||||
// Warn.
|
||||
Con::warnf("(TypeTextureAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
Con::warnf("(TypeGameObjectAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GameObjectAsset::GameObjectAsset() :
|
||||
mpOwningAssetManager(NULL),
|
||||
mAssetInitialized(false),
|
||||
mAcquireReferenceCount(0)
|
||||
GameObjectAsset::GameObjectAsset()
|
||||
{
|
||||
// Generate an asset definition.
|
||||
mpAssetDefinition = new AssetDefinition();
|
||||
|
||||
mGameObjectName = StringTable->lookup("");
|
||||
mScriptFilePath = StringTable->lookup("");
|
||||
mTAMLFilePath = StringTable->lookup("");
|
||||
|
|
@ -131,4 +125,94 @@ void GameObjectAsset::copyTo(SimObject* object)
|
|||
{
|
||||
// Call to parent.
|
||||
Parent::copyTo(object);
|
||||
}
|
||||
|
||||
void GameObjectAsset::initializeAsset()
|
||||
{
|
||||
if (Platform::isFile(mScriptFilePath))
|
||||
Con::executeFile(mScriptFilePath, false, false);
|
||||
}
|
||||
|
||||
void GameObjectAsset::onAssetRefresh()
|
||||
{
|
||||
if (Platform::isFile(mScriptFilePath))
|
||||
Con::executeFile(mScriptFilePath, false, false);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorTypeAssetId
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorTypeGameObjectAssetPtr);
|
||||
|
||||
ConsoleDocClass(GuiInspectorTypeGameObjectAssetPtr,
|
||||
"@brief Inspector field type for Game Objects\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
void GuiInspectorTypeGameObjectAssetPtr::consoleInit()
|
||||
{
|
||||
Parent::consoleInit();
|
||||
|
||||
ConsoleBaseType::getType(TypeGameObjectAssetPtr)->setInspectorFieldType("GuiInspectorTypeGameObjectAssetPtr");
|
||||
}
|
||||
|
||||
GuiControl* GuiInspectorTypeGameObjectAssetPtr::constructEditControl()
|
||||
{
|
||||
// Create base filename edit controls
|
||||
GuiControl *retCtrl = Parent::constructEditControl();
|
||||
if (retCtrl == NULL)
|
||||
return retCtrl;
|
||||
|
||||
// Change filespec
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"GameObjectAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
|
||||
mInspector->getComponentGroupTargetId(), mCaption);
|
||||
mBrowseButton->setField("Command", szBuffer);
|
||||
|
||||
// Create "Open in ShapeEditor" button
|
||||
mSMEdButton = new GuiBitmapButtonCtrl();
|
||||
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "echo(\"Game Object Editor not implemented yet!\");", retCtrl->getId());
|
||||
mSMEdButton->setField("Command", szBuffer);
|
||||
|
||||
char bitmapName[512] = "tools/worldEditor/images/toolbar/shape-editor";
|
||||
mSMEdButton->setBitmap(bitmapName);
|
||||
|
||||
mSMEdButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
|
||||
mSMEdButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
|
||||
mSMEdButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
|
||||
mSMEdButton->setDataField(StringTable->insert("tooltip"), NULL, "Open this file in the State Machine Editor");
|
||||
|
||||
mSMEdButton->registerObject();
|
||||
addObject(mSMEdButton);
|
||||
|
||||
return retCtrl;
|
||||
}
|
||||
|
||||
bool GuiInspectorTypeGameObjectAssetPtr::updateRects()
|
||||
{
|
||||
S32 dividerPos, dividerMargin;
|
||||
mInspector->getDivider(dividerPos, dividerMargin);
|
||||
Point2I fieldExtent = getExtent();
|
||||
Point2I fieldPos = getPosition();
|
||||
|
||||
mCaptionRect.set(0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y);
|
||||
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y);
|
||||
|
||||
bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
|
||||
if (mBrowseButton != NULL)
|
||||
{
|
||||
mBrowseRect.set(fieldExtent.x - 32, 2, 14, fieldExtent.y - 4);
|
||||
resized |= mBrowseButton->resize(mBrowseRect.point, mBrowseRect.extent);
|
||||
}
|
||||
|
||||
if (mSMEdButton != NULL)
|
||||
{
|
||||
RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4);
|
||||
resized |= mSMEdButton->resize(shapeEdRect.point, shapeEdRect.extent);
|
||||
}
|
||||
|
||||
return resized;
|
||||
}
|
||||
|
|
@ -38,17 +38,15 @@
|
|||
#ifndef _ASSET_FIELD_TYPES_H_
|
||||
#include "assets/assetFieldTypes.h"
|
||||
#endif
|
||||
#ifndef _GUI_INSPECTOR_TYPES_H_
|
||||
#include "gui/editor/guiInspectorTypes.h"
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class GameObjectAsset : public AssetBase
|
||||
{
|
||||
typedef AssetBase Parent;
|
||||
|
||||
AssetManager* mpOwningAssetManager;
|
||||
bool mAssetInitialized;
|
||||
AssetDefinition* mpAssetDefinition;
|
||||
U32 mAcquireReferenceCount;
|
||||
|
||||
StringTableEntry mGameObjectName;
|
||||
StringTableEntry mScriptFilePath;
|
||||
StringTableEntry mTAMLFilePath;
|
||||
|
|
@ -65,11 +63,29 @@ public:
|
|||
DECLARE_CONOBJECT(GameObjectAsset);
|
||||
|
||||
protected:
|
||||
virtual void initializeAsset(void) {}
|
||||
virtual void onAssetRefresh(void) {}
|
||||
virtual void initializeAsset(void);
|
||||
virtual void onAssetRefresh(void);
|
||||
};
|
||||
|
||||
DefineConsoleType(TypeGameObjectAssetPtr, GameObjectAsset)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeAssetId GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeGameObjectAssetPtr : public GuiInspectorTypeFileName
|
||||
{
|
||||
typedef GuiInspectorTypeFileName Parent;
|
||||
public:
|
||||
|
||||
GuiBitmapButtonCtrl *mSMEdButton;
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeGameObjectAssetPtr);
|
||||
static void consoleInit();
|
||||
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual bool updateRects();
|
||||
};
|
||||
|
||||
#endif // _ASSET_BASE_H_
|
||||
|
||||
|
|
|
|||
156
Engine/source/T3D/assets/ImageAsset.cpp
Normal file
156
Engine/source/T3D/assets/ImageAsset.cpp
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef IMAGE_ASSET_H
|
||||
#include "ImageAsset.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_MANAGER_H_
|
||||
#include "assets/assetManager.h"
|
||||
#endif
|
||||
|
||||
#ifndef _CONSOLETYPES_H_
|
||||
#include "console/consoleTypes.h"
|
||||
#endif
|
||||
|
||||
#ifndef _TAML_
|
||||
#include "persistence/taml/taml.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_PTR_H_
|
||||
#include "assets/assetPtr.h"
|
||||
#endif
|
||||
|
||||
// Debug Profiling.
|
||||
#include "platform/profiler.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(ImageAsset);
|
||||
|
||||
ConsoleType(ImageAssetPtr, TypeImageAssetPtr, ImageAsset, ASSET_ID_FIELD_PREFIX)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleGetType(TypeImageAssetPtr)
|
||||
{
|
||||
// Fetch asset Id.
|
||||
return (*((AssetPtr<ImageAsset>*)dptr)).getAssetId();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleSetType(TypeImageAssetPtr)
|
||||
{
|
||||
// Was a single argument specified?
|
||||
if (argc == 1)
|
||||
{
|
||||
// Yes, so fetch field value.
|
||||
const char* pFieldValue = argv[0];
|
||||
|
||||
// Fetch asset pointer.
|
||||
AssetPtr<ImageAsset>* pAssetPtr = dynamic_cast<AssetPtr<ImageAsset>*>((AssetPtrBase*)(dptr));
|
||||
|
||||
// Is the asset pointer the correct type?
|
||||
if (pAssetPtr == NULL)
|
||||
{
|
||||
// No, so fail.
|
||||
//Con::warnf("(TypeImageAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set asset.
|
||||
pAssetPtr->setAssetId(pFieldValue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Warn.
|
||||
Con::warnf("(TypeImageAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ImageAsset::ImageAsset() : AssetBase(), mImage(nullptr), mUseMips(true), mIsHDRImage(false), mIsValidImage(false)
|
||||
{
|
||||
mImageFileName = StringTable->EmptyString();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ImageAsset::~ImageAsset()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ImageAsset::initPersistFields()
|
||||
{
|
||||
// Call parent.
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("imageFile", TypeString, Offset(mImageFileName, ImageAsset), "Path to the image file.");
|
||||
addField("useMips", TypeBool, Offset(mUseMips, ImageAsset), "Should the image use mips? (Currently unused).");
|
||||
addField("isHDRImage", TypeBool, Offset(mIsHDRImage, ImageAsset), "Is the image in an HDR format? (Currently unused)");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void ImageAsset::copyTo(SimObject* object)
|
||||
{
|
||||
// Call to parent.
|
||||
Parent::copyTo(object);
|
||||
}
|
||||
|
||||
void ImageAsset::loadImage()
|
||||
{
|
||||
SAFE_DELETE(mImage);
|
||||
|
||||
if (mImageFileName)
|
||||
{
|
||||
if (!Platform::isFile(mImageFileName))
|
||||
{
|
||||
Con::errorf("ImageAsset::initializeAsset: Attempted to load file %s but it was not valid!", mImageFileName);
|
||||
return;
|
||||
}
|
||||
|
||||
mImage.set(mImageFileName, &GFXStaticTextureSRGBProfile, avar("%s() - mImage (line %d)", __FUNCTION__, __LINE__));
|
||||
|
||||
if (mImage)
|
||||
{
|
||||
mIsValidImage = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mIsValidImage = false;
|
||||
}
|
||||
|
||||
void ImageAsset::initializeAsset()
|
||||
{
|
||||
loadImage();
|
||||
}
|
||||
|
||||
void ImageAsset::onAssetRefresh()
|
||||
{
|
||||
loadImage();
|
||||
}
|
||||
85
Engine/source/T3D/assets/ImageAsset.h
Normal file
85
Engine/source/T3D/assets/ImageAsset.h
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
#pragma once
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef IMAGE_ASSET_H
|
||||
#define IMAGE_ASSET_H
|
||||
|
||||
#ifndef _ASSET_BASE_H_
|
||||
#include "assets/assetBase.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_DEFINITION_H_
|
||||
#include "assets/assetDefinition.h"
|
||||
#endif
|
||||
|
||||
#ifndef _STRINGUNIT_H_
|
||||
#include "string/stringUnit.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_FIELD_TYPES_H_
|
||||
#include "assets/assetFieldTypes.h"
|
||||
#endif
|
||||
|
||||
#include "gfx/bitmap/gBitmap.h"
|
||||
#include "gfx/gfxTextureHandle.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class ImageAsset : public AssetBase
|
||||
{
|
||||
typedef AssetBase Parent;
|
||||
|
||||
StringTableEntry mImageFileName;
|
||||
|
||||
GFXTexHandle mImage;
|
||||
|
||||
bool mIsValidImage;
|
||||
bool mUseMips;
|
||||
bool mIsHDRImage;
|
||||
|
||||
public:
|
||||
ImageAsset();
|
||||
virtual ~ImageAsset();
|
||||
|
||||
/// Engine.
|
||||
static void initPersistFields();
|
||||
virtual void copyTo(SimObject* object);
|
||||
|
||||
/// Declare Console Object.
|
||||
DECLARE_CONOBJECT(ImageAsset);
|
||||
|
||||
StringTableEntry getImageFileName() { return mImageFileName; }
|
||||
|
||||
bool isValid() { return mIsValidImage; }
|
||||
|
||||
GFXTexHandle* getImage() { return &mImage; }
|
||||
|
||||
protected:
|
||||
virtual void initializeAsset(void);
|
||||
virtual void onAssetRefresh(void);
|
||||
|
||||
void loadImage();
|
||||
};
|
||||
|
||||
DefineConsoleType(TypeImageAssetPtr, ImageAsset)
|
||||
|
||||
#endif
|
||||
|
||||
128
Engine/source/T3D/assets/LevelAsset.cpp
Normal file
128
Engine/source/T3D/assets/LevelAsset.cpp
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef LEVEL_ASSET_H
|
||||
#include "LevelAsset.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_MANAGER_H_
|
||||
#include "assets/assetManager.h"
|
||||
#endif
|
||||
|
||||
#ifndef _CONSOLETYPES_H_
|
||||
#include "console/consoleTypes.h"
|
||||
#endif
|
||||
|
||||
#ifndef _TAML_
|
||||
#include "persistence/taml/taml.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_PTR_H_
|
||||
#include "assets/assetPtr.h"
|
||||
#endif
|
||||
|
||||
// Debug Profiling.
|
||||
#include "platform/profiler.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(LevelAsset);
|
||||
|
||||
ConsoleType(LevelAssetPtr, TypeLevelAssetPtr, LevelAsset, ASSET_ID_FIELD_PREFIX)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleGetType(TypeLevelAssetPtr)
|
||||
{
|
||||
// Fetch asset Id.
|
||||
return (*((AssetPtr<LevelAsset>*)dptr)).getAssetId();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleSetType(TypeLevelAssetPtr)
|
||||
{
|
||||
// Was a single argument specified?
|
||||
if (argc == 1)
|
||||
{
|
||||
// Yes, so fetch field value.
|
||||
const char* pFieldValue = argv[0];
|
||||
|
||||
// Fetch asset pointer.
|
||||
AssetPtr<LevelAsset>* pAssetPtr = dynamic_cast<AssetPtr<LevelAsset>*>((AssetPtrBase*)(dptr));
|
||||
|
||||
// Is the asset pointer the correct type?
|
||||
if (pAssetPtr == NULL)
|
||||
{
|
||||
// No, so fail.
|
||||
//Con::warnf("(TypeLevelAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set asset.
|
||||
pAssetPtr->setAssetId(pFieldValue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Warn.
|
||||
Con::warnf("(TypeLevelAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
LevelAsset::LevelAsset() : AssetBase(), mIsSubLevel(false)
|
||||
{
|
||||
mLevelFile = StringTable->EmptyString();
|
||||
mPreviewImage = StringTable->EmptyString();
|
||||
|
||||
mMainLevelAsset = StringTable->EmptyString();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
LevelAsset::~LevelAsset()
|
||||
{
|
||||
// If the asset manager does not own the asset then we own the
|
||||
// asset definition so delete it.
|
||||
if (!getOwned())
|
||||
delete mpAssetDefinition;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void LevelAsset::initPersistFields()
|
||||
{
|
||||
// Call parent.
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("LevelFile", TypeString, Offset(mLevelFile, LevelAsset), "Path to the actual level file.");
|
||||
addField("PreviewImage", TypeString, Offset(mPreviewImage, LevelAsset), "Path to the image used for selection preview.");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void LevelAsset::copyTo(SimObject* object)
|
||||
{
|
||||
// Call to parent.
|
||||
Parent::copyTo(object);
|
||||
}
|
||||
72
Engine/source/T3D/assets/LevelAsset.h
Normal file
72
Engine/source/T3D/assets/LevelAsset.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#pragma once
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef LEVEL_ASSET_H
|
||||
#define LEVEL_ASSET_H
|
||||
|
||||
#ifndef _ASSET_BASE_H_
|
||||
#include "assets/assetBase.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_DEFINITION_H_
|
||||
#include "assets/assetDefinition.h"
|
||||
#endif
|
||||
|
||||
#ifndef _STRINGUNIT_H_
|
||||
#include "string/stringUnit.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_FIELD_TYPES_H_
|
||||
#include "assets/assetFieldTypes.h"
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class LevelAsset : public AssetBase
|
||||
{
|
||||
typedef AssetBase Parent;
|
||||
|
||||
StringTableEntry mLevelFile;
|
||||
StringTableEntry mPreviewImage;
|
||||
|
||||
bool mIsSubLevel;
|
||||
StringTableEntry mMainLevelAsset;
|
||||
|
||||
public:
|
||||
LevelAsset();
|
||||
virtual ~LevelAsset();
|
||||
|
||||
/// Engine.
|
||||
static void initPersistFields();
|
||||
virtual void copyTo(SimObject* object);
|
||||
|
||||
/// Declare Console Object.
|
||||
DECLARE_CONOBJECT(LevelAsset);
|
||||
|
||||
protected:
|
||||
virtual void initializeAsset(void) {}
|
||||
virtual void onAssetRefresh(void) {}
|
||||
};
|
||||
|
||||
DefineConsoleType(TypeLevelAssetPtr, LevelAsset)
|
||||
|
||||
#endif // _ASSET_BASE_H_
|
||||
|
||||
241
Engine/source/T3D/assets/MaterialAsset.cpp
Normal file
241
Engine/source/T3D/assets/MaterialAsset.cpp
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef MATERIALASSET_H
|
||||
#include "MaterialAsset.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_MANAGER_H_
|
||||
#include "assets/assetManager.h"
|
||||
#endif
|
||||
|
||||
#ifndef _CONSOLETYPES_H_
|
||||
#include "console/consoleTypes.h"
|
||||
#endif
|
||||
|
||||
#ifndef _TAML_
|
||||
#include "persistence/taml/taml.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_PTR_H_
|
||||
#include "assets/assetPtr.h"
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(MaterialAsset);
|
||||
|
||||
ConsoleType(MaterialAssetPtr, TypeMaterialAssetPtr, MaterialAsset, ASSET_ID_FIELD_PREFIX)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleGetType(TypeMaterialAssetPtr)
|
||||
{
|
||||
// Fetch asset Id.
|
||||
return (*((AssetPtr<MaterialAsset>*)dptr)).getAssetId();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleSetType(TypeMaterialAssetPtr)
|
||||
{
|
||||
// Was a single argument specified?
|
||||
if (argc == 1)
|
||||
{
|
||||
// Yes, so fetch field value.
|
||||
const char* pFieldValue = argv[0];
|
||||
|
||||
// Fetch asset pointer.
|
||||
AssetPtr<MaterialAsset>* pAssetPtr = dynamic_cast<AssetPtr<MaterialAsset>*>((AssetPtrBase*)(dptr));
|
||||
|
||||
// Is the asset pointer the correct type?
|
||||
if (pAssetPtr == NULL)
|
||||
{
|
||||
// No, so fail.
|
||||
//Con::warnf("(TypeMaterialAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set asset.
|
||||
pAssetPtr->setAssetId(pFieldValue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Warn.
|
||||
Con::warnf("(TypeMaterialAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
MaterialAsset::MaterialAsset()
|
||||
{
|
||||
mShaderGraphFile = "";
|
||||
mScriptFile = "";
|
||||
mMatDefinitionName = "";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
MaterialAsset::~MaterialAsset()
|
||||
{
|
||||
// If the asset manager does not own the asset then we own the
|
||||
// asset definition so delete it.
|
||||
if (!getOwned())
|
||||
delete mpAssetDefinition;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void MaterialAsset::initPersistFields()
|
||||
{
|
||||
// Call parent.
|
||||
Parent::initPersistFields();
|
||||
|
||||
//addField("shaderGraph", TypeRealString, Offset(mShaderGraphFile, MaterialAsset), "");
|
||||
addField("scriptFile", TypeRealString, Offset(mScriptFile, MaterialAsset), "Path to the file containing the material definition.");
|
||||
addField("materialDefinitionName", TypeRealString, Offset(mMatDefinitionName, MaterialAsset), "Name of the material definition this asset is for.");
|
||||
}
|
||||
|
||||
void MaterialAsset::initializeAsset()
|
||||
{
|
||||
// Call parent.
|
||||
Parent::initializeAsset();
|
||||
|
||||
compileShader();
|
||||
|
||||
if (Platform::isFile(mScriptFile))
|
||||
Con::executeFile(mScriptFile, false, false);
|
||||
}
|
||||
|
||||
void MaterialAsset::onAssetRefresh()
|
||||
{
|
||||
if (Platform::isFile(mScriptFile))
|
||||
Con::executeFile(mScriptFile, false, false);
|
||||
|
||||
if (!mMatDefinitionName.isEmpty())
|
||||
{
|
||||
Material* matDef;
|
||||
if (!Sim::findObject(mMatDefinitionName.c_str(), matDef))
|
||||
{
|
||||
Con::errorf("MaterialAsset: Unable to find the Material %s", mMatDefinitionName.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
matDef->reload();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void MaterialAsset::compileShader()
|
||||
{
|
||||
}
|
||||
|
||||
void MaterialAsset::copyTo(SimObject* object)
|
||||
{
|
||||
// Call to parent.
|
||||
Parent::copyTo(object);
|
||||
}
|
||||
|
||||
DefineEngineMethod(MaterialAsset, compileShader, void, (), , "Compiles the material's generated shader, if any. Not yet implemented\n")
|
||||
{
|
||||
object->compileShader();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorTypeAssetId
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorTypeMaterialAssetPtr);
|
||||
|
||||
ConsoleDocClass(GuiInspectorTypeMaterialAssetPtr,
|
||||
"@brief Inspector field type for Material Asset Objects\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
void GuiInspectorTypeMaterialAssetPtr::consoleInit()
|
||||
{
|
||||
Parent::consoleInit();
|
||||
|
||||
ConsoleBaseType::getType(TypeMaterialAssetPtr)->setInspectorFieldType("GuiInspectorTypeMaterialAssetPtr");
|
||||
}
|
||||
|
||||
GuiControl* GuiInspectorTypeMaterialAssetPtr::constructEditControl()
|
||||
{
|
||||
// Create base filename edit controls
|
||||
GuiControl *retCtrl = Parent::constructEditControl();
|
||||
if (retCtrl == NULL)
|
||||
return retCtrl;
|
||||
|
||||
// Change filespec
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"MaterialAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
|
||||
mInspector->getComponentGroupTargetId(), mCaption);
|
||||
mBrowseButton->setField("Command", szBuffer);
|
||||
|
||||
// Create "Open in ShapeEditor" button
|
||||
mSMEdButton = new GuiBitmapButtonCtrl();
|
||||
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "echo(\"Game Object Editor not implemented yet!\");", retCtrl->getId());
|
||||
mSMEdButton->setField("Command", szBuffer);
|
||||
|
||||
char bitmapName[512] = "tools/worldEditor/images/toolbar/shape-editor";
|
||||
mSMEdButton->setBitmap(bitmapName);
|
||||
|
||||
mSMEdButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
|
||||
mSMEdButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
|
||||
mSMEdButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
|
||||
mSMEdButton->setDataField(StringTable->insert("tooltip"), NULL, "Open this file in the Material Editor");
|
||||
|
||||
mSMEdButton->registerObject();
|
||||
addObject(mSMEdButton);
|
||||
|
||||
return retCtrl;
|
||||
}
|
||||
|
||||
bool GuiInspectorTypeMaterialAssetPtr::updateRects()
|
||||
{
|
||||
S32 dividerPos, dividerMargin;
|
||||
mInspector->getDivider(dividerPos, dividerMargin);
|
||||
Point2I fieldExtent = getExtent();
|
||||
Point2I fieldPos = getPosition();
|
||||
|
||||
mCaptionRect.set(0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y);
|
||||
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y);
|
||||
|
||||
bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
|
||||
if (mBrowseButton != NULL)
|
||||
{
|
||||
mBrowseRect.set(fieldExtent.x - 32, 2, 14, fieldExtent.y - 4);
|
||||
resized |= mBrowseButton->resize(mBrowseRect.point, mBrowseRect.extent);
|
||||
}
|
||||
|
||||
if (mSMEdButton != NULL)
|
||||
{
|
||||
RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4);
|
||||
resized |= mSMEdButton->resize(shapeEdRect.point, shapeEdRect.extent);
|
||||
}
|
||||
|
||||
return resized;
|
||||
}
|
||||
101
Engine/source/T3D/assets/MaterialAsset.h
Normal file
101
Engine/source/T3D/assets/MaterialAsset.h
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef MATERIALASSET_H
|
||||
#define MATERIALASSET_H
|
||||
|
||||
#ifndef _ASSET_BASE_H_
|
||||
#include "assets/assetBase.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_DEFINITION_H_
|
||||
#include "assets/assetDefinition.h"
|
||||
#endif
|
||||
|
||||
#ifndef _STRINGUNIT_H_
|
||||
#include "string/stringUnit.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_FIELD_TYPES_H_
|
||||
#include "assets/assetFieldTypes.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GFXDEVICE_H_
|
||||
#include "gfx/gfxDevice.h"
|
||||
#endif
|
||||
|
||||
#ifndef _GUI_INSPECTOR_TYPES_H_
|
||||
#include "gui/editor/guiInspectorTypes.h"
|
||||
#endif
|
||||
|
||||
#include "materials/matTextureTarget.h"
|
||||
#include "materials/materialDefinition.h"
|
||||
#include "materials/customMaterialDefinition.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class MaterialAsset : public AssetBase
|
||||
{
|
||||
typedef AssetBase Parent;
|
||||
|
||||
String mShaderGraphFile;
|
||||
String mScriptFile;
|
||||
String mMatDefinitionName;
|
||||
|
||||
public:
|
||||
MaterialAsset();
|
||||
virtual ~MaterialAsset();
|
||||
|
||||
/// Engine.
|
||||
static void initPersistFields();
|
||||
virtual void copyTo(SimObject* object);
|
||||
|
||||
virtual void initializeAsset();
|
||||
virtual void onAssetRefresh(void);
|
||||
|
||||
void compileShader();
|
||||
|
||||
String getMaterialDefinitionName() { return mMatDefinitionName; }
|
||||
|
||||
/// Declare Console Object.
|
||||
DECLARE_CONOBJECT(MaterialAsset);
|
||||
};
|
||||
|
||||
DefineConsoleType(TypeMaterialAssetPtr, MaterialAsset)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeAssetId GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeMaterialAssetPtr : public GuiInspectorTypeFileName
|
||||
{
|
||||
typedef GuiInspectorTypeFileName Parent;
|
||||
public:
|
||||
|
||||
GuiBitmapButtonCtrl *mSMEdButton;
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeMaterialAssetPtr);
|
||||
static void consoleInit();
|
||||
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual bool updateRects();
|
||||
};
|
||||
|
||||
#endif // _ASSET_BASE_H_
|
||||
|
||||
205
Engine/source/T3D/assets/ParticleAsset.cpp
Normal file
205
Engine/source/T3D/assets/ParticleAsset.cpp
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef PARTICLE_ASSET_H
|
||||
#include "ParticleAsset.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_MANAGER_H_
|
||||
#include "assets/assetManager.h"
|
||||
#endif
|
||||
|
||||
#ifndef _CONSOLETYPES_H_
|
||||
#include "console/consoleTypes.h"
|
||||
#endif
|
||||
|
||||
#ifndef _TAML_
|
||||
#include "persistence/taml/taml.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_PTR_H_
|
||||
#include "assets/assetPtr.h"
|
||||
#endif
|
||||
|
||||
// Debug Profiling.
|
||||
#include "platform/profiler.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(ParticleAsset);
|
||||
|
||||
ConsoleType(ParticleAssetPtr, TypeParticleAssetPtr, ParticleAsset, ASSET_ID_FIELD_PREFIX)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleGetType(TypeParticleAssetPtr)
|
||||
{
|
||||
// Fetch asset Id.
|
||||
return (*((AssetPtr<ParticleAsset>*)dptr)).getAssetId();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleSetType(TypeParticleAssetPtr)
|
||||
{
|
||||
// Was a single argument specified?
|
||||
if (argc == 1)
|
||||
{
|
||||
// Yes, so fetch field value.
|
||||
const char* pFieldValue = argv[0];
|
||||
|
||||
// Fetch asset pointer.
|
||||
AssetPtr<ParticleAsset>* pAssetPtr = dynamic_cast<AssetPtr<ParticleAsset>*>((AssetPtrBase*)(dptr));
|
||||
|
||||
// Is the asset pointer the correct type?
|
||||
if (pAssetPtr == NULL)
|
||||
{
|
||||
// No, so fail.
|
||||
//Con::warnf("(TypeParticleAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set asset.
|
||||
pAssetPtr->setAssetId(pFieldValue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Warn.
|
||||
Con::warnf("(TypeParticleAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ParticleAsset::ParticleAsset()
|
||||
{
|
||||
mScriptFilePath = StringTable->EmptyString();
|
||||
mDatablockFilePath = StringTable->EmptyString();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ParticleAsset::~ParticleAsset()
|
||||
{
|
||||
// If the asset manager does not own the asset then we own the
|
||||
// asset definition so delete it.
|
||||
if (!getOwned())
|
||||
delete mpAssetDefinition;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ParticleAsset::initPersistFields()
|
||||
{
|
||||
// Call parent.
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("scriptFilePath", TypeString, Offset(mScriptFilePath, ParticleAsset), "Path to the script file for the particle effect");
|
||||
addField("DatablockFilePath", TypeString, Offset(mDatablockFilePath, ParticleAsset), "Path to the datablock file");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void ParticleAsset::copyTo(SimObject* object)
|
||||
{
|
||||
// Call to parent.
|
||||
Parent::copyTo(object);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorTypeAssetId
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorTypeParticleAssetPtr);
|
||||
|
||||
ConsoleDocClass(GuiInspectorTypeParticleAssetPtr,
|
||||
"@brief Inspector field type for Partial Asset Objects\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
void GuiInspectorTypeParticleAssetPtr::consoleInit()
|
||||
{
|
||||
Parent::consoleInit();
|
||||
|
||||
ConsoleBaseType::getType(TypeParticleAssetPtr)->setInspectorFieldType("GuiInspectorTypeParticleAssetPtr");
|
||||
}
|
||||
|
||||
GuiControl* GuiInspectorTypeParticleAssetPtr::constructEditControl()
|
||||
{
|
||||
// Create base filename edit controls
|
||||
GuiControl *retCtrl = Parent::constructEditControl();
|
||||
if (retCtrl == NULL)
|
||||
return retCtrl;
|
||||
|
||||
// Change filespec
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"ParticleAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
|
||||
mInspector->getComponentGroupTargetId(), mCaption);
|
||||
mBrowseButton->setField("Command", szBuffer);
|
||||
|
||||
// Create "Open in ShapeEditor" button
|
||||
mSMEdButton = new GuiBitmapButtonCtrl();
|
||||
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "echo(\"Game Object Editor not implemented yet!\");", retCtrl->getId());
|
||||
mSMEdButton->setField("Command", szBuffer);
|
||||
|
||||
char bitmapName[512] = "tools/worldEditor/images/toolbar/shape-editor";
|
||||
mSMEdButton->setBitmap(bitmapName);
|
||||
|
||||
mSMEdButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
|
||||
mSMEdButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
|
||||
mSMEdButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
|
||||
mSMEdButton->setDataField(StringTable->insert("tooltip"), NULL, "Open this file in the State Machine Editor");
|
||||
|
||||
mSMEdButton->registerObject();
|
||||
addObject(mSMEdButton);
|
||||
|
||||
return retCtrl;
|
||||
}
|
||||
|
||||
bool GuiInspectorTypeParticleAssetPtr::updateRects()
|
||||
{
|
||||
S32 dividerPos, dividerMargin;
|
||||
mInspector->getDivider(dividerPos, dividerMargin);
|
||||
Point2I fieldExtent = getExtent();
|
||||
Point2I fieldPos = getPosition();
|
||||
|
||||
mCaptionRect.set(0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y);
|
||||
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y);
|
||||
|
||||
bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
|
||||
if (mBrowseButton != NULL)
|
||||
{
|
||||
mBrowseRect.set(fieldExtent.x - 32, 2, 14, fieldExtent.y - 4);
|
||||
resized |= mBrowseButton->resize(mBrowseRect.point, mBrowseRect.extent);
|
||||
}
|
||||
|
||||
if (mSMEdButton != NULL)
|
||||
{
|
||||
RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4);
|
||||
resized |= mSMEdButton->resize(shapeEdRect.point, shapeEdRect.extent);
|
||||
}
|
||||
|
||||
return resized;
|
||||
}
|
||||
89
Engine/source/T3D/assets/ParticleAsset.h
Normal file
89
Engine/source/T3D/assets/ParticleAsset.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#pragma once
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef PARTICLE_ASSET_H
|
||||
#define PARTICLE_ASSET_H
|
||||
|
||||
#ifndef _ASSET_BASE_H_
|
||||
#include "assets/assetBase.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_DEFINITION_H_
|
||||
#include "assets/assetDefinition.h"
|
||||
#endif
|
||||
|
||||
#ifndef _STRINGUNIT_H_
|
||||
#include "string/stringUnit.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_FIELD_TYPES_H_
|
||||
#include "assets/assetFieldTypes.h"
|
||||
#endif
|
||||
|
||||
#include "gui/editor/guiInspectorTypes.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class ParticleAsset : public AssetBase
|
||||
{
|
||||
typedef AssetBase Parent;
|
||||
|
||||
StringTableEntry mScriptFilePath;
|
||||
StringTableEntry mDatablockFilePath;
|
||||
|
||||
public:
|
||||
ParticleAsset();
|
||||
virtual ~ParticleAsset();
|
||||
|
||||
/// Engine.
|
||||
static void initPersistFields();
|
||||
virtual void copyTo(SimObject* object);
|
||||
|
||||
/// Declare Console Object.
|
||||
DECLARE_CONOBJECT(ParticleAsset);
|
||||
|
||||
protected:
|
||||
virtual void initializeAsset(void) {}
|
||||
virtual void onAssetRefresh(void) {}
|
||||
};
|
||||
|
||||
DefineConsoleType(TypeParticleAssetPtr, ParticleAsset)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeAssetId GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeParticleAssetPtr : public GuiInspectorTypeFileName
|
||||
{
|
||||
typedef GuiInspectorTypeFileName Parent;
|
||||
public:
|
||||
|
||||
GuiBitmapButtonCtrl *mSMEdButton;
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeParticleAssetPtr);
|
||||
static void consoleInit();
|
||||
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual bool updateRects();
|
||||
};
|
||||
|
||||
#endif // _ASSET_BASE_H_
|
||||
|
||||
129
Engine/source/T3D/assets/PostEffectAsset.cpp
Normal file
129
Engine/source/T3D/assets/PostEffectAsset.cpp
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef POSTEFFECT_ASSET_H
|
||||
#include "PostEffectAsset.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_MANAGER_H_
|
||||
#include "assets/assetManager.h"
|
||||
#endif
|
||||
|
||||
#ifndef _CONSOLETYPES_H_
|
||||
#include "console/consoleTypes.h"
|
||||
#endif
|
||||
|
||||
#ifndef _TAML_
|
||||
#include "persistence/taml/taml.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_PTR_H_
|
||||
#include "assets/assetPtr.h"
|
||||
#endif
|
||||
|
||||
// Debug Profiling.
|
||||
#include "platform/profiler.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(PostEffectAsset);
|
||||
|
||||
ConsoleType(PostEffectAssetPtr, TypePostEffectAssetPtr, PostEffectAsset, ASSET_ID_FIELD_PREFIX)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleGetType(TypePostEffectAssetPtr)
|
||||
{
|
||||
// Fetch asset Id.
|
||||
return (*((AssetPtr<PostEffectAsset>*)dptr)).getAssetId();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleSetType(TypePostEffectAssetPtr)
|
||||
{
|
||||
// Was a single argument specified?
|
||||
if (argc == 1)
|
||||
{
|
||||
// Yes, so fetch field value.
|
||||
const char* pFieldValue = argv[0];
|
||||
|
||||
// Fetch asset pointer.
|
||||
AssetPtr<PostEffectAsset>* pAssetPtr = dynamic_cast<AssetPtr<PostEffectAsset>*>((AssetPtrBase*)(dptr));
|
||||
|
||||
// Is the asset pointer the correct type?
|
||||
if (pAssetPtr == NULL)
|
||||
{
|
||||
// No, so fail.
|
||||
//Con::warnf("(TypePostEffectAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set asset.
|
||||
pAssetPtr->setAssetId(pFieldValue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Warn.
|
||||
Con::warnf("(TypePostEffectAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PostEffectAsset::PostEffectAsset()
|
||||
{
|
||||
mScriptFile = StringTable->EmptyString();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PostEffectAsset::~PostEffectAsset()
|
||||
{
|
||||
// If the asset manager does not own the asset then we own the
|
||||
// asset definition so delete it.
|
||||
if (!getOwned())
|
||||
delete mpAssetDefinition;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void PostEffectAsset::initPersistFields()
|
||||
{
|
||||
// Call parent.
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("scriptFile", TypeString, Offset(mScriptFile, PostEffectAsset), "Path to the script file.");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void PostEffectAsset::copyTo(SimObject* object)
|
||||
{
|
||||
// Call to parent.
|
||||
Parent::copyTo(object);
|
||||
}
|
||||
|
||||
void PostEffectAsset::initializeAsset()
|
||||
{
|
||||
//mPostEffect = new PostEffect();
|
||||
}
|
||||
71
Engine/source/T3D/assets/PostEffectAsset.h
Normal file
71
Engine/source/T3D/assets/PostEffectAsset.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#pragma once
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef POSTEFFECT_ASSET_H
|
||||
#define POSTEFFECT_ASSET_H
|
||||
|
||||
#ifndef _ASSET_BASE_H_
|
||||
#include "assets/assetBase.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_DEFINITION_H_
|
||||
#include "assets/assetDefinition.h"
|
||||
#endif
|
||||
|
||||
#ifndef _STRINGUNIT_H_
|
||||
#include "string/stringUnit.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_FIELD_TYPES_H_
|
||||
#include "assets/assetFieldTypes.h"
|
||||
#endif
|
||||
|
||||
#include "postFx/postEffect.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class PostEffectAsset : public AssetBase
|
||||
{
|
||||
typedef AssetBase Parent;
|
||||
|
||||
StringTableEntry mScriptFile;
|
||||
|
||||
public:
|
||||
PostEffectAsset();
|
||||
virtual ~PostEffectAsset();
|
||||
|
||||
/// Engine.
|
||||
static void initPersistFields();
|
||||
virtual void copyTo(SimObject* object);
|
||||
|
||||
virtual void initializeAsset();
|
||||
|
||||
/// Declare Console Object.
|
||||
DECLARE_CONOBJECT(PostEffectAsset);
|
||||
|
||||
protected:
|
||||
virtual void onAssetRefresh(void) {}
|
||||
};
|
||||
|
||||
DefineConsoleType(TypePostEffectAssetPtr, PostEffectAsset)
|
||||
|
||||
#endif // _ASSET_BASE_H_
|
||||
|
||||
137
Engine/source/T3D/assets/ScriptAsset.cpp
Normal file
137
Engine/source/T3D/assets/ScriptAsset.cpp
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef SCRIPT_ASSET_H
|
||||
#include "ScriptAsset.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_MANAGER_H_
|
||||
#include "assets/assetManager.h"
|
||||
#endif
|
||||
|
||||
#ifndef _CONSOLETYPES_H_
|
||||
#include "console/consoleTypes.h"
|
||||
#endif
|
||||
|
||||
#ifndef _TAML_
|
||||
#include "persistence/taml/taml.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_PTR_H_
|
||||
#include "assets/assetPtr.h"
|
||||
#endif
|
||||
|
||||
// Debug Profiling.
|
||||
#include "platform/profiler.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(ScriptAsset);
|
||||
|
||||
ConsoleType(ScriptAssetPtr, TypeScriptAssetPtr, ScriptAsset, ASSET_ID_FIELD_PREFIX)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleGetType(TypeScriptAssetPtr)
|
||||
{
|
||||
// Fetch asset Id.
|
||||
return (*((AssetPtr<ScriptAsset>*)dptr)).getAssetId();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleSetType(TypeScriptAssetPtr)
|
||||
{
|
||||
// Was a single argument specified?
|
||||
if (argc == 1)
|
||||
{
|
||||
// Yes, so fetch field value.
|
||||
const char* pFieldValue = argv[0];
|
||||
|
||||
// Fetch asset pointer.
|
||||
AssetPtr<ScriptAsset>* pAssetPtr = dynamic_cast<AssetPtr<ScriptAsset>*>((AssetPtrBase*)(dptr));
|
||||
|
||||
// Is the asset pointer the correct type?
|
||||
if (pAssetPtr == NULL)
|
||||
{
|
||||
// No, so fail.
|
||||
//Con::warnf("(TypeScriptAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set asset.
|
||||
pAssetPtr->setAssetId(pFieldValue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Warn.
|
||||
Con::warnf("(TypeScriptAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ScriptAsset::ScriptAsset() : AssetBase(), mIsServerSide(true)
|
||||
{
|
||||
mScriptFilePath = StringTable->EmptyString();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ScriptAsset::~ScriptAsset()
|
||||
{
|
||||
// If the asset manager does not own the asset then we own the
|
||||
// asset definition so delete it.
|
||||
if (!getOwned())
|
||||
delete mpAssetDefinition;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ScriptAsset::initPersistFields()
|
||||
{
|
||||
// Call parent.
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("scriptFilePath", TypeString, Offset(mScriptFilePath, ScriptAsset), "Path to the script file.");
|
||||
addField("isServerSide", TypeBool, Offset(mIsServerSide, ScriptAsset), "Is this script file to be run on the server side?");
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void ScriptAsset::copyTo(SimObject* object)
|
||||
{
|
||||
// Call to parent.
|
||||
Parent::copyTo(object);
|
||||
}
|
||||
|
||||
void ScriptAsset::initializeAsset()
|
||||
{
|
||||
if (Platform::isFile(mScriptFilePath))
|
||||
Con::executeFile(mScriptFilePath, false, false);
|
||||
}
|
||||
|
||||
void ScriptAsset::onAssetRefresh()
|
||||
{
|
||||
if (Platform::isFile(mScriptFilePath))
|
||||
Con::executeFile(mScriptFilePath, false, false);
|
||||
}
|
||||
69
Engine/source/T3D/assets/ScriptAsset.h
Normal file
69
Engine/source/T3D/assets/ScriptAsset.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef SCRIPT_ASSET_H
|
||||
#define SCRIPT_ASSET_H
|
||||
#pragma once
|
||||
|
||||
#ifndef _ASSET_BASE_H_
|
||||
#include "assets/assetBase.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_DEFINITION_H_
|
||||
#include "assets/assetDefinition.h"
|
||||
#endif
|
||||
|
||||
#ifndef _STRINGUNIT_H_
|
||||
#include "string/stringUnit.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_FIELD_TYPES_H_
|
||||
#include "assets/assetFieldTypes.h"
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class ScriptAsset : public AssetBase
|
||||
{
|
||||
typedef AssetBase Parent;
|
||||
|
||||
StringTableEntry mScriptFilePath;
|
||||
bool mIsServerSide;
|
||||
|
||||
public:
|
||||
ScriptAsset();
|
||||
virtual ~ScriptAsset();
|
||||
|
||||
/// Engine.
|
||||
static void initPersistFields();
|
||||
virtual void copyTo(SimObject* object);
|
||||
|
||||
/// Declare Console Object.
|
||||
DECLARE_CONOBJECT(ScriptAsset);
|
||||
|
||||
protected:
|
||||
virtual void initializeAsset(void);
|
||||
virtual void onAssetRefresh(void);
|
||||
};
|
||||
|
||||
DefineConsoleType(TypeScriptAssetPtr, ScriptAsset)
|
||||
|
||||
#endif // _ASSET_BASE_H_
|
||||
|
||||
175
Engine/source/T3D/assets/ShapeAnimationAsset.cpp
Normal file
175
Engine/source/T3D/assets/ShapeAnimationAsset.cpp
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef SHAPE_ANIMATION_ASSET_H
|
||||
#include "ShapeAnimationAsset.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_MANAGER_H_
|
||||
#include "assets/assetManager.h"
|
||||
#endif
|
||||
|
||||
#ifndef _CONSOLETYPES_H_
|
||||
#include "console/consoleTypes.h"
|
||||
#endif
|
||||
|
||||
#ifndef _TAML_
|
||||
#include "persistence/taml/taml.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_PTR_H_
|
||||
#include "assets/assetPtr.h"
|
||||
#endif
|
||||
|
||||
#include "core/resourceManager.h"
|
||||
|
||||
// Debug Profiling.
|
||||
#include "platform/profiler.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(ShapeAnimationAsset);
|
||||
|
||||
ConsoleType(ShapeAnimationAssetPtr, TypeShapeAnimationAssetPtr, ShapeAnimationAsset, ASSET_ID_FIELD_PREFIX)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleGetType(TypeShapeAnimationAssetPtr)
|
||||
{
|
||||
// Fetch asset Id.
|
||||
return (*((AssetPtr<ShapeAnimationAsset>*)dptr)).getAssetId();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleSetType(TypeShapeAnimationAssetPtr)
|
||||
{
|
||||
// Was a single argument specified?
|
||||
if (argc == 1)
|
||||
{
|
||||
// Yes, so fetch field value.
|
||||
const char* pFieldValue = argv[0];
|
||||
|
||||
// Fetch asset pointer.
|
||||
AssetPtr<ShapeAnimationAsset>* pAssetPtr = dynamic_cast<AssetPtr<ShapeAnimationAsset>*>((AssetPtrBase*)(dptr));
|
||||
|
||||
// Is the asset pointer the correct type?
|
||||
if (pAssetPtr == NULL)
|
||||
{
|
||||
// No, so fail.
|
||||
//Con::warnf("(TypeShapeAnimationAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set asset.
|
||||
pAssetPtr->setAssetId(pFieldValue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Warn.
|
||||
Con::warnf("(TypeShapeAnimationAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ShapeAnimationAsset::ShapeAnimationAsset() :
|
||||
mIsEmbedded(false), mIsCyclical(true), mIsBlend(false), mBlendFrame(0), mStartFrame(0), mEndFrame(-1), mPadRotation(true), mPadTransforms(false)
|
||||
{
|
||||
mFileName = StringTable->EmptyString();
|
||||
mAnimationName = StringTable->EmptyString();
|
||||
|
||||
mBlendAnimAssetName = StringTable->EmptyString();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ShapeAnimationAsset::~ShapeAnimationAsset()
|
||||
{
|
||||
// If the asset manager does not own the asset then we own the
|
||||
// asset definition so delete it.
|
||||
if (!getOwned())
|
||||
delete mpAssetDefinition;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ShapeAnimationAsset::initPersistFields()
|
||||
{
|
||||
// Call parent.
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("animationFile", TypeFilename, Offset(mFileName, ShapeAnimationAsset), "Path to the file name containing the animation");
|
||||
addField("animationName", TypeString, Offset(mAnimationName, ShapeAnimationAsset), "Name of the animation");
|
||||
|
||||
addField("isEmbedded", TypeBool, Offset(mIsEmbedded, ShapeAnimationAsset), "If true, this animation asset just referrs to an embedded animation of a regular shape mesh. If false, it is a self-contained animation file");
|
||||
|
||||
addField("isCyclic", TypeBool, Offset(mIsCyclical, ShapeAnimationAsset), "Is this animation looping?");
|
||||
|
||||
addField("isBlend", TypeBool, Offset(mIsBlend, ShapeAnimationAsset), "Is this animation blended with another?");
|
||||
addField("blendRefAnimation", TypeString, Offset(mBlendAnimAssetName, ShapeAnimationAsset), "AssetID of the animation to reference for our blending");
|
||||
addField("blendFrame", TypeS32, Offset(mBlendFrame, ShapeAnimationAsset), "Which frame of the reference animation do we use for our blending");
|
||||
|
||||
addField("startFrame", TypeS32, Offset(mStartFrame, ShapeAnimationAsset), "What frame does this animation clip start on");
|
||||
addField("endFrame", TypeS32, Offset(mEndFrame, ShapeAnimationAsset), "What fram does this animation clip end on");
|
||||
addField("padRotation", TypeBool, Offset(mPadRotation, ShapeAnimationAsset), "Are the rotation values padded");
|
||||
addField("padTransforms", TypeBool, Offset(mPadTransforms, ShapeAnimationAsset), "Are the transform values padded");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void ShapeAnimationAsset::copyTo(SimObject* object)
|
||||
{
|
||||
// Call to parent.
|
||||
Parent::copyTo(object);
|
||||
}
|
||||
|
||||
void ShapeAnimationAsset::initializeAsset(void)
|
||||
{
|
||||
if (!mIsEmbedded)
|
||||
{
|
||||
//If we're not embedded, we need to load in our initial shape and do some prepwork
|
||||
|
||||
char filenameBuf[1024];
|
||||
Con::expandScriptFilename(filenameBuf, sizeof(filenameBuf), mFileName);
|
||||
|
||||
mSourceShape = ResourceManager::get().load(filenameBuf);
|
||||
|
||||
if (!mSourceShape->addSequence("ambient", "", mAnimationName, mStartFrame, mEndFrame, mPadRotation, mPadTransforms))
|
||||
{
|
||||
Con::errorf("ShapeAnimationAsset::initializeAsset - Unable to do initial setup of the animation clip named %s for asset %s", mAnimationName, getAssetName());
|
||||
return;
|
||||
}
|
||||
|
||||
S32 sequenceId = mSourceShape->findSequence(mAnimationName);
|
||||
|
||||
if(mIsCyclical)
|
||||
mSourceShape->sequences[sequenceId].flags |= TSShape::Cyclic;
|
||||
else
|
||||
mSourceShape->sequences[sequenceId].flags &= (~(TSShape::Cyclic));
|
||||
}
|
||||
}
|
||||
|
||||
void ShapeAnimationAsset::onAssetRefresh(void)
|
||||
{
|
||||
|
||||
}
|
||||
126
Engine/source/T3D/assets/ShapeAnimationAsset.h
Normal file
126
Engine/source/T3D/assets/ShapeAnimationAsset.h
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef SHAPE_ANIMATION_ASSET_H
|
||||
#define SHAPE_ANIMATION_ASSET_H
|
||||
|
||||
#ifndef _ASSET_BASE_H_
|
||||
#include "assets/assetBase.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_DEFINITION_H_
|
||||
#include "assets/assetDefinition.h"
|
||||
#endif
|
||||
|
||||
#ifndef _STRINGUNIT_H_
|
||||
#include "string/stringUnit.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_FIELD_TYPES_H_
|
||||
#include "assets/assetFieldTypes.h"
|
||||
#endif
|
||||
#ifndef _TSSHAPE_H_
|
||||
#include "ts/tsShape.h"
|
||||
#endif
|
||||
#ifndef __RESOURCE_H__
|
||||
#include "core/resource.h"
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class ShapeAnimationAsset : public AssetBase
|
||||
{
|
||||
typedef AssetBase Parent;
|
||||
|
||||
protected:
|
||||
StringTableEntry mFileName;
|
||||
|
||||
bool mIsEmbedded;
|
||||
bool mIsCyclical;
|
||||
|
||||
bool mIsBlend;
|
||||
|
||||
StringTableEntry mBlendAnimAssetName;
|
||||
|
||||
S32 mBlendFrame;
|
||||
|
||||
//
|
||||
StringTableEntry mAnimationName;
|
||||
S32 mStartFrame;
|
||||
S32 mEndFrame;
|
||||
bool mPadRotation;
|
||||
bool mPadTransforms;
|
||||
|
||||
Resource<TSShape> mSourceShape;
|
||||
|
||||
public:
|
||||
ShapeAnimationAsset();
|
||||
virtual ~ShapeAnimationAsset();
|
||||
|
||||
/// Engine.
|
||||
static void initPersistFields();
|
||||
virtual void copyTo(SimObject* object);
|
||||
|
||||
/// Declare Console Object.
|
||||
DECLARE_CONOBJECT(ShapeAnimationAsset);
|
||||
|
||||
protected:
|
||||
virtual void initializeAsset(void);
|
||||
virtual void onAssetRefresh(void);
|
||||
|
||||
public:
|
||||
StringTableEntry getAnimationFilename() { return mFileName; }
|
||||
StringTableEntry getAnimationName() { return mAnimationName; }
|
||||
StringTableEntry getBlendAnimationName() { return mBlendAnimAssetName; }
|
||||
|
||||
S32 getStartFrame() { return mStartFrame; }
|
||||
S32 getEndFrame() { return mEndFrame; }
|
||||
|
||||
bool getPadRotation() { return mPadRotation; }
|
||||
bool getPadTransforms() { return mPadTransforms; }
|
||||
|
||||
bool isEmbedded() { return mIsEmbedded; }
|
||||
bool isCyclic() { return mIsCyclical; }
|
||||
bool isBlend() { return mIsBlend; }
|
||||
|
||||
S32 getBlendFrame() { return mBlendFrame; }
|
||||
};
|
||||
|
||||
DefineConsoleType(TypeShapeAnimationAssetPtr, ShapeAnimationAsset)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeAssetId GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
/*class GuiInspectorTypeShapeAnimationAssetPtr : public GuiInspectorTypeFileName
|
||||
{
|
||||
typedef GuiInspectorTypeFileName Parent;
|
||||
public:
|
||||
|
||||
GuiBitmapButtonCtrl *mShapeEdButton;
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeShapeAnimationAssetPtr);
|
||||
static void consoleInit();
|
||||
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual bool updateRects();
|
||||
};*/
|
||||
|
||||
#endif // _ASSET_BASE_H_
|
||||
|
||||
|
|
@ -49,14 +49,14 @@
|
|||
|
||||
IMPLEMENT_CONOBJECT(ShapeAsset);
|
||||
|
||||
ConsoleType(TestAssetPtr, TypeShapeAssetPtr, ShapeAsset, ASSET_ID_FIELD_PREFIX)
|
||||
ConsoleType(assetIdString, TypeShapeAssetPtr, String, ASSET_ID_FIELD_PREFIX)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleGetType(TypeShapeAssetPtr)
|
||||
{
|
||||
// Fetch asset Id.
|
||||
return (*((AssetPtr<ShapeAsset>*)dptr)).getAssetId();
|
||||
return *((StringTableEntry*)dptr);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -69,33 +69,22 @@ ConsoleSetType(TypeShapeAssetPtr)
|
|||
// Yes, so fetch field value.
|
||||
const char* pFieldValue = argv[0];
|
||||
|
||||
// Fetch asset pointer.
|
||||
AssetPtr<ShapeAsset>* pAssetPtr = dynamic_cast<AssetPtr<ShapeAsset>*>((AssetPtrBase*)(dptr));
|
||||
// Fetch asset Id.
|
||||
StringTableEntry* assetId = (StringTableEntry*)(dptr);
|
||||
|
||||
// Is the asset pointer the correct type?
|
||||
if (pAssetPtr == NULL)
|
||||
{
|
||||
// No, so fail.
|
||||
//Con::warnf("(TypeTextureAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set asset.
|
||||
pAssetPtr->setAssetId(pFieldValue);
|
||||
// Update asset value.
|
||||
*assetId = StringTable->insert(pFieldValue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Warn.
|
||||
Con::warnf("(TypeTextureAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
Con::warnf("(TypeAssetId) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ShapeAsset::ShapeAsset() :
|
||||
mpOwningAssetManager(NULL),
|
||||
mAssetInitialized(false),
|
||||
mAcquireReferenceCount(0)
|
||||
ShapeAsset::ShapeAsset()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -116,7 +105,21 @@ void ShapeAsset::initPersistFields()
|
|||
// Call parent.
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("fileName", TypeFilename, Offset(mFileName, ShapeAsset), "Path to the script file we want to execute");
|
||||
addField("fileName", TypeFilename, Offset(mFileName, ShapeAsset), "Path to the shape file we want to render");
|
||||
}
|
||||
|
||||
void ShapeAsset::setDataField(StringTableEntry slotName, const char *array, const char *value)
|
||||
{
|
||||
Parent::setDataField(slotName, array, value);
|
||||
|
||||
//Now, if it's a material slot of some fashion, set it up
|
||||
StringTableEntry matSlotName = StringTable->insert("materialAsset");
|
||||
if (String(slotName).startsWith(matSlotName))
|
||||
{
|
||||
StringTableEntry matId = StringTable->insert(value);
|
||||
|
||||
mMaterialAssetIds.push_back(matId);
|
||||
}
|
||||
}
|
||||
|
||||
void ShapeAsset::initializeAsset()
|
||||
|
|
@ -132,6 +135,45 @@ void ShapeAsset::initializeAsset()
|
|||
|
||||
bool ShapeAsset::loadShape()
|
||||
{
|
||||
mMaterialAssets.clear();
|
||||
mMaterialAssetIds.clear();
|
||||
|
||||
//First, load any material, animation, etc assets we may be referencing in our asset
|
||||
// Find any asset dependencies.
|
||||
AssetManager::typeAssetDependsOnHash::Iterator assetDependenciesItr = mpOwningAssetManager->getDependedOnAssets()->find(mpAssetDefinition->mAssetId);
|
||||
|
||||
// Does the asset have any dependencies?
|
||||
if (assetDependenciesItr != mpOwningAssetManager->getDependedOnAssets()->end())
|
||||
{
|
||||
// Iterate all dependencies.
|
||||
while (assetDependenciesItr != mpOwningAssetManager->getDependedOnAssets()->end() && assetDependenciesItr->key == mpAssetDefinition->mAssetId)
|
||||
{
|
||||
StringTableEntry assetType = mpOwningAssetManager->getAssetType(assetDependenciesItr->value);
|
||||
|
||||
if (assetType == StringTable->insert("MaterialAsset"))
|
||||
{
|
||||
mMaterialAssetIds.push_back(assetDependenciesItr->value);
|
||||
|
||||
//Force the asset to become initialized if it hasn't been already
|
||||
AssetPtr<MaterialAsset> matAsset = assetDependenciesItr->value;
|
||||
|
||||
mMaterialAssets.push_back(matAsset);
|
||||
}
|
||||
else if (assetType == StringTable->insert("ShapeAnimationAsset"))
|
||||
{
|
||||
mAnimationAssetIds.push_back(assetDependenciesItr->value);
|
||||
|
||||
//Force the asset to become initialized if it hasn't been already
|
||||
AssetPtr<ShapeAnimationAsset> animAsset = assetDependenciesItr->value;
|
||||
|
||||
mAnimationAssets.push_back(animAsset);
|
||||
}
|
||||
|
||||
// Next dependency.
|
||||
assetDependenciesItr++;
|
||||
}
|
||||
}
|
||||
|
||||
mShape = ResourceManager::get().load(mFileName);
|
||||
|
||||
if (!mShape)
|
||||
|
|
@ -140,6 +182,51 @@ bool ShapeAsset::loadShape()
|
|||
return false; //if it failed to load, bail out
|
||||
}
|
||||
|
||||
bool hasBlends = false;
|
||||
|
||||
//Now that we've successfully loaded our shape and have any materials and animations loaded
|
||||
//we need to set up the animations we're using on our shape
|
||||
for (S32 i = mAnimationAssets.size()-1; i >= 0; --i)
|
||||
{
|
||||
String srcName = mAnimationAssets[i]->getAnimationName();
|
||||
String srcPath(mAnimationAssets[i]->getAnimationFilename());
|
||||
//SplitSequencePathAndName(srcPath, srcName);
|
||||
|
||||
if (!mShape->addSequence(srcPath, srcName, srcName,
|
||||
mAnimationAssets[i]->getStartFrame(), mAnimationAssets[i]->getEndFrame(), mAnimationAssets[i]->getPadRotation(), mAnimationAssets[i]->getPadTransforms()))
|
||||
return false;
|
||||
|
||||
if (mAnimationAssets[i]->isBlend())
|
||||
hasBlends = true;
|
||||
}
|
||||
|
||||
//if any of our animations are blends, set those up now
|
||||
if (hasBlends)
|
||||
{
|
||||
for (U32 i=0; i < mAnimationAssets.size(); ++i)
|
||||
{
|
||||
if (mAnimationAssets[i]->isBlend() && mAnimationAssets[i]->getBlendAnimationName() != StringTable->EmptyString())
|
||||
{
|
||||
//gotta do a bit of logic here.
|
||||
//First, we need to make sure the anim asset we depend on for our blend is loaded
|
||||
AssetPtr<ShapeAnimationAsset> blendAnimAsset = mAnimationAssets[i]->getBlendAnimationName();
|
||||
|
||||
if (blendAnimAsset.isNull())
|
||||
{
|
||||
Con::errorf("ShapeAsset::initializeAsset - Unable to acquire reference animation asset %s for asset %s to blend!", mAnimationAssets[i]->getBlendAnimationName(), mAnimationAssets[i]->getAssetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
String refAnimName = blendAnimAsset->getAnimationName();
|
||||
if (!mShape->setSequenceBlend(mAnimationAssets[i]->getAnimationName(), true, blendAnimAsset->getAnimationName(), mAnimationAssets[i]->getBlendFrame()))
|
||||
{
|
||||
Con::errorf("ShapeAnimationAsset::initializeAsset - Unable to set animation clip %s for asset %s to blend!", mAnimationAssets[i]->getAnimationName(), mAnimationAssets[i]->getAssetName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -153,4 +240,141 @@ void ShapeAsset::copyTo(SimObject* object)
|
|||
|
||||
void ShapeAsset::onAssetRefresh(void)
|
||||
{
|
||||
if (dStrcmp(mFileName, "") == 0)
|
||||
return;
|
||||
|
||||
loadShape();
|
||||
}
|
||||
|
||||
void ShapeAsset::SplitSequencePathAndName(String& srcPath, String& srcName)
|
||||
{
|
||||
srcName = "";
|
||||
|
||||
// Determine if there is a sequence name at the end of the source string, and
|
||||
// if so, split the filename from the sequence name
|
||||
S32 split = srcPath.find(' ', 0, String::Right);
|
||||
S32 split2 = srcPath.find('\t', 0, String::Right);
|
||||
if ((split == String::NPos) || (split2 > split))
|
||||
split = split2;
|
||||
if (split != String::NPos)
|
||||
{
|
||||
split2 = split + 1;
|
||||
while ((srcPath[split2] != '\0') && dIsspace(srcPath[split2]))
|
||||
split2++;
|
||||
|
||||
// now 'split' is at the end of the path, and 'split2' is at the start of the sequence name
|
||||
srcName = srcPath.substr(split2);
|
||||
srcPath = srcPath.erase(split, srcPath.length() - split);
|
||||
}
|
||||
}
|
||||
|
||||
ShapeAnimationAsset* ShapeAsset::getAnimation(S32 index)
|
||||
{
|
||||
if (index < mAnimationAssets.size())
|
||||
{
|
||||
return mAnimationAssets[index];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DefineEngineMethod(ShapeAsset, getMaterialCount, S32, (), ,
|
||||
"Gets the number of materials for this shape asset.\n"
|
||||
"@return Material count.\n")
|
||||
{
|
||||
return object->getMaterialCount();
|
||||
}
|
||||
|
||||
DefineEngineMethod(ShapeAsset, getAnimationCount, S32, (), ,
|
||||
"Gets the number of animations for this shape asset.\n"
|
||||
"@return Animation count.\n")
|
||||
{
|
||||
return object->getAnimationCount();
|
||||
}
|
||||
|
||||
DefineEngineMethod(ShapeAsset, getAnimation, ShapeAnimationAsset*, (S32 index), (0),
|
||||
"Gets a particular shape animation asset for this shape.\n"
|
||||
"@param animation asset index.\n"
|
||||
"@return Shape Animation Asset.\n")
|
||||
{
|
||||
return object->getAnimation(index);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorTypeAssetId
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorTypeShapeAssetPtr);
|
||||
|
||||
ConsoleDocClass(GuiInspectorTypeShapeAssetPtr,
|
||||
"@brief Inspector field type for Shapes\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
void GuiInspectorTypeShapeAssetPtr::consoleInit()
|
||||
{
|
||||
Parent::consoleInit();
|
||||
|
||||
ConsoleBaseType::getType(TypeShapeAssetPtr)->setInspectorFieldType("GuiInspectorTypeShapeAssetPtr");
|
||||
}
|
||||
|
||||
GuiControl* GuiInspectorTypeShapeAssetPtr::constructEditControl()
|
||||
{
|
||||
// Create base filename edit controls
|
||||
GuiControl *retCtrl = Parent::constructEditControl();
|
||||
if (retCtrl == NULL)
|
||||
return retCtrl;
|
||||
|
||||
// Change filespec
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"ShapeAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
|
||||
mInspector->getComponentGroupTargetId(), mCaption);
|
||||
mBrowseButton->setField("Command", szBuffer);
|
||||
|
||||
setDataField(StringTable->insert("ComponentOwner"), NULL, String::ToString(mInspector->getComponentGroupTargetId()).c_str());
|
||||
|
||||
// Create "Open in ShapeEditor" button
|
||||
mShapeEdButton = new GuiBitmapButtonCtrl();
|
||||
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "ShapeEditorPlugin.openShapeAsset(%d.getText());", retCtrl->getId());
|
||||
mShapeEdButton->setField("Command", szBuffer);
|
||||
|
||||
char bitmapName[512] = "tools/worldEditor/images/toolbar/shape-editor";
|
||||
mShapeEdButton->setBitmap(bitmapName);
|
||||
|
||||
mShapeEdButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
|
||||
mShapeEdButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
|
||||
mShapeEdButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
|
||||
mShapeEdButton->setDataField(StringTable->insert("tooltip"), NULL, "Open this file in the Shape Editor");
|
||||
|
||||
mShapeEdButton->registerObject();
|
||||
addObject(mShapeEdButton);
|
||||
|
||||
return retCtrl;
|
||||
}
|
||||
|
||||
bool GuiInspectorTypeShapeAssetPtr::updateRects()
|
||||
{
|
||||
S32 dividerPos, dividerMargin;
|
||||
mInspector->getDivider(dividerPos, dividerMargin);
|
||||
Point2I fieldExtent = getExtent();
|
||||
Point2I fieldPos = getPosition();
|
||||
|
||||
mCaptionRect.set(0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y);
|
||||
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y);
|
||||
|
||||
bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
|
||||
if (mBrowseButton != NULL)
|
||||
{
|
||||
mBrowseRect.set(fieldExtent.x - 32, 2, 14, fieldExtent.y - 4);
|
||||
resized |= mBrowseButton->resize(mBrowseRect.point, mBrowseRect.extent);
|
||||
}
|
||||
|
||||
if (mShapeEdButton != NULL)
|
||||
{
|
||||
RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4);
|
||||
resized |= mShapeEdButton->resize(shapeEdRect.point, shapeEdRect.extent);
|
||||
}
|
||||
|
||||
return resized;
|
||||
}
|
||||
|
|
@ -44,21 +44,35 @@
|
|||
#ifndef __RESOURCE_H__
|
||||
#include "core/resource.h"
|
||||
#endif
|
||||
#ifndef _ASSET_PTR_H_
|
||||
#include "assets/assetPtr.h"
|
||||
#endif
|
||||
#ifndef MATERIALASSET_H
|
||||
#include "MaterialAsset.h"
|
||||
#endif
|
||||
#ifndef SHAPE_ANIMATION_ASSET_H
|
||||
#include "ShapeAnimationAsset.h"
|
||||
#endif
|
||||
|
||||
#include "gui/editor/guiInspectorTypes.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class ShapeAsset : public AssetBase
|
||||
{
|
||||
typedef AssetBase Parent;
|
||||
|
||||
AssetManager* mpOwningAssetManager;
|
||||
bool mAssetInitialized;
|
||||
AssetDefinition* mpAssetDefinition;
|
||||
U32 mAcquireReferenceCount;
|
||||
|
||||
protected:
|
||||
StringTableEntry mFileName;
|
||||
Resource<TSShape> mShape;
|
||||
|
||||
//Material assets we're dependent on and use
|
||||
Vector<StringTableEntry> mMaterialAssetIds;
|
||||
Vector<AssetPtr<MaterialAsset>> mMaterialAssets;
|
||||
|
||||
//Animation assets we're dependent on and use
|
||||
Vector<StringTableEntry> mAnimationAssetIds;
|
||||
Vector<AssetPtr<ShapeAnimationAsset>> mAnimationAssets;
|
||||
|
||||
public:
|
||||
ShapeAsset();
|
||||
virtual ~ShapeAsset();
|
||||
|
|
@ -67,6 +81,8 @@ public:
|
|||
static void initPersistFields();
|
||||
virtual void copyTo(SimObject* object);
|
||||
|
||||
virtual void setDataField(StringTableEntry slotName, const char *array, const char *value);
|
||||
|
||||
virtual void initializeAsset();
|
||||
|
||||
/// Declare Console Object.
|
||||
|
|
@ -78,11 +94,37 @@ public:
|
|||
|
||||
Resource<TSShape> getShapeResource() { return mShape; }
|
||||
|
||||
void SplitSequencePathAndName(String& srcPath, String& srcName);
|
||||
String getShapeFilename() { return mFileName; }
|
||||
|
||||
U32 getShapeFilenameHash() { return _StringTable::hashString(mFileName); }
|
||||
|
||||
S32 getMaterialCount() { return mMaterialAssets.size(); }
|
||||
S32 getAnimationCount() { return mAnimationAssets.size(); }
|
||||
ShapeAnimationAsset* getAnimation(S32 index);
|
||||
|
||||
protected:
|
||||
virtual void onAssetRefresh(void);
|
||||
};
|
||||
|
||||
DefineConsoleType(TypeShapeAssetPtr, ShapeAsset)
|
||||
DefineConsoleType(TypeShapeAssetPtr, S32)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeAssetId GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeShapeAssetPtr : public GuiInspectorTypeFileName
|
||||
{
|
||||
typedef GuiInspectorTypeFileName Parent;
|
||||
public:
|
||||
|
||||
GuiBitmapButtonCtrl *mShapeEdButton;
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeShapeAssetPtr);
|
||||
static void consoleInit();
|
||||
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual bool updateRects();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
141
Engine/source/T3D/assets/SoundAsset.cpp
Normal file
141
Engine/source/T3D/assets/SoundAsset.cpp
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef SOUND_ASSET_H
|
||||
#include "SoundAsset.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_MANAGER_H_
|
||||
#include "assets/assetManager.h"
|
||||
#endif
|
||||
|
||||
#ifndef _CONSOLETYPES_H_
|
||||
#include "console/consoleTypes.h"
|
||||
#endif
|
||||
|
||||
#ifndef _TAML_
|
||||
#include "persistence/taml/taml.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_PTR_H_
|
||||
#include "assets/assetPtr.h"
|
||||
#endif
|
||||
|
||||
// Debug Profiling.
|
||||
#include "platform/profiler.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(SoundAsset);
|
||||
|
||||
ConsoleType(SoundAssetPtr, TypeSoundAssetPtr, SoundAsset, ASSET_ID_FIELD_PREFIX)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleGetType(TypeSoundAssetPtr)
|
||||
{
|
||||
// Fetch asset Id.
|
||||
return (*((AssetPtr<SoundAsset>*)dptr)).getAssetId();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleSetType(TypeSoundAssetPtr)
|
||||
{
|
||||
// Was a single argument specified?
|
||||
if (argc == 1)
|
||||
{
|
||||
// Yes, so fetch field value.
|
||||
const char* pFieldValue = argv[0];
|
||||
|
||||
// Fetch asset pointer.
|
||||
AssetPtr<SoundAsset>* pAssetPtr = dynamic_cast<AssetPtr<SoundAsset>*>((AssetPtrBase*)(dptr));
|
||||
|
||||
// Is the asset pointer the correct type?
|
||||
if (pAssetPtr == NULL)
|
||||
{
|
||||
// No, so fail.
|
||||
//Con::warnf("(TypeSoundAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set asset.
|
||||
pAssetPtr->setAssetId(pFieldValue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Warn.
|
||||
Con::warnf("(TypeSoundAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
SoundAsset::SoundAsset()
|
||||
{
|
||||
mSoundFilePath = StringTable->EmptyString();
|
||||
|
||||
mPitchAdjust = 0;
|
||||
mVolumeAdjust = 0;
|
||||
|
||||
//mSound = nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
SoundAsset::~SoundAsset()
|
||||
{
|
||||
// If the asset manager does not own the asset then we own the
|
||||
// asset definition so delete it.
|
||||
if (!getOwned())
|
||||
delete mpAssetDefinition;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SoundAsset::initPersistFields()
|
||||
{
|
||||
// Call parent.
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("soundFilePath", TypeFilename, Offset(mSoundFilePath, SoundAsset), "Path to the sound file.");
|
||||
|
||||
addField("pitchAdjust", TypeF32, Offset(mPitchAdjust, SoundAsset), "Adjustment of the pitch value");
|
||||
addField("volumeAdjust", TypeF32, Offset(mVolumeAdjust, SoundAsset), "Adjustment to the volume.");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void SoundAsset::copyTo(SimObject* object)
|
||||
{
|
||||
// Call to parent.
|
||||
Parent::copyTo(object);
|
||||
}
|
||||
|
||||
void SoundAsset::initializeAsset(void)
|
||||
{
|
||||
}
|
||||
|
||||
void SoundAsset::onAssetRefresh(void)
|
||||
{
|
||||
|
||||
}
|
||||
75
Engine/source/T3D/assets/SoundAsset.h
Normal file
75
Engine/source/T3D/assets/SoundAsset.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
#pragma once
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef SOUND_ASSET_H
|
||||
#define SOUND_ASSET_H
|
||||
|
||||
#ifndef _ASSET_BASE_H_
|
||||
#include "assets/assetBase.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_DEFINITION_H_
|
||||
#include "assets/assetDefinition.h"
|
||||
#endif
|
||||
|
||||
#ifndef _STRINGUNIT_H_
|
||||
#include "string/stringUnit.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_FIELD_TYPES_H_
|
||||
#include "assets/assetFieldTypes.h"
|
||||
#endif
|
||||
|
||||
class SFXTrack;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class SoundAsset : public AssetBase
|
||||
{
|
||||
typedef AssetBase Parent;
|
||||
|
||||
protected:
|
||||
StringTableEntry mSoundFilePath;
|
||||
F32 mPitchAdjust;
|
||||
F32 mVolumeAdjust;
|
||||
|
||||
public:
|
||||
SoundAsset();
|
||||
virtual ~SoundAsset();
|
||||
|
||||
/// Engine.
|
||||
static void initPersistFields();
|
||||
virtual void copyTo(SimObject* object);
|
||||
|
||||
/// Declare Console Object.
|
||||
DECLARE_CONOBJECT(SoundAsset);
|
||||
|
||||
StringTableEntry getSoundFilePath() { return mSoundFilePath; }
|
||||
|
||||
protected:
|
||||
virtual void initializeAsset(void);
|
||||
virtual void onAssetRefresh(void);
|
||||
};
|
||||
|
||||
DefineConsoleType(TypeSoundAssetPtr, SoundAsset)
|
||||
|
||||
#endif // _ASSET_BASE_H_
|
||||
|
||||
207
Engine/source/T3D/assets/stateMachineAsset.cpp
Normal file
207
Engine/source/T3D/assets/stateMachineAsset.cpp
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef STATE_MACHINE_ASSET_H
|
||||
#include "stateMachineAsset.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_MANAGER_H_
|
||||
#include "assets/assetManager.h"
|
||||
#endif
|
||||
|
||||
#ifndef _CONSOLETYPES_H_
|
||||
#include "console/consoleTypes.h"
|
||||
#endif
|
||||
|
||||
#ifndef _TAML_
|
||||
#include "persistence/taml/taml.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_PTR_H_
|
||||
#include "assets/assetPtr.h"
|
||||
#endif
|
||||
|
||||
// Debug Profiling.
|
||||
#include "platform/profiler.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(StateMachineAsset);
|
||||
|
||||
ConsoleType(StateMachineAssetPtr, TypeStateMachineAssetPtr, StateMachineAsset, ASSET_ID_FIELD_PREFIX)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleGetType(TypeStateMachineAssetPtr)
|
||||
{
|
||||
// Fetch asset Id.
|
||||
return (*((AssetPtr<StateMachineAsset>*)dptr)).getAssetId();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ConsoleSetType(TypeStateMachineAssetPtr)
|
||||
{
|
||||
// Was a single argument specified?
|
||||
if (argc == 1)
|
||||
{
|
||||
// Yes, so fetch field value.
|
||||
const char* pFieldValue = argv[0];
|
||||
|
||||
// Fetch asset pointer.
|
||||
AssetPtr<StateMachineAsset>* pAssetPtr = dynamic_cast<AssetPtr<StateMachineAsset>*>((AssetPtrBase*)(dptr));
|
||||
|
||||
// Is the asset pointer the correct type?
|
||||
if (pAssetPtr == NULL)
|
||||
{
|
||||
// No, so fail.
|
||||
//Con::warnf("(TypeStateMachineAssetPtr) - Failed to set asset Id '%d'.", pFieldValue);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set asset.
|
||||
pAssetPtr->setAssetId(pFieldValue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Warn.
|
||||
Con::warnf("(TypeStateMachineAssetPtr) - Cannot set multiple args to a single asset.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
StateMachineAsset::StateMachineAsset()
|
||||
{
|
||||
mStateMachineFileName = StringTable->EmptyString();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
StateMachineAsset::~StateMachineAsset()
|
||||
{
|
||||
// If the asset manager does not own the asset then we own the
|
||||
// asset definition so delete it.
|
||||
if (!getOwned())
|
||||
delete mpAssetDefinition;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void StateMachineAsset::initPersistFields()
|
||||
{
|
||||
// Call parent.
|
||||
Parent::initPersistFields();
|
||||
|
||||
addField("stateMachineFile", TypeString, Offset(mStateMachineFileName, StateMachineAsset), "Path to the state machine file.");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void StateMachineAsset::copyTo(SimObject* object)
|
||||
{
|
||||
// Call to parent.
|
||||
Parent::copyTo(object);
|
||||
}
|
||||
|
||||
DefineEngineMethod(StateMachineAsset, notifyAssetChanged, void, (),,"")
|
||||
{
|
||||
ResourceManager::get().getChangedSignal().trigger(object->getStateMachineFileName());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GuiInspectorTypeAssetId
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CONOBJECT(GuiInspectorTypeStateMachineAssetPtr);
|
||||
|
||||
ConsoleDocClass(GuiInspectorTypeStateMachineAssetPtr,
|
||||
"@brief Inspector field type for State Machines\n\n"
|
||||
"Editor use only.\n\n"
|
||||
"@internal"
|
||||
);
|
||||
|
||||
void GuiInspectorTypeStateMachineAssetPtr::consoleInit()
|
||||
{
|
||||
Parent::consoleInit();
|
||||
|
||||
ConsoleBaseType::getType(TypeStateMachineAssetPtr)->setInspectorFieldType("GuiInspectorTypeStateMachineAssetPtr");
|
||||
}
|
||||
|
||||
GuiControl* GuiInspectorTypeStateMachineAssetPtr::constructEditControl()
|
||||
{
|
||||
// Create base filename edit controls
|
||||
GuiControl *retCtrl = Parent::constructEditControl();
|
||||
if (retCtrl == NULL)
|
||||
return retCtrl;
|
||||
|
||||
// Change filespec
|
||||
char szBuffer[512];
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "AssetBrowser.showDialog(\"StateMachineAsset\", \"AssetBrowser.changeAsset\", %d, %s);",
|
||||
mInspector->getComponentGroupTargetId(), mCaption);
|
||||
mBrowseButton->setField("Command", szBuffer);
|
||||
|
||||
// Create "Open in ShapeEditor" button
|
||||
mSMEdButton = new GuiBitmapButtonCtrl();
|
||||
|
||||
dSprintf(szBuffer, sizeof(szBuffer), "StateMachineEditor.loadStateMachineAsset(%d.getText()); Canvas.pushDialog(StateMachineEditor);", retCtrl->getId());
|
||||
mSMEdButton->setField("Command", szBuffer);
|
||||
|
||||
char bitmapName[512] = "tools/worldEditor/images/toolbar/shape-editor";
|
||||
mSMEdButton->setBitmap(bitmapName);
|
||||
|
||||
mSMEdButton->setDataField(StringTable->insert("Profile"), NULL, "GuiButtonProfile");
|
||||
mSMEdButton->setDataField(StringTable->insert("tooltipprofile"), NULL, "GuiToolTipProfile");
|
||||
mSMEdButton->setDataField(StringTable->insert("hovertime"), NULL, "1000");
|
||||
mSMEdButton->setDataField(StringTable->insert("tooltip"), NULL, "Open this file in the State Machine Editor");
|
||||
|
||||
mSMEdButton->registerObject();
|
||||
addObject(mSMEdButton);
|
||||
|
||||
return retCtrl;
|
||||
}
|
||||
|
||||
bool GuiInspectorTypeStateMachineAssetPtr::updateRects()
|
||||
{
|
||||
S32 dividerPos, dividerMargin;
|
||||
mInspector->getDivider(dividerPos, dividerMargin);
|
||||
Point2I fieldExtent = getExtent();
|
||||
Point2I fieldPos = getPosition();
|
||||
|
||||
mCaptionRect.set(0, 0, fieldExtent.x - dividerPos - dividerMargin, fieldExtent.y);
|
||||
mEditCtrlRect.set(fieldExtent.x - dividerPos + dividerMargin, 1, dividerPos - dividerMargin - 34, fieldExtent.y);
|
||||
|
||||
bool resized = mEdit->resize(mEditCtrlRect.point, mEditCtrlRect.extent);
|
||||
if (mBrowseButton != NULL)
|
||||
{
|
||||
mBrowseRect.set(fieldExtent.x - 32, 2, 14, fieldExtent.y - 4);
|
||||
resized |= mBrowseButton->resize(mBrowseRect.point, mBrowseRect.extent);
|
||||
}
|
||||
|
||||
if (mSMEdButton != NULL)
|
||||
{
|
||||
RectI shapeEdRect(fieldExtent.x - 16, 2, 14, fieldExtent.y - 4);
|
||||
resized |= mSMEdButton->resize(shapeEdRect.point, shapeEdRect.extent);
|
||||
}
|
||||
|
||||
return resized;
|
||||
}
|
||||
89
Engine/source/T3D/assets/stateMachineAsset.h
Normal file
89
Engine/source/T3D/assets/stateMachineAsset.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#pragma once
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef STATE_MACHINE_ASSET_H
|
||||
#define STATE_MACHINE_ASSET_H
|
||||
|
||||
#ifndef _ASSET_BASE_H_
|
||||
#include "assets/assetBase.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_DEFINITION_H_
|
||||
#include "assets/assetDefinition.h"
|
||||
#endif
|
||||
|
||||
#ifndef _STRINGUNIT_H_
|
||||
#include "string/stringUnit.h"
|
||||
#endif
|
||||
|
||||
#ifndef _ASSET_FIELD_TYPES_H_
|
||||
#include "assets/assetFieldTypes.h"
|
||||
#endif
|
||||
|
||||
#include "gui/editor/guiInspectorTypes.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class StateMachineAsset : public AssetBase
|
||||
{
|
||||
typedef AssetBase Parent;
|
||||
|
||||
StringTableEntry mStateMachineFileName;
|
||||
|
||||
public:
|
||||
StateMachineAsset();
|
||||
virtual ~StateMachineAsset();
|
||||
|
||||
/// Engine.
|
||||
static void initPersistFields();
|
||||
virtual void copyTo(SimObject* object);
|
||||
|
||||
/// Declare Console Object.
|
||||
DECLARE_CONOBJECT(StateMachineAsset);
|
||||
|
||||
StringTableEntry getStateMachineFileName() { return mStateMachineFileName; }
|
||||
|
||||
protected:
|
||||
virtual void initializeAsset(void) {}
|
||||
virtual void onAssetRefresh(void) {}
|
||||
};
|
||||
|
||||
DefineConsoleType(TypeStateMachineAssetPtr, StateMachineAsset)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TypeAssetId GuiInspectorField Class
|
||||
//-----------------------------------------------------------------------------
|
||||
class GuiInspectorTypeStateMachineAssetPtr : public GuiInspectorTypeFileName
|
||||
{
|
||||
typedef GuiInspectorTypeFileName Parent;
|
||||
public:
|
||||
|
||||
GuiBitmapButtonCtrl *mSMEdButton;
|
||||
|
||||
DECLARE_CONOBJECT(GuiInspectorTypeStateMachineAssetPtr);
|
||||
static void consoleInit();
|
||||
|
||||
virtual GuiControl* constructEditControl();
|
||||
virtual bool updateRects();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _CAMERA_H_
|
||||
#define _CAMERA_H_
|
||||
|
||||
|
|
@ -246,6 +251,8 @@ class Camera: public ShapeBase
|
|||
DECLARE_CONOBJECT( Camera );
|
||||
DECLARE_CATEGORY( "Game" );
|
||||
DECLARE_DESCRIPTION( "Represents a position, direction and field of view to render a scene from." );
|
||||
static F32 getMovementSpeed() { return smMovementSpeed; }
|
||||
bool isCamera() const { return true; }
|
||||
};
|
||||
|
||||
typedef Camera::CameraMotionMode CameraMotionMode;
|
||||
|
|
|
|||
|
|
@ -72,7 +72,6 @@ IMPLEMENT_CALLBACK(AnimationComponent, onAnimationTrigger, void, (Component* obj
|
|||
AnimationComponent::AnimationComponent() : Component()
|
||||
{
|
||||
mNetworked = true;
|
||||
mNetFlags.set(Ghostable | ScopeAlways);
|
||||
|
||||
mFriendlyName = "Animation(Component)";
|
||||
mComponentType = "Render";
|
||||
|
|
@ -223,29 +222,17 @@ U32 AnimationComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stre
|
|||
{
|
||||
U32 retMask = Parent::packUpdate(con, mask, stream);
|
||||
|
||||
//early test if we lack an owner, ghost-wise
|
||||
//no point in trying, just re-queue the mask and go
|
||||
if (!mOwner || con->getGhostIndex(mOwner) == -1)
|
||||
for (int i = 0; i < MaxScriptThreads; i++)
|
||||
{
|
||||
stream->writeFlag(false);
|
||||
return retMask |= ThreadMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream->writeFlag(true);
|
||||
|
||||
for (int i = 0; i < MaxScriptThreads; i++)
|
||||
Thread& st = mAnimationThreads[i];
|
||||
if (stream->writeFlag((st.sequence != -1 || st.state == Thread::Destroy) && (mask & (ThreadMaskN << i))))
|
||||
{
|
||||
Thread& st = mAnimationThreads[i];
|
||||
if (stream->writeFlag( (st.sequence != -1 || st.state == Thread::Destroy) && (mask & (ThreadMaskN << i)) ) )
|
||||
{
|
||||
stream->writeInt(st.sequence,ThreadSequenceBits);
|
||||
stream->writeInt(st.state,2);
|
||||
stream->write(st.timescale);
|
||||
stream->write(st.position);
|
||||
stream->writeFlag(st.atEnd);
|
||||
stream->writeFlag(st.transition);
|
||||
}
|
||||
stream->writeInt(st.sequence, ThreadSequenceBits);
|
||||
stream->writeInt(st.state, 2);
|
||||
stream->write(st.timescale);
|
||||
stream->write(st.position);
|
||||
stream->writeFlag(st.atEnd);
|
||||
stream->writeFlag(st.transition);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -256,29 +243,26 @@ void AnimationComponent::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
{
|
||||
Parent::unpackUpdate(con, stream);
|
||||
|
||||
if (stream->readFlag())
|
||||
for (S32 i = 0; i < MaxScriptThreads; i++)
|
||||
{
|
||||
for (S32 i = 0; i < MaxScriptThreads; i++)
|
||||
if (stream->readFlag())
|
||||
{
|
||||
if (stream->readFlag())
|
||||
{
|
||||
Thread& st = mAnimationThreads[i];
|
||||
U32 seq = stream->readInt(ThreadSequenceBits);
|
||||
st.state = stream->readInt(2);
|
||||
stream->read( &st.timescale );
|
||||
stream->read( &st.position );
|
||||
st.atEnd = stream->readFlag();
|
||||
bool transition = stream->readFlag();
|
||||
Thread& st = mAnimationThreads[i];
|
||||
U32 seq = stream->readInt(ThreadSequenceBits);
|
||||
st.state = stream->readInt(2);
|
||||
stream->read( &st.timescale );
|
||||
stream->read( &st.position );
|
||||
st.atEnd = stream->readFlag();
|
||||
bool transition = stream->readFlag();
|
||||
|
||||
if (!st.thread || st.sequence != seq && st.state != Thread::Destroy)
|
||||
setThreadSequence(i, seq, false, transition);
|
||||
else
|
||||
updateThread(st);
|
||||
|
||||
}
|
||||
if (!st.thread || st.sequence != seq && st.state != Thread::Destroy)
|
||||
setThreadSequence(i, seq, false, transition);
|
||||
else
|
||||
updateThread(st);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationComponent::processTick()
|
||||
{
|
||||
Parent::processTick();
|
||||
|
|
@ -327,9 +311,6 @@ const char *AnimationComponent::getThreadSequenceName(U32 slot)
|
|||
|
||||
bool AnimationComponent::setThreadSequence(U32 slot, S32 seq, bool reset, bool transition, F32 transTime)
|
||||
{
|
||||
if (!mOwnerShapeInstance)
|
||||
return false;
|
||||
|
||||
Thread& st = mAnimationThreads[slot];
|
||||
if (st.thread && st.sequence == seq && st.state == Thread::Play && !reset)
|
||||
return true;
|
||||
|
|
@ -340,7 +321,6 @@ bool AnimationComponent::setThreadSequence(U32 slot, S32 seq, bool reset, bool t
|
|||
|
||||
if (seq < MaxSequenceIndex)
|
||||
{
|
||||
setMaskBits(-1);
|
||||
setMaskBits(ThreadMaskN << slot);
|
||||
st.sequence = seq;
|
||||
st.transition = transition;
|
||||
|
|
@ -633,6 +613,9 @@ void AnimationComponent::advanceThreads(F32 dt)
|
|||
if (!mOwnerRenderInst)
|
||||
return;
|
||||
|
||||
if (mOwnerShapeInstance == nullptr || !getShape())
|
||||
return;
|
||||
|
||||
for (U32 i = 0; i < MaxScriptThreads; i++)
|
||||
{
|
||||
Thread& st = mAnimationThreads[i];
|
||||
|
|
@ -647,7 +630,7 @@ void AnimationComponent::advanceThreads(F32 dt)
|
|||
st.atEnd = true;
|
||||
updateThread(st);
|
||||
|
||||
if (!isGhost())
|
||||
if (!isClientObject())
|
||||
{
|
||||
Con::executef(this, "onAnimationEnd", st.thread->getSequenceName());
|
||||
}
|
||||
|
|
@ -660,20 +643,28 @@ void AnimationComponent::advanceThreads(F32 dt)
|
|||
mOwnerShapeInstance->advanceTime(dt, st.thread);
|
||||
}
|
||||
|
||||
if (mOwnerShapeInstance && !isGhost())
|
||||
if (mOwnerShapeInstance && !isClientObject())
|
||||
{
|
||||
for (U32 i = 1; i < 32; i++)
|
||||
for (U32 stateIDx = 1; stateIDx < 32; stateIDx++)
|
||||
{
|
||||
if (mOwnerShapeInstance->getTriggerState(i))
|
||||
if (mOwnerShapeInstance->getTriggerState(stateIDx))
|
||||
{
|
||||
const char* animName = st.thread->getSequenceName().c_str();
|
||||
onAnimationTrigger_callback(this, animName, i);
|
||||
onAnimationTrigger_callback(this, animName, stateIDx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isGhost())
|
||||
if (isClientObject())
|
||||
{
|
||||
mOwnerShapeInstance->animate();
|
||||
/*mOwnerShapeInstance->animateGround();
|
||||
MatrixF groundTransform = mOwnerShapeInstance->getGroundTransform();
|
||||
if (groundTransform != MatrixF::Identity)
|
||||
{
|
||||
mOwner->setPosition(groundTransform.getPosition());
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
422
Engine/source/T3D/components/audio/SoundComponent.cpp
Normal file
422
Engine/source/T3D/components/audio/SoundComponent.cpp
Normal file
|
|
@ -0,0 +1,422 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "T3D/components/audio/SoundComponent.h"
|
||||
#include "core/stream/bitStream.h"
|
||||
#include "sim/netConnection.h"
|
||||
|
||||
#include "sfx/sfxSystem.h"
|
||||
#include "sfx/sfxSource.h"
|
||||
#include "sfx/sfxTrack.h"
|
||||
#include "sfx/sfxDescription.h"
|
||||
#include "T3D/sfx/sfx3DWorld.h"
|
||||
|
||||
#include "sfx/sfxTrack.h"
|
||||
#include "sfx/sfxTypes.h"
|
||||
|
||||
#include "renderInstance/renderPassManager.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
|
||||
// Timeout for non-looping sounds on a channel
|
||||
static SimTime sAudioTimeout = 500;
|
||||
|
||||
extern bool gEditingMission;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Constructor/Destructor
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SoundComponent::SoundComponent() : Component()
|
||||
{
|
||||
//These flags inform that, in this particular component, we network down to the client, which enables the pack/unpackData functions to operate
|
||||
mNetworked = true;
|
||||
|
||||
mFriendlyName = "Sound(Component)";
|
||||
mComponentType = "Sound";
|
||||
mDescription = getDescriptionText("Stores up to 4 sounds for playback.");
|
||||
|
||||
for (U32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++) {
|
||||
mSoundThread[slotNum].play = false;
|
||||
mSoundThread[slotNum].profile = 0;
|
||||
mSoundThread[slotNum].sound = 0;
|
||||
|
||||
mSoundFile[slotNum] = NULL;
|
||||
mPreviewSound[slotNum] = false;
|
||||
mPlay[slotNum] = false;
|
||||
}
|
||||
}
|
||||
|
||||
SoundComponent::~SoundComponent()
|
||||
{
|
||||
}
|
||||
|
||||
IMPLEMENT_CO_NETOBJECT_V1(SoundComponent);
|
||||
|
||||
//Standard onAdd function, for when the component is created
|
||||
bool SoundComponent::onAdd()
|
||||
{
|
||||
if (!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
for (U32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
|
||||
mPreviewSound[slotNum] = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//Standard onRemove function, when the component object is deleted
|
||||
void SoundComponent::onRemove()
|
||||
{
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
//This is called when the component has been added to an entity
|
||||
void SoundComponent::onComponentAdd()
|
||||
{
|
||||
Parent::onComponentAdd();
|
||||
|
||||
Con::printf("We were added to an entity! SoundComponent reporting in for owner entity %i", mOwner->getId());
|
||||
}
|
||||
|
||||
//This is called when the component has been removed from an entity
|
||||
void SoundComponent::onComponentRemove()
|
||||
{
|
||||
Con::printf("We were removed from our entity! SoundComponent signing off for owner entity %i", mOwner->getId());
|
||||
Parent::onComponentRemove();
|
||||
}
|
||||
|
||||
//This is called any time a component is added to an entity. Every component currently owned by the entity is informed of the event.
|
||||
//This allows you to do dependency behavior, like collisions being aware of a mesh component, etc
|
||||
void SoundComponent::componentAddedToOwner(Component *comp)
|
||||
{
|
||||
for (S32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
|
||||
{
|
||||
if (mPlay[slotNum])
|
||||
{
|
||||
playAudio(slotNum, mSoundFile[slotNum]);
|
||||
}
|
||||
}
|
||||
Con::printf("Our owner entity has a new component being added! SoundComponent welcomes component %i of type %s", comp->getId(), comp->getClassRep()->getNameSpace());
|
||||
}
|
||||
|
||||
//This is called any time a component is removed from an entity. Every component current owned by the entity is informed of the event.
|
||||
//This allows cleanup and dependency management.
|
||||
void SoundComponent::componentRemovedFromOwner(Component *comp)
|
||||
{
|
||||
Con::printf("Our owner entity has a removed a component! SoundComponent waves farewell to component %i of type %s", comp->getId(), comp->getClassRep()->getNameSpace());
|
||||
}
|
||||
|
||||
//Regular init persist fields function to set up static fields.
|
||||
void SoundComponent::initPersistFields()
|
||||
{
|
||||
//addArray("Sounds", MaxSoundThreads);
|
||||
addField("mSoundFile", TypeSFXTrackName, Offset(mSoundFile, SoundComponent), MaxSoundThreads, "If the text will not fit in the control, the deniedSound is played.");
|
||||
addProtectedField("mPreviewSound", TypeBool, Offset(mPreviewSound, SoundComponent),
|
||||
&_previewSound, &defaultProtectedGetFn, MaxSoundThreads, "Preview Sound", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
|
||||
addProtectedField("play", TypeBool, Offset(mPlay, SoundComponent),
|
||||
&_autoplay, &defaultProtectedGetFn, MaxSoundThreads, "Whether playback of the emitter's sound should start as soon as the emitter object is added to the level.\n"
|
||||
"If this is true, the emitter will immediately start to play when the level is loaded.");
|
||||
//endArray("Sounds");
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
bool SoundComponent::_previewSound(void *object, const char *index, const char *data)
|
||||
{
|
||||
U32 slotNum = (index != NULL) ? dAtoui(index) : 0;
|
||||
SoundComponent* component = reinterpret_cast< SoundComponent* >(object);
|
||||
if (!component->mPreviewSound[slotNum])
|
||||
component->playAudio(slotNum, component->mSoundFile[slotNum]);
|
||||
else
|
||||
component->stopAudio(slotNum);
|
||||
component->mPreviewSound[slotNum] = !component->mPreviewSound[slotNum];
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SoundComponent::_autoplay(void *object, const char *index, const char *data)
|
||||
{
|
||||
U32 slotNum = (index != NULL) ? dAtoui(index) : 0;
|
||||
SoundComponent* component = reinterpret_cast< SoundComponent* >(object);
|
||||
component->mPlay[slotNum] = dAtoui(data);
|
||||
if (component->mPlay[slotNum])
|
||||
component->playAudio(slotNum, component->mSoundFile[slotNum]);
|
||||
else
|
||||
component->stopAudio(slotNum);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
U32 SoundComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
||||
{
|
||||
U32 retMask = Parent::packUpdate(con, mask, stream);
|
||||
|
||||
if (mask & InitialUpdateMask)
|
||||
{
|
||||
// mask off sounds that aren't playing
|
||||
S32 slotNum;
|
||||
for (slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
|
||||
if (!mSoundThread[slotNum].play)
|
||||
mask &= ~(SoundMaskN << slotNum);
|
||||
}
|
||||
|
||||
for (S32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
|
||||
stream->writeFlag(mPreviewSound[slotNum]);
|
||||
|
||||
if (stream->writeFlag(mask & SoundMask))
|
||||
{
|
||||
for (S32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
|
||||
{
|
||||
Sound& st = mSoundThread[slotNum];
|
||||
|
||||
if (stream->writeFlag(mask & (SoundMaskN << slotNum)))
|
||||
{
|
||||
if (stream->writeFlag(st.play))
|
||||
//stream->writeRangedU32(st.profile->getId(), DataBlockObjectIdFirst,
|
||||
// DataBlockObjectIdLast);
|
||||
stream->writeString(st.profile->getName());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retMask;
|
||||
}
|
||||
|
||||
void SoundComponent::unpackUpdate(NetConnection *con, BitStream *stream)
|
||||
{
|
||||
Parent::unpackUpdate(con, stream);
|
||||
|
||||
for (S32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
|
||||
mPreviewSound[slotNum] = stream->readFlag();
|
||||
|
||||
if (stream->readFlag())
|
||||
{
|
||||
for (S32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
|
||||
{
|
||||
if (stream->readFlag())
|
||||
{
|
||||
Sound& st = mSoundThread[slotNum];
|
||||
st.play = stream->readFlag();
|
||||
if (st.play)
|
||||
{
|
||||
//st.profile = (SFXTrack*)stream->readRangedU32(DataBlockObjectIdFirst,
|
||||
// DataBlockObjectIdLast);
|
||||
char profileName[255];
|
||||
stream->readString(profileName);
|
||||
|
||||
if (!Sim::findObject(profileName, st.profile))
|
||||
Con::errorf("Could not find SFXTrack");
|
||||
}
|
||||
|
||||
//if (isProperlyAdded())
|
||||
updateAudioState(st);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//This allows custom behavior in the event the owner is being edited
|
||||
void SoundComponent::onInspect()
|
||||
{
|
||||
}
|
||||
|
||||
//This allows cleanup of the custom editor behavior if our owner stopped being edited
|
||||
void SoundComponent::onEndInspect()
|
||||
{
|
||||
}
|
||||
|
||||
//Process tick update function, natch
|
||||
void SoundComponent::processTick()
|
||||
{
|
||||
Parent::processTick();
|
||||
}
|
||||
|
||||
//Client-side advance function
|
||||
void SoundComponent::advanceTime(F32 dt)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//Client-side interpolation function
|
||||
void SoundComponent::interpolateTick(F32 delta)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SoundComponent::prepRenderImage(SceneRenderState *state)
|
||||
{
|
||||
if (!mEnabled || !mOwner || !gEditingMission)
|
||||
return;
|
||||
ObjectRenderInst* ri = state->getRenderPass()->allocInst< ObjectRenderInst >();
|
||||
|
||||
ri->renderDelegate.bind(this, &SoundComponent::_renderObject);
|
||||
ri->type = RenderPassManager::RIT_Editor;
|
||||
ri->defaultKey = 0;
|
||||
ri->defaultKey2 = 0;
|
||||
|
||||
state->getRenderPass()->addInst(ri);
|
||||
}
|
||||
|
||||
void SoundComponent::_renderObject(ObjectRenderInst *ri,
|
||||
SceneRenderState *state,
|
||||
BaseMatInstance *overrideMat)
|
||||
{
|
||||
if (overrideMat)
|
||||
return;
|
||||
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setBlend(true);
|
||||
|
||||
MatrixF camera = GFX->getWorldMatrix();
|
||||
camera.inverse();
|
||||
Point3F pos = mOwner->getPosition();
|
||||
|
||||
for (S32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
|
||||
{
|
||||
if (mPreviewSound[slotNum])
|
||||
{
|
||||
Sound& st = mSoundThread[slotNum];
|
||||
if (st.sound && st.sound->getDescription())
|
||||
{
|
||||
F32 minRad = st.sound->getDescription()->mMinDistance;
|
||||
F32 falloffRad = st.sound->getDescription()->mMaxDistance;
|
||||
SphereF sphere(pos, falloffRad);
|
||||
if (sphere.isContained(camera.getPosition()))
|
||||
desc.setCullMode(GFXCullNone);
|
||||
|
||||
GFX->getDrawUtil()->drawSphere(desc, minRad, pos, ColorI(255, 0, 255, 64));
|
||||
GFX->getDrawUtil()->drawSphere(desc, falloffRad, pos, ColorI(128, 0, 128, 64));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoundComponent::playAudio(U32 slotNum, SFXTrack* _profile)
|
||||
{
|
||||
AssertFatal(slotNum < MaxSoundThreads, "ShapeBase::playAudio() bad slot index");
|
||||
SFXTrack* profile = (_profile != NULL) ? _profile : mSoundFile[slotNum];
|
||||
Sound& st = mSoundThread[slotNum];
|
||||
if (profile && (!st.play || st.profile != profile))
|
||||
{
|
||||
setMaskBits(SoundMaskN << slotNum);
|
||||
st.play = true;
|
||||
st.profile = profile;
|
||||
updateAudioState(st);
|
||||
}
|
||||
}
|
||||
|
||||
void SoundComponent::stopAudio(U32 slotNum)
|
||||
{
|
||||
AssertFatal(slotNum < MaxSoundThreads, "ShapeBase::stopAudio() bad slot index");
|
||||
|
||||
Sound& st = mSoundThread[slotNum];
|
||||
if (st.play)
|
||||
{
|
||||
st.play = false;
|
||||
setMaskBits(SoundMaskN << slotNum);
|
||||
updateAudioState(st);
|
||||
}
|
||||
}
|
||||
|
||||
void SoundComponent::updateServerAudio()
|
||||
{
|
||||
// Timeout non-looping sounds
|
||||
for (S32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
|
||||
{
|
||||
Sound& st = mSoundThread[slotNum];
|
||||
if (st.play && st.timeout && st.timeout < Sim::getCurrentTime())
|
||||
{
|
||||
//clearMaskBits(SoundMaskN << slotNum);
|
||||
st.play = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoundComponent::updateAudioState(Sound& st)
|
||||
{
|
||||
SFX_DELETE(st.sound);
|
||||
|
||||
if (st.play && st.profile)
|
||||
{
|
||||
if (isClientObject())
|
||||
{
|
||||
//if (Sim::findObject(SimObjectId((uintptr_t)st.profile), st.profile))
|
||||
// {
|
||||
MatrixF transform = mOwner->getTransform();
|
||||
st.sound = SFX->createSource(st.profile, &transform);
|
||||
if (st.sound)
|
||||
st.sound->play();
|
||||
//}
|
||||
else
|
||||
st.play = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Non-looping sounds timeout on the server
|
||||
st.timeout = 0;
|
||||
if (!st.profile->getDescription()->mIsLooping)
|
||||
st.timeout = Sim::getCurrentTime() + sAudioTimeout;
|
||||
}
|
||||
}
|
||||
else
|
||||
st.play = false;
|
||||
}
|
||||
|
||||
void SoundComponent::updateAudioPos()
|
||||
{
|
||||
for (S32 slotNum = 0; slotNum < MaxSoundThreads; slotNum++)
|
||||
{
|
||||
SFXSource* source = mSoundThread[slotNum].sound;
|
||||
if (source)
|
||||
source->setTransform(mOwner->getTransform());
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
DefineEngineMethod(SoundComponent, playAudio, bool, (S32 slot, SFXTrack* track), (0, nullAsType<SFXTrack*>()),
|
||||
"@brief Attach a sound to this shape and start playing it.\n\n"
|
||||
|
||||
"@param slot Audio slot index for the sound (valid range is 0 - 3)\n" // 3 = ShapeBase::MaxSoundThreads-1
|
||||
"@param track SFXTrack to play\n"
|
||||
"@return true if the sound was attached successfully, false if failed\n\n"
|
||||
|
||||
"@see stopAudio()\n")
|
||||
{
|
||||
if (track && slot >= 0 && slot < SoundComponent::MaxSoundThreads) {
|
||||
object->playAudio(slot, track);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DefineEngineMethod(SoundComponent, stopAudio, bool, (S32 slot), ,
|
||||
"@brief Stop a sound started with playAudio.\n\n"
|
||||
|
||||
"@param slot audio slot index (started with playAudio)\n"
|
||||
"@return true if the sound was stopped successfully, false if failed\n\n"
|
||||
|
||||
"@see playAudio()\n")
|
||||
{
|
||||
if (slot >= 0 && slot < SoundComponent::MaxSoundThreads) {
|
||||
object->stopAudio(slot);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
129
Engine/source/T3D/components/audio/SoundComponent.h
Normal file
129
Engine/source/T3D/components/audio/SoundComponent.h
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef EXAMPLE_COMPONENT_H
|
||||
#define EXAMPLE_COMPONENT_H
|
||||
#pragma once
|
||||
|
||||
#ifndef COMPONENT_H
|
||||
#include "T3D/components/component.h"
|
||||
#endif
|
||||
#ifndef RENDER_COMPONENT_INTERFACE_H
|
||||
#include "T3D/components/render/renderComponentInterface.h"
|
||||
#endif
|
||||
|
||||
class SFXSource;
|
||||
|
||||
//SoundComponent
|
||||
//A basic example of the various functions you can utilize to make your own component!
|
||||
//This example doesn't really DO anything, persay, but you can readily copy it as a base
|
||||
//and use it as a starting point for your own.
|
||||
class SoundComponent : public Component, public RenderComponentInterface, public EditorInspectInterface
|
||||
{
|
||||
typedef Component Parent;
|
||||
|
||||
public:
|
||||
enum PublicConstants
|
||||
{
|
||||
MaxSoundThreads = 4, ///< Should be a power of 2
|
||||
};
|
||||
|
||||
/// @name Network state masks
|
||||
/// @{
|
||||
|
||||
///
|
||||
enum SoundComponentMasks
|
||||
{
|
||||
SoundMaskN = Parent::NextFreeMask << 6, ///< Extends + MaxSoundThreads bits
|
||||
};
|
||||
|
||||
enum BaseMaskConstants
|
||||
{
|
||||
SoundMask = (SoundMaskN << MaxSoundThreads) - SoundMaskN,
|
||||
};
|
||||
/// @name Scripted Sound
|
||||
/// @{
|
||||
struct Sound {
|
||||
bool play; ///< Are we playing this sound?
|
||||
SimTime timeout; ///< Time until we stop playing this sound.
|
||||
SFXTrack* profile; ///< Profile on server
|
||||
SFXSource* sound; ///< Sound on client
|
||||
Sound()
|
||||
{
|
||||
play = false;
|
||||
timeout = 0;
|
||||
profile = NULL;
|
||||
sound = NULL;
|
||||
}
|
||||
};
|
||||
Sound mSoundThread[MaxSoundThreads];
|
||||
SFXTrack* mSoundFile[MaxSoundThreads];
|
||||
bool mPreviewSound[MaxSoundThreads];
|
||||
bool mPlay[MaxSoundThreads];
|
||||
/// @}
|
||||
|
||||
SoundComponent();
|
||||
virtual ~SoundComponent();
|
||||
DECLARE_CONOBJECT(SoundComponent);
|
||||
|
||||
virtual bool onAdd();
|
||||
virtual void onRemove();
|
||||
static void initPersistFields();
|
||||
static bool _previewSound(void *object, const char *index, const char *data);
|
||||
static bool _autoplay(void *object, const char *index, const char *data);
|
||||
|
||||
virtual U32 packUpdate(NetConnection *con, U32 mask, BitStream *stream);
|
||||
virtual void unpackUpdate(NetConnection *con, BitStream *stream);
|
||||
|
||||
virtual void onComponentRemove();
|
||||
virtual void onComponentAdd();
|
||||
|
||||
virtual void componentAddedToOwner(Component *comp);
|
||||
virtual void componentRemovedFromOwner(Component *comp);
|
||||
|
||||
virtual void onInspect();
|
||||
virtual void onEndInspect();
|
||||
|
||||
virtual void processTick();
|
||||
virtual void advanceTime(F32 dt);
|
||||
virtual void interpolateTick(F32 delta);
|
||||
|
||||
void prepRenderImage(SceneRenderState* state);
|
||||
void _renderObject(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat);
|
||||
|
||||
virtual void playAudio(U32 slotNum, SFXTrack* profile = NULL);
|
||||
virtual void stopAudio(U32 slot);
|
||||
virtual void updateServerAudio();
|
||||
virtual void updateAudioState(Sound& st);
|
||||
virtual void updateAudioPos();
|
||||
|
||||
//why god why
|
||||
virtual TSShape* getShape() { return NULL; };
|
||||
Signal< void(RenderComponentInterface*) > onShapeChanged;
|
||||
virtual TSShapeInstance* getShapeInstance() { return NULL; };
|
||||
Signal< void(RenderComponentInterface*) > onShapeInstanceChanged;
|
||||
virtual MatrixF getNodeTransform(S32 nodeIdx) { return MatrixF::Identity; };
|
||||
virtual Vector<MatrixF> getNodeTransforms() { return NULL; };
|
||||
virtual void setNodeTransforms(Vector<MatrixF> transforms) {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -79,6 +79,7 @@ CameraComponent::CameraComponent() : Component()
|
|||
mTargetNode = "";
|
||||
|
||||
mUseParentTransform = true;
|
||||
mNetworked = true;
|
||||
|
||||
mFriendlyName = "Camera(Component)";
|
||||
}
|
||||
|
|
@ -202,7 +203,7 @@ void CameraComponent::setCameraFov(F32 fov)
|
|||
void CameraComponent::onCameraScopeQuery(NetConnection *cr, CameraScopeQuery * query)
|
||||
{
|
||||
// update the camera query
|
||||
query->camera = this;
|
||||
query->camera = mOwner;//this;
|
||||
|
||||
if(GameConnection * con = dynamic_cast<GameConnection*>(cr))
|
||||
{
|
||||
|
|
@ -357,7 +358,8 @@ U32 CameraComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|||
mTargetNodeIdx = nodeIndex;
|
||||
}
|
||||
|
||||
stream->writeInt(mTargetNodeIdx, 32);
|
||||
if(stream->writeFlag(mTargetNodeIdx > -1))
|
||||
stream->writeInt(mTargetNodeIdx, 32);
|
||||
//send offsets here
|
||||
|
||||
stream->writeCompressedPoint(mPosOffset);
|
||||
|
|
@ -382,7 +384,10 @@ void CameraComponent::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
|
||||
if(stream->readFlag())
|
||||
{
|
||||
mTargetNodeIdx = stream->readInt(32);
|
||||
if (stream->readFlag())
|
||||
mTargetNodeIdx = stream->readInt(32);
|
||||
else
|
||||
mTargetNodeIdx = -1;
|
||||
|
||||
stream->readCompressedPoint(&mPosOffset);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,13 +24,14 @@
|
|||
#include "T3D/components/camera/cameraComponent.h"
|
||||
|
||||
//Basically, this only exists for backwards compatibility for parts of the editors
|
||||
ConsoleMethod(CameraComponent, getMode, const char*, 2, 2, "() - We get the first behavior of the requested type on our owner object.\n"
|
||||
DefineEngineMethod(CameraComponent, getMode, const char*, (),,
|
||||
"@brief We get the first behavior of the requested type on our owner object.\n"
|
||||
"@return (string name) The type of the behavior we're requesting")
|
||||
{
|
||||
return "fly";
|
||||
}
|
||||
|
||||
DefineConsoleMethod(CameraComponent, getForwardVector, VectorF, (), ,
|
||||
DefineEngineMethod(CameraComponent, getForwardVector, VectorF, (), ,
|
||||
"Get the number of static fields on the object.\n"
|
||||
"@return The number of static fields defined on the object.")
|
||||
{
|
||||
|
|
@ -44,7 +45,7 @@ DefineConsoleMethod(CameraComponent, getForwardVector, VectorF, (), ,
|
|||
return returnVec;
|
||||
}
|
||||
|
||||
DefineConsoleMethod(CameraComponent, getRightVector, VectorF, (), ,
|
||||
DefineEngineMethod(CameraComponent, getRightVector, VectorF, (), ,
|
||||
"Get the number of static fields on the object.\n"
|
||||
"@return The number of static fields defined on the object.")
|
||||
{
|
||||
|
|
@ -58,7 +59,7 @@ DefineConsoleMethod(CameraComponent, getRightVector, VectorF, (), ,
|
|||
return returnVec;
|
||||
}
|
||||
|
||||
DefineConsoleMethod(CameraComponent, getUpVector, VectorF, (), ,
|
||||
DefineEngineMethod(CameraComponent, getUpVector, VectorF, (), ,
|
||||
"Get the number of static fields on the object.\n"
|
||||
"@return The number of static fields defined on the object.")
|
||||
{
|
||||
|
|
@ -72,14 +73,14 @@ DefineConsoleMethod(CameraComponent, getUpVector, VectorF, (), ,
|
|||
return returnVec;
|
||||
}
|
||||
|
||||
DefineConsoleMethod(CameraComponent, setForwardVector, void, (VectorF newForward), (VectorF(0, 0, 0)),
|
||||
DefineEngineMethod(CameraComponent, setForwardVector, void, (VectorF newForward), (VectorF(0, 0, 0)),
|
||||
"Get the number of static fields on the object.\n"
|
||||
"@return The number of static fields defined on the object.")
|
||||
{
|
||||
object->setForwardVector(newForward);
|
||||
}
|
||||
|
||||
DefineConsoleMethod(CameraComponent, getWorldPosition, Point3F, (), ,
|
||||
DefineEngineMethod(CameraComponent, getWorldPosition, Point3F, (), ,
|
||||
"Get the number of static fields on the object.\n"
|
||||
"@return The number of static fields defined on the object.")
|
||||
{
|
||||
|
|
|
|||
|
|
@ -125,8 +125,6 @@ EndImplementEnumType;
|
|||
//
|
||||
CollisionComponent::CollisionComponent() : Component()
|
||||
{
|
||||
mNetFlags.set(Ghostable | ScopeAlways);
|
||||
|
||||
mFriendlyName = "Collision(Component)";
|
||||
|
||||
mOwnerRenderInterface = NULL;
|
||||
|
|
@ -144,10 +142,12 @@ CollisionComponent::CollisionComponent() : Component()
|
|||
StaticShapeObjectType | VehicleObjectType |
|
||||
VehicleBlockerObjectType | DynamicShapeObjectType | StaticObjectType | EntityObjectType | TriggerObjectType);
|
||||
|
||||
mPhysicsRep = NULL;
|
||||
mPhysicsWorld = NULL;
|
||||
mPhysicsRep = nullptr;
|
||||
mPhysicsWorld = nullptr;
|
||||
|
||||
mTimeoutList = NULL;
|
||||
mTimeoutList = nullptr;
|
||||
|
||||
mAnimated = false;
|
||||
}
|
||||
|
||||
CollisionComponent::~CollisionComponent()
|
||||
|
|
|
|||
|
|
@ -24,21 +24,21 @@
|
|||
#include "T3D/components/collision/collisionComponent.h"
|
||||
#include "materials/baseMatInstance.h"
|
||||
|
||||
DefineConsoleMethod(CollisionComponent, getNumberOfContacts, S32, (), ,
|
||||
DefineEngineMethod(CollisionComponent, getNumberOfContacts, S32, (), ,
|
||||
"Gets the number of contacts this collider has hit.\n"
|
||||
"@return The number of static fields defined on the object.")
|
||||
{
|
||||
return object->getCollisionList()->getCount();
|
||||
}
|
||||
|
||||
DefineConsoleMethod(CollisionComponent, getBestContact, S32, (), ,
|
||||
DefineEngineMethod(CollisionComponent, getBestContact, S32, (), ,
|
||||
"Gets the number of contacts this collider has hit.\n"
|
||||
"@return The number of static fields defined on the object.")
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
DefineConsoleMethod(CollisionComponent, getContactNormal, Point3F, (), ,
|
||||
DefineEngineMethod(CollisionComponent, getContactNormal, Point3F, (), ,
|
||||
"Gets the number of contacts this collider has hit.\n"
|
||||
"@return The number of static fields defined on the object.")
|
||||
{
|
||||
|
|
@ -53,7 +53,7 @@ DefineConsoleMethod(CollisionComponent, getContactNormal, Point3F, (), ,
|
|||
return Point3F::Zero;
|
||||
}
|
||||
|
||||
DefineConsoleMethod(CollisionComponent, getContactMaterial, S32, (), ,
|
||||
DefineEngineMethod(CollisionComponent, getContactMaterial, S32, (), ,
|
||||
"Gets the number of contacts this collider has hit.\n"
|
||||
"@return The number of static fields defined on the object.")
|
||||
{
|
||||
|
|
@ -69,7 +69,7 @@ DefineConsoleMethod(CollisionComponent, getContactMaterial, S32, (), ,
|
|||
return 0;
|
||||
}
|
||||
|
||||
DefineConsoleMethod(CollisionComponent, getContactObject, S32, (), ,
|
||||
DefineEngineMethod(CollisionComponent, getContactObject, S32, (), ,
|
||||
"Gets the number of contacts this collider has hit.\n"
|
||||
"@return The number of static fields defined on the object.")
|
||||
{
|
||||
|
|
@ -81,7 +81,7 @@ DefineConsoleMethod(CollisionComponent, getContactObject, S32, (), ,
|
|||
return 0;
|
||||
}
|
||||
|
||||
DefineConsoleMethod(CollisionComponent, getContactPoint, Point3F, (), ,
|
||||
DefineEngineMethod(CollisionComponent, getContactPoint, Point3F, (), ,
|
||||
"Gets the number of contacts this collider has hit.\n"
|
||||
"@return The number of static fields defined on the object.")
|
||||
{
|
||||
|
|
@ -96,7 +96,7 @@ DefineConsoleMethod(CollisionComponent, getContactPoint, Point3F, (), ,
|
|||
return Point3F::Zero;
|
||||
}
|
||||
|
||||
DefineConsoleMethod(CollisionComponent, getContactTime, S32, (), ,
|
||||
DefineEngineMethod(CollisionComponent, getContactTime, S32, (), ,
|
||||
"Gets the number of contacts this collider has hit.\n"
|
||||
"@return The number of static fields defined on the object.")
|
||||
{
|
||||
|
|
|
|||
|
|
@ -357,12 +357,12 @@ void CollisionTrigger::setTriggerPolyhedron(const Polyhedron& rPolyhedron)
|
|||
{
|
||||
mCollisionTriggerPolyhedron = rPolyhedron;
|
||||
|
||||
if (mCollisionTriggerPolyhedron.pointList.size() != 0) {
|
||||
if (mCollisionTriggerPolyhedron.mPointList.size() != 0) {
|
||||
mObjBox.minExtents.set(1e10, 1e10, 1e10);
|
||||
mObjBox.maxExtents.set(-1e10, -1e10, -1e10);
|
||||
for (U32 i = 0; i < mCollisionTriggerPolyhedron.pointList.size(); i++) {
|
||||
mObjBox.minExtents.setMin(mCollisionTriggerPolyhedron.pointList[i]);
|
||||
mObjBox.maxExtents.setMax(mCollisionTriggerPolyhedron.pointList[i]);
|
||||
for (U32 i = 0; i < mCollisionTriggerPolyhedron.mPointList.size(); i++) {
|
||||
mObjBox.minExtents.setMin(mCollisionTriggerPolyhedron.mPointList[i]);
|
||||
mObjBox.maxExtents.setMax(mCollisionTriggerPolyhedron.mPointList[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -374,7 +374,7 @@ void CollisionTrigger::setTriggerPolyhedron(const Polyhedron& rPolyhedron)
|
|||
setTransform(xform);
|
||||
|
||||
mClippedList.clear();
|
||||
mClippedList.mPlaneList = mCollisionTriggerPolyhedron.planeList;
|
||||
mClippedList.mPlaneList = mCollisionTriggerPolyhedron.mPlaneList;
|
||||
// for (U32 i = 0; i < mClippedList.mPlaneList.size(); i++)
|
||||
// mClippedList.mPlaneList[i].neg();
|
||||
|
||||
|
|
@ -412,7 +412,7 @@ void CollisionTrigger::setTriggerPolyhedron(const Polyhedron& rPolyhedron)
|
|||
|
||||
bool CollisionTrigger::testObject(GameBase* enter)
|
||||
{
|
||||
if (mCollisionTriggerPolyhedron.pointList.size() == 0)
|
||||
if (mCollisionTriggerPolyhedron.mPointList.size() == 0)
|
||||
return false;
|
||||
|
||||
mClippedList.clear();
|
||||
|
|
@ -507,17 +507,17 @@ U32 CollisionTrigger::packUpdate(NetConnection* con, U32 mask, BitStream* stream
|
|||
// Write the polyhedron
|
||||
if (stream->writeFlag(mask & PolyMask))
|
||||
{
|
||||
stream->write(mCollisionTriggerPolyhedron.pointList.size());
|
||||
for (i = 0; i < mCollisionTriggerPolyhedron.pointList.size(); i++)
|
||||
mathWrite(*stream, mCollisionTriggerPolyhedron.pointList[i]);
|
||||
stream->write(mCollisionTriggerPolyhedron.mPointList.size());
|
||||
for (i = 0; i < mCollisionTriggerPolyhedron.mPointList.size(); i++)
|
||||
mathWrite(*stream, mCollisionTriggerPolyhedron.mPointList[i]);
|
||||
|
||||
stream->write(mCollisionTriggerPolyhedron.planeList.size());
|
||||
for (i = 0; i < mCollisionTriggerPolyhedron.planeList.size(); i++)
|
||||
mathWrite(*stream, mCollisionTriggerPolyhedron.planeList[i]);
|
||||
stream->write(mCollisionTriggerPolyhedron.mPlaneList.size());
|
||||
for (i = 0; i < mCollisionTriggerPolyhedron.mPlaneList.size(); i++)
|
||||
mathWrite(*stream, mCollisionTriggerPolyhedron.mPlaneList[i]);
|
||||
|
||||
stream->write(mCollisionTriggerPolyhedron.edgeList.size());
|
||||
for (i = 0; i < mCollisionTriggerPolyhedron.edgeList.size(); i++) {
|
||||
const Polyhedron::Edge& rEdge = mCollisionTriggerPolyhedron.edgeList[i];
|
||||
stream->write(mCollisionTriggerPolyhedron.mEdgeList.size());
|
||||
for (i = 0; i < mCollisionTriggerPolyhedron.mEdgeList.size(); i++) {
|
||||
const Polyhedron::Edge& rEdge = mCollisionTriggerPolyhedron.mEdgeList[i];
|
||||
|
||||
stream->write(rEdge.face[0]);
|
||||
stream->write(rEdge.face[1]);
|
||||
|
|
@ -555,19 +555,19 @@ void CollisionTrigger::unpackUpdate(NetConnection* con, BitStream* stream)
|
|||
{
|
||||
Polyhedron tempPH;
|
||||
stream->read(&size);
|
||||
tempPH.pointList.setSize(size);
|
||||
for (i = 0; i < tempPH.pointList.size(); i++)
|
||||
mathRead(*stream, &tempPH.pointList[i]);
|
||||
tempPH.mPointList.setSize(size);
|
||||
for (i = 0; i < tempPH.mPointList.size(); i++)
|
||||
mathRead(*stream, &tempPH.mPointList[i]);
|
||||
|
||||
stream->read(&size);
|
||||
tempPH.planeList.setSize(size);
|
||||
for (i = 0; i < tempPH.planeList.size(); i++)
|
||||
mathRead(*stream, &tempPH.planeList[i]);
|
||||
tempPH.mPlaneList.setSize(size);
|
||||
for (i = 0; i < tempPH.mPlaneList.size(); i++)
|
||||
mathRead(*stream, &tempPH.mPlaneList[i]);
|
||||
|
||||
stream->read(&size);
|
||||
tempPH.edgeList.setSize(size);
|
||||
for (i = 0; i < tempPH.edgeList.size(); i++) {
|
||||
Polyhedron::Edge& rEdge = tempPH.edgeList[i];
|
||||
tempPH.mEdgeList.setSize(size);
|
||||
for (i = 0; i < tempPH.mEdgeList.size(); i++) {
|
||||
Polyhedron::Edge& rEdge = tempPH.mEdgeList[i];
|
||||
|
||||
stream->read(&rEdge.face[0]);
|
||||
stream->read(&rEdge.face[1]);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "console/engineAPI.h"
|
||||
#include "sim/netConnection.h"
|
||||
#include "console/consoleInternal.h"
|
||||
#include "T3D/assets/MaterialAsset.h"
|
||||
|
||||
#define DECLARE_NATIVE_COMPONENT( ComponentType ) \
|
||||
Component* staticComponentTemplate = new ComponentType; \
|
||||
|
|
@ -42,17 +43,16 @@
|
|||
|
||||
Component::Component()
|
||||
{
|
||||
mFriendlyName = StringTable->lookup("");
|
||||
mFromResource = StringTable->lookup("");
|
||||
mComponentType = StringTable->lookup("");
|
||||
mComponentGroup = StringTable->lookup("");
|
||||
mNetworkType = StringTable->lookup("");
|
||||
mTemplateName = StringTable->lookup("");
|
||||
//mDependency = StringTable->lookup("");
|
||||
mFriendlyName = StringTable->EmptyString();
|
||||
mFromResource = StringTable->EmptyString();
|
||||
mComponentType = StringTable->EmptyString();
|
||||
mComponentGroup = StringTable->EmptyString();
|
||||
mNetworkType = StringTable->EmptyString();
|
||||
mTemplateName = StringTable->EmptyString();
|
||||
//mDependency = StringTable->EmptyString();
|
||||
|
||||
mNetworked = false;
|
||||
|
||||
|
||||
// [tom, 1/12/2007] We manage the memory for the description since it
|
||||
// could be loaded from a file and thus massive. This is accomplished with
|
||||
// protected fields, but since they still call Con::getData() the field
|
||||
|
|
@ -64,7 +64,16 @@ Component::Component()
|
|||
|
||||
mCanSaveFieldDictionary = false;
|
||||
|
||||
mNetFlags.set(Ghostable);
|
||||
mOriginatingAssetId = StringTable->EmptyString();
|
||||
|
||||
mIsServerObject = true;
|
||||
|
||||
componentIdx = 0;
|
||||
|
||||
mHidden = false;
|
||||
mEnabled = true;
|
||||
|
||||
mDirtyMaskBits = 0;
|
||||
}
|
||||
|
||||
Component::~Component()
|
||||
|
|
@ -97,6 +106,10 @@ void Component::initPersistFields()
|
|||
|
||||
//addField("hidden", TypeBool, Offset(mHidden, Component), "Flags if this behavior is shown in the editor or not", AbstractClassRep::FieldFlags::FIELD_HideInInspectors);
|
||||
addProtectedField("enabled", TypeBool, Offset(mEnabled, Component), &_setEnabled, &defaultProtectedGetFn, "");
|
||||
|
||||
addField("originatingAsset", TypeComponentAssetPtr, Offset(mOriginatingAsset, Component),
|
||||
"Asset that spawned this component, used for tracking/housekeeping", AbstractClassRep::FieldFlags::FIELD_HideInInspectors);
|
||||
|
||||
endGroup("Component");
|
||||
|
||||
Parent::initPersistFields();
|
||||
|
|
@ -149,6 +162,7 @@ bool Component::onAdd()
|
|||
return false;
|
||||
|
||||
setMaskBits(UpdateMask);
|
||||
setMaskBits(NamespaceMask);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -191,7 +205,6 @@ void Component::onComponentRemove()
|
|||
{
|
||||
mOwner->onComponentAdded.remove(this, &Component::componentAddedToOwner);
|
||||
mOwner->onComponentRemoved.remove(this, &Component::componentRemovedFromOwner);
|
||||
mOwner->onTransformSet.remove(this, &Component::ownerTransformSet);
|
||||
}
|
||||
|
||||
mOwner = NULL;
|
||||
|
|
@ -205,7 +218,6 @@ void Component::setOwner(Entity* owner)
|
|||
{
|
||||
mOwner->onComponentAdded.remove(this, &Component::componentAddedToOwner);
|
||||
mOwner->onComponentRemoved.remove(this, &Component::componentRemovedFromOwner);
|
||||
mOwner->onTransformSet.remove(this, &Component::ownerTransformSet);
|
||||
|
||||
mOwner->removeComponent(this, false);
|
||||
}
|
||||
|
|
@ -216,11 +228,18 @@ void Component::setOwner(Entity* owner)
|
|||
{
|
||||
mOwner->onComponentAdded.notify(this, &Component::componentAddedToOwner);
|
||||
mOwner->onComponentRemoved.notify(this, &Component::componentRemovedFromOwner);
|
||||
mOwner->onTransformSet.notify(this, &Component::ownerTransformSet);
|
||||
}
|
||||
|
||||
if (isServerObject())
|
||||
{
|
||||
setMaskBits(OwnerMask);
|
||||
|
||||
//if we have any outstanding maskbits, push them along to have the network update happen on the entity
|
||||
if (mDirtyMaskBits != 0 && mOwner)
|
||||
{
|
||||
mOwner->setMaskBits(Entity::ComponentsUpdateMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Component::componentAddedToOwner(Component *comp)
|
||||
|
|
@ -233,16 +252,19 @@ void Component::componentRemovedFromOwner(Component *comp)
|
|||
return;
|
||||
}
|
||||
|
||||
void Component::ownerTransformSet(MatrixF *mat)
|
||||
void Component::setMaskBits(U32 orMask)
|
||||
{
|
||||
return;
|
||||
AssertFatal(orMask != 0, "Invalid net mask bits set.");
|
||||
|
||||
if (mOwner)
|
||||
mOwner->setComponentNetMask(this, orMask);
|
||||
}
|
||||
|
||||
U32 Component::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
||||
{
|
||||
U32 retMask = Parent::packUpdate(con, mask, stream);
|
||||
U32 retMask = 0;
|
||||
|
||||
if (mask & OwnerMask)
|
||||
/*if (mask & OwnerMask)
|
||||
{
|
||||
if (mOwner != NULL)
|
||||
{
|
||||
|
|
@ -267,21 +289,32 @@ U32 Component::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|||
}
|
||||
}
|
||||
else
|
||||
stream->writeFlag(false);
|
||||
stream->writeFlag(false);*/
|
||||
|
||||
if (stream->writeFlag(mask & EnableMask))
|
||||
{
|
||||
stream->writeFlag(mEnabled);
|
||||
}
|
||||
|
||||
/*if (stream->writeFlag(mask & NamespaceMask))
|
||||
{
|
||||
const char* name = getName();
|
||||
if (stream->writeFlag(name && name[0]))
|
||||
stream->writeString(String(name));
|
||||
|
||||
if (stream->writeFlag(mSuperClassName && mSuperClassName[0]))
|
||||
stream->writeString(String(mSuperClassName));
|
||||
|
||||
if (stream->writeFlag(mClassName && mClassName[0]))
|
||||
stream->writeString(String(mClassName));
|
||||
}*/
|
||||
|
||||
return retMask;
|
||||
}
|
||||
|
||||
void Component::unpackUpdate(NetConnection *con, BitStream *stream)
|
||||
{
|
||||
Parent::unpackUpdate(con, stream);
|
||||
|
||||
if (stream->readFlag())
|
||||
/*if (stream->readFlag())
|
||||
{
|
||||
if (stream->readFlag())
|
||||
{
|
||||
|
|
@ -297,12 +330,38 @@ void Component::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
//it's being nulled out
|
||||
setOwner(NULL);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
if (stream->readFlag())
|
||||
{
|
||||
mEnabled = stream->readFlag();
|
||||
}
|
||||
|
||||
/*if (stream->readFlag())
|
||||
{
|
||||
if (stream->readFlag())
|
||||
{
|
||||
char name[256];
|
||||
stream->readString(name);
|
||||
assignName(name);
|
||||
}
|
||||
|
||||
if (stream->readFlag())
|
||||
{
|
||||
char superClassname[256];
|
||||
stream->readString(superClassname);
|
||||
mSuperClassName = superClassname;
|
||||
}
|
||||
|
||||
if (stream->readFlag())
|
||||
{
|
||||
char classname[256];
|
||||
stream->readString(classname);
|
||||
mClassName = classname;
|
||||
}
|
||||
|
||||
linkNamespaces();
|
||||
}*/
|
||||
}
|
||||
|
||||
void Component::packToStream(Stream &stream, U32 tabStop, S32 behaviorID, U32 flags /* = 0 */)
|
||||
|
|
@ -346,6 +405,10 @@ void Component::setDataField(StringTableEntry slotName, const char *array, const
|
|||
onDataSet.trigger(this, slotName, value);
|
||||
}
|
||||
|
||||
StringTableEntry Component::getComponentName()
|
||||
{
|
||||
return getNamespace()->getName();
|
||||
}
|
||||
|
||||
//catch any behavior field updates
|
||||
void Component::onStaticModified(const char* slotName, const char* newValue)
|
||||
|
|
@ -417,7 +480,7 @@ void Component::addComponentField(const char *fieldName, const char *desc, const
|
|||
else if (fieldType == StringTable->insert("vector"))
|
||||
fieldTypeMask = TypePoint3F;
|
||||
else if (fieldType == StringTable->insert("material"))
|
||||
fieldTypeMask = TypeMaterialName;
|
||||
fieldTypeMask = TypeMaterialAssetPtr;
|
||||
else if (fieldType == StringTable->insert("image"))
|
||||
fieldTypeMask = TypeImageFilename;
|
||||
else if (fieldType == StringTable->insert("shape"))
|
||||
|
|
@ -426,8 +489,19 @@ void Component::addComponentField(const char *fieldName, const char *desc, const
|
|||
fieldTypeMask = TypeBool;
|
||||
else if (fieldType == StringTable->insert("object"))
|
||||
fieldTypeMask = TypeSimObjectPtr;
|
||||
else if (fieldType == StringTable->insert("string"))
|
||||
fieldTypeMask = TypeString;
|
||||
else if (fieldType == StringTable->insert("colorI"))
|
||||
fieldTypeMask = TypeColorI;
|
||||
else if (fieldType == StringTable->insert("colorF"))
|
||||
fieldTypeMask = TypeColorF;
|
||||
else if (fieldType == StringTable->insert("ease"))
|
||||
fieldTypeMask = TypeEaseF;
|
||||
else if (fieldType == StringTable->insert("gameObject"))
|
||||
fieldTypeMask = TypeGameObjectAssetPtr;
|
||||
else
|
||||
fieldTypeMask = TypeString;
|
||||
field.mFieldTypeName = fieldType;
|
||||
|
||||
field.mFieldType = fieldTypeMask;
|
||||
|
||||
|
|
@ -468,13 +542,14 @@ const char * Component::getDescriptionText(const char *desc)
|
|||
if (desc == NULL)
|
||||
return NULL;
|
||||
|
||||
char *newDesc;
|
||||
char *newDesc = "";
|
||||
|
||||
// [tom, 1/12/2007] If it isn't a file, just do it the easy way
|
||||
if (!Platform::isFile(desc))
|
||||
{
|
||||
newDesc = new char[dStrlen(desc) + 1];
|
||||
dStrcpy(newDesc, desc);
|
||||
dsize_t newDescLen = dStrlen(desc) + 1;
|
||||
newDesc = new char[newDescLen];
|
||||
dStrcpy(newDesc, desc, newDescLen);
|
||||
|
||||
return newDesc;
|
||||
}
|
||||
|
|
@ -501,7 +576,7 @@ const char * Component::getDescriptionText(const char *desc)
|
|||
}
|
||||
|
||||
str.close();
|
||||
delete stream;
|
||||
//delete stream;
|
||||
|
||||
return newDesc;
|
||||
}
|
||||
|
|
@ -530,8 +605,8 @@ void Component::addDependency(StringTableEntry name)
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
// Console Methods
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ConsoleMethod(Component, beginGroup, void, 3, 3, "(groupName)\n"
|
||||
"Starts the grouping for following fields being added to be grouped into\n"
|
||||
DefineEngineMethod(Component, beginGroup, void, (String groupName),,
|
||||
"@brief Starts the grouping for following fields being added to be grouped into\n"
|
||||
"@param groupName The name of this group\n"
|
||||
"@param desc The Description of this field\n"
|
||||
"@param type The DataType for this field (default, int, float, Point2F, bool, enum, Object, keybind, color)\n"
|
||||
|
|
@ -541,11 +616,11 @@ ConsoleMethod(Component, beginGroup, void, 3, 3, "(groupName)\n"
|
|||
"-object: the T2D object type that are valid choices for the field. The object types observe inheritance, so if you have a t2dSceneObject field you will be able to choose t2dStaticSrpites, t2dAnimatedSprites, etc.\n"
|
||||
"@return Nothing\n")
|
||||
{
|
||||
object->beginFieldGroup(argv[2]);
|
||||
object->beginFieldGroup(groupName);
|
||||
}
|
||||
|
||||
ConsoleMethod(Component, endGroup, void, 2, 2, "()\n"
|
||||
"Ends the grouping for prior fields being added to be grouped into\n"
|
||||
DefineEngineMethod(Component, endGroup, void, (),,
|
||||
"@brief Ends the grouping for prior fields being added to be grouped into\n"
|
||||
"@param groupName The name of this group\n"
|
||||
"@param desc The Description of this field\n"
|
||||
"@param type The DataType for this field (default, int, float, Point2F, bool, enum, Object, keybind, color)\n"
|
||||
|
|
@ -558,7 +633,7 @@ ConsoleMethod(Component, endGroup, void, 2, 2, "()\n"
|
|||
object->endFieldGroup();
|
||||
}
|
||||
|
||||
DefineConsoleMethod(Component, addComponentField, void, (String fieldName, String fieldDesc, String fieldType, String defValue, String userData, bool hidden),
|
||||
DefineEngineMethod(Component, addComponentField, void, (String fieldName, String fieldDesc, String fieldType, String defValue, String userData, bool hidden),
|
||||
("", "", "", "", "", false),
|
||||
"Get the number of static fields on the object.\n"
|
||||
"@return The number of static fields defined on the object.")
|
||||
|
|
@ -566,7 +641,8 @@ DefineConsoleMethod(Component, addComponentField, void, (String fieldName, Strin
|
|||
object->addComponentField(fieldName, fieldDesc, fieldType, defValue, userData, hidden);
|
||||
}
|
||||
|
||||
ConsoleMethod(Component, getComponentFieldCount, S32, 2, 2, "() - Get the number of ComponentField's on this object\n"
|
||||
DefineEngineMethod(Component, getComponentFieldCount, S32, (),,
|
||||
"@brief Get the number of ComponentField's on this object\n"
|
||||
"@return Returns the number of BehaviorFields as a nonnegative integer\n")
|
||||
{
|
||||
return object->getComponentFieldCount();
|
||||
|
|
@ -575,11 +651,12 @@ ConsoleMethod(Component, getComponentFieldCount, S32, 2, 2, "() - Get the number
|
|||
// [tom, 1/12/2007] Field accessors split into multiple methods to allow space
|
||||
// for long descriptions and type data.
|
||||
|
||||
ConsoleMethod(Component, getComponentField, const char *, 3, 3, "(int index) - Gets a Tab-Delimited list of information about a ComponentField specified by Index\n"
|
||||
DefineEngineMethod(Component, getComponentField, const char *, (S32 index),,
|
||||
"@brief Gets a Tab-Delimited list of information about a ComponentField specified by Index\n"
|
||||
"@param index The index of the behavior\n"
|
||||
"@return FieldName, FieldType and FieldDefaultValue, each separated by a TAB character.\n")
|
||||
{
|
||||
ComponentField *field = object->getComponentField(dAtoi(argv[2]));
|
||||
ComponentField *field = object->getComponentField(index);
|
||||
if (field == NULL)
|
||||
return "";
|
||||
|
||||
|
|
@ -589,11 +666,12 @@ ConsoleMethod(Component, getComponentField, const char *, 3, 3, "(int index) - G
|
|||
return buf;
|
||||
}
|
||||
|
||||
ConsoleMethod(Component, setComponentield, const char *, 3, 3, "(int index) - Gets a Tab-Delimited list of information about a ComponentField specified by Index\n"
|
||||
DefineEngineMethod(Component, setComponentield, const char *, (S32 index),,
|
||||
"@brief Gets a Tab-Delimited list of information about a ComponentField specified by Index\n"
|
||||
"@param index The index of the behavior\n"
|
||||
"@return FieldName, FieldType and FieldDefaultValue, each separated by a TAB character.\n")
|
||||
{
|
||||
ComponentField *field = object->getComponentField(dAtoi(argv[2]));
|
||||
ComponentField *field = object->getComponentField(index);
|
||||
if (field == NULL)
|
||||
return "";
|
||||
|
||||
|
|
@ -603,36 +681,51 @@ ConsoleMethod(Component, setComponentield, const char *, 3, 3, "(int index) - Ge
|
|||
return buf;
|
||||
}
|
||||
|
||||
ConsoleMethod(Component, getBehaviorFieldUserData, const char *, 3, 3, "(int index) - Gets the UserData associated with a field by index in the field list\n"
|
||||
DefineEngineMethod(Component, getComponentFieldType, const char *, (String fieldName), ,
|
||||
"Get the number of static fields on the object.\n"
|
||||
"@return The number of static fields defined on the object.")
|
||||
{
|
||||
ComponentField *field = object->getComponentField(fieldName);
|
||||
if (field == NULL)
|
||||
return "";
|
||||
|
||||
return field->mFieldTypeName;;
|
||||
}
|
||||
|
||||
DefineEngineMethod(Component, getBehaviorFieldUserData, const char *, (S32 index),,
|
||||
"@brief Gets the UserData associated with a field by index in the field list\n"
|
||||
"@param index The index of the behavior\n"
|
||||
"@return Returns a string representing the user data of this field\n")
|
||||
{
|
||||
ComponentField *field = object->getComponentField(dAtoi(argv[2]));
|
||||
ComponentField *field = object->getComponentField(index);
|
||||
if (field == NULL)
|
||||
return "";
|
||||
|
||||
return field->mUserData;
|
||||
}
|
||||
|
||||
ConsoleMethod(Component, getComponentFieldDescription, const char *, 3, 3, "(int index) - Gets a field description by index\n"
|
||||
DefineEngineMethod(Component, getComponentFieldDescription, const char *, (S32 index),,
|
||||
"@brief Gets a field description by index\n"
|
||||
"@param index The index of the behavior\n"
|
||||
"@return Returns a string representing the description of this field\n")
|
||||
{
|
||||
ComponentField *field = object->getComponentField(dAtoi(argv[2]));
|
||||
ComponentField *field = object->getComponentField(index);
|
||||
if (field == NULL)
|
||||
return "";
|
||||
|
||||
return field->mFieldDescription ? field->mFieldDescription : "";
|
||||
}
|
||||
|
||||
ConsoleMethod(Component, addDependency, void, 3, 3, "(string behaviorName) - Gets a field description by index\n"
|
||||
DefineEngineMethod(Component, addDependency, void, (String behaviorName),,
|
||||
"@brief Gets a field description by index\n"
|
||||
"@param index The index of the behavior\n"
|
||||
"@return Returns a string representing the description of this field\n")
|
||||
{
|
||||
object->addDependency(argv[2]);
|
||||
object->addDependency(behaviorName);
|
||||
}
|
||||
|
||||
ConsoleMethod(Component, setDirty, void, 2, 2, "() - Gets a field description by index\n"
|
||||
DefineEngineMethod(Component, setDirty, void, (),,
|
||||
"@brief Gets a field description by index\n"
|
||||
"@param index The index of the behavior\n"
|
||||
"@return Returns a string representing the description of this field\n")
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,14 +32,22 @@
|
|||
#ifndef CORE_INTERFACES_H
|
||||
#include "T3D/components/coreInterfaces.h"
|
||||
#endif
|
||||
#ifndef _ASSET_PTR_H_
|
||||
#include "assets/assetPtr.h"
|
||||
#endif
|
||||
#ifndef COMPONENT_ASSET_H
|
||||
#include "T3D/assets/ComponentAsset.h"
|
||||
#endif
|
||||
|
||||
class Entity;
|
||||
class Namespace;
|
||||
|
||||
struct ComponentField
|
||||
{
|
||||
StringTableEntry mFieldName;
|
||||
StringTableEntry mFieldDescription;
|
||||
|
||||
StringTableEntry mFieldTypeName;
|
||||
S32 mFieldType;
|
||||
StringTableEntry mUserData;
|
||||
|
||||
|
|
@ -56,9 +64,9 @@ struct ComponentField
|
|||
///
|
||||
///
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class Component : public NetObject, public UpdateInterface
|
||||
class Component : public SimObject, public UpdateInterface
|
||||
{
|
||||
typedef NetObject Parent;
|
||||
typedef SimObject Parent;
|
||||
|
||||
protected:
|
||||
StringTableEntry mFriendlyName;
|
||||
|
|
@ -81,6 +89,13 @@ protected:
|
|||
bool mHidden;
|
||||
bool mEnabled;
|
||||
|
||||
StringTableEntry mOriginatingAssetId;
|
||||
AssetPtr<ComponentAsset> mOriginatingAsset;
|
||||
|
||||
U32 mDirtyMaskBits;
|
||||
|
||||
bool mIsServerObject;
|
||||
|
||||
public:
|
||||
Component();
|
||||
virtual ~Component();
|
||||
|
|
@ -102,7 +117,8 @@ public:
|
|||
//This is called when a different component is removed from our owner entity
|
||||
virtual void componentRemovedFromOwner(Component *comp);
|
||||
|
||||
virtual void ownerTransformSet(MatrixF *mat);
|
||||
//Overridden by components that actually care
|
||||
virtual void ownerTransformSet(MatrixF *mat) {}
|
||||
|
||||
void setOwner(Entity* pOwner);
|
||||
inline Entity *getOwner() { return mOwner ? mOwner : NULL; }
|
||||
|
|
@ -175,9 +191,20 @@ public:
|
|||
OwnerMask = BIT(1),
|
||||
UpdateMask = BIT(2),
|
||||
EnableMask = BIT(3),
|
||||
NextFreeMask = BIT(4)
|
||||
NamespaceMask = BIT(4),
|
||||
NextFreeMask = BIT(5)
|
||||
};
|
||||
|
||||
virtual void setMaskBits(U32 orMask);
|
||||
virtual void clearMaskBits() {
|
||||
mDirtyMaskBits = 0;
|
||||
}
|
||||
|
||||
bool isServerObject() { return mIsServerObject; }
|
||||
bool isClientObject() { return !mIsServerObject; }
|
||||
|
||||
void setIsServerObject(bool isServerObj) { mIsServerObject = isServerObj; }
|
||||
|
||||
virtual U32 packUpdate(NetConnection *con, U32 mask, BitStream *stream);
|
||||
virtual void unpackUpdate(NetConnection *con, BitStream *stream);
|
||||
/// @}
|
||||
|
|
@ -192,6 +219,8 @@ public:
|
|||
void checkComponentFieldModified(const char* slotName, const char* newValue);
|
||||
|
||||
virtual void checkDependencies(){}
|
||||
|
||||
StringTableEntry getComponentName();
|
||||
};
|
||||
|
||||
#endif // COMPONENT_H
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ StateMachine::StateMachine()
|
|||
mStartingState = "";
|
||||
|
||||
mCurCreateState = NULL;
|
||||
|
||||
mStateMachineFile = StringTable->EmptyString();
|
||||
|
||||
mCurCreateState = nullptr;
|
||||
}
|
||||
|
||||
StateMachine::~StateMachine()
|
||||
|
|
|
|||
|
|
@ -158,6 +158,8 @@ public:
|
|||
{
|
||||
if (index <= mFields.size())
|
||||
return mFields[index];
|
||||
|
||||
return StateField(); //return a blank one
|
||||
}
|
||||
|
||||
Signal< void(StateMachine*, S32 stateIdx) > onStateChanged;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ StateMachineComponent::StateMachineComponent() : Component()
|
|||
|
||||
//doesn't need to be networked
|
||||
mNetworked = false;
|
||||
mNetFlags.clear();
|
||||
}
|
||||
|
||||
StateMachineComponent::~StateMachineComponent()
|
||||
|
|
|
|||
|
|
@ -119,8 +119,11 @@ PlayerControllerComponent::PlayerControllerComponent() : Component()
|
|||
|
||||
mInputVelocity = Point3F(0, 0, 0);
|
||||
|
||||
mPhysicsRep = NULL;
|
||||
mPhysicsWorld = NULL;
|
||||
mPhysicsRep = nullptr;
|
||||
mPhysicsWorld = nullptr;
|
||||
|
||||
mOwnerCollisionInterface = nullptr;
|
||||
mIntegrationCount = 0;
|
||||
}
|
||||
|
||||
PlayerControllerComponent::~PlayerControllerComponent()
|
||||
|
|
@ -330,93 +333,6 @@ void PlayerControllerComponent::updateMove()
|
|||
bool doStandardMove = true;
|
||||
GameConnection* con = mOwner->getControllingClient();
|
||||
|
||||
#ifdef TORQUE_EXTENDED_MOVE
|
||||
// Work with an absolute rotation from the ExtendedMove class?
|
||||
if (con && con->getControlSchemeAbsoluteRotation())
|
||||
{
|
||||
doStandardMove = false;
|
||||
const ExtendedMove* emove = dynamic_cast<const ExtendedMove*>(move);
|
||||
U32 emoveIndex = smExtendedMoveHeadPosRotIndex;
|
||||
if (emoveIndex >= ExtendedMove::MaxPositionsRotations)
|
||||
emoveIndex = 0;
|
||||
|
||||
if (emove->EulerBasedRotation[emoveIndex])
|
||||
{
|
||||
// Head pitch
|
||||
mHead.x += (emove->rotX[emoveIndex] - mLastAbsolutePitch);
|
||||
|
||||
// Do we also include the relative yaw value?
|
||||
if (con->getControlSchemeAddPitchToAbsRot())
|
||||
{
|
||||
F32 x = move->pitch;
|
||||
if (x > M_PI_F)
|
||||
x -= M_2PI_F;
|
||||
|
||||
mHead.x += x;
|
||||
}
|
||||
|
||||
// Constrain the range of mHead.x
|
||||
while (mHead.x < -M_PI_F)
|
||||
mHead.x += M_2PI_F;
|
||||
while (mHead.x > M_PI_F)
|
||||
mHead.x -= M_2PI_F;
|
||||
|
||||
// Rotate (heading) head or body?
|
||||
if (move->freeLook && ((isMounted() && getMountNode() == 0) || (con && !con->isFirstPerson())))
|
||||
{
|
||||
// Rotate head
|
||||
mHead.z += (emove->rotZ[emoveIndex] - mLastAbsoluteYaw);
|
||||
|
||||
// Do we also include the relative yaw value?
|
||||
if (con->getControlSchemeAddYawToAbsRot())
|
||||
{
|
||||
F32 z = move->yaw;
|
||||
if (z > M_PI_F)
|
||||
z -= M_2PI_F;
|
||||
|
||||
mHead.z += z;
|
||||
}
|
||||
|
||||
// Constrain the range of mHead.z
|
||||
while (mHead.z < 0.0f)
|
||||
mHead.z += M_2PI_F;
|
||||
while (mHead.z > M_2PI_F)
|
||||
mHead.z -= M_2PI_F;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rotate body
|
||||
mRot.z += (emove->rotZ[emoveIndex] - mLastAbsoluteYaw);
|
||||
|
||||
// Do we also include the relative yaw value?
|
||||
if (con->getControlSchemeAddYawToAbsRot())
|
||||
{
|
||||
F32 z = move->yaw;
|
||||
if (z > M_PI_F)
|
||||
z -= M_2PI_F;
|
||||
|
||||
mRot.z += z;
|
||||
}
|
||||
|
||||
// Constrain the range of mRot.z
|
||||
while (mRot.z < 0.0f)
|
||||
mRot.z += M_2PI_F;
|
||||
while (mRot.z > M_2PI_F)
|
||||
mRot.z -= M_2PI_F;
|
||||
}
|
||||
mLastAbsoluteYaw = emove->rotZ[emoveIndex];
|
||||
mLastAbsolutePitch = emove->rotX[emoveIndex];
|
||||
|
||||
// Head bank
|
||||
mHead.y = emove->rotY[emoveIndex];
|
||||
|
||||
// Constrain the range of mHead.y
|
||||
while (mHead.y > M_PI_F)
|
||||
mHead.y -= M_2PI_F;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
MatrixF zRot;
|
||||
zRot.set(EulerF(0.0f, 0.0f, mOwner->getRotation().asEulerF().z));
|
||||
|
||||
|
|
@ -525,16 +441,15 @@ void PlayerControllerComponent::updateMove()
|
|||
|
||||
// get the head pitch and add it to the moveVec
|
||||
// This more accurate swim vector calc comes from Matt Fairfax
|
||||
MatrixF xRot, zRot;
|
||||
MatrixF xRot;
|
||||
xRot.set(EulerF(mOwner->getRotation().asEulerF().x, 0, 0));
|
||||
zRot.set(EulerF(0, 0, mOwner->getRotation().asEulerF().z));
|
||||
zRot.set(EulerF(0, 0, mOwner->getRotation().asEulerF().z));//reset prior uses
|
||||
MatrixF rot;
|
||||
rot.mul(zRot, xRot);
|
||||
rot.getColumn(0, &moveVec);
|
||||
|
||||
moveVec *= move->x;
|
||||
VectorF tv;
|
||||
rot.getColumn(1, &tv);
|
||||
rot.getColumn(1, &tv);//reset prior uses
|
||||
moveVec += tv * move->y;
|
||||
rot.getColumn(2, &tv);
|
||||
moveVec += tv * move->z;
|
||||
|
|
|
|||
|
|
@ -288,7 +288,7 @@ void RigidBodyComponent::processTick()
|
|||
return;
|
||||
|
||||
// SINGLE PLAYER HACK!!!!
|
||||
if (PHYSICSMGR->isSinglePlayer() && isClientObject() && getServerObject())
|
||||
/*if (PHYSICSMGR->isSinglePlayer() && isClientObject() && getServerObject())
|
||||
{
|
||||
RigidBodyComponent *servObj = (RigidBodyComponent*)getServerObject();
|
||||
mOwner->setTransform(servObj->mState.getTransform());
|
||||
|
|
@ -296,7 +296,7 @@ void RigidBodyComponent::processTick()
|
|||
mRenderState[1] = servObj->mRenderState[1];
|
||||
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
// Store the last render state.
|
||||
mRenderState[0] = mRenderState[1];
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include "lighting/lightQuery.h"
|
||||
#include "scene/sceneManager.h"
|
||||
#include "gfx/bitmap/ddsFile.h"
|
||||
#include "gfx/bitmap/ddsUtils.h"
|
||||
#include "gfx/gfxTextureManager.h"
|
||||
#include "materials/materialFeatureTypes.h"
|
||||
#include "renderInstance/renderImposterMgr.h"
|
||||
|
|
@ -46,52 +45,49 @@
|
|||
#include "core/strings/findMatch.h"
|
||||
#include "T3D/components/render/meshComponent_ScriptBinding.h"
|
||||
|
||||
ImplementEnumType(BatchingMode,
|
||||
"Type of mesh data available in a shape.\n"
|
||||
"@ingroup gameObjects")
|
||||
{
|
||||
MeshComponent::Individual, "Individual", "This mesh is rendered indivudally, wthout batching or instancing."
|
||||
},
|
||||
{ MeshComponent::StaticBatch, "Static Batching", "Statically batches this mesh together with others to reduce drawcalls." },
|
||||
//{ MeshComponent::DynamicBatch, "Dynamic Batching", "Dynamical batches this mesh together with others to reduce drawcalls each frame." },
|
||||
// { MeshComponent::Instanced, "Instanced", "This mesh is rendered as an instance, reducing draw overhead with others that share the same mesh and material." },
|
||||
EndImplementEnumType;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Constructor/Destructor
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
MeshComponent::MeshComponent() : Component()
|
||||
MeshComponent::MeshComponent() : Component(), mShape(nullptr), mRenderMode(Individual)
|
||||
{
|
||||
mShapeName = StringTable->insert("");
|
||||
mShapeAsset = StringTable->insert("");
|
||||
mShapeInstance = NULL;
|
||||
|
||||
mChangingMaterials.clear();
|
||||
|
||||
mMaterials.clear();
|
||||
|
||||
mFriendlyName = "Mesh Component";
|
||||
mComponentType = "Render";
|
||||
|
||||
mDescription = getDescriptionText("Causes the object to render a non-animating 3d shape using the file provided.");
|
||||
|
||||
mNetworked = true;
|
||||
mNetFlags.set(Ghostable | ScopeAlways);
|
||||
|
||||
mShapeName = StringTable->EmptyString();
|
||||
mShapeAsset = StringTable->EmptyString();
|
||||
|
||||
mMeshAsset = StringTable->EmptyString();
|
||||
mMeshAssetId = StringTable->EmptyString();
|
||||
|
||||
mInterfaceData = new MeshRenderSystemInterface();
|
||||
|
||||
mRenderMode = Individual;
|
||||
}
|
||||
|
||||
MeshComponent::~MeshComponent(){}
|
||||
MeshComponent::~MeshComponent()
|
||||
{
|
||||
if (mInterfaceData)
|
||||
SAFE_DELETE(mInterfaceData);
|
||||
}
|
||||
|
||||
IMPLEMENT_CO_NETOBJECT_V1(MeshComponent);
|
||||
|
||||
//==========================================================================================
|
||||
void MeshComponent::boneObject::addObject(SimObject* object)
|
||||
{
|
||||
SceneObject* sc = dynamic_cast<SceneObject*>(object);
|
||||
|
||||
if(sc && mOwner)
|
||||
{
|
||||
if(TSShape* shape = mOwner->getShape())
|
||||
{
|
||||
S32 nodeID = shape->findNode(mBoneName);
|
||||
|
||||
//we may have a offset on the shape's center
|
||||
//so make sure we accomodate for that when setting up the mount offsets
|
||||
MatrixF mat = mOwner->getNodeTransform(nodeID);
|
||||
|
||||
mOwner->getOwner()->mountObject(sc, nodeID, mat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MeshComponent::onAdd()
|
||||
{
|
||||
if(! Parent::onAdd())
|
||||
|
|
@ -107,6 +103,12 @@ void MeshComponent::onComponentAdd()
|
|||
{
|
||||
Parent::onComponentAdd();
|
||||
|
||||
if (isClientObject())
|
||||
mInterfaceData->mIsClient = true;
|
||||
|
||||
// if (mInterfaceData != nullptr)
|
||||
// mInterfaceData->mIsClient = isClientObject();
|
||||
|
||||
//get the default shape, if any
|
||||
updateShape();
|
||||
}
|
||||
|
|
@ -114,10 +116,6 @@ void MeshComponent::onComponentAdd()
|
|||
void MeshComponent::onRemove()
|
||||
{
|
||||
Parent::onRemove();
|
||||
|
||||
mMeshAsset.clear();
|
||||
|
||||
SAFE_DELETE(mShapeInstance);
|
||||
}
|
||||
|
||||
void MeshComponent::onComponentRemove()
|
||||
|
|
@ -136,9 +134,14 @@ void MeshComponent::initPersistFields()
|
|||
{
|
||||
Parent::initPersistFields();
|
||||
|
||||
addGroup("Rendering");
|
||||
addField("BatchingMode", TypeBatchingMode, Offset(mRenderMode, MeshComponent),
|
||||
"The mode of batching this shape should be rendered with.");
|
||||
endGroup("Rendering");
|
||||
|
||||
//create a hook to our internal variables
|
||||
addGroup("Model");
|
||||
addProtectedField("MeshAsset", TypeAssetId, Offset(mShapeAsset, MeshComponent), &_setMesh, &defaultProtectedGetFn,
|
||||
addProtectedField("MeshAsset", TypeShapeAssetPtr, Offset(mShapeAsset, MeshComponent), &_setMesh, &defaultProtectedGetFn,
|
||||
"The asset Id used for the mesh.", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
|
||||
endGroup("Model");
|
||||
}
|
||||
|
|
@ -166,6 +169,9 @@ bool MeshComponent::_setShape( void *object, const char *index, const char *data
|
|||
bool MeshComponent::setMeshAsset(const char* assetName)
|
||||
{
|
||||
// Fetch the asset Id.
|
||||
if (mInterfaceData == nullptr)
|
||||
return false;
|
||||
|
||||
mMeshAssetId = StringTable->insert(assetName);
|
||||
|
||||
mMeshAsset = mMeshAssetId;
|
||||
|
|
@ -184,9 +190,129 @@ bool MeshComponent::setMeshAsset(const char* assetName)
|
|||
return true;
|
||||
}
|
||||
|
||||
void MeshComponent::updateShape()
|
||||
{
|
||||
if (mInterfaceData == nullptr)
|
||||
return;
|
||||
|
||||
//if ((mShapeName && mShapeName[0] != '\0') || (mShapeAsset && mShapeAsset[0] != '\0'))
|
||||
if ((mShapeName && mShapeName[0] != '\0') || (mMeshAssetId && mMeshAssetId[0] != '\0'))
|
||||
|
||||
{
|
||||
if (mMeshAsset == NULL)
|
||||
return;
|
||||
|
||||
mShape = mMeshAsset->getShape();
|
||||
|
||||
if (!mMeshAsset->getShape())
|
||||
return;
|
||||
|
||||
setupShape();
|
||||
|
||||
//Do this on both the server and client
|
||||
S32 materialCount = mMeshAsset->getShape()->materialList->getMaterialNameList().size();
|
||||
|
||||
if (isServerObject())
|
||||
{
|
||||
//we need to update the editor
|
||||
for (U32 i = 0; i < mFields.size(); i++)
|
||||
{
|
||||
//find any with the materialslot title and clear them out
|
||||
if (FindMatch::isMatch("MaterialSlot*", mFields[i].mFieldName, false))
|
||||
{
|
||||
setDataField(mFields[i].mFieldName, NULL, "");
|
||||
mFields.erase(i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//next, get a listing of our materials in the shape, and build our field list for them
|
||||
char matFieldName[128];
|
||||
|
||||
if (materialCount > 0)
|
||||
mComponentGroup = StringTable->insert("Materials");
|
||||
|
||||
for (U32 i = 0; i < materialCount; i++)
|
||||
{
|
||||
String materialname = mMeshAsset->getShape()->materialList->getMaterialName(i);
|
||||
if (materialname == String("ShapeBounds"))
|
||||
continue;
|
||||
|
||||
dSprintf(matFieldName, 128, "MaterialSlot%d", i);
|
||||
|
||||
addComponentField(matFieldName, "A material used in the shape file", "Material", materialname, "");
|
||||
}
|
||||
|
||||
if (materialCount > 0)
|
||||
mComponentGroup = "";
|
||||
}
|
||||
|
||||
if (mOwner != NULL)
|
||||
{
|
||||
Point3F min, max, pos;
|
||||
pos = mOwner->getPosition();
|
||||
|
||||
mOwner->getWorldToObj().mulP(pos);
|
||||
|
||||
min = mMeshAsset->getShape()->mBounds.minExtents;
|
||||
max = mMeshAsset->getShape()->mBounds.maxExtents;
|
||||
|
||||
if (mInterfaceData)
|
||||
{
|
||||
mInterfaceData->mBounds.set(min, max);
|
||||
mInterfaceData->mScale = mOwner->getScale();
|
||||
mInterfaceData->mTransform = mOwner->getRenderTransform();
|
||||
}
|
||||
|
||||
mOwner->setObjectBox(Box3F(min, max));
|
||||
|
||||
mOwner->resetWorldBox();
|
||||
|
||||
if (mOwner->getSceneManager() != NULL)
|
||||
mOwner->getSceneManager()->notifyObjectDirty(mOwner);
|
||||
}
|
||||
|
||||
if (isClientObject() && mInterfaceData)
|
||||
{
|
||||
if (mRenderMode == StaticBatch)
|
||||
{
|
||||
mInterfaceData->mStatic = true;
|
||||
|
||||
OptimizedPolyList geom;
|
||||
MatrixF transform = mInterfaceData->mTransform;
|
||||
mInterfaceData->mGeometry.setTransform(&transform, mInterfaceData->mScale);
|
||||
mInterfaceData->mGeometry.setObject(mOwner);
|
||||
|
||||
mInterfaceData->mShapeInstance->buildPolyList(&mInterfaceData->mGeometry, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
mInterfaceData->mStatic = false;
|
||||
}
|
||||
|
||||
MeshRenderSystem::rebuildBuffers();
|
||||
}
|
||||
|
||||
//finally, notify that our shape was changed
|
||||
onShapeInstanceChanged.trigger(this);
|
||||
}
|
||||
}
|
||||
|
||||
void MeshComponent::setupShape()
|
||||
{
|
||||
mInterfaceData->mShapeInstance = new TSShapeInstance(mMeshAsset->getShape(), true);
|
||||
}
|
||||
|
||||
void MeshComponent::_onResourceChanged( const Torque::Path &path )
|
||||
{
|
||||
if ( path != Torque::Path( mShapeName ) )
|
||||
if (mInterfaceData == nullptr)
|
||||
return;
|
||||
|
||||
String filePath;
|
||||
if (mMeshAsset)
|
||||
filePath = Torque::Path(mMeshAsset->getShapeFilename());
|
||||
|
||||
if (!mMeshAsset || path != Torque::Path(mMeshAsset->getShapeFilename()) )
|
||||
return;
|
||||
|
||||
updateShape();
|
||||
|
|
@ -217,6 +343,8 @@ U32 MeshComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|||
if (stream->writeFlag(mask & ShapeMask))
|
||||
{
|
||||
stream->writeString(mShapeName);
|
||||
|
||||
stream->writeInt(mRenderMode, 8);
|
||||
}
|
||||
|
||||
if (stream->writeFlag( mask & MaterialMask ))
|
||||
|
|
@ -227,7 +355,7 @@ U32 MeshComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|||
{
|
||||
stream->writeInt(mChangingMaterials[i].slot, 16);
|
||||
|
||||
NetStringHandle matNameStr = mChangingMaterials[i].matName.c_str();
|
||||
NetStringHandle matNameStr = mChangingMaterials[i].assetId.c_str();
|
||||
con->packNetStringHandleU(stream, matNameStr);
|
||||
}
|
||||
|
||||
|
|
@ -244,6 +372,8 @@ void MeshComponent::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
if(stream->readFlag())
|
||||
{
|
||||
mShapeName = stream->readSTString();
|
||||
|
||||
mRenderMode = (RenderMode)stream->readInt(8);
|
||||
setMeshAsset(mShapeName);
|
||||
updateShape();
|
||||
}
|
||||
|
|
@ -257,7 +387,10 @@ void MeshComponent::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
{
|
||||
matMap newMatMap;
|
||||
newMatMap.slot = stream->readInt(16);
|
||||
newMatMap.matName = String(con->unpackNetStringHandleU(stream).getString());
|
||||
newMatMap.assetId = String(con->unpackNetStringHandleU(stream).getString());
|
||||
|
||||
//do the lookup, now
|
||||
newMatMap.matAsset = AssetDatabase.acquireAsset<MaterialAsset>(newMatMap.assetId);
|
||||
|
||||
mChangingMaterials.push_back(newMatMap);
|
||||
}
|
||||
|
|
@ -268,7 +401,7 @@ void MeshComponent::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
|
||||
void MeshComponent::prepRenderImage( SceneRenderState *state )
|
||||
{
|
||||
if (!mEnabled || !mOwner || !mShapeInstance)
|
||||
/*if (!mEnabled || !mOwner || !mShapeInstance)
|
||||
return;
|
||||
|
||||
Point3F cameraOffset;
|
||||
|
|
@ -301,114 +434,41 @@ void MeshComponent::prepRenderImage( SceneRenderState *state )
|
|||
rdata.setLightQuery(&query);
|
||||
|
||||
MatrixF mat = mOwner->getRenderTransform();
|
||||
Point3F renderPos = mat.getPosition();
|
||||
EulerF renderRot = mat.toEuler();
|
||||
|
||||
if (mOwner->isMounted())
|
||||
{
|
||||
MatrixF wrldPos = mOwner->getWorldTransform();
|
||||
Point3F wrldPosPos = wrldPos.getPosition();
|
||||
|
||||
Point3F mntPs = mat.getPosition();
|
||||
EulerF mntRt = RotationF(mat).asEulerF();
|
||||
|
||||
bool tr = true;
|
||||
}
|
||||
|
||||
mat.scale(objScale);
|
||||
GFX->setWorldMatrix(mat);
|
||||
|
||||
mShapeInstance->render(rdata);
|
||||
}
|
||||
|
||||
void MeshComponent::updateShape()
|
||||
{
|
||||
bool isServer = isServerObject();
|
||||
|
||||
if ((mShapeName && mShapeName[0] != '\0') || (mShapeAsset && mShapeAsset[0] != '\0'))
|
||||
{
|
||||
if (mMeshAsset == NULL)
|
||||
return;
|
||||
|
||||
mShape = mMeshAsset->getShape();
|
||||
|
||||
if (!mShape)
|
||||
return;
|
||||
|
||||
setupShape();
|
||||
|
||||
//Do this on both the server and client
|
||||
S32 materialCount = mShape->materialList->getMaterialNameList().size();
|
||||
|
||||
if(isServerObject())
|
||||
{
|
||||
//we need to update the editor
|
||||
for (U32 i = 0; i < mFields.size(); i++)
|
||||
{
|
||||
//find any with the materialslot title and clear them out
|
||||
if (FindMatch::isMatch("MaterialSlot*", mFields[i].mFieldName, false))
|
||||
{
|
||||
setDataField(mFields[i].mFieldName, NULL, "");
|
||||
mFields.erase(i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//next, get a listing of our materials in the shape, and build our field list for them
|
||||
char matFieldName[128];
|
||||
|
||||
if(materialCount > 0)
|
||||
mComponentGroup = StringTable->insert("Materials");
|
||||
|
||||
for(U32 i=0; i < materialCount; i++)
|
||||
{
|
||||
String materialname = mShape->materialList->getMaterialName(i);
|
||||
if(materialname == String("ShapeBounds"))
|
||||
continue;
|
||||
|
||||
dSprintf(matFieldName, 128, "MaterialSlot%d", i);
|
||||
|
||||
addComponentField(matFieldName, "A material used in the shape file", "TypeAssetId", materialname, "");
|
||||
}
|
||||
|
||||
if(materialCount > 0)
|
||||
mComponentGroup = "";
|
||||
}
|
||||
|
||||
if(mOwner != NULL)
|
||||
{
|
||||
Point3F min, max, pos;
|
||||
pos = mOwner->getPosition();
|
||||
|
||||
mOwner->getWorldToObj().mulP(pos);
|
||||
|
||||
min = mShape->bounds.minExtents;
|
||||
max = mShape->bounds.maxExtents;
|
||||
|
||||
mShapeBounds.set(min, max);
|
||||
|
||||
mOwner->setObjectBox(Box3F(min, max));
|
||||
|
||||
if( mOwner->getSceneManager() != NULL )
|
||||
mOwner->getSceneManager()->notifyObjectDirty( mOwner );
|
||||
}
|
||||
|
||||
//finally, notify that our shape was changed
|
||||
onShapeInstanceChanged.trigger(this);
|
||||
}
|
||||
}
|
||||
|
||||
void MeshComponent::setupShape()
|
||||
{
|
||||
mShapeInstance = new TSShapeInstance(mShape, true);
|
||||
mShapeInstance->render(rdata);*/
|
||||
}
|
||||
|
||||
void MeshComponent::updateMaterials()
|
||||
{
|
||||
if (mChangingMaterials.empty() || !mShape)
|
||||
if (mChangingMaterials.empty() || !mMeshAsset->getShape())
|
||||
return;
|
||||
|
||||
TSMaterialList* pMatList = mShapeInstance->getMaterialList();
|
||||
TSMaterialList* pMatList = mInterfaceData->mShapeInstance->getMaterialList();
|
||||
pMatList->setTextureLookupPath(getShapeResource().getPath().getPath());
|
||||
|
||||
const Vector<String> &materialNames = pMatList->getMaterialNameList();
|
||||
for ( S32 i = 0; i < materialNames.size(); i++ )
|
||||
{
|
||||
const String &pName = materialNames[i];
|
||||
|
||||
for(U32 m=0; m < mChangingMaterials.size(); m++)
|
||||
{
|
||||
if(mChangingMaterials[m].slot == i)
|
||||
{
|
||||
pMatList->renameMaterial( i, mChangingMaterials[m].matName );
|
||||
//Fetch the actual material asset
|
||||
pMatList->renameMaterial( i, mChangingMaterials[m].matAsset->getMaterialDefinitionName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -416,22 +476,31 @@ void MeshComponent::updateMaterials()
|
|||
}
|
||||
|
||||
// Initialize the material instances
|
||||
mShapeInstance->initMaterialList();
|
||||
mInterfaceData->mShapeInstance->initMaterialList();
|
||||
}
|
||||
|
||||
MatrixF MeshComponent::getNodeTransform(S32 nodeIdx)
|
||||
{
|
||||
if (mShape)
|
||||
if (mInterfaceData != nullptr && mMeshAsset->getShape())
|
||||
{
|
||||
S32 nodeCount = getShape()->nodes.size();
|
||||
|
||||
if(nodeIdx >= 0 && nodeIdx < nodeCount)
|
||||
{
|
||||
//animate();
|
||||
MatrixF mountTransform = mShapeInstance->mNodeTransforms[nodeIdx];
|
||||
mountTransform.mul(mOwner->getRenderTransform());
|
||||
MatrixF nodeTransform = mInterfaceData->mShapeInstance->mNodeTransforms[nodeIdx];
|
||||
const Point3F& scale = mOwner->getScale();
|
||||
|
||||
return mountTransform;
|
||||
// The position of the node needs to be scaled.
|
||||
Point3F position = nodeTransform.getPosition();
|
||||
position.convolve(scale);
|
||||
nodeTransform.setPosition(position);
|
||||
|
||||
MatrixF finalTransform = MatrixF::Identity;
|
||||
|
||||
finalTransform.mul(mOwner->getRenderTransform(), nodeTransform);
|
||||
|
||||
return finalTransform;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -440,7 +509,7 @@ MatrixF MeshComponent::getNodeTransform(S32 nodeIdx)
|
|||
|
||||
S32 MeshComponent::getNodeByName(String nodeName)
|
||||
{
|
||||
if (mShape)
|
||||
if (mMeshAsset->getShape())
|
||||
{
|
||||
S32 nodeIdx = getShape()->findNode(nodeName);
|
||||
|
||||
|
|
@ -486,12 +555,18 @@ void MeshComponent::onDynamicModified(const char* slotName, const char* newValue
|
|||
if(slot == -1)
|
||||
return;
|
||||
|
||||
//Safe to assume the inbound value for the material will be a MaterialAsset, so lets do a lookup on the name
|
||||
MaterialAsset* matAsset = AssetDatabase.acquireAsset<MaterialAsset>(newValue);
|
||||
if (!matAsset)
|
||||
return;
|
||||
|
||||
bool found = false;
|
||||
for(U32 i=0; i < mChangingMaterials.size(); i++)
|
||||
{
|
||||
if(mChangingMaterials[i].slot == slot)
|
||||
{
|
||||
mChangingMaterials[i].matName = String(newValue);
|
||||
mChangingMaterials[i].matAsset = matAsset;
|
||||
mChangingMaterials[i].assetId = newValue;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -500,7 +575,8 @@ void MeshComponent::onDynamicModified(const char* slotName, const char* newValue
|
|||
{
|
||||
matMap newMatMap;
|
||||
newMatMap.slot = slot;
|
||||
newMatMap.matName = String(newValue);
|
||||
newMatMap.matAsset = matAsset;
|
||||
newMatMap.assetId = newValue;
|
||||
|
||||
mChangingMaterials.push_back(newMatMap);
|
||||
}
|
||||
|
|
@ -511,14 +587,31 @@ void MeshComponent::onDynamicModified(const char* slotName, const char* newValue
|
|||
Parent::onDynamicModified(slotName, newValue);
|
||||
}
|
||||
|
||||
void MeshComponent::changeMaterial(U32 slot, const char* newMat)
|
||||
void MeshComponent::changeMaterial(U32 slot, MaterialAsset* newMat)
|
||||
{
|
||||
|
||||
char fieldName[512];
|
||||
|
||||
//update our respective field
|
||||
dSprintf(fieldName, 512, "materialSlot%d", slot);
|
||||
setDataField(fieldName, NULL, newMat);
|
||||
setDataField(fieldName, NULL, newMat->getAssetId());
|
||||
}
|
||||
|
||||
bool MeshComponent::setMatInstField(U32 slot, const char* field, const char* value)
|
||||
{
|
||||
TSMaterialList* pMatList = mInterfaceData->mShapeInstance->getMaterialList();
|
||||
pMatList->setTextureLookupPath(getShapeResource().getPath().getPath());
|
||||
|
||||
MaterialParameters* params = pMatList->getMaterialInst(slot)->getMaterialParameters();
|
||||
|
||||
if (pMatList->getMaterialInst(slot)->getFeatures().hasFeature(MFT_DiffuseColor))
|
||||
{
|
||||
MaterialParameterHandle* handle = pMatList->getMaterialInst(slot)->getMaterialParameterHandle("DiffuseColor");
|
||||
|
||||
params->set(handle, LinearColorF(0, 0, 0));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MeshComponent::onInspect()
|
||||
|
|
@ -527,4 +620,13 @@ void MeshComponent::onInspect()
|
|||
|
||||
void MeshComponent::onEndInspect()
|
||||
{
|
||||
}
|
||||
|
||||
void MeshComponent::ownerTransformSet(MatrixF *mat)
|
||||
{
|
||||
if (mInterfaceData != nullptr)
|
||||
{
|
||||
MatrixF newTransform = *mat;
|
||||
mInterfaceData->mTransform = newTransform;
|
||||
}
|
||||
}
|
||||
|
|
@ -60,6 +60,8 @@
|
|||
#include "gfx/gfxVertexFormat.h"
|
||||
#endif
|
||||
|
||||
#include "T3D/systems/render/meshRenderSystem.h"
|
||||
|
||||
class TSShapeInstance;
|
||||
class SceneRenderState;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -84,37 +86,38 @@ protected:
|
|||
StringTableEntry mShapeName;
|
||||
StringTableEntry mShapeAsset;
|
||||
TSShape* mShape;
|
||||
Box3F mShapeBounds;
|
||||
//Box3F mShapeBounds;
|
||||
Point3F mCenterOffset;
|
||||
|
||||
MeshRenderSystemInterface* mInterfaceData;
|
||||
|
||||
struct matMap
|
||||
{
|
||||
String matName;
|
||||
MaterialAsset* matAsset;
|
||||
String assetId;
|
||||
U32 slot;
|
||||
};
|
||||
|
||||
Vector<matMap> mChangingMaterials;
|
||||
Vector<matMap> mMaterials;
|
||||
|
||||
class boneObject : public SimGroup
|
||||
public:
|
||||
enum RenderMode
|
||||
{
|
||||
MeshComponent *mOwner;
|
||||
public:
|
||||
boneObject(MeshComponent *owner){ mOwner = owner; }
|
||||
|
||||
StringTableEntry mBoneName;
|
||||
S32 mItemID;
|
||||
|
||||
virtual void addObject(SimObject *obj);
|
||||
Individual = 0,
|
||||
DynamicBatch,
|
||||
StaticBatch,
|
||||
Instanced
|
||||
};
|
||||
|
||||
Vector<boneObject*> mNodesList;
|
||||
protected:
|
||||
RenderMode mRenderMode;
|
||||
|
||||
public:
|
||||
StringTableEntry mMeshAssetId;
|
||||
AssetPtr<ShapeAsset> mMeshAsset;
|
||||
|
||||
TSShapeInstance* mShapeInstance;
|
||||
//TSShapeInstance* mShapeInstance;
|
||||
|
||||
public:
|
||||
MeshComponent();
|
||||
|
|
@ -132,7 +135,7 @@ public:
|
|||
virtual U32 packUpdate(NetConnection *con, U32 mask, BitStream *stream);
|
||||
virtual void unpackUpdate(NetConnection *con, BitStream *stream);
|
||||
|
||||
Box3F getShapeBounds() { return mShapeBounds; }
|
||||
Box3F getShapeBounds() { return mInterfaceData->mBounds; }
|
||||
|
||||
virtual MatrixF getNodeTransform(S32 nodeIdx);
|
||||
S32 getNodeByName(String nodeName);
|
||||
|
|
@ -144,6 +147,8 @@ public:
|
|||
virtual void onComponentRemove();
|
||||
virtual void onComponentAdd();
|
||||
|
||||
virtual void ownerTransformSet(MatrixF *mat);
|
||||
|
||||
static bool _setMesh(void *object, const char *index, const char *data);
|
||||
static bool _setShape(void *object, const char *index, const char *data);
|
||||
const char* _getShape(void *object, const char *data);
|
||||
|
|
@ -151,7 +156,7 @@ public:
|
|||
bool setMeshAsset(const char* assetName);
|
||||
|
||||
virtual TSShape* getShape() { if (mMeshAsset) return mMeshAsset->getShape(); else return NULL; }
|
||||
virtual TSShapeInstance* getShapeInstance() { return mShapeInstance; }
|
||||
virtual TSShapeInstance* getShapeInstance() { return mInterfaceData->mShapeInstance; }
|
||||
|
||||
Resource<TSShape> getShapeResource() { return mMeshAsset->getShapeResource(); }
|
||||
|
||||
|
|
@ -163,7 +168,8 @@ public:
|
|||
|
||||
virtual void onDynamicModified(const char* slotName, const char* newValue);
|
||||
|
||||
void changeMaterial(U32 slot, const char* newMat);
|
||||
void changeMaterial(U32 slot, MaterialAsset* newMat);
|
||||
bool setMatInstField(U32 slot, const char* field, const char* value);
|
||||
|
||||
virtual void onInspect();
|
||||
virtual void onEndInspect();
|
||||
|
|
@ -180,4 +186,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
typedef MeshComponent::RenderMode BatchingMode;
|
||||
DefineEnumType(BatchingMode);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -126,6 +126,28 @@ DefineEngineMethod(MeshComponent, getNodePosition, Point3F,
|
|||
return Point3F(0, 0, 0);
|
||||
}
|
||||
|
||||
DefineEngineMethod(MeshComponent, getNodeRotation, EulerF,
|
||||
(S32 node), (-1),
|
||||
"@brief Mount objB to this object at the desired slot with optional transform.\n\n"
|
||||
|
||||
"@param objB Object to mount onto us\n"
|
||||
"@param slot Mount slot ID\n"
|
||||
"@param txfm (optional) mount offset transform\n"
|
||||
"@return true if successful, false if failed (objB is not valid)")
|
||||
{
|
||||
if (node != -1)
|
||||
{
|
||||
//BUG: Unsure how it broke, but atm the default transform passed in here is rotated 180 degrees. This doesn't happen
|
||||
//for the SceneObject mountobject method. Hackish, but for now, just default to a clean MatrixF::Identity
|
||||
//object->mountObjectToNode( objB, node, /*MatrixF::Identity*/txfm.getMatrix() );
|
||||
RotationF mat = object->getNodeTransform(node);
|
||||
|
||||
return mat.asEulerF(RotationF::Degrees);
|
||||
}
|
||||
|
||||
return EulerF(0, 0, 0);
|
||||
}
|
||||
|
||||
DefineEngineMethod(MeshComponent, getNodeByName, S32,
|
||||
(String nodeName), ,
|
||||
"@brief Mount objB to this object at the desired slot with optional transform.\n\n"
|
||||
|
|
@ -148,8 +170,14 @@ DefineEngineMethod(MeshComponent, getNodeByName, S32,
|
|||
return -1;
|
||||
}
|
||||
|
||||
DefineEngineMethod(MeshComponent, changeMaterial, void, (U32 slot, const char* newMat), (0, ""),
|
||||
DefineEngineMethod(MeshComponent, changeMaterial, void, (U32 slot, MaterialAsset* newMat), (0, nullAsType<MaterialAsset*>()),
|
||||
"@brief Change one of the materials on the shape.\n\n")
|
||||
{
|
||||
object->changeMaterial(slot, newMat);
|
||||
}
|
||||
|
||||
DefineEngineMethod(MeshComponent, setMatInstField, bool, (U32 slot, const char* field, const char* value), (0, "", ""),
|
||||
"@brief Change one of the materials on the shape.\n\n")
|
||||
{
|
||||
return object->setMatInstField(slot, field, value);
|
||||
}
|
||||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/containerQuery.h"
|
||||
|
||||
|
|
@ -91,7 +96,9 @@ void physicalZoneFind(SceneObject* obj, void *key)
|
|||
|
||||
if (pz->isActive()) {
|
||||
info->gravityScale *= pz->getGravityMod();
|
||||
info->appliedForce += pz->getForce();
|
||||
Point3F center;
|
||||
info->box.getCenter(¢er);
|
||||
info->appliedForce += pz->getForce(¢er);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -492,7 +492,6 @@ void ConvexShape::unpackUpdate( NetConnection *conn, BitStream *stream )
|
|||
|
||||
void ConvexShape::prepRenderImage( SceneRenderState *state )
|
||||
{
|
||||
/*
|
||||
if ( state->isDiffusePass() )
|
||||
{
|
||||
ObjectRenderInst *ri2 = state->getRenderPass()->allocInst<ObjectRenderInst>();
|
||||
|
|
@ -500,8 +499,7 @@ void ConvexShape::prepRenderImage( SceneRenderState *state )
|
|||
ri2->type = RenderPassManager::RIT_Editor;
|
||||
state->getRenderPass()->addInst( ri2 );
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
if ( mVertexBuffer.isNull() || !state)
|
||||
return;
|
||||
|
||||
|
|
@ -697,6 +695,54 @@ bool ConvexShape::buildPolyList( PolyListContext context, AbstractPolyList *plis
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ConvexShape::buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &)
|
||||
{
|
||||
if (mGeometry.points.empty())
|
||||
return false;
|
||||
|
||||
//Get the collision mesh geometry
|
||||
{
|
||||
ColladaUtils::ExportData::colMesh* colMesh;
|
||||
exportData->colMeshes.increment();
|
||||
colMesh = &exportData->colMeshes.last();
|
||||
|
||||
colMesh->mesh.setTransform(&mObjToWorld, mObjScale);
|
||||
colMesh->mesh.setObject(this);
|
||||
|
||||
//Just get the visible
|
||||
buildPolyList(PLC_Export, &colMesh->mesh, getWorldBox(), getWorldSphere());
|
||||
|
||||
colMesh->colMeshName = String::ToString("ColMesh%d-1", exportData->colMeshes.size());
|
||||
}
|
||||
|
||||
//Next, process the geometry and materials.
|
||||
//Convex shapes only have the one 'level', so we'll just rely on the export post-process to back-fill
|
||||
if (isServerObject() && getClientObject())
|
||||
{
|
||||
ConvexShape* clientShape = dynamic_cast<ConvexShape*>(getClientObject());
|
||||
|
||||
exportData->meshData.increment();
|
||||
|
||||
//Prep a meshData for this shape in particular
|
||||
ColladaUtils::ExportData::meshLODData* meshData = &exportData->meshData.last();
|
||||
|
||||
//Fill out the info we'll need later to actually append our mesh data for the detail levels during the processing phase
|
||||
meshData->shapeInst = nullptr;
|
||||
meshData->originatingObject = this;
|
||||
meshData->meshTransform = mObjToWorld;
|
||||
meshData->scale = mObjScale;
|
||||
|
||||
meshData->meshDetailLevels.increment();
|
||||
|
||||
ColladaUtils::ExportData::detailLevel* curDetail = &meshData->meshDetailLevels.last();
|
||||
|
||||
//Make sure we denote the size this detail level has
|
||||
curDetail->size = 512;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConvexShape::_export( OptimizedPolyList *plist, const Box3F &box, const SphereF &sphere )
|
||||
{
|
||||
BaseMatInstance *matInst = mMaterialInst;
|
||||
|
|
@ -747,21 +793,10 @@ bool ConvexShape::castRay( const Point3F &start, const Point3F &end, RayInfo *in
|
|||
F32 t;
|
||||
F32 tmin = F32_MAX;
|
||||
S32 hitFace = -1;
|
||||
Point3F hitPnt, pnt;
|
||||
Point3F pnt;
|
||||
VectorF rayDir( end - start );
|
||||
rayDir.normalizeSafe();
|
||||
|
||||
if ( false )
|
||||
{
|
||||
PlaneF plane( Point3F(0,0,0), Point3F(0,0,1) );
|
||||
Point3F sp( 0,0,-1 );
|
||||
Point3F ep( 0,0,1 );
|
||||
|
||||
F32 t = plane.intersect( sp, ep );
|
||||
Point3F hitPnt;
|
||||
hitPnt.interpolate( sp, ep, t );
|
||||
}
|
||||
|
||||
|
||||
for ( S32 i = 0; i < planeCount; i++ )
|
||||
{
|
||||
// Don't hit the back-side of planes.
|
||||
|
|
@ -1180,11 +1215,11 @@ void ConvexShape::_renderDebug( ObjectRenderInst *ri, SceneRenderState *state, B
|
|||
GFX->setTexture( 0, NULL );
|
||||
|
||||
// Render world box.
|
||||
if ( false )
|
||||
if (Con::getBoolVariable("$pref::convexDBG::ShowWorldBox", false))
|
||||
{
|
||||
Box3F wbox( mWorldBox );
|
||||
//if ( getServerObject() )
|
||||
// Box3F wbox = static_cast<ConvexShape*>( getServerObject() )->mWorldBox;
|
||||
if ( getServerObject() )
|
||||
wbox = static_cast<ConvexShape*>( getServerObject() )->mWorldBox;
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setCullMode( GFXCullNone );
|
||||
desc.setFillModeWireframe();
|
||||
|
|
@ -1196,7 +1231,7 @@ void ConvexShape::_renderDebug( ObjectRenderInst *ri, SceneRenderState *state, B
|
|||
const Vector< ConvexShape::Face > &faceList = mGeometry.faces;
|
||||
|
||||
// Render Edges.
|
||||
if ( false )
|
||||
if (Con::getBoolVariable("$pref::convexDBG::ShowEdges", false))
|
||||
{
|
||||
GFXTransformSaver saver;
|
||||
//GFXFrustumSaver fsaver;
|
||||
|
|
@ -1250,7 +1285,7 @@ void ConvexShape::_renderDebug( ObjectRenderInst *ri, SceneRenderState *state, B
|
|||
objToWorld.scale( mObjScale );
|
||||
|
||||
// Render faces centers/colors.
|
||||
if ( false )
|
||||
if (Con::getBoolVariable("$pref::convexDBG::ShowFaceColors", false))
|
||||
{
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setCullMode( GFXCullNone );
|
||||
|
|
@ -1274,7 +1309,7 @@ void ConvexShape::_renderDebug( ObjectRenderInst *ri, SceneRenderState *state, B
|
|||
}
|
||||
|
||||
// Render winding order.
|
||||
if ( false )
|
||||
if (Con::getBoolVariable("$pref::convexDBG::ShowWinding", false))
|
||||
{
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setCullMode( GFXCullNone );
|
||||
|
|
@ -1331,7 +1366,7 @@ void ConvexShape::_renderDebug( ObjectRenderInst *ri, SceneRenderState *state, B
|
|||
}
|
||||
|
||||
// Render surface transforms.
|
||||
if ( false )
|
||||
if (Con::getBoolVariable("$pref::convexDBG::ShowSurfaceTransforms", false))
|
||||
{
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setBlend( false );
|
||||
|
|
@ -1341,7 +1376,7 @@ void ConvexShape::_renderDebug( ObjectRenderInst *ri, SceneRenderState *state, B
|
|||
|
||||
for ( S32 i = 0; i < mSurfaces.size(); i++ )
|
||||
{
|
||||
MatrixF objToWorld( mObjToWorld );
|
||||
objToWorld = mObjToWorld;
|
||||
objToWorld.scale( mObjScale );
|
||||
|
||||
MatrixF renderMat;
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ public:
|
|||
virtual void prepRenderImage( SceneRenderState *state );
|
||||
virtual void buildConvex( const Box3F &box, Convex *convex );
|
||||
virtual bool buildPolyList( PolyListContext context, AbstractPolyList *polyList, const Box3F &box, const SphereF &sphere );
|
||||
virtual bool buildExportPolyList(ColladaUtils::ExportData* exportData, const Box3F &box, const SphereF &);
|
||||
virtual bool castRay( const Point3F &start, const Point3F &end, RayInfo *info );
|
||||
virtual bool collideBox( const Point3F &start, const Point3F &end, RayInfo *info );
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/debris.h"
|
||||
|
||||
|
|
@ -113,6 +118,85 @@ DebrisData::DebrisData()
|
|||
ignoreWater = true;
|
||||
}
|
||||
|
||||
//#define TRACK_DEBRIS_DATA_CLONES
|
||||
|
||||
#ifdef TRACK_DEBRIS_DATA_CLONES
|
||||
static int debris_data_clones = 0;
|
||||
#endif
|
||||
|
||||
DebrisData::DebrisData(const DebrisData& other, bool temp_clone) : GameBaseData(other, temp_clone)
|
||||
{
|
||||
#ifdef TRACK_DEBRIS_DATA_CLONES
|
||||
debris_data_clones++;
|
||||
if (debris_data_clones == 1)
|
||||
Con::errorf("DebrisData -- Clones are on the loose!");
|
||||
#endif
|
||||
velocity = other.velocity;
|
||||
velocityVariance = other.velocityVariance;
|
||||
friction = other.friction;
|
||||
elasticity = other.elasticity;
|
||||
lifetime = other.lifetime;
|
||||
lifetimeVariance = other.lifetimeVariance;
|
||||
numBounces = other.numBounces;
|
||||
bounceVariance = other.bounceVariance;
|
||||
minSpinSpeed = other.minSpinSpeed;
|
||||
maxSpinSpeed = other.maxSpinSpeed;
|
||||
explodeOnMaxBounce = other.explodeOnMaxBounce;
|
||||
staticOnMaxBounce = other.staticOnMaxBounce;
|
||||
snapOnMaxBounce = other.snapOnMaxBounce;
|
||||
fade = other.fade;
|
||||
useRadiusMass = other.useRadiusMass;
|
||||
baseRadius = other.baseRadius;
|
||||
gravModifier = other.gravModifier;
|
||||
terminalVelocity = other.terminalVelocity;
|
||||
ignoreWater = other.ignoreWater;
|
||||
shapeName = other.shapeName;
|
||||
shape = other.shape; // -- TSShape loaded using shapeName
|
||||
textureName = other.textureName;
|
||||
explosionId = other.explosionId; // -- for pack/unpack of explosion ptr
|
||||
explosion = other.explosion;
|
||||
dMemcpy( emitterList, other.emitterList, sizeof( emitterList ) );
|
||||
dMemcpy( emitterIDList, other.emitterIDList, sizeof( emitterIDList ) ); // -- for pack/unpack of emitterList ptrs
|
||||
}
|
||||
|
||||
DebrisData::~DebrisData()
|
||||
{
|
||||
if (!isTempClone())
|
||||
return;
|
||||
|
||||
#ifdef TRACK_DEBRIS_DATA_CLONES
|
||||
if (debris_data_clones > 0)
|
||||
{
|
||||
debris_data_clones--;
|
||||
if (debris_data_clones == 0)
|
||||
Con::errorf("DebrisData -- Clones eliminated!");
|
||||
}
|
||||
else
|
||||
Con::errorf("DebrisData -- Too many clones deleted!");
|
||||
#endif
|
||||
}
|
||||
|
||||
DebrisData* DebrisData::cloneAndPerformSubstitutions(const SimObject* owner, S32 index)
|
||||
{
|
||||
if (!owner || getSubstitutionCount() == 0)
|
||||
return this;
|
||||
|
||||
DebrisData* sub_debris_db = new DebrisData(*this, true);
|
||||
performSubstitutions(sub_debris_db, owner, index);
|
||||
|
||||
return sub_debris_db;
|
||||
}
|
||||
|
||||
void DebrisData::onPerformSubstitutions()
|
||||
{
|
||||
if( shapeName && shapeName[0] != '\0')
|
||||
{
|
||||
shape = ResourceManager::get().load(shapeName);
|
||||
if( bool(shape) == false )
|
||||
Con::errorf("DebrisData::onPerformSubstitutions(): failed to load shape \"%s\"", shapeName);
|
||||
}
|
||||
}
|
||||
|
||||
bool DebrisData::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
|
|
@ -269,6 +353,9 @@ void DebrisData::initPersistFields()
|
|||
addField("ignoreWater", TypeBool, Offset(ignoreWater, DebrisData), "If true, this debris object will not collide with water, acting as if the water is not there.");
|
||||
endGroup("Behavior");
|
||||
|
||||
// disallow some field substitutions
|
||||
onlyKeepClearSubstitutions("emitters"); // subs resolving to "~~", or "~0" are OK
|
||||
onlyKeepClearSubstitutions("explosion");
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
|
|
@ -309,7 +396,7 @@ void DebrisData::packData(BitStream* stream)
|
|||
|
||||
if( stream->writeFlag( explosion ) )
|
||||
{
|
||||
stream->writeRangedU32(packed? SimObjectId((uintptr_t)explosion):
|
||||
stream->writeRangedU32(mPacked ? SimObjectId((uintptr_t)explosion):
|
||||
explosion->getId(),DataBlockObjectIdFirst,DataBlockObjectIdLast);
|
||||
}
|
||||
|
||||
|
|
@ -451,6 +538,8 @@ Debris::Debris()
|
|||
|
||||
// Only allocated client side.
|
||||
mNetFlags.set( IsGhost );
|
||||
ss_object = 0;
|
||||
ss_index = 0;
|
||||
}
|
||||
|
||||
Debris::~Debris()
|
||||
|
|
@ -466,6 +555,12 @@ Debris::~Debris()
|
|||
delete mPart;
|
||||
mPart = NULL;
|
||||
}
|
||||
|
||||
if (mDataBlock && mDataBlock->isTempClone())
|
||||
{
|
||||
delete mDataBlock;
|
||||
mDataBlock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Debris::initPersistFields()
|
||||
|
|
@ -495,6 +590,8 @@ bool Debris::onNewDataBlock( GameBaseData *dptr, bool reload )
|
|||
if( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) )
|
||||
return false;
|
||||
|
||||
if (mDataBlock->isTempClone())
|
||||
return true;
|
||||
scriptOnNewDataBlock();
|
||||
return true;
|
||||
|
||||
|
|
@ -519,7 +616,7 @@ bool Debris::onAdd()
|
|||
if( mDataBlock->emitterList[i] != NULL )
|
||||
{
|
||||
ParticleEmitter * pEmitter = new ParticleEmitter;
|
||||
pEmitter->onNewDataBlock( mDataBlock->emitterList[i], false );
|
||||
pEmitter->onNewDataBlock(mDataBlock->emitterList[i]->cloneAndPerformSubstitutions(ss_object, ss_index), false);
|
||||
if( !pEmitter->registerObject() )
|
||||
{
|
||||
Con::warnf( ConsoleLogEntry::General, "Could not register emitter for particle of class: %s", mDataBlock->getName() );
|
||||
|
|
@ -537,7 +634,8 @@ bool Debris::onAdd()
|
|||
{
|
||||
sizeList[0] = mSize * 0.5;
|
||||
sizeList[1] = mSize;
|
||||
sizeList[2] = mSize * 1.5;
|
||||
for (U32 i = 2; i < ParticleData::PDC_NUM_KEYS; i++)
|
||||
sizeList[i] = mSize * 1.5;
|
||||
|
||||
mEmitterList[0]->setSizes( sizeList );
|
||||
}
|
||||
|
|
@ -546,7 +644,8 @@ bool Debris::onAdd()
|
|||
{
|
||||
sizeList[0] = 0.0;
|
||||
sizeList[1] = mSize * 0.5;
|
||||
sizeList[2] = mSize;
|
||||
for (U32 i = 2; i < ParticleData::PDC_NUM_KEYS; i++)
|
||||
sizeList[i] = mSize;
|
||||
|
||||
mEmitterList[1]->setSizes( sizeList );
|
||||
}
|
||||
|
|
@ -570,7 +669,7 @@ bool Debris::onAdd()
|
|||
// Setup our bounding box
|
||||
if( mDataBlock->shape )
|
||||
{
|
||||
mObjBox = mDataBlock->shape->bounds;
|
||||
mObjBox = mDataBlock->shape->mBounds;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -798,7 +897,8 @@ void Debris::explode()
|
|||
Point3F explosionPos = getPosition();
|
||||
|
||||
Explosion* pExplosion = new Explosion;
|
||||
pExplosion->onNewDataBlock(mDataBlock->explosion, false);
|
||||
pExplosion->setSubstitutionData(ss_object, ss_index);
|
||||
pExplosion->onNewDataBlock(mDataBlock->explosion->cloneAndPerformSubstitutions(ss_object, ss_index), false);
|
||||
|
||||
MatrixF trans( true );
|
||||
trans.setPosition( getPosition() );
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _DEBRIS_H_
|
||||
#define _DEBRIS_H_
|
||||
|
||||
|
|
@ -97,6 +102,12 @@ struct DebrisData : public GameBaseData
|
|||
|
||||
DECLARE_CONOBJECT(DebrisData);
|
||||
|
||||
public:
|
||||
/*C*/ DebrisData(const DebrisData&, bool = false);
|
||||
/*D*/ ~DebrisData();
|
||||
DebrisData* cloneAndPerformSubstitutions(const SimObject*, S32 index=0);
|
||||
virtual void onPerformSubstitutions();
|
||||
virtual bool allowSubstitutions() const { return true; }
|
||||
};
|
||||
|
||||
//**************************************************************************
|
||||
|
|
@ -165,6 +176,11 @@ public:
|
|||
|
||||
DECLARE_CONOBJECT(Debris);
|
||||
|
||||
private:
|
||||
SimObject* ss_object;
|
||||
S32 ss_index;
|
||||
public:
|
||||
void setSubstitutionData(SimObject* obj, S32 idx=0) { ss_object = obj; ss_index = idx; }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ bool DecalDataFile::write( Stream& stream )
|
|||
{
|
||||
DecalInstance *inst = allDecals[i];
|
||||
|
||||
dataIter = find( allDatablocks.begin(), allDatablocks.end(), inst->mDataBlock );
|
||||
dataIter = T3D::find( allDatablocks.begin(), allDatablocks.end(), inst->mDataBlock );
|
||||
U8 dataIndex = dataIter - allDatablocks.begin();
|
||||
|
||||
stream.write( dataIndex );
|
||||
|
|
|
|||
|
|
@ -1302,14 +1302,14 @@ void DecalManager::prepRenderImage( SceneRenderState* state )
|
|||
// Loop through batches allocating buffers and submitting render instances.
|
||||
for ( U32 i = 0; i < batches.size(); i++ )
|
||||
{
|
||||
DecalBatch ¤tBatch = batches[i];
|
||||
currentBatch = &batches[i];
|
||||
|
||||
// Copy data into the system memory arrays, from all decals in this batch...
|
||||
|
||||
DecalVertex *vpPtr = vertData;
|
||||
U16 *pbPtr = indexData;
|
||||
|
||||
U32 lastDecal = currentBatch.startDecal + currentBatch.decalCount;
|
||||
U32 lastDecal = currentBatch->startDecal + currentBatch->decalCount;
|
||||
|
||||
U32 voffset = 0;
|
||||
U32 ioffset = 0;
|
||||
|
|
@ -1317,13 +1317,13 @@ void DecalManager::prepRenderImage( SceneRenderState* state )
|
|||
// This is an ugly hack for ProjectedShadow!
|
||||
GFXTextureObject *customTex = NULL;
|
||||
|
||||
for ( U32 j = currentBatch.startDecal; j < lastDecal; j++ )
|
||||
for ( U32 j = currentBatch->startDecal; j < lastDecal; j++ )
|
||||
{
|
||||
DecalInstance *dinst = mDecalQueue[j];
|
||||
dinst = mDecalQueue[j];
|
||||
|
||||
const U32 indxCount =
|
||||
(dinst->mIndxCount > currentBatch.iCount) ?
|
||||
currentBatch.iCount : dinst->mIndxCount;
|
||||
(dinst->mIndxCount > currentBatch->iCount) ?
|
||||
currentBatch->iCount : dinst->mIndxCount;
|
||||
for ( U32 k = 0; k < indxCount; k++ )
|
||||
{
|
||||
*( pbPtr + ioffset + k ) = dinst->mIndices[k] + voffset;
|
||||
|
|
@ -1332,8 +1332,8 @@ void DecalManager::prepRenderImage( SceneRenderState* state )
|
|||
ioffset += indxCount;
|
||||
|
||||
const U32 vertCount =
|
||||
(dinst->mVertCount > currentBatch.vCount) ?
|
||||
currentBatch.vCount : dinst->mVertCount;
|
||||
(dinst->mVertCount > currentBatch->vCount) ?
|
||||
currentBatch->vCount : dinst->mVertCount;
|
||||
dMemcpy( vpPtr + voffset, dinst->mVerts, sizeof( DecalVertex ) * vertCount );
|
||||
voffset += vertCount;
|
||||
|
||||
|
|
@ -1342,8 +1342,8 @@ void DecalManager::prepRenderImage( SceneRenderState* state )
|
|||
customTex = *dinst->mCustomTex;
|
||||
}
|
||||
|
||||
AssertFatal( ioffset == currentBatch.iCount, "bad" );
|
||||
AssertFatal( voffset == currentBatch.vCount, "bad" );
|
||||
AssertFatal( ioffset == currentBatch->iCount, "bad" );
|
||||
AssertFatal( voffset == currentBatch->vCount, "bad" );
|
||||
|
||||
// Get handles to video memory buffers we will be filling...
|
||||
|
||||
|
|
@ -1385,9 +1385,9 @@ void DecalManager::prepRenderImage( SceneRenderState* state )
|
|||
pb->lock( &pbPtr );
|
||||
|
||||
// Memcpy from system to video memory.
|
||||
const U32 vpCount = sizeof( DecalVertex ) * currentBatch.vCount;
|
||||
const U32 vpCount = sizeof( DecalVertex ) * currentBatch->vCount;
|
||||
dMemcpy( vpPtr, vertData, vpCount );
|
||||
const U32 pbCount = sizeof( U16 ) * currentBatch.iCount;
|
||||
const U32 pbCount = sizeof( U16 ) * currentBatch->iCount;
|
||||
dMemcpy( pbPtr, indexData, pbCount );
|
||||
|
||||
pb->unlock();
|
||||
|
|
@ -1400,7 +1400,7 @@ void DecalManager::prepRenderImage( SceneRenderState* state )
|
|||
|
||||
// Get the best lights for the current camera position
|
||||
// if the materail is forward lit and we haven't got them yet.
|
||||
if ( currentBatch.matInst->isForwardLit() && !baseRenderInst.lights[0] )
|
||||
if ( currentBatch->matInst->isForwardLit() && !baseRenderInst.lights[0] )
|
||||
{
|
||||
LightQuery query;
|
||||
query.init( rootFrustum.getPosition(),
|
||||
|
|
@ -1416,15 +1416,15 @@ void DecalManager::prepRenderImage( SceneRenderState* state )
|
|||
ri->primBuff = pb;
|
||||
ri->vertBuff = vb;
|
||||
|
||||
ri->matInst = currentBatch.matInst;
|
||||
ri->matInst = currentBatch->matInst;
|
||||
|
||||
ri->prim = renderPass->allocPrim();
|
||||
ri->prim->type = GFXTriangleList;
|
||||
ri->prim->minIndex = 0;
|
||||
ri->prim->startIndex = 0;
|
||||
ri->prim->numPrimitives = currentBatch.iCount / 3;
|
||||
ri->prim->numPrimitives = currentBatch->iCount / 3;
|
||||
ri->prim->startVertex = 0;
|
||||
ri->prim->numVertices = currentBatch.vCount;
|
||||
ri->prim->numVertices = currentBatch->vCount;
|
||||
|
||||
// Ugly hack for ProjectedShadow!
|
||||
if ( customTex )
|
||||
|
|
@ -1433,7 +1433,7 @@ void DecalManager::prepRenderImage( SceneRenderState* state )
|
|||
// The decal bin will contain render instances for both decals and decalRoad's.
|
||||
// Dynamic decals render last, then editor decals and roads in priority order.
|
||||
// DefaultKey is sorted in descending order.
|
||||
ri->defaultKey = currentBatch.dynamic ? 0xFFFFFFFF : (U32)currentBatch.priority;
|
||||
ri->defaultKey = currentBatch->dynamic ? 0xFFFFFFFF : (U32)currentBatch->priority;
|
||||
ri->defaultKey2 = 1;//(U32)lastDecal->mDataBlock;
|
||||
|
||||
renderPass->addInst( ri );
|
||||
|
|
@ -1495,7 +1495,7 @@ bool DecalManager::_createDataFile()
|
|||
|
||||
// See if we know our current mission name
|
||||
char missionName[1024];
|
||||
dStrcpy( missionName, Con::getVariable( "$Client::MissionFile" ) );
|
||||
dStrcpy( missionName, Con::getVariable( "$Client::MissionFile" ), 1024 );
|
||||
char *dot = dStrstr((const char*)missionName, ".mis");
|
||||
if(dot)
|
||||
*dot = '\0';
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -35,6 +35,12 @@
|
|||
#ifndef _CONTAINERQUERY_H_
|
||||
#include "T3D/containerQuery.h"
|
||||
#endif
|
||||
#ifndef _ASSET_PTR_H_
|
||||
#include "assets/assetPtr.h"
|
||||
#endif
|
||||
#ifndef GAME_OBJECT_ASSET_H
|
||||
#include "T3D/assets/GameObjectAsset.h"
|
||||
#endif
|
||||
|
||||
class Component;
|
||||
|
||||
|
|
@ -52,18 +58,43 @@ private:
|
|||
|
||||
Vector<Component*> mComponents;
|
||||
|
||||
Vector<Component*> mToLoadComponents;
|
||||
//Bit of helper data to let us track and manage the adding, removal and updating of networked components
|
||||
struct NetworkedComponent
|
||||
{
|
||||
U32 componentIndex;
|
||||
|
||||
enum UpdateState
|
||||
{
|
||||
None,
|
||||
Adding,
|
||||
Removing,
|
||||
Updating
|
||||
};
|
||||
|
||||
UpdateState updateState;
|
||||
|
||||
U32 updateMaskBits;
|
||||
};
|
||||
|
||||
Vector<NetworkedComponent> mNetworkedComponents;
|
||||
|
||||
U32 mComponentNetMask;
|
||||
|
||||
bool mStartComponentUpdate;
|
||||
|
||||
StringTableEntry mGameObjectAssetId;
|
||||
AssetPtr<GameObjectAsset> mGameObjectAsset;
|
||||
|
||||
ContainerQueryInfo containerInfo;
|
||||
|
||||
bool mInitialized;
|
||||
|
||||
String mTags;
|
||||
|
||||
Signal< void(Component*) > onComponentAdded;
|
||||
Signal< void(Component*) > onComponentRemoved;
|
||||
|
||||
Signal< void(MatrixF*) > onTransformSet;
|
||||
S32 mLifetimeMS;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
@ -96,9 +127,12 @@ public:
|
|||
{
|
||||
TransformMask = Parent::NextFreeMask << 0,
|
||||
BoundsMask = Parent::NextFreeMask << 1,
|
||||
ComponentsMask = Parent::NextFreeMask << 2,
|
||||
NoWarpMask = Parent::NextFreeMask << 3,
|
||||
NextFreeMask = Parent::NextFreeMask << 4
|
||||
ComponentsUpdateMask = Parent::NextFreeMask << 2,
|
||||
AddComponentsMask = Parent::NextFreeMask << 3,
|
||||
RemoveComponentsMask = Parent::NextFreeMask << 4,
|
||||
NoWarpMask = Parent::NextFreeMask << 5,
|
||||
NamespaceMask = Parent::NextFreeMask << 6,
|
||||
NextFreeMask = Parent::NextFreeMask << 7
|
||||
};
|
||||
|
||||
StateDelta mDelta;
|
||||
|
|
@ -106,6 +140,8 @@ public:
|
|||
|
||||
Move lastMove;
|
||||
|
||||
S32 mStartTimeMS;
|
||||
|
||||
//
|
||||
Entity();
|
||||
~Entity();
|
||||
|
|
@ -116,25 +152,23 @@ public:
|
|||
virtual void setTransform(const MatrixF &mat);
|
||||
virtual void setRenderTransform(const MatrixF &mat);
|
||||
|
||||
void setTransform(Point3F position, RotationF rotation);
|
||||
void setTransform(const Point3F& position, const RotationF& rotation);
|
||||
|
||||
void setRenderTransform(Point3F position, RotationF rotation);
|
||||
void setRenderTransform(const Point3F& position, const RotationF& rotation);
|
||||
|
||||
virtual MatrixF getTransform();
|
||||
virtual Point3F getPosition() const { return mPos; }
|
||||
|
||||
//void setTransform(Point3F position, RotationF rot);
|
||||
|
||||
//void setRotation(RotationF rotation);
|
||||
|
||||
void setRotation(RotationF rotation) {
|
||||
void setRotation(const RotationF& rotation) {
|
||||
mRot = rotation;
|
||||
setMaskBits(TransformMask);
|
||||
};
|
||||
RotationF getRotation() { return mRot; }
|
||||
|
||||
void setMountOffset(Point3F posOffset);
|
||||
void setMountRotation(EulerF rotOffset);
|
||||
static bool _setGameObject(void *object, const char *index, const char *data);
|
||||
|
||||
void setMountOffset(const Point3F& posOffset);
|
||||
void setMountRotation(const EulerF& rotOffset);
|
||||
|
||||
//static bool _setEulerRotation( void *object, const char *index, const char *data );
|
||||
static bool _setPosition(void *object, const char *index, const char *data);
|
||||
|
|
@ -146,13 +180,18 @@ public:
|
|||
virtual void getMountTransform(S32 index, const MatrixF &xfm, MatrixF *outMat);
|
||||
virtual void getRenderMountTransform(F32 delta, S32 index, const MatrixF &xfm, MatrixF *outMat);
|
||||
|
||||
void setForwardVector(VectorF newForward, VectorF upVector = VectorF::Zero);
|
||||
|
||||
virtual void mountObject(SceneObject *obj, S32 node, const MatrixF &xfm = MatrixF::Identity);
|
||||
void mountObject(SceneObject* objB, MatrixF txfm);
|
||||
void mountObject(SceneObject* objB, const MatrixF& txfm);
|
||||
void onMount(SceneObject *obj, S32 node);
|
||||
void onUnmount(SceneObject *obj, S32 node);
|
||||
|
||||
/// Sets the client controlling this object
|
||||
/// @param client Client that is now controlling this object
|
||||
virtual void setControllingClient(GameConnection *client);
|
||||
|
||||
//
|
||||
//Networking
|
||||
//
|
||||
// NetObject
|
||||
U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream);
|
||||
void unpackUpdate(NetConnection *conn, BitStream *stream);
|
||||
|
|
@ -160,9 +199,13 @@ public:
|
|||
void setComponentsDirty();
|
||||
void setComponentDirty(Component *comp, bool forceUpdate = false);
|
||||
|
||||
void setComponentNetMask(Component* comp, U32 mask);
|
||||
|
||||
//Components
|
||||
virtual bool deferAddingComponents() const { return true; }
|
||||
|
||||
void notifyComponents(String signalFunction, String argA, String argB, String argC, String argD, String argE);
|
||||
|
||||
template <class T>
|
||||
T* getComponent();
|
||||
template <class T>
|
||||
|
|
@ -175,7 +218,7 @@ public:
|
|||
return mComponents.size();
|
||||
}
|
||||
|
||||
virtual void setObjectBox(Box3F objBox);
|
||||
virtual void setObjectBox(const Box3F& objBox);
|
||||
|
||||
void resetWorldBox() { Parent::resetWorldBox(); }
|
||||
void resetObjectBox() { Parent::resetObjectBox(); }
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ void RenderShapeExample::createShape()
|
|||
}
|
||||
|
||||
// Update the bounding box
|
||||
mObjBox = mShape->bounds;
|
||||
mObjBox = mShape->mBounds;
|
||||
resetWorldBox();
|
||||
setRenderTransform(mObjToWorld);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/fx/explosion.h"
|
||||
|
||||
|
|
@ -50,6 +55,8 @@
|
|||
#include "renderInstance/renderPassManager.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
#include "sfx/sfxProfile.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(Explosion);
|
||||
|
||||
ConsoleDocClass( Explosion,
|
||||
|
|
@ -281,6 +288,105 @@ ExplosionData::ExplosionData()
|
|||
lightNormalOffset = 0.1f;
|
||||
}
|
||||
|
||||
//#define TRACK_EXPLOSION_DATA_CLONES
|
||||
|
||||
#ifdef TRACK_EXPLOSION_DATA_CLONES
|
||||
static int explosion_data_clones = 0;
|
||||
#endif
|
||||
|
||||
ExplosionData::ExplosionData(const ExplosionData& other, bool temp_clone) : GameBaseData(other, temp_clone)
|
||||
{
|
||||
#ifdef TRACK_EXPLOSION_DATA_CLONES
|
||||
explosion_data_clones++;
|
||||
if (explosion_data_clones == 1)
|
||||
Con::errorf("ExplosionData -- Clones are on the loose!");
|
||||
#endif
|
||||
|
||||
dtsFileName = other.dtsFileName;
|
||||
faceViewer = other.faceViewer;
|
||||
particleDensity = other.particleDensity;
|
||||
particleRadius = other.particleRadius;
|
||||
soundProfile = other.soundProfile;
|
||||
particleEmitter = other.particleEmitter;
|
||||
particleEmitterId = other.particleEmitterId; // -- for pack/unpack of particleEmitter ptr
|
||||
explosionScale = other.explosionScale;
|
||||
playSpeed = other.playSpeed;
|
||||
explosionShape = other.explosionShape; // -- TSShape loaded using dtsFileName
|
||||
explosionAnimation = other.explosionAnimation; // -- from explosionShape sequence "ambient"
|
||||
dMemcpy( emitterList, other.emitterList, sizeof( emitterList ) );
|
||||
dMemcpy( emitterIDList, other.emitterIDList, sizeof( emitterIDList ) ); // -- for pack/unpack of emitterList ptrs
|
||||
dMemcpy( debrisList, other.debrisList, sizeof( debrisList ) );
|
||||
dMemcpy( debrisIDList, other.debrisIDList, sizeof( debrisIDList ) ); // -- for pack/unpack of debrisList ptrs
|
||||
debrisThetaMin = other.debrisThetaMin;
|
||||
debrisThetaMax = other.debrisThetaMax;
|
||||
debrisPhiMin = other.debrisPhiMin;
|
||||
debrisPhiMax = other.debrisPhiMax;
|
||||
debrisNum = other.debrisNum;
|
||||
debrisNumVariance = other.debrisNumVariance;
|
||||
debrisVelocity = other.debrisVelocity;
|
||||
debrisVelocityVariance = other.debrisVelocityVariance;
|
||||
dMemcpy( explosionList, other.explosionList, sizeof( explosionList ) );
|
||||
dMemcpy( explosionIDList, other.explosionIDList, sizeof( explosionIDList ) ); // -- for pack/unpack of explosionList ptrs
|
||||
delayMS = other.delayMS;
|
||||
delayVariance = other.delayVariance;
|
||||
lifetimeMS = other.lifetimeMS;
|
||||
lifetimeVariance = other.lifetimeVariance;
|
||||
offset = other.offset;
|
||||
dMemcpy( sizes, other.times, sizeof( sizes ) );
|
||||
dMemcpy( times, other.times, sizeof( times ) );
|
||||
shakeCamera = other.shakeCamera;
|
||||
camShakeFreq = other.camShakeFreq;
|
||||
camShakeAmp = other.camShakeAmp;
|
||||
camShakeDuration = other.camShakeDuration;
|
||||
camShakeRadius = other.camShakeRadius;
|
||||
camShakeFalloff = other.camShakeFalloff;
|
||||
lightStartRadius = other.lightStartRadius;
|
||||
lightEndRadius = other.lightEndRadius;
|
||||
lightStartColor = other.lightStartColor;
|
||||
lightEndColor = other.lightEndColor;
|
||||
lightStartBrightness = other.lightStartBrightness;
|
||||
lightEndBrightness = other.lightEndBrightness;
|
||||
lightNormalOffset = other.lightNormalOffset;
|
||||
// Note - Explosion calls mDataBlock->getName() in warning messages but
|
||||
// that should be safe.
|
||||
}
|
||||
|
||||
ExplosionData::~ExplosionData()
|
||||
{
|
||||
if (!isTempClone())
|
||||
return;
|
||||
|
||||
if (soundProfile && soundProfile->isTempClone())
|
||||
{
|
||||
delete soundProfile;
|
||||
soundProfile = 0;
|
||||
}
|
||||
|
||||
// particleEmitter, emitterList[*], debrisList[*], explosionList[*] will delete themselves
|
||||
|
||||
#ifdef TRACK_EXPLOSION_DATA_CLONES
|
||||
if (explosion_data_clones > 0)
|
||||
{
|
||||
explosion_data_clones--;
|
||||
if (explosion_data_clones == 0)
|
||||
Con::errorf("ExplosionData -- Clones eliminated!");
|
||||
}
|
||||
else
|
||||
Con::errorf("ExplosionData -- Too many clones deleted!");
|
||||
#endif
|
||||
}
|
||||
|
||||
ExplosionData* ExplosionData::cloneAndPerformSubstitutions(const SimObject* owner, S32 index)
|
||||
{
|
||||
if (!owner || getSubstitutionCount() == 0)
|
||||
return this;
|
||||
|
||||
ExplosionData* sub_explosion_db = new ExplosionData(*this, true);
|
||||
performSubstitutions(sub_explosion_db, owner, index);
|
||||
|
||||
return sub_explosion_db;
|
||||
}
|
||||
|
||||
void ExplosionData::initPersistFields()
|
||||
{
|
||||
addField( "explosionShape", TypeShapeFilename, Offset(dtsFileName, ExplosionData),
|
||||
|
|
@ -412,6 +518,12 @@ void ExplosionData::initPersistFields()
|
|||
"Distance (in the explosion normal direction) of the PointLight position "
|
||||
"from the explosion center." );
|
||||
|
||||
// disallow some field substitutions
|
||||
onlyKeepClearSubstitutions("debris"); // subs resolving to "~~", or "~0" are OK
|
||||
onlyKeepClearSubstitutions("emitter");
|
||||
onlyKeepClearSubstitutions("particleEmitter");
|
||||
onlyKeepClearSubstitutions("soundProfile");
|
||||
onlyKeepClearSubstitutions("subExplosion");
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
|
|
@ -808,6 +920,10 @@ Explosion::Explosion()
|
|||
mLight = LIGHTMGR->createLightInfo();
|
||||
|
||||
mNetFlags.set( IsGhost );
|
||||
ss_object = 0;
|
||||
ss_index = 0;
|
||||
mDataBlock = 0;
|
||||
soundProfile_clone = 0;
|
||||
}
|
||||
|
||||
Explosion::~Explosion()
|
||||
|
|
@ -820,6 +936,18 @@ Explosion::~Explosion()
|
|||
}
|
||||
|
||||
SAFE_DELETE(mLight);
|
||||
|
||||
if (soundProfile_clone)
|
||||
{
|
||||
delete soundProfile_clone;
|
||||
soundProfile_clone = 0;
|
||||
}
|
||||
|
||||
if (mDataBlock && mDataBlock->isTempClone())
|
||||
{
|
||||
delete mDataBlock;
|
||||
mDataBlock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -978,6 +1106,8 @@ bool Explosion::onNewDataBlock( GameBaseData *dptr, bool reload )
|
|||
if (!mDataBlock || !Parent::onNewDataBlock( dptr, reload ))
|
||||
return false;
|
||||
|
||||
if (mDataBlock->isTempClone())
|
||||
return true;
|
||||
scriptOnNewDataBlock();
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1190,7 +1320,8 @@ void Explosion::launchDebris( Point3F &axis )
|
|||
launchDir *= debrisVel;
|
||||
|
||||
Debris *debris = new Debris;
|
||||
debris->setDataBlock( mDataBlock->debrisList[0] );
|
||||
debris->setSubstitutionData(ss_object, ss_index);
|
||||
debris->setDataBlock(mDataBlock->debrisList[0]->cloneAndPerformSubstitutions(ss_object, ss_index));
|
||||
debris->setTransform( getTransform() );
|
||||
debris->init( pos, launchDir );
|
||||
|
||||
|
|
@ -1218,7 +1349,8 @@ void Explosion::spawnSubExplosions()
|
|||
{
|
||||
MatrixF trans = getTransform();
|
||||
Explosion* pExplosion = new Explosion;
|
||||
pExplosion->setDataBlock( mDataBlock->explosionList[i] );
|
||||
pExplosion->setSubstitutionData(ss_object, ss_index);
|
||||
pExplosion->setDataBlock(mDataBlock->explosionList[i]->cloneAndPerformSubstitutions(ss_object, ss_index));
|
||||
pExplosion->setTransform( trans );
|
||||
pExplosion->setInitialState( trans.getPosition(), mInitialNormal, 1);
|
||||
if (!pExplosion->registerObject())
|
||||
|
|
@ -1252,16 +1384,22 @@ bool Explosion::explode()
|
|||
mEndingMS = U32(mExplosionInstance->getScaledDuration(mExplosionThread) * 1000.0f);
|
||||
|
||||
mObjScale.convolve(mDataBlock->explosionScale);
|
||||
mObjBox = mDataBlock->explosionShape->bounds;
|
||||
mObjBox = mDataBlock->explosionShape->mBounds;
|
||||
resetWorldBox();
|
||||
}
|
||||
|
||||
if (mDataBlock->soundProfile)
|
||||
SFX->playOnce( mDataBlock->soundProfile, &getTransform() );
|
||||
SFXProfile* sound_prof = dynamic_cast<SFXProfile*>(mDataBlock->soundProfile);
|
||||
if (sound_prof)
|
||||
{
|
||||
soundProfile_clone = sound_prof->cloneAndPerformSubstitutions(ss_object, ss_index);
|
||||
SFX->playOnce( soundProfile_clone, &getTransform() );
|
||||
if (!soundProfile_clone->isTempClone())
|
||||
soundProfile_clone = 0;
|
||||
}
|
||||
|
||||
if (mDataBlock->particleEmitter) {
|
||||
mMainEmitter = new ParticleEmitter;
|
||||
mMainEmitter->setDataBlock(mDataBlock->particleEmitter);
|
||||
mMainEmitter->setDataBlock(mDataBlock->particleEmitter->cloneAndPerformSubstitutions(ss_object, ss_index));
|
||||
mMainEmitter->registerObject();
|
||||
|
||||
mMainEmitter->emitParticles(getPosition(), mInitialNormal, mDataBlock->particleRadius,
|
||||
|
|
@ -1273,7 +1411,7 @@ bool Explosion::explode()
|
|||
if( mDataBlock->emitterList[i] != NULL )
|
||||
{
|
||||
ParticleEmitter * pEmitter = new ParticleEmitter;
|
||||
pEmitter->setDataBlock( mDataBlock->emitterList[i] );
|
||||
pEmitter->setDataBlock(mDataBlock->emitterList[i]->cloneAndPerformSubstitutions(ss_object, ss_index));
|
||||
if( !pEmitter->registerObject() )
|
||||
{
|
||||
Con::warnf( ConsoleLogEntry::General, "Could not register emitter for particle of class: %s", mDataBlock->getName() );
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _EXPLOSION_H_
|
||||
#define _EXPLOSION_H_
|
||||
|
||||
|
|
@ -42,6 +47,7 @@ class TSThread;
|
|||
class SFXTrack;
|
||||
struct DebrisData;
|
||||
|
||||
class SFXProfile;
|
||||
//--------------------------------------------------------------------------
|
||||
class ExplosionData : public GameBaseData {
|
||||
public:
|
||||
|
|
@ -126,6 +132,11 @@ class ExplosionData : public GameBaseData {
|
|||
static void initPersistFields();
|
||||
virtual void packData(BitStream* stream);
|
||||
virtual void unpackData(BitStream* stream);
|
||||
public:
|
||||
/*C*/ ExplosionData(const ExplosionData&, bool = false);
|
||||
/*D*/ ~ExplosionData();
|
||||
ExplosionData* cloneAndPerformSubstitutions(const SimObject*, S32 index=0);
|
||||
virtual bool allowSubstitutions() const { return true; }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -188,6 +199,12 @@ class Explosion : public GameBase, public ISceneLight
|
|||
|
||||
DECLARE_CONOBJECT(Explosion);
|
||||
static void initPersistFields();
|
||||
private:
|
||||
SimObject* ss_object;
|
||||
S32 ss_index;
|
||||
SFXProfile* soundProfile_clone;
|
||||
public:
|
||||
void setSubstitutionData(SimObject* obj, S32 idx=0) { ss_object = obj; ss_index = idx; }
|
||||
};
|
||||
|
||||
#endif // _H_EXPLOSION
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@
|
|||
// POTENTIAL TODO LIST:
|
||||
// TODO: Clamp item alpha to fog alpha
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/fx/fxFoliageReplicator.h"
|
||||
|
||||
|
|
@ -402,6 +407,9 @@ void fxFoliageReplicator::initPersistFields()
|
|||
addField( "AllowedTerrainSlope", TypeS32, Offset( mFieldData.mAllowedTerrainSlope, fxFoliageReplicator ), "Maximum surface angle allowed for foliage instances." );
|
||||
endGroup( "Restrictions" ); // MM: Added Group Footer.
|
||||
|
||||
addGroup( "AFX" );
|
||||
addField( "AmbientModulationBias", TypeF32, Offset( mFieldData.mAmbientModulationBias,fxFoliageReplicator ), "Multiplier controling amount foliage is modulated by sun's ambient." );
|
||||
endGroup( "AFX" );
|
||||
// Initialise parents' persistent fields.
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
|
@ -1564,7 +1572,12 @@ void fxFoliageReplicator::renderObject(ObjectRenderInst *ri, SceneRenderState *s
|
|||
mFoliageShaderConsts->setSafe(mFoliageShaderGroundAlphaSC, Point4F(mFieldData.mGroundAlpha, mFieldData.mGroundAlpha, mFieldData.mGroundAlpha, mFieldData.mGroundAlpha));
|
||||
|
||||
if (mFoliageShaderAmbientColorSC->isValid())
|
||||
mFoliageShaderConsts->set(mFoliageShaderAmbientColorSC, state->getAmbientLightColor());
|
||||
{
|
||||
LinearColorF ambient = state->getAmbientLightColor();
|
||||
LinearColorF ambient_inv(1.0f-ambient.red, 1.0f-ambient.green, 1.0f-ambient.blue, 0.0f);
|
||||
ambient += ambient_inv*(1.0f - mFieldData.mAmbientModulationBias);
|
||||
mFoliageShaderConsts->set(mFoliageShaderAmbientColorSC, ambient);
|
||||
}
|
||||
|
||||
GFX->setShaderConstBuffer(mFoliageShaderConsts);
|
||||
|
||||
|
|
@ -1705,6 +1718,7 @@ U32 fxFoliageReplicator::packUpdate(NetConnection * con, U32 mask, BitStream * s
|
|||
stream->writeFlag(mFieldData.mShowPlacementArea); // Show Placement Area Flag.
|
||||
stream->write(mFieldData.mPlacementBandHeight); // Placement Area Height.
|
||||
stream->write(mFieldData.mPlaceAreaColour); // Placement Area Colour.
|
||||
stream->write(mFieldData.mAmbientModulationBias);
|
||||
}
|
||||
|
||||
// Were done ...
|
||||
|
|
@ -1782,6 +1796,7 @@ void fxFoliageReplicator::unpackUpdate(NetConnection * con, BitStream * stream)
|
|||
stream->read(&mFieldData.mPlacementBandHeight); // Placement Area Height.
|
||||
stream->read(&mFieldData.mPlaceAreaColour);
|
||||
|
||||
stream->read(&mFieldData.mAmbientModulationBias);
|
||||
// Calculate Fade-In/Out Gradients.
|
||||
mFadeInGradient = 1.0f / mFieldData.mFadeInRegion;
|
||||
mFadeOutGradient = 1.0f / mFieldData.mFadeOutRegion;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _FOLIAGEREPLICATOR_H_
|
||||
#define _FOLIAGEREPLICATOR_H_
|
||||
|
||||
|
|
@ -319,6 +324,7 @@ public:
|
|||
U32 mPlacementBandHeight;
|
||||
LinearColorF mPlaceAreaColour;
|
||||
|
||||
F32 mAmbientModulationBias;
|
||||
tagFieldData()
|
||||
{
|
||||
// Set Defaults.
|
||||
|
|
@ -377,6 +383,7 @@ public:
|
|||
mShowPlacementArea = true;
|
||||
mPlacementBandHeight = 25;
|
||||
mPlaceAreaColour .set(0.4f, 0, 0.8f);
|
||||
mAmbientModulationBias = 1.0f;
|
||||
}
|
||||
|
||||
} mFieldData;
|
||||
|
|
|
|||
|
|
@ -1142,7 +1142,7 @@ GroundCoverCell* GroundCover::_generateCell( const Point2I& index,
|
|||
const F32 typeMaxElevation = mMaxElevation[type];
|
||||
const F32 typeMinElevation = mMinElevation[type];
|
||||
const bool typeIsShape = mShapeInstances[ type ] != NULL;
|
||||
const Box3F typeShapeBounds = typeIsShape ? mShapeInstances[ type ]->getShape()->bounds : Box3F();
|
||||
const Box3F typeShapeBounds = typeIsShape ? mShapeInstances[ type ]->getShape()->mBounds : Box3F();
|
||||
const F32 typeWindScale = mWindScale[type];
|
||||
StringTableEntry typeLayer = mLayer[type];
|
||||
const bool typeInvertLayer = mInvertLayer[type];
|
||||
|
|
@ -1184,9 +1184,9 @@ GroundCoverCell* GroundCover::_generateCell( const Point2I& index,
|
|||
terrainBlock = dynamic_cast< TerrainBlock* >( terrainBlocks.first() );
|
||||
else
|
||||
{
|
||||
for ( U32 i = 0; i < terrainBlocks.size(); i++ )
|
||||
for ( U32 blockIDx = 0; blockIDx < terrainBlocks.size(); blockIDx++ )
|
||||
{
|
||||
TerrainBlock *terrain = dynamic_cast< TerrainBlock* >( terrainBlocks[ i ] );
|
||||
TerrainBlock *terrain = dynamic_cast< TerrainBlock* >( terrainBlocks[ blockIDx ] );
|
||||
if( !terrain )
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,12 @@
|
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "particle.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/typeValidators.h"
|
||||
|
|
@ -72,6 +78,8 @@ static const F32 sgDefaultSpinSpeed = 1.f;
|
|||
static const F32 sgDefaultSpinRandomMin = 0.f;
|
||||
static const F32 sgDefaultSpinRandomMax = 0.f;
|
||||
|
||||
static const F32 sgDefaultSpinBias = 1.0f;
|
||||
static const F32 sgDefaultSizeBias = 1.0f;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
|
|
@ -102,9 +110,9 @@ ParticleData::ParticleData()
|
|||
}
|
||||
|
||||
times[0] = 0.0f;
|
||||
times[1] = 0.33f;
|
||||
times[2] = 0.66f;
|
||||
times[3] = 1.0f;
|
||||
times[1] = 1.0f;
|
||||
for (i = 2; i < PDC_NUM_KEYS; i++)
|
||||
times[i] = -1.0f;
|
||||
|
||||
texCoords[0].set(0.0,0.0); // texture coords at 4 corners
|
||||
texCoords[1].set(0.0,1.0); // of particle quad
|
||||
|
|
@ -115,18 +123,20 @@ ParticleData::ParticleData()
|
|||
animTexUVs = NULL; // array of tile vertex UVs
|
||||
textureName = NULL; // texture filename
|
||||
textureHandle = NULL; // loaded texture handle
|
||||
textureExtName = NULL;
|
||||
textureExtHandle = NULL;
|
||||
constrain_pos = false;
|
||||
start_angle = 0.0f;
|
||||
angle_variance = 0.0f;
|
||||
sizeBias = sgDefaultSizeBias;
|
||||
spinBias = sgDefaultSpinBias;
|
||||
randomizeSpinDir = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
ParticleData::~ParticleData()
|
||||
{
|
||||
if (animTexUVs)
|
||||
{
|
||||
delete [] animTexUVs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FRangeValidator dragCoefFValidator(0.f, 5.f);
|
||||
FRangeValidator gravCoefFValidator(-10.f, 10.f);
|
||||
|
|
@ -214,6 +224,15 @@ void ParticleData::initPersistFields()
|
|||
"@brief Time keys used with the colors and sizes keyframes.\n\n"
|
||||
"Values are from 0.0 (particle creation) to 1.0 (end of lifespace)." );
|
||||
|
||||
addGroup("AFX");
|
||||
addField("textureExtName", TypeFilename, Offset(textureExtName, ParticleData));
|
||||
addField("constrainPos", TypeBool, Offset(constrain_pos, ParticleData));
|
||||
addField("angle", TypeF32, Offset(start_angle, ParticleData));
|
||||
addField("angleVariance", TypeF32, Offset(angle_variance, ParticleData));
|
||||
addField("sizeBias", TypeF32, Offset(sizeBias, ParticleData));
|
||||
addField("spinBias", TypeF32, Offset(spinBias, ParticleData));
|
||||
addField("randomizeSpinDir", TypeBool, Offset(randomizeSpinDir, ParticleData));
|
||||
endGroup("AFX");
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
|
|
@ -243,18 +262,22 @@ void ParticleData::packData(BitStream* stream)
|
|||
stream->writeInt((S32)(spinRandomMin + 1000), 11);
|
||||
stream->writeInt((S32)(spinRandomMax + 1000), 11);
|
||||
}
|
||||
if(stream->writeFlag(spinBias != sgDefaultSpinBias))
|
||||
stream->write(spinBias);
|
||||
stream->writeFlag(randomizeSpinDir);
|
||||
stream->writeFlag(useInvAlpha);
|
||||
|
||||
S32 i, count;
|
||||
|
||||
// see how many frames there are:
|
||||
for(count = 0; count < 3; count++)
|
||||
for(count = 0; count < ParticleData::PDC_NUM_KEYS-1; count++)
|
||||
if(times[count] >= 1)
|
||||
break;
|
||||
|
||||
count++;
|
||||
|
||||
stream->writeInt(count-1, 2);
|
||||
// An extra bit is needed for 8 keys.
|
||||
stream->writeInt(count-1, 3);
|
||||
|
||||
for( i=0; i<count; i++ )
|
||||
{
|
||||
|
|
@ -262,7 +285,8 @@ void ParticleData::packData(BitStream* stream)
|
|||
stream->writeFloat( colors[i].green, 7);
|
||||
stream->writeFloat( colors[i].blue, 7);
|
||||
stream->writeFloat( colors[i].alpha, 7);
|
||||
stream->writeFloat( sizes[i]/MaxParticleSize, 14);
|
||||
// AFX bits raised from 14 to 16 to allow larger sizes
|
||||
stream->writeFloat( sizes[i]/MaxParticleSize, 16);
|
||||
stream->writeFloat( times[i], 8);
|
||||
}
|
||||
|
||||
|
|
@ -279,6 +303,13 @@ void ParticleData::packData(BitStream* stream)
|
|||
mathWrite(*stream, animTexTiling);
|
||||
stream->writeInt(framesPerSec, 8);
|
||||
}
|
||||
if (stream->writeFlag(textureExtName && textureExtName[0]))
|
||||
stream->writeString(textureExtName);
|
||||
stream->writeFlag(constrain_pos);
|
||||
stream->writeFloat(start_angle/360.0f, 11);
|
||||
stream->writeFloat(angle_variance/180.0f, 10);
|
||||
if(stream->writeFlag(sizeBias != sgDefaultSizeBias))
|
||||
stream->write(sizeBias);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -322,17 +353,24 @@ void ParticleData::unpackData(BitStream* stream)
|
|||
spinRandomMax = sgDefaultSpinRandomMax;
|
||||
}
|
||||
|
||||
if(stream->readFlag())
|
||||
stream->read(&spinBias);
|
||||
else
|
||||
spinBias = sgDefaultSpinBias;
|
||||
randomizeSpinDir = stream->readFlag();
|
||||
useInvAlpha = stream->readFlag();
|
||||
|
||||
S32 i;
|
||||
S32 count = stream->readInt(2) + 1;
|
||||
// An extra bit is needed for 8 keys.
|
||||
S32 count = stream->readInt(3) + 1;
|
||||
for(i = 0;i < count; i++)
|
||||
{
|
||||
colors[i].red = stream->readFloat(7);
|
||||
colors[i].green = stream->readFloat(7);
|
||||
colors[i].blue = stream->readFloat(7);
|
||||
colors[i].alpha = stream->readFloat(7);
|
||||
sizes[i] = stream->readFloat(14) * MaxParticleSize;
|
||||
// AFX bits raised from 14 to 16 to allow larger sizes
|
||||
sizes[i] = stream->readFloat(16) * MaxParticleSize;
|
||||
times[i] = stream->readFloat(8);
|
||||
}
|
||||
textureName = (stream->readFlag()) ? stream->readSTString() : 0;
|
||||
|
|
@ -346,6 +384,14 @@ void ParticleData::unpackData(BitStream* stream)
|
|||
mathRead(*stream, &animTexTiling);
|
||||
framesPerSec = stream->readInt(8);
|
||||
}
|
||||
textureExtName = (stream->readFlag()) ? stream->readSTString() : 0;
|
||||
constrain_pos = stream->readFlag();
|
||||
start_angle = 360.0f*stream->readFloat(11);
|
||||
angle_variance = 180.0f*stream->readFloat(10);
|
||||
if(stream->readFlag())
|
||||
stream->read(&sizeBias);
|
||||
else
|
||||
sizeBias = sgDefaultSizeBias;
|
||||
}
|
||||
|
||||
bool ParticleData::protectedSetSizes( void *object, const char *index, const char *data)
|
||||
|
|
@ -427,11 +473,33 @@ bool ParticleData::onAdd()
|
|||
}
|
||||
|
||||
times[0] = 0.0f;
|
||||
for (U32 i = 1; i < 4; i++) {
|
||||
if (times[i] < times[i-1]) {
|
||||
Con::warnf(ConsoleLogEntry::General, "ParticleData(%s) times[%d] < times[%d]", getName(), i, i-1);
|
||||
times[i] = times[i-1];
|
||||
}
|
||||
for (U32 i = 1; i < PDC_NUM_KEYS; i++)
|
||||
{
|
||||
if (times[i] < 0.0f)
|
||||
break;
|
||||
if (times[i] < times[i-1])
|
||||
{
|
||||
Con::warnf(ConsoleLogEntry::General, "ParticleData(%s) times[%d] < times[%d]", getName(), i, i-1);
|
||||
times[i] = times[i-1];
|
||||
}
|
||||
}
|
||||
|
||||
times[0] = 0.0f;
|
||||
|
||||
U32 last_idx = 0;
|
||||
for (U32 i = 1; i < PDC_NUM_KEYS; i++)
|
||||
{
|
||||
if (times[i] < 0.0f)
|
||||
break;
|
||||
else
|
||||
last_idx = i;
|
||||
}
|
||||
|
||||
for (U32 i = last_idx+1; i < PDC_NUM_KEYS; i++)
|
||||
{
|
||||
times[i] = times[last_idx];
|
||||
colors[i] = colors[last_idx];
|
||||
sizes[i] = sizes[last_idx];
|
||||
}
|
||||
|
||||
// Here we validate parameters
|
||||
|
|
@ -470,6 +538,10 @@ bool ParticleData::onAdd()
|
|||
}
|
||||
}
|
||||
|
||||
start_angle = mFmod(start_angle, 360.0f);
|
||||
if (start_angle < 0.0f)
|
||||
start_angle += 360.0f;
|
||||
angle_variance = mClampF(angle_variance, -180.0f, 180.0f);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -495,6 +567,15 @@ bool ParticleData::preload(bool server, String &errorStr)
|
|||
error = true;
|
||||
}
|
||||
}
|
||||
if (textureExtName && textureExtName[0])
|
||||
{
|
||||
textureExtHandle = GFXTexHandle(textureExtName, &GFXStaticTextureSRGBProfile, avar("%s() - textureExtHandle (line %d)", __FUNCTION__, __LINE__));
|
||||
if (!textureExtHandle)
|
||||
{
|
||||
errorStr = String::ToString("Missing particle texture: %s", textureName);
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (animateTexture)
|
||||
{
|
||||
|
|
@ -513,8 +594,9 @@ bool ParticleData::preload(bool server, String &errorStr)
|
|||
|
||||
animTexFrames.clear();
|
||||
|
||||
char* tokCopy = new char[dStrlen(animTexFramesString) + 1];
|
||||
dStrcpy(tokCopy, animTexFramesString);
|
||||
dsize_t tokLen = dStrlen(animTexFramesString) + 1;
|
||||
char* tokCopy = new char[tokLen];
|
||||
dStrcpy(tokCopy, animTexFramesString, tokLen);
|
||||
|
||||
char* currTok = dStrtok(tokCopy, " \t");
|
||||
while (currTok != NULL)
|
||||
|
|
@ -606,6 +688,11 @@ void ParticleData::initializeParticle(Particle* init, const Point3F& inheritVelo
|
|||
|
||||
// assign spin amount
|
||||
init->spinSpeed = spinSpeed * gRandGen.randF( spinRandomMin, spinRandomMax );
|
||||
// apply spin bias
|
||||
init->spinSpeed *= spinBias;
|
||||
// randomize spin direction
|
||||
if (randomizeSpinDir && (gRandGen.randI( 0, 1 ) == 1))
|
||||
init->spinSpeed = -init->spinSpeed;
|
||||
}
|
||||
|
||||
bool ParticleData::reload(char errorBuffer[256])
|
||||
|
|
@ -653,3 +740,78 @@ DefineEngineMethod(ParticleData, reload, void, (),,
|
|||
char errorBuffer[256];
|
||||
object->reload(errorBuffer);
|
||||
}
|
||||
//#define TRACK_PARTICLE_DATA_CLONES
|
||||
|
||||
#ifdef TRACK_PARTICLE_DATA_CLONES
|
||||
static int particle_data_clones = 0;
|
||||
#endif
|
||||
|
||||
ParticleData::ParticleData(const ParticleData& other, bool temp_clone) : SimDataBlock(other, temp_clone)
|
||||
{
|
||||
#ifdef TRACK_PARTICLE_DATA_CLONES
|
||||
particle_data_clones++;
|
||||
if (particle_data_clones == 1)
|
||||
Con::errorf("ParticleData -- Clones are on the loose!");
|
||||
#endif
|
||||
|
||||
dragCoefficient = other.dragCoefficient;
|
||||
windCoefficient = other.windCoefficient;
|
||||
gravityCoefficient = other.gravityCoefficient;
|
||||
inheritedVelFactor = other.inheritedVelFactor;
|
||||
constantAcceleration = other.constantAcceleration;
|
||||
lifetimeMS = other.lifetimeMS;
|
||||
lifetimeVarianceMS = other.lifetimeVarianceMS;
|
||||
spinSpeed = other.spinSpeed;
|
||||
spinRandomMin = other.spinRandomMin;
|
||||
spinRandomMax = other.spinRandomMax;
|
||||
useInvAlpha = other.useInvAlpha;
|
||||
animateTexture = other.animateTexture;
|
||||
numFrames = other.numFrames; // -- calc from other fields
|
||||
framesPerSec = other.framesPerSec;
|
||||
dMemcpy( colors, other.colors, sizeof( colors ) );
|
||||
dMemcpy( sizes, other.sizes, sizeof( sizes ) );
|
||||
dMemcpy( times, other.times, sizeof( times ) );
|
||||
animTexUVs = other.animTexUVs; // -- calc from other fields
|
||||
dMemcpy( texCoords, other.texCoords, sizeof( texCoords ) );
|
||||
animTexTiling = other.animTexTiling;
|
||||
animTexFramesString = other.animTexFramesString;
|
||||
animTexFrames = other.animTexFrames; // -- parsed from animTexFramesString
|
||||
textureName = other.textureName;
|
||||
textureHandle = other.textureHandle;
|
||||
spinBias = other.spinBias;
|
||||
randomizeSpinDir = other.randomizeSpinDir;
|
||||
textureExtName = other.textureExtName;
|
||||
textureExtHandle = other.textureExtHandle;
|
||||
constrain_pos = other.constrain_pos;
|
||||
start_angle = other.start_angle;
|
||||
angle_variance = other.angle_variance;
|
||||
sizeBias = other.sizeBias;
|
||||
}
|
||||
|
||||
ParticleData::~ParticleData()
|
||||
{
|
||||
if (animTexUVs)
|
||||
{
|
||||
delete [] animTexUVs;
|
||||
}
|
||||
|
||||
if (!isTempClone())
|
||||
return;
|
||||
|
||||
#ifdef TRACK_PARTICLE_DATA_CLONES
|
||||
if (particle_data_clones > 0)
|
||||
{
|
||||
particle_data_clones--;
|
||||
if (particle_data_clones == 0)
|
||||
Con::errorf("ParticleData -- Clones eliminated!");
|
||||
}
|
||||
else
|
||||
Con::errorf("ParticleData -- Too many clones deleted!");
|
||||
#endif
|
||||
}
|
||||
|
||||
void ParticleData::onPerformSubstitutions()
|
||||
{
|
||||
char errorBuffer[256];
|
||||
reload(errorBuffer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _PARTICLE_H_
|
||||
#define _PARTICLE_H_
|
||||
|
||||
|
|
@ -44,7 +49,9 @@ class ParticleData : public SimDataBlock
|
|||
public:
|
||||
enum PDConst
|
||||
{
|
||||
PDC_NUM_KEYS = 4,
|
||||
// This increase the keyframes from 4 to 8. Especially useful for premult-alpha blended particles
|
||||
// for which 4 keyframes is often not enough.
|
||||
PDC_NUM_KEYS = 8,
|
||||
};
|
||||
|
||||
F32 dragCoefficient;
|
||||
|
|
@ -97,6 +104,23 @@ class ParticleData : public SimDataBlock
|
|||
static void initPersistFields();
|
||||
|
||||
bool reload(char errorBuffer[256]);
|
||||
public:
|
||||
/*C*/ ParticleData(const ParticleData&, bool = false);
|
||||
virtual void onPerformSubstitutions();
|
||||
virtual bool allowSubstitutions() const { return true; }
|
||||
protected:
|
||||
F32 spinBias;
|
||||
bool randomizeSpinDir;
|
||||
StringTableEntry textureExtName;
|
||||
public:
|
||||
GFXTexHandle textureExtHandle;
|
||||
bool constrain_pos;
|
||||
F32 start_angle;
|
||||
F32 angle_variance;
|
||||
F32 sizeBias;
|
||||
public:
|
||||
bool loadParameters();
|
||||
bool reload(String &errorStr);
|
||||
};
|
||||
|
||||
//*****************************************************************************
|
||||
|
|
@ -123,6 +147,10 @@ struct Particle
|
|||
|
||||
F32 spinSpeed;
|
||||
Particle * next;
|
||||
Point3F pos_local;
|
||||
F32 t_last;
|
||||
Point3F radial_v; // radial vector for concentric effects
|
||||
// note -- for non-oriented particles, we use orientDir.x to store the billboard start angle.
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/fx/particleEmitter.h"
|
||||
|
||||
|
|
@ -38,6 +43,10 @@
|
|||
#include "lighting/lightInfo.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
#include "afx/util/afxParticlePool.h"
|
||||
#endif
|
||||
|
||||
Point3F ParticleEmitter::mWindVelocity( 0.0, 0.0, 0.0 );
|
||||
const F32 ParticleEmitter::AgedSpinToRadians = (1.0f/1000.0f) * (1.0f/360.0f) * M_PI_F * 2.0f;
|
||||
|
||||
|
|
@ -149,6 +158,21 @@ ParticleEmitterData::ParticleEmitterData()
|
|||
|
||||
alignParticles = false;
|
||||
alignDirection = Point3F(0.0f, 1.0f, 0.0f);
|
||||
|
||||
ejectionInvert = false;
|
||||
fade_color = false;
|
||||
fade_alpha = false;
|
||||
fade_size = false;
|
||||
parts_per_eject = 1;
|
||||
use_emitter_xfm = false;
|
||||
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
pool_datablock = 0;
|
||||
pool_index = 0;
|
||||
pool_depth_fade = false;
|
||||
pool_radial_fade = false;
|
||||
do_pool_id_convert = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -293,6 +317,26 @@ void ParticleEmitterData::initPersistFields()
|
|||
|
||||
endGroup( "ParticleEmitterData" );
|
||||
|
||||
addGroup("AFX");
|
||||
addField("ejectionInvert", TypeBool, Offset(ejectionInvert, ParticleEmitterData));
|
||||
addField("fadeColor", TypeBool, Offset(fade_color, ParticleEmitterData));
|
||||
addField("fadeAlpha", TypeBool, Offset(fade_alpha, ParticleEmitterData));
|
||||
addField("fadeSize", TypeBool, Offset(fade_size, ParticleEmitterData));
|
||||
// useEmitterTransform currently does not work in TGEA or T3D
|
||||
addField("useEmitterTransform", TypeBool, Offset(use_emitter_xfm, ParticleEmitterData));
|
||||
endGroup("AFX");
|
||||
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
addGroup("AFX Pooled Particles");
|
||||
addField("poolData", TYPEID<afxParticlePoolData>(), Offset(pool_datablock, ParticleEmitterData));
|
||||
addField("poolIndex", TypeS32, Offset(pool_index, ParticleEmitterData));
|
||||
addField("poolDepthFade", TypeBool, Offset(pool_depth_fade, ParticleEmitterData));
|
||||
addField("poolRadialFade", TypeBool, Offset(pool_radial_fade, ParticleEmitterData));
|
||||
endGroup("AFX Pooled Particles");
|
||||
#endif
|
||||
// disallow some field substitutions
|
||||
disableFieldSubstitutions("particles");
|
||||
onlyKeepClearSubstitutions("poolData"); // subs resolving to "~~", or "~0" are OK
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
|
|
@ -358,6 +402,22 @@ void ParticleEmitterData::packData(BitStream* stream)
|
|||
stream->writeFlag(renderReflection);
|
||||
stream->writeFlag(glow);
|
||||
stream->writeInt( blendStyle, 4 );
|
||||
|
||||
stream->writeFlag(ejectionInvert);
|
||||
stream->writeFlag(fade_color);
|
||||
stream->writeFlag(fade_alpha);
|
||||
stream->writeFlag(fade_size);
|
||||
stream->writeFlag(use_emitter_xfm);
|
||||
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
if (stream->writeFlag(pool_datablock))
|
||||
{
|
||||
stream->writeRangedU32(mPacked ? SimObjectId((uintptr_t)pool_datablock) : pool_datablock->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast);
|
||||
stream->write(pool_index);
|
||||
stream->writeFlag(pool_depth_fade);
|
||||
stream->writeFlag(pool_radial_fade);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -421,6 +481,22 @@ void ParticleEmitterData::unpackData(BitStream* stream)
|
|||
renderReflection = stream->readFlag();
|
||||
glow = stream->readFlag();
|
||||
blendStyle = stream->readInt( 4 );
|
||||
ejectionInvert = stream->readFlag();
|
||||
fade_color = stream->readFlag();
|
||||
fade_alpha = stream->readFlag();
|
||||
fade_size = stream->readFlag();
|
||||
use_emitter_xfm = stream->readFlag();
|
||||
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
if (stream->readFlag())
|
||||
{
|
||||
pool_datablock = (afxParticlePoolData*)stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
|
||||
stream->read(&pool_index);
|
||||
pool_depth_fade = stream->readFlag();
|
||||
pool_radial_fade = stream->readFlag();
|
||||
do_pool_id_convert = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -532,8 +608,9 @@ bool ParticleEmitterData::onAdd()
|
|||
|
||||
// First we parse particleString into a list of particle name tokens
|
||||
Vector<char*> dataBlocks(__FILE__, __LINE__);
|
||||
char* tokCopy = new char[dStrlen(particleString) + 1];
|
||||
dStrcpy(tokCopy, particleString);
|
||||
dsize_t tokLen = dStrlen(particleString) + 1;
|
||||
char* tokCopy = new char[tokLen];
|
||||
dStrcpy(tokCopy, particleString, tokLen);
|
||||
|
||||
char* currTok = dStrtok(tokCopy, " \t");
|
||||
while (currTok != NULL)
|
||||
|
|
@ -600,6 +677,22 @@ bool ParticleEmitterData::preload(bool server, String &errorStr)
|
|||
|
||||
if (!server)
|
||||
{
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
if (do_pool_id_convert)
|
||||
{
|
||||
SimObjectId db_id = (SimObjectId)(uintptr_t)pool_datablock;
|
||||
if (db_id != 0)
|
||||
{
|
||||
// try to convert id to pointer
|
||||
if (!Sim::findObject(db_id, pool_datablock))
|
||||
{
|
||||
Con::errorf("ParticleEmitterData::reload() -- bad datablockId: 0x%x (poolData)", db_id);
|
||||
}
|
||||
}
|
||||
do_pool_id_convert = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// load emitter texture if specified
|
||||
if (textureName && textureName[0])
|
||||
{
|
||||
|
|
@ -669,6 +762,8 @@ void ParticleEmitterData::allocPrimBuffer( S32 overrideSize )
|
|||
|
||||
partListInitSize = maxPartLife / (ejectionPeriodMS - periodVarianceMS);
|
||||
partListInitSize += 8; // add 8 as "fudge factor" to make sure it doesn't realloc if it goes over by 1
|
||||
if (parts_per_eject > 1)
|
||||
partListInitSize *= parts_per_eject;
|
||||
|
||||
// if override size is specified, then the emitter overran its buffer and needs a larger allocation
|
||||
if( overrideSize != -1 )
|
||||
|
|
@ -705,6 +800,134 @@ void ParticleEmitterData::allocPrimBuffer( S32 overrideSize )
|
|||
delete [] indices;
|
||||
}
|
||||
|
||||
//#define TRACK_PARTICLE_EMITTER_DATA_CLONES
|
||||
|
||||
#ifdef TRACK_PARTICLE_EMITTER_DATA_CLONES
|
||||
static int emitter_data_clones = 0;
|
||||
#endif
|
||||
|
||||
ParticleEmitterData::ParticleEmitterData(const ParticleEmitterData& other, bool temp_clone) : GameBaseData(other, temp_clone)
|
||||
{
|
||||
#ifdef TRACK_PARTICLE_EMITTER_DATA_CLONES
|
||||
emitter_data_clones++;
|
||||
if (emitter_data_clones == 1)
|
||||
Con::errorf("ParticleEmitterData -- Clones are on the loose!");
|
||||
#endif
|
||||
|
||||
ejectionPeriodMS = other.ejectionPeriodMS;
|
||||
periodVarianceMS = other.periodVarianceMS;
|
||||
ejectionVelocity = other.ejectionVelocity;
|
||||
velocityVariance = other.velocityVariance;
|
||||
ejectionOffset = other.ejectionOffset;
|
||||
ejectionOffsetVariance = other.ejectionOffsetVariance;
|
||||
thetaMin = other.thetaMin;
|
||||
thetaMax = other.thetaMax;
|
||||
phiReferenceVel = other.phiReferenceVel;
|
||||
phiVariance = other.phiVariance;
|
||||
softnessDistance = other.softnessDistance;
|
||||
ambientFactor = other.ambientFactor;
|
||||
lifetimeMS = other.lifetimeMS;
|
||||
lifetimeVarianceMS = other.lifetimeVarianceMS;
|
||||
overrideAdvance = other.overrideAdvance;
|
||||
orientParticles = other.orientParticles;
|
||||
orientOnVelocity = other.orientOnVelocity;
|
||||
useEmitterSizes = other.useEmitterSizes;
|
||||
useEmitterColors = other.useEmitterColors;
|
||||
alignParticles = other.alignParticles;
|
||||
alignDirection = other.alignDirection;
|
||||
particleString = other.particleString;
|
||||
particleDataBlocks = other.particleDataBlocks; // -- derived from particleString
|
||||
dataBlockIds = other.dataBlockIds; // -- derived from particleString
|
||||
partListInitSize = other.partListInitSize; // -- approx calc from other fields
|
||||
primBuff = other.primBuff;
|
||||
blendStyle = other.blendStyle;
|
||||
sortParticles = other.sortParticles;
|
||||
reverseOrder = other.reverseOrder;
|
||||
textureName = other.textureName;
|
||||
textureHandle = other.textureHandle; // -- TextureHandle loads using textureName
|
||||
highResOnly = other.highResOnly;
|
||||
renderReflection = other.renderReflection;
|
||||
fade_color = other.fade_color;
|
||||
fade_size = other.fade_size;
|
||||
fade_alpha = other.fade_alpha;
|
||||
ejectionInvert = other.ejectionInvert;
|
||||
parts_per_eject = other.parts_per_eject; // -- set to 1 (used by subclasses)
|
||||
use_emitter_xfm = other.use_emitter_xfm;
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
pool_datablock = other.pool_datablock;
|
||||
pool_index = other.pool_index;
|
||||
pool_depth_fade = other.pool_depth_fade;
|
||||
pool_radial_fade = other.pool_radial_fade;
|
||||
do_pool_id_convert = other.do_pool_id_convert; // -- flags pool id conversion need
|
||||
#endif
|
||||
}
|
||||
|
||||
ParticleEmitterData::~ParticleEmitterData()
|
||||
{
|
||||
if (!isTempClone())
|
||||
return;
|
||||
|
||||
for (S32 i = 0; i < particleDataBlocks.size(); i++)
|
||||
{
|
||||
if (particleDataBlocks[i] && particleDataBlocks[i]->isTempClone())
|
||||
{
|
||||
delete particleDataBlocks[i];
|
||||
particleDataBlocks[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TRACK_PARTICLE_EMITTER_DATA_CLONES
|
||||
if (emitter_data_clones > 0)
|
||||
{
|
||||
emitter_data_clones--;
|
||||
if (emitter_data_clones == 0)
|
||||
Con::errorf("ParticleEmitterData -- Clones eliminated!");
|
||||
}
|
||||
else
|
||||
Con::errorf("ParticleEmitterData -- Too many clones deleted!");
|
||||
#endif
|
||||
}
|
||||
|
||||
ParticleEmitterData* ParticleEmitterData::cloneAndPerformSubstitutions(const SimObject* owner, S32 index)
|
||||
{
|
||||
if (!owner)
|
||||
return this;
|
||||
|
||||
bool clone_parts_db = false;
|
||||
|
||||
// note -- this could be checked when the particle blocks are evaluated
|
||||
for (S32 i = 0; i < this->particleDataBlocks.size(); i++)
|
||||
{
|
||||
if (this->particleDataBlocks[i] && (this->particleDataBlocks[i]->getSubstitutionCount() > 0))
|
||||
{
|
||||
clone_parts_db = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ParticleEmitterData* sub_emitter_db = this;
|
||||
|
||||
if (this->getSubstitutionCount() > 0 || clone_parts_db)
|
||||
{
|
||||
sub_emitter_db = new ParticleEmitterData(*this, true);
|
||||
performSubstitutions(sub_emitter_db, owner, index);
|
||||
|
||||
if (clone_parts_db)
|
||||
{
|
||||
for (S32 i = 0; i < sub_emitter_db->particleDataBlocks.size(); i++)
|
||||
{
|
||||
if (sub_emitter_db->particleDataBlocks[i] && (sub_emitter_db->particleDataBlocks[i]->getSubstitutionCount() > 0))
|
||||
{
|
||||
ParticleData* orig_db = sub_emitter_db->particleDataBlocks[i];
|
||||
sub_emitter_db->particleDataBlocks[i] = new ParticleData(*orig_db, true);
|
||||
orig_db->performSubstitutions(sub_emitter_db->particleDataBlocks[i], owner, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sub_emitter_db;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ParticleEmitter
|
||||
|
|
@ -736,6 +959,16 @@ ParticleEmitter::ParticleEmitter()
|
|||
|
||||
// ParticleEmitter should be allocated on the client only.
|
||||
mNetFlags.set( IsGhost );
|
||||
fade_amt = 1.0f;
|
||||
forced_bbox = false;
|
||||
db_temp_clone = false;
|
||||
pos_pe.set(0,0,0);
|
||||
sort_priority = 0;
|
||||
mDataBlock = 0;
|
||||
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
pool = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -747,6 +980,19 @@ ParticleEmitter::~ParticleEmitter()
|
|||
{
|
||||
delete [] part_store[i];
|
||||
}
|
||||
if (db_temp_clone && mDataBlock && mDataBlock->isTempClone())
|
||||
{
|
||||
for (S32 i = 0; i < mDataBlock->particleDataBlocks.size(); i++)
|
||||
{
|
||||
if (mDataBlock->particleDataBlocks[i] && mDataBlock->particleDataBlocks[i]->isTempClone())
|
||||
{
|
||||
delete mDataBlock->particleDataBlocks[i];
|
||||
mDataBlock->particleDataBlocks[i] = 0;
|
||||
}
|
||||
}
|
||||
delete mDataBlock;
|
||||
mDataBlock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -771,6 +1017,11 @@ bool ParticleEmitter::onAdd()
|
|||
mObjBox.maxExtents = Point3F(radius, radius, radius);
|
||||
resetWorldBox();
|
||||
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
if (pool)
|
||||
pool->addParticleEmitter(this);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -780,6 +1031,14 @@ bool ParticleEmitter::onAdd()
|
|||
//-----------------------------------------------------------------------------
|
||||
void ParticleEmitter::onRemove()
|
||||
{
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
if (pool)
|
||||
{
|
||||
pool->removeParticleEmitter(this);
|
||||
pool = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
removeFromScene();
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
|
@ -825,6 +1084,11 @@ bool ParticleEmitter::onNewDataBlock( GameBaseData *dptr, bool reload )
|
|||
part_list_head.next = NULL;
|
||||
n_parts = 0;
|
||||
}
|
||||
if (mDataBlock->isTempClone())
|
||||
{
|
||||
db_temp_clone = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
scriptOnNewDataBlock();
|
||||
return true;
|
||||
|
|
@ -861,6 +1125,11 @@ LinearColorF ParticleEmitter::getCollectiveColor()
|
|||
//-----------------------------------------------------------------------------
|
||||
void ParticleEmitter::prepRenderImage(SceneRenderState* state)
|
||||
{
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
if (pool)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if( state->isReflectPass() && !getDataBlock()->renderReflection )
|
||||
return;
|
||||
|
||||
|
|
@ -889,6 +1158,7 @@ void ParticleEmitter::prepRenderImage(SceneRenderState* state)
|
|||
ri->translucentSort = true;
|
||||
ri->type = RenderPassManager::RIT_Particle;
|
||||
ri->sortDistSq = getRenderWorldBox().getSqDistanceToPoint( camPos );
|
||||
ri->defaultKey = (-sort_priority*100);
|
||||
|
||||
// Draw the system offscreen unless the highResOnly flag is set on the datablock
|
||||
ri->systemState = ( getDataBlock()->highResOnly ? PSS_AwaitingHighResDraw : PSS_AwaitingOffscreenDraw );
|
||||
|
|
@ -992,6 +1262,7 @@ void ParticleEmitter::emitParticles(const Point3F& point,
|
|||
return;
|
||||
}
|
||||
|
||||
pos_pe = point;
|
||||
Point3F realStart;
|
||||
if( useLastPosition && mHasLastPosition )
|
||||
realStart = mLastPosition;
|
||||
|
|
@ -1059,7 +1330,8 @@ void ParticleEmitter::emitParticles(const Point3F& start,
|
|||
// Create particle at the correct position
|
||||
Point3F pos;
|
||||
pos.interpolate(start, end, F32(currTime) / F32(numMilliseconds));
|
||||
addParticle(pos, axis, velocity, axisx);
|
||||
addParticle(pos, axis, velocity, axisx, numMilliseconds-currTime);
|
||||
|
||||
particlesAdded = true;
|
||||
mNextParticleTime = 0;
|
||||
}
|
||||
|
|
@ -1089,7 +1361,7 @@ void ParticleEmitter::emitParticles(const Point3F& start,
|
|||
// Create particle at the correct position
|
||||
Point3F pos;
|
||||
pos.interpolate(start, end, F32(currTime) / F32(numMilliseconds));
|
||||
addParticle(pos, axis, velocity, axisx);
|
||||
addParticle(pos, axis, velocity, axisx, numMilliseconds-currTime);
|
||||
particlesAdded = true;
|
||||
|
||||
// This override-advance code is restored in order to correctly adjust
|
||||
|
|
@ -1114,17 +1386,27 @@ void ParticleEmitter::emitParticles(const Point3F& start,
|
|||
{
|
||||
if (advanceMS != 0)
|
||||
{
|
||||
F32 t = F32(advanceMS) / 1000.0;
|
||||
F32 t = F32(advanceMS) / 1000.0;
|
||||
|
||||
Point3F a = last_part->acc;
|
||||
a -= last_part->vel * last_part->dataBlock->dragCoefficient;
|
||||
a -= mWindVelocity * last_part->dataBlock->windCoefficient;
|
||||
a += Point3F(0.0f, 0.0f, -9.81f) * last_part->dataBlock->gravityCoefficient;
|
||||
Point3F a = last_part->acc;
|
||||
a -= last_part->vel * last_part->dataBlock->dragCoefficient;
|
||||
a += mWindVelocity * last_part->dataBlock->windCoefficient;
|
||||
//a += Point3F(0.0f, 0.0f, -9.81f) * last_part->dataBlock->gravityCoefficient;
|
||||
a.z += -9.81f*last_part->dataBlock->gravityCoefficient; // as long as gravity is a constant, this is faster
|
||||
|
||||
last_part->vel += a * t;
|
||||
last_part->pos += last_part->vel * t;
|
||||
last_part->vel += a * t;
|
||||
//last_part->pos += last_part->vel * t;
|
||||
last_part->pos_local += last_part->vel * t;
|
||||
|
||||
updateKeyData( last_part );
|
||||
// AFX -- allow subclasses to adjust the particle params here
|
||||
sub_particleUpdate(last_part);
|
||||
|
||||
if (last_part->dataBlock->constrain_pos)
|
||||
last_part->pos = last_part->pos_local + this->pos_pe;
|
||||
else
|
||||
last_part->pos = last_part->pos_local;
|
||||
|
||||
updateKeyData( last_part );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1196,7 +1478,7 @@ void ParticleEmitter::emitParticles(const Point3F& rCenter,
|
|||
axis.normalize();
|
||||
pos += rCenter;
|
||||
|
||||
addParticle(pos, axis, velocity, axisz);
|
||||
addParticle(pos, axis, velocity, axisz, 0);
|
||||
}
|
||||
|
||||
// Set world bounding box
|
||||
|
|
@ -1219,6 +1501,8 @@ void ParticleEmitter::emitParticles(const Point3F& rCenter,
|
|||
//-----------------------------------------------------------------------------
|
||||
void ParticleEmitter::updateBBox()
|
||||
{
|
||||
if (forced_bbox)
|
||||
return;
|
||||
Point3F minPt(1e10, 1e10, 1e10);
|
||||
Point3F maxPt(-1e10, -1e10, -1e10);
|
||||
|
||||
|
|
@ -1239,15 +1523,18 @@ void ParticleEmitter::updateBBox()
|
|||
boxScale.y = getMax(boxScale.y, 1.0f);
|
||||
boxScale.z = getMax(boxScale.z, 1.0f);
|
||||
mBBObjToWorld.scale(boxScale);
|
||||
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
if (pool)
|
||||
pool->updatePoolBBox(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// addParticle
|
||||
//-----------------------------------------------------------------------------
|
||||
void ParticleEmitter::addParticle(const Point3F& pos,
|
||||
const Point3F& axis,
|
||||
const Point3F& vel,
|
||||
const Point3F& axisx)
|
||||
void ParticleEmitter::addParticle(const Point3F& pos, const Point3F& axis, const Point3F& vel,
|
||||
const Point3F& axisx, const U32 age_offset)
|
||||
{
|
||||
n_parts++;
|
||||
if (n_parts > n_part_capacity || n_parts > mDataBlock->partListInitSize)
|
||||
|
|
@ -1269,6 +1556,16 @@ void ParticleEmitter::addParticle(const Point3F& pos,
|
|||
pNew->next = part_list_head.next;
|
||||
part_list_head.next = pNew;
|
||||
|
||||
// for earlier access to constrain_pos, the ParticleData datablock is chosen here instead
|
||||
// of later in the method.
|
||||
U32 dBlockIndex = gRandGen.randI() % mDataBlock->particleDataBlocks.size();
|
||||
ParticleData* part_db = mDataBlock->particleDataBlocks[dBlockIndex];
|
||||
// set start position to world or local space
|
||||
Point3F pos_start;
|
||||
if (part_db->constrain_pos)
|
||||
pos_start.set(0,0,0);
|
||||
else
|
||||
pos_start = pos;
|
||||
Point3F ejectionAxis = axis;
|
||||
F32 theta = (mDataBlock->thetaMax - mDataBlock->thetaMin) * gRandGen.randF() +
|
||||
mDataBlock->thetaMin;
|
||||
|
|
@ -1290,14 +1587,17 @@ void ParticleEmitter::addParticle(const Point3F& pos,
|
|||
F32 initialVel = mDataBlock->ejectionVelocity;
|
||||
initialVel += (mDataBlock->velocityVariance * 2.0f * gRandGen.randF()) - mDataBlock->velocityVariance;
|
||||
|
||||
pNew->pos = pos + (ejectionAxis * (mDataBlock->ejectionOffset + mDataBlock->ejectionOffsetVariance* gRandGen.randF()) );
|
||||
pNew->vel = ejectionAxis * initialVel;
|
||||
pNew->orientDir = ejectionAxis;
|
||||
pNew->pos = pos_start + (ejectionAxis * (mDataBlock->ejectionOffset + mDataBlock->ejectionOffsetVariance* gRandGen.randF()) );
|
||||
pNew->pos_local = pNew->pos;
|
||||
pNew->vel = mDataBlock->ejectionInvert ? ejectionAxis * -initialVel : ejectionAxis * initialVel;
|
||||
if (mDataBlock->orientParticles)
|
||||
pNew->orientDir = ejectionAxis;
|
||||
else
|
||||
// note -- for non-oriented particles, we use orientDir.x to store the billboard start angle.
|
||||
pNew->orientDir.x = mDegToRad(part_db->start_angle + part_db->angle_variance*2.0f*gRandGen.randF() - part_db->angle_variance);
|
||||
pNew->acc.set(0, 0, 0);
|
||||
pNew->currentAge = 0;
|
||||
|
||||
// Choose a new particle datablack randomly from the list
|
||||
U32 dBlockIndex = gRandGen.randI() % mDataBlock->particleDataBlocks.size();
|
||||
pNew->currentAge = age_offset;
|
||||
pNew->t_last = 0.0f;
|
||||
mDataBlock->particleDataBlocks[dBlockIndex]->initializeParticle(pNew, vel);
|
||||
updateKeyData( pNew );
|
||||
|
||||
|
|
@ -1379,8 +1679,10 @@ void ParticleEmitter::updateKeyData( Particle *part )
|
|||
if( part->totalLifetime < 1 )
|
||||
part->totalLifetime = 1;
|
||||
|
||||
F32 t = F32(part->currentAge) / F32(part->totalLifetime);
|
||||
AssertFatal(t <= 1.0f, "Out out bounds filter function for particle.");
|
||||
if (part->currentAge > part->totalLifetime)
|
||||
part->currentAge = part->totalLifetime;
|
||||
F32 t = (F32)part->currentAge / (F32)part->totalLifetime;
|
||||
|
||||
|
||||
for( U32 i = 1; i < ParticleData::PDC_NUM_KEYS; i++ )
|
||||
{
|
||||
|
|
@ -1412,7 +1714,25 @@ void ParticleEmitter::updateKeyData( Particle *part )
|
|||
{
|
||||
part->size = (part->dataBlock->sizes[i-1] * (1.0 - firstPart)) +
|
||||
(part->dataBlock->sizes[i] * firstPart);
|
||||
part->size *= part->dataBlock->sizeBias;
|
||||
}
|
||||
|
||||
if (mDataBlock->fade_color)
|
||||
{
|
||||
if (mDataBlock->fade_alpha)
|
||||
part->color *= fade_amt;
|
||||
else
|
||||
{
|
||||
part->color.red *= fade_amt;
|
||||
part->color.green *= fade_amt;
|
||||
part->color.blue *= fade_amt;
|
||||
}
|
||||
}
|
||||
else if (mDataBlock->fade_alpha)
|
||||
part->color.alpha *= fade_amt;
|
||||
|
||||
if (mDataBlock->fade_size)
|
||||
part->size *= fade_amt;
|
||||
break;
|
||||
|
||||
}
|
||||
|
|
@ -1424,19 +1744,25 @@ void ParticleEmitter::updateKeyData( Particle *part )
|
|||
//-----------------------------------------------------------------------------
|
||||
void ParticleEmitter::update( U32 ms )
|
||||
{
|
||||
// TODO: Prefetch
|
||||
F32 t = F32(ms)/1000.0f; // AFX -- moved outside loop, no need to recalculate this for every particle
|
||||
|
||||
for (Particle* part = part_list_head.next; part != NULL; part = part->next)
|
||||
{
|
||||
F32 t = F32(ms) / 1000.0;
|
||||
|
||||
Point3F a = part->acc;
|
||||
a -= part->vel * part->dataBlock->dragCoefficient;
|
||||
a -= mWindVelocity * part->dataBlock->windCoefficient;
|
||||
a += Point3F(0.0f, 0.0f, -9.81f) * part->dataBlock->gravityCoefficient;
|
||||
a -= part->vel * part->dataBlock->dragCoefficient;
|
||||
a += mWindVelocity * part->dataBlock->windCoefficient;
|
||||
a.z += -9.81f*part->dataBlock->gravityCoefficient; // AFX -- as long as gravity is a constant, this is faster
|
||||
|
||||
part->vel += a * t;
|
||||
part->pos += part->vel * t;
|
||||
part->pos_local += part->vel * t;
|
||||
|
||||
// AFX -- allow subclasses to adjust the particle params here
|
||||
sub_particleUpdate(part);
|
||||
|
||||
if (part->dataBlock->constrain_pos)
|
||||
part->pos = part->pos_local + this->pos_pe;
|
||||
else
|
||||
part->pos = part->pos_local;
|
||||
|
||||
updateKeyData( part );
|
||||
}
|
||||
|
|
@ -1999,3 +2325,43 @@ DefineEngineMethod(ParticleEmitterData, reload, void,(),,
|
|||
{
|
||||
object->reload();
|
||||
}
|
||||
void ParticleEmitter::emitParticlesExt(const MatrixF& xfm, const Point3F& point,
|
||||
const Point3F& velocity, const U32 numMilliseconds)
|
||||
{
|
||||
if (mDataBlock->use_emitter_xfm)
|
||||
{
|
||||
Point3F zero_point(0.0f, 0.0f, 0.0f);
|
||||
this->pos_pe = zero_point;
|
||||
this->setTransform(xfm);
|
||||
Point3F axis(0.0,0.0,1.0);
|
||||
xfm.mulV(axis);
|
||||
emitParticles(zero_point, true, axis, velocity, numMilliseconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->pos_pe = point;
|
||||
Point3F axis(0.0,0.0,1.0);
|
||||
xfm.mulV(axis);
|
||||
emitParticles(point, true, axis, velocity, numMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEmitter::setForcedObjBox(Box3F& box)
|
||||
{
|
||||
mObjBox = box;
|
||||
forced_bbox = true;
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
if (pool)
|
||||
pool->updatePoolBBox(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ParticleEmitter::setSortPriority(S8 priority)
|
||||
{
|
||||
sort_priority = (priority == 0) ? 1 : priority;
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
if (pool)
|
||||
pool->setSortPriority(sort_priority);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _H_PARTICLE_EMITTER
|
||||
#define _H_PARTICLE_EMITTER
|
||||
|
||||
|
|
@ -42,6 +47,14 @@
|
|||
class RenderPassManager;
|
||||
class ParticleData;
|
||||
|
||||
#ifdef TORQUE_AFX_ENABLED
|
||||
#define AFX_CAP_PARTICLE_POOLS
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
class afxParticlePoolData;
|
||||
class afxParticlePool;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
// Particle Emitter Data
|
||||
//*****************************************************************************
|
||||
|
|
@ -113,6 +126,26 @@ class ParticleEmitterData : public GameBaseData
|
|||
bool glow; ///< Renders this emitter into the glow buffer.
|
||||
|
||||
bool reload();
|
||||
public:
|
||||
bool fade_color;
|
||||
bool fade_size;
|
||||
bool fade_alpha;
|
||||
bool ejectionInvert;
|
||||
U8 parts_per_eject;
|
||||
bool use_emitter_xfm;
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
public:
|
||||
afxParticlePoolData* pool_datablock;
|
||||
U32 pool_index;
|
||||
bool pool_depth_fade;
|
||||
bool pool_radial_fade;
|
||||
bool do_pool_id_convert;
|
||||
#endif
|
||||
public:
|
||||
/*C*/ ParticleEmitterData(const ParticleEmitterData&, bool = false);
|
||||
/*D*/ ~ParticleEmitterData();
|
||||
virtual ParticleEmitterData* cloneAndPerformSubstitutions(const SimObject*, S32 index=0);
|
||||
virtual bool allowSubstitutions() const { return true; }
|
||||
};
|
||||
|
||||
//*****************************************************************************
|
||||
|
|
@ -121,6 +154,9 @@ class ParticleEmitterData : public GameBaseData
|
|||
class ParticleEmitter : public GameBase
|
||||
{
|
||||
typedef GameBase Parent;
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
friend class afxParticlePool;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
|
|
@ -190,7 +226,7 @@ class ParticleEmitter : public GameBase
|
|||
/// @param axis
|
||||
/// @param vel Initial velocity
|
||||
/// @param axisx
|
||||
void addParticle(const Point3F &pos, const Point3F &axis, const Point3F &vel, const Point3F &axisx);
|
||||
void addParticle(const Point3F &pos, const Point3F &axis, const Point3F &vel, const Point3F &axisx, const U32 age_offset);
|
||||
|
||||
|
||||
inline void setupBillboard( Particle *part,
|
||||
|
|
@ -227,7 +263,12 @@ class ParticleEmitter : public GameBase
|
|||
// PEngine interface
|
||||
private:
|
||||
|
||||
// AFX subclasses to ParticleEmitter require access to some members and methods of
|
||||
// ParticleEmitter which are normally declared with private scope. In this section,
|
||||
// protected and private scope statements have been inserted inline with the original
|
||||
// code to expose the necessary members and methods.
|
||||
void update( U32 ms );
|
||||
protected:
|
||||
inline void updateKeyData( Particle *part );
|
||||
|
||||
|
||||
|
|
@ -239,25 +280,30 @@ class ParticleEmitter : public GameBase
|
|||
|
||||
ParticleEmitterData* mDataBlock;
|
||||
|
||||
protected:
|
||||
U32 mInternalClock;
|
||||
|
||||
U32 mNextParticleTime;
|
||||
|
||||
Point3F mLastPosition;
|
||||
bool mHasLastPosition;
|
||||
private:
|
||||
MatrixF mBBObjToWorld;
|
||||
|
||||
bool mDeleteWhenEmpty;
|
||||
bool mDeleteOnTick;
|
||||
|
||||
protected:
|
||||
S32 mLifetimeMS;
|
||||
S32 mElapsedTimeMS;
|
||||
|
||||
private:
|
||||
F32 sizes[ ParticleData::PDC_NUM_KEYS ];
|
||||
LinearColorF colors[ ParticleData::PDC_NUM_KEYS ];
|
||||
|
||||
GFXVertexBufferHandle<ParticleVertexType> mVertBuff;
|
||||
|
||||
protected:
|
||||
// These members are for implementing a link-list of the active emitter
|
||||
// particles. Member part_store contains blocks of particles that can be
|
||||
// chained in a link-list. Usually the first part_store block is large
|
||||
|
|
@ -268,8 +314,28 @@ class ParticleEmitter : public GameBase
|
|||
Particle part_list_head;
|
||||
S32 n_part_capacity;
|
||||
S32 n_parts;
|
||||
private:
|
||||
S32 mCurBuffSize;
|
||||
|
||||
protected:
|
||||
F32 fade_amt;
|
||||
bool forced_bbox;
|
||||
bool db_temp_clone;
|
||||
Point3F pos_pe;
|
||||
S8 sort_priority;
|
||||
virtual void sub_particleUpdate(Particle*) { }
|
||||
public:
|
||||
virtual void emitParticlesExt(const MatrixF& xfm, const Point3F& point, const Point3F& velocity, const U32 numMilliseconds);
|
||||
void setFadeAmount(F32 amt) { fade_amt = amt; }
|
||||
void setForcedObjBox(Box3F& box);
|
||||
void setSortPriority(S8 priority);
|
||||
#if defined(AFX_CAP_PARTICLE_POOLS)
|
||||
protected:
|
||||
afxParticlePool* pool;
|
||||
public:
|
||||
void clearPool() { pool = 0; }
|
||||
void setPool(afxParticlePool* p) { pool = p; }
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // _H_PARTICLE_EMITTER
|
||||
|
|
|
|||
|
|
@ -508,10 +508,10 @@ void Ribbon::prepRenderImage(SceneRenderState *state)
|
|||
|
||||
// Set up our vertex buffer and primitive buffer
|
||||
if(mUpdateBuffers)
|
||||
createBuffers(state, verts, primBuffer, segments);
|
||||
createBuffers(state, mVerts, mPrimBuffer, segments);
|
||||
|
||||
ri->vertBuff = &verts;
|
||||
ri->primBuff = &primBuffer;
|
||||
ri->vertBuff = &mVerts;
|
||||
ri->primBuff = &mPrimBuffer;
|
||||
ri->visibility = 1.0f;
|
||||
|
||||
ri->prim = renderPass->allocPrim();
|
||||
|
|
|
|||
|
|
@ -99,8 +99,8 @@ class Ribbon : public GameBase
|
|||
BaseMatInstance *mRibbonMat;
|
||||
MaterialParameterHandle* mRadiusSC;
|
||||
MaterialParameterHandle* mRibbonProjSC;
|
||||
GFXPrimitiveBufferHandle primBuffer;
|
||||
GFXVertexBufferHandle<GFXVertexPCNTT> verts;
|
||||
GFXPrimitiveBufferHandle mPrimBuffer;
|
||||
GFXVertexBufferHandle<GFXVertexPCNTT> mVerts;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ WindEmitter::WindEmitter()
|
|||
|
||||
WindEmitter::~WindEmitter()
|
||||
{
|
||||
WindEmitterList::iterator iter = find( smAllEmitters.begin(), smAllEmitters.end(), this );
|
||||
WindEmitterList::iterator iter = T3D::find( smAllEmitters.begin(), smAllEmitters.end(), this );
|
||||
smAllEmitters.erase( iter );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/gameBase/gameBase.h"
|
||||
#include "console/consoleTypes.h"
|
||||
|
|
@ -36,6 +41,9 @@
|
|||
#include "T3D/aiConnection.h"
|
||||
#endif
|
||||
|
||||
#ifdef TORQUE_AFX_ENABLED
|
||||
#include "afx/arcaneFX.h"
|
||||
#endif
|
||||
//----------------------------------------------------------------------------
|
||||
// Ghost update relative priority values
|
||||
|
||||
|
|
@ -119,8 +127,14 @@ IMPLEMENT_CALLBACK( GameBase, setControl, void, ( bool controlled ), ( controlle
|
|||
|
||||
GameBaseData::GameBaseData()
|
||||
{
|
||||
category = "";
|
||||
packed = false;
|
||||
mCategory = "";
|
||||
mPacked = false;
|
||||
}
|
||||
GameBaseData::GameBaseData(const GameBaseData& other, bool temp_clone) : SimDataBlock(other, temp_clone)
|
||||
{
|
||||
mPacked = other.mPacked;
|
||||
mCategory = other.mCategory;
|
||||
//mReloadSignal = other.mReloadSignal; // DO NOT copy the mReloadSignal member.
|
||||
}
|
||||
|
||||
void GameBaseData::inspectPostApply()
|
||||
|
|
@ -144,7 +158,7 @@ void GameBaseData::initPersistFields()
|
|||
{
|
||||
addGroup("Scripting");
|
||||
|
||||
addField( "category", TypeCaseString, Offset( category, GameBaseData ),
|
||||
addField( "category", TypeCaseString, Offset(mCategory, GameBaseData ),
|
||||
"The group that this datablock will show up in under the \"Scripted\" "
|
||||
"tab in the World Editor Library." );
|
||||
|
||||
|
|
@ -157,14 +171,14 @@ bool GameBaseData::preload(bool server, String &errorStr)
|
|||
{
|
||||
if (!Parent::preload(server, errorStr))
|
||||
return false;
|
||||
packed = false;
|
||||
mPacked = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameBaseData::unpackData(BitStream* stream)
|
||||
{
|
||||
Parent::unpackData(stream);
|
||||
packed = true;
|
||||
mPacked = true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
@ -244,6 +258,10 @@ GameBase::GameBase()
|
|||
|
||||
GameBase::~GameBase()
|
||||
{
|
||||
#ifdef TORQUE_AFX_ENABLED
|
||||
if (mScope_registered)
|
||||
arcaneFX::unregisterScopedObject(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -256,8 +274,21 @@ bool GameBase::onAdd()
|
|||
|
||||
// Datablock must be initialized on the server.
|
||||
// Client datablock are initialized by the initial update.
|
||||
#ifdef TORQUE_AFX_ENABLED
|
||||
if (isClientObject())
|
||||
{
|
||||
if (mScope_id > 0 && !mScope_registered)
|
||||
arcaneFX::registerScopedObject(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( mDataBlock && !onNewDataBlock( mDataBlock, false ) )
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if ( isServerObject() && mDataBlock && !onNewDataBlock( mDataBlock, false ) )
|
||||
return false;
|
||||
#endif
|
||||
|
||||
setProcessTick( true );
|
||||
|
||||
|
|
@ -266,6 +297,10 @@ bool GameBase::onAdd()
|
|||
|
||||
void GameBase::onRemove()
|
||||
{
|
||||
#ifdef TORQUE_AFX_ENABLED
|
||||
if (mScope_registered)
|
||||
arcaneFX::unregisterScopedObject(this);
|
||||
#endif
|
||||
// EDITOR FEATURE: Remove us from the reload signal of our datablock.
|
||||
if ( mDataBlock )
|
||||
mDataBlock->mReloadSignal.remove( this, &GameBase::_onDatablockModified );
|
||||
|
|
@ -290,6 +325,11 @@ bool GameBase::onNewDataBlock( GameBaseData *dptr, bool reload )
|
|||
|
||||
if ( !mDataBlock )
|
||||
return false;
|
||||
#ifdef TORQUE_AFX_ENABLED
|
||||
// Don't set mask when new datablock is a temp-clone.
|
||||
if (mDataBlock->isTempClone())
|
||||
return true;
|
||||
#endif
|
||||
|
||||
setMaskBits(DataBlockMask);
|
||||
return true;
|
||||
|
|
@ -415,7 +455,7 @@ F32 GameBase::getUpdatePriority(CameraScopeQuery *camInfo, U32 updateMask, S32 u
|
|||
// Projectiles are more interesting if they
|
||||
// are heading for us.
|
||||
wInterest = 0.30f;
|
||||
F32 dot = -mDot(pos,getVelocity());
|
||||
dot = -mDot(pos,getVelocity());
|
||||
if (dot > 0.0f)
|
||||
wInterest += 0.20 * dot;
|
||||
}
|
||||
|
|
@ -543,6 +583,13 @@ U32 GameBase::packUpdate( NetConnection *connection, U32 mask, BitStream *stream
|
|||
stream->writeFlag(mIsAiControlled);
|
||||
#endif
|
||||
|
||||
#ifdef TORQUE_AFX_ENABLED
|
||||
if (stream->writeFlag(mask & ScopeIdMask))
|
||||
{
|
||||
if (stream->writeFlag(mScope_refs > 0))
|
||||
stream->writeInt(mScope_id, SCOPE_ID_BITS);
|
||||
}
|
||||
#endif
|
||||
return retMask;
|
||||
}
|
||||
|
||||
|
|
@ -581,6 +628,13 @@ void GameBase::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
mTicksSinceLastMove = 0;
|
||||
mIsAiControlled = stream->readFlag();
|
||||
#endif
|
||||
#ifdef TORQUE_AFX_ENABLED
|
||||
if (stream->readFlag())
|
||||
{
|
||||
mScope_id = (stream->readFlag()) ? (U16) stream->readInt(SCOPE_ID_BITS) : 0;
|
||||
mScope_refs = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GameBase::onMount( SceneObject *obj, S32 node )
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _GAMEBASE_H_
|
||||
#define _GAMEBASE_H_
|
||||
|
||||
|
|
@ -86,8 +91,8 @@ private:
|
|||
|
||||
public:
|
||||
|
||||
bool packed;
|
||||
StringTableEntry category;
|
||||
bool mPacked;
|
||||
StringTableEntry mCategory;
|
||||
|
||||
// Signal triggered when this datablock is modified.
|
||||
// GameBase objects referencing this datablock notify with this signal.
|
||||
|
|
@ -113,6 +118,8 @@ public:
|
|||
DECLARE_CALLBACK( void, onMount, ( SceneObject* obj, SceneObject* mountObj, S32 node ) );
|
||||
DECLARE_CALLBACK( void, onUnmount, ( SceneObject* obj, SceneObject* mountObj, S32 node ) );
|
||||
/// @}
|
||||
public:
|
||||
GameBaseData(const GameBaseData&, bool = false);
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
@ -229,7 +236,8 @@ public:
|
|||
enum GameBaseMasks {
|
||||
DataBlockMask = Parent::NextFreeMask << 0,
|
||||
ExtendedInfoMask = Parent::NextFreeMask << 1,
|
||||
NextFreeMask = Parent::NextFreeMask << 2
|
||||
ScopeIdMask = Parent::NextFreeMask << 2,
|
||||
NextFreeMask = Parent::NextFreeMask << 3,
|
||||
};
|
||||
|
||||
// net flags added by game base
|
||||
|
|
@ -453,6 +461,8 @@ private:
|
|||
/// within this callback.
|
||||
///
|
||||
void _onDatablockModified();
|
||||
protected:
|
||||
void onScopeIdChange() { setMaskBits(ScopeIdMask); }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/gameBase/gameConnection.h"
|
||||
|
||||
|
|
@ -39,10 +44,8 @@
|
|||
#include "console/engineAPI.h"
|
||||
#include "math/mTransform.h"
|
||||
|
||||
#ifdef TORQUE_EXPERIMENTAL_EC
|
||||
#include "T3D/entity.h"
|
||||
#include "T3D/components/coreInterfaces.h"
|
||||
#endif
|
||||
|
||||
#ifdef TORQUE_HIFI_NET
|
||||
#include "T3D/gameBase/hifi/hifiMoveList.h"
|
||||
|
|
@ -52,6 +55,13 @@
|
|||
#include "T3D/gameBase/std/stdMoveList.h"
|
||||
#endif
|
||||
|
||||
#ifdef AFX_CAP_DATABLOCK_CACHE
|
||||
#include "core/stream/fileStream.h"
|
||||
#endif
|
||||
|
||||
#ifdef TORQUE_AFX_ENABLED
|
||||
#include "afx/arcaneFX.h"
|
||||
#endif
|
||||
//----------------------------------------------------------------------------
|
||||
#define MAX_MOVE_PACKET_SENDS 4
|
||||
|
||||
|
|
@ -173,9 +183,28 @@ IMPLEMENT_CALLBACK( GameConnection, onFlash, void, (bool state), (state),
|
|||
"either is on or both are off. Typically this is used to enable the flash postFx.\n\n"
|
||||
"@param state Set to true if either the damage flash or white out conditions are active.\n\n");
|
||||
|
||||
#ifdef AFX_CAP_DATABLOCK_CACHE
|
||||
StringTableEntry GameConnection::server_cache_filename = "";
|
||||
StringTableEntry GameConnection::client_cache_filename = "";
|
||||
bool GameConnection::server_cache_on = false;
|
||||
bool GameConnection::client_cache_on = false;
|
||||
#endif
|
||||
//----------------------------------------------------------------------------
|
||||
GameConnection::GameConnection()
|
||||
{
|
||||
#ifdef TORQUE_AFX_ENABLED
|
||||
mRolloverObj = NULL;
|
||||
mPreSelectedObj = NULL;
|
||||
mSelectedObj = NULL;
|
||||
mChangedSelectedObj = false;
|
||||
mPreSelectTimestamp = 0;
|
||||
zoned_in = false;
|
||||
#endif
|
||||
|
||||
#ifdef AFX_CAP_DATABLOCK_CACHE
|
||||
client_db_stream = new InfiniteBitStream;
|
||||
server_cache_CRC = 0xffffffff;
|
||||
#endif
|
||||
mLagging = false;
|
||||
mControlObject = NULL;
|
||||
mCameraObject = NULL;
|
||||
|
|
@ -246,6 +275,10 @@ GameConnection::~GameConnection()
|
|||
dFree(mConnectArgv[i]);
|
||||
dFree(mJoinPassword);
|
||||
delete mMoveList;
|
||||
|
||||
#ifdef AFX_CAP_DATABLOCK_CACHE
|
||||
delete client_db_stream;
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
@ -293,7 +326,7 @@ DefineEngineMethod( GameConnection, setJoinPassword, void, (const char* password
|
|||
object->setJoinPassword(password);
|
||||
}
|
||||
|
||||
ConsoleMethod(GameConnection, setConnectArgs, void, 3, 17,
|
||||
DefineEngineStringlyVariadicMethod(GameConnection, setConnectArgs, void, 3, 17,
|
||||
"(const char* args) @brief On the client, pass along a variable set of parameters to the server.\n\n"
|
||||
|
||||
"Once the connection is established with the server, the server calls its onConnect() method "
|
||||
|
|
@ -754,7 +787,6 @@ bool GameConnection::getControlCameraFov(F32 * fov)
|
|||
}
|
||||
if (cObj)
|
||||
{
|
||||
#ifdef TORQUE_EXPERIMENTAL_EC
|
||||
if (Entity* ent = dynamic_cast<Entity*>(cObj))
|
||||
{
|
||||
if (CameraInterface* camInterface = ent->getComponent<CameraInterface>())
|
||||
|
|
@ -764,11 +796,9 @@ bool GameConnection::getControlCameraFov(F32 * fov)
|
|||
}
|
||||
else
|
||||
{
|
||||
*fov = cObj->getCameraFov();
|
||||
*fov = cObj->getCameraFov();
|
||||
}
|
||||
#else
|
||||
*fov = cObj->getCameraFov();
|
||||
#endif
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
|
@ -788,7 +818,6 @@ bool GameConnection::isValidControlCameraFov(F32 fov)
|
|||
|
||||
if (cObj)
|
||||
{
|
||||
#ifdef TORQUE_EXPERIMENTAL_EC
|
||||
if (Entity* ent = dynamic_cast<Entity*>(cObj))
|
||||
{
|
||||
if (CameraInterface* camInterface = ent->getComponent<CameraInterface>())
|
||||
|
|
@ -800,9 +829,6 @@ bool GameConnection::isValidControlCameraFov(F32 fov)
|
|||
{
|
||||
return cObj->isValidCameraFov(fov);
|
||||
}
|
||||
#else
|
||||
return cObj->isValidCameraFov(fov);
|
||||
#endif
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
@ -820,8 +846,6 @@ bool GameConnection::setControlCameraFov(F32 fov)
|
|||
}
|
||||
if (cObj)
|
||||
{
|
||||
|
||||
#ifdef TORQUE_EXPERIMENTAL_EC
|
||||
F32 newFov = 90.f;
|
||||
if (Entity* ent = dynamic_cast<Entity*>(cObj))
|
||||
{
|
||||
|
|
@ -841,11 +865,6 @@ bool GameConnection::setControlCameraFov(F32 fov)
|
|||
cObj->setCameraFov(mClampF(fov, MinCameraFov, MaxCameraFov));
|
||||
newFov = cObj->getCameraFov();
|
||||
}
|
||||
#else
|
||||
// allow shapebase to clamp fov to its datablock values
|
||||
cObj->setCameraFov(mClampF(fov, MinCameraFov, MaxCameraFov));
|
||||
F32 newFov = cObj->getCameraFov();
|
||||
#endif
|
||||
|
||||
// server fov of client has 1degree resolution
|
||||
if( S32(newFov) != S32(mCameraFov) || newFov != fov )
|
||||
|
|
@ -1144,6 +1163,20 @@ void GameConnection::readPacket(BitStream *bstream)
|
|||
{
|
||||
mMoveList->clientReadMovePacket(bstream);
|
||||
|
||||
#ifdef TORQUE_AFX_ENABLED
|
||||
// selected object - do we have a change in status?
|
||||
if (bstream->readFlag())
|
||||
{
|
||||
if (bstream->readFlag())
|
||||
{
|
||||
S32 gIndex = bstream->readInt(NetConnection::GhostIdBitSize);
|
||||
setSelectedObj(static_cast<SceneObject*>(resolveGhost(gIndex)));
|
||||
}
|
||||
else
|
||||
setSelectedObj(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool hadFlash = mDamageFlash > 0 || mWhiteOut > 0;
|
||||
mDamageFlash = 0;
|
||||
mWhiteOut = 0;
|
||||
|
|
@ -1387,6 +1420,37 @@ void GameConnection::writePacket(BitStream *bstream, PacketNotify *note)
|
|||
// all the damage flash & white out
|
||||
|
||||
S32 gIndex = -1;
|
||||
#ifdef TORQUE_AFX_ENABLED
|
||||
if (mChangedSelectedObj)
|
||||
{
|
||||
S32 gidx;
|
||||
// send NULL player
|
||||
if ((mSelectedObj == NULL) || mSelectedObj.isNull())
|
||||
{
|
||||
bstream->writeFlag(true);
|
||||
bstream->writeFlag(false);
|
||||
mChangedSelectedObj = false;
|
||||
}
|
||||
// send ghost-idx
|
||||
else if ((gidx = getGhostIndex(mSelectedObj)) != -1)
|
||||
{
|
||||
Con::printf("SEND OBJECT SELECTION");
|
||||
bstream->writeFlag(true);
|
||||
bstream->writeFlag(true);
|
||||
bstream->writeInt(gidx, NetConnection::GhostIdBitSize);
|
||||
mChangedSelectedObj = false;
|
||||
}
|
||||
// not fully changed yet
|
||||
else
|
||||
{
|
||||
bstream->writeFlag(false);
|
||||
mChangedSelectedObj = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
bstream->writeFlag(false);
|
||||
#endif
|
||||
|
||||
if (!mControlObject.isNull())
|
||||
{
|
||||
gIndex = getGhostIndex(mControlObject);
|
||||
|
|
@ -1608,6 +1672,14 @@ void GameConnection::preloadNextDataBlock(bool hadNewFiles)
|
|||
sendConnectionMessage(DataBlocksDownloadDone, mDataBlockSequence);
|
||||
|
||||
// gResourceManager->setMissingFileLogging(false);
|
||||
|
||||
#ifdef AFX_CAP_DATABLOCK_CACHE
|
||||
// This should be the last of the datablocks. An argument of false
|
||||
// indicates that this is a client save.
|
||||
if (clientCacheEnabled())
|
||||
saveDatablockCache(false);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
mFilesWereDownloaded = hadNewFiles;
|
||||
|
|
@ -1771,7 +1843,11 @@ DefineEngineMethod( GameConnection, transmitDataBlocks, void, (S32 sequence),,
|
|||
const U32 iCount = pGroup->size();
|
||||
|
||||
// If this is the local client...
|
||||
#ifdef AFX_CAP_DATABLOCK_CACHE
|
||||
if (GameConnection::getLocalClientConnection() == object && !GameConnection::serverCacheEnabled())
|
||||
#else
|
||||
if (GameConnection::getLocalClientConnection() == object)
|
||||
#endif
|
||||
{
|
||||
// Set up a pointer to the datablock.
|
||||
SimDataBlock* pDataBlock = 0;
|
||||
|
|
@ -2166,6 +2242,13 @@ void GameConnection::consoleInit()
|
|||
"@ingroup Networking\n");
|
||||
|
||||
// Con::addVariable("specialFog", TypeBool, &SceneGraph::useSpecial);
|
||||
|
||||
#ifdef AFX_CAP_DATABLOCK_CACHE
|
||||
Con::addVariable("$Pref::Server::DatablockCacheFilename", TypeString, &server_cache_filename);
|
||||
Con::addVariable("$pref::Client::DatablockCacheFilename", TypeString, &client_cache_filename);
|
||||
Con::addVariable("$Pref::Server::EnableDatablockCache", TypeBool, &server_cache_on);
|
||||
Con::addVariable("$pref::Client::EnableDatablockCache", TypeBool, &client_cache_on);
|
||||
#endif
|
||||
}
|
||||
|
||||
DefineEngineMethod( GameConnection, startRecording, void, (const char* fileName),,
|
||||
|
|
@ -2360,4 +2443,518 @@ DefineEngineMethod( GameConnection, getVisibleGhostDistance, F32, (),,
|
|||
)
|
||||
{
|
||||
return object->getVisibleGhostDistance();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TORQUE_AFX_ENABLED
|
||||
// The object selection code here is, in part, based, on functionality described
|
||||
// in the following resource:
|
||||
// Object Selection in Torque by Dave Myers
|
||||
// http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=7335
|
||||
|
||||
DefineEngineMethod(GameConnection, setSelectedObj, bool, (SceneObject* obj, bool propagate_to_client), (false), "")
|
||||
{
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
object->setSelectedObj(obj, propagate_to_client);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DefineEngineMethod(GameConnection, getSelectedObj, SimObject*, (),, "")
|
||||
{
|
||||
return object->getSelectedObj();
|
||||
}
|
||||
|
||||
DefineEngineMethod(GameConnection, clearSelectedObj, void, (bool propagate_to_client), (false), "")
|
||||
{
|
||||
object->setSelectedObj(NULL, propagate_to_client);
|
||||
}
|
||||
|
||||
DefineEngineMethod(GameConnection, setPreSelectedObjFromRollover, void, (),, "")
|
||||
{
|
||||
object->setPreSelectedObjFromRollover();
|
||||
}
|
||||
|
||||
DefineEngineMethod(GameConnection, clearPreSelectedObj, void, (),, "")
|
||||
{
|
||||
object->clearPreSelectedObj();
|
||||
}
|
||||
|
||||
DefineEngineMethod(GameConnection, setSelectedObjFromPreSelected, void, (),, "")
|
||||
{
|
||||
object->setSelectedObjFromPreSelected();
|
||||
}
|
||||
|
||||
void GameConnection::setSelectedObj(SceneObject* so, bool propagate_to_client)
|
||||
{
|
||||
if (!isConnectionToServer())
|
||||
{
|
||||
// clear previously selected object
|
||||
if (mSelectedObj)
|
||||
clearNotify(mSelectedObj);
|
||||
|
||||
// save new selection
|
||||
mSelectedObj = so;
|
||||
|
||||
// mark selected object
|
||||
if (mSelectedObj)
|
||||
deleteNotify(mSelectedObj);
|
||||
|
||||
// mark selection dirty
|
||||
if (propagate_to_client)
|
||||
mChangedSelectedObj = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// clear previously selected object
|
||||
if (mSelectedObj)
|
||||
{
|
||||
mSelectedObj->setSelectionFlags(mSelectedObj->getSelectionFlags() & ~SceneObject::SELECTED);
|
||||
clearNotify(mSelectedObj);
|
||||
Con::executef(this, "onObjectDeselected", mSelectedObj->getIdString());
|
||||
}
|
||||
|
||||
// save new selection
|
||||
mSelectedObj = so;
|
||||
|
||||
// mark selected object
|
||||
if (mSelectedObj)
|
||||
{
|
||||
mSelectedObj->setSelectionFlags(mSelectedObj->getSelectionFlags() | SceneObject::SELECTED);
|
||||
deleteNotify(mSelectedObj);
|
||||
}
|
||||
|
||||
// mark selection dirty
|
||||
//mChangedSelectedObj = true;
|
||||
|
||||
// notify appropriate script of the change
|
||||
if (mSelectedObj)
|
||||
Con::executef(this, "onObjectSelected", mSelectedObj->getIdString());
|
||||
}
|
||||
|
||||
void GameConnection::setRolloverObj(SceneObject* so)
|
||||
{
|
||||
// save new selection
|
||||
mRolloverObj = so;
|
||||
|
||||
// notify appropriate script of the change
|
||||
Con::executef(this, "onObjectRollover", (mRolloverObj) ? mRolloverObj->getIdString() : "");
|
||||
}
|
||||
|
||||
void GameConnection::setPreSelectedObjFromRollover()
|
||||
{
|
||||
mPreSelectedObj = mRolloverObj;
|
||||
mPreSelectTimestamp = Platform::getRealMilliseconds();
|
||||
}
|
||||
|
||||
void GameConnection::clearPreSelectedObj()
|
||||
{
|
||||
mPreSelectedObj = 0;
|
||||
mPreSelectTimestamp = 0;
|
||||
}
|
||||
|
||||
void GameConnection::setSelectedObjFromPreSelected()
|
||||
{
|
||||
U32 now = Platform::getRealMilliseconds();
|
||||
if (now - mPreSelectTimestamp < arcaneFX::sTargetSelectionTimeoutMS)
|
||||
setSelectedObj(mPreSelectedObj);
|
||||
mPreSelectedObj = 0;
|
||||
}
|
||||
|
||||
void GameConnection::onDeleteNotify(SimObject* obj)
|
||||
{
|
||||
if (obj == mSelectedObj)
|
||||
setSelectedObj(NULL);
|
||||
|
||||
Parent::onDeleteNotify(obj);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef AFX_CAP_DATABLOCK_CACHE
|
||||
|
||||
void GameConnection::tempDisableStringBuffering(BitStream* bs) const
|
||||
{
|
||||
bs->setStringBuffer(0);
|
||||
}
|
||||
|
||||
void GameConnection::restoreStringBuffering(BitStream* bs) const
|
||||
{
|
||||
bs->clearStringBuffer();
|
||||
}
|
||||
|
||||
// rewind to stream postion and then move raw bytes into client_db_stream
|
||||
// for caching purposes.
|
||||
void GameConnection::repackClientDatablock(BitStream* bstream, S32 start_pos)
|
||||
{
|
||||
static U8 bit_buffer[Net::MaxPacketDataSize];
|
||||
|
||||
if (!clientCacheEnabled() || !client_db_stream)
|
||||
return;
|
||||
|
||||
S32 cur_pos = bstream->getCurPos();
|
||||
S32 n_bits = cur_pos - start_pos;
|
||||
if (n_bits <= 0)
|
||||
return;
|
||||
|
||||
bstream->setCurPos(start_pos);
|
||||
bstream->readBits(n_bits, bit_buffer);
|
||||
bstream->setCurPos(cur_pos);
|
||||
|
||||
//S32 start_pos2 = client_db_stream->getCurPos();
|
||||
client_db_stream->writeBits(n_bits, bit_buffer);
|
||||
}
|
||||
|
||||
#define CLIENT_CACHE_VERSION_CODE 47241113
|
||||
|
||||
void GameConnection::saveDatablockCache(bool on_server)
|
||||
{
|
||||
InfiniteBitStream bit_stream;
|
||||
BitStream* bstream = 0;
|
||||
|
||||
if (on_server)
|
||||
{
|
||||
SimDataBlockGroup *g = Sim::getDataBlockGroup();
|
||||
|
||||
// find the first one we haven't sent:
|
||||
U32 i, groupCount = g->size();
|
||||
S32 key = this->getDataBlockModifiedKey();
|
||||
for (i = 0; i < groupCount; i++)
|
||||
if (((SimDataBlock*)(*g)[i])->getModifiedKey() > key)
|
||||
break;
|
||||
|
||||
// nothing to save
|
||||
if (i == groupCount)
|
||||
return;
|
||||
|
||||
bstream = &bit_stream;
|
||||
|
||||
for (;i < groupCount; i++)
|
||||
{
|
||||
SimDataBlock* obj = (SimDataBlock*)(*g)[i];
|
||||
GameConnection* gc = this;
|
||||
NetConnection* conn = this;
|
||||
SimObjectId id = obj->getId();
|
||||
|
||||
if (bstream->writeFlag(gc->getDataBlockModifiedKey() < obj->getModifiedKey())) // A - flag
|
||||
{
|
||||
if (obj->getModifiedKey() > gc->getMaxDataBlockModifiedKey())
|
||||
gc->setMaxDataBlockModifiedKey(obj->getModifiedKey());
|
||||
|
||||
bstream->writeInt(id - DataBlockObjectIdFirst,DataBlockObjectIdBitSize); // B - int
|
||||
|
||||
S32 classId = obj->getClassId(conn->getNetClassGroup());
|
||||
bstream->writeClassId(classId, NetClassTypeDataBlock, conn->getNetClassGroup()); // C - id
|
||||
bstream->writeInt(i, DataBlockObjectIdBitSize); // D - int
|
||||
bstream->writeInt(groupCount, DataBlockObjectIdBitSize + 1); // E - int
|
||||
obj->packData(bstream);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bstream = client_db_stream;
|
||||
}
|
||||
|
||||
if (bstream->getPosition() <= 0)
|
||||
return;
|
||||
|
||||
// zero out any leftover bits short of an even byte count
|
||||
U32 n_leftover_bits = (bstream->getPosition()*8) - bstream->getCurPos();
|
||||
if (n_leftover_bits >= 0 && n_leftover_bits <= 8)
|
||||
{
|
||||
// note - an unusual problem regarding setCurPos() results when there
|
||||
// are no leftover bytes. Adding a buffer byte in this case avoids the problem.
|
||||
if (n_leftover_bits == 0)
|
||||
n_leftover_bits = 8;
|
||||
U8 bzero = 0;
|
||||
bstream->writeBits(n_leftover_bits, &bzero);
|
||||
}
|
||||
|
||||
// this is where we actually save the file
|
||||
const char* filename = (on_server) ? server_cache_filename : client_cache_filename;
|
||||
if (filename && filename[0] != '\0')
|
||||
{
|
||||
FileStream* f_stream;
|
||||
if((f_stream = FileStream::createAndOpen(filename, Torque::FS::File::Write )) == NULL)
|
||||
{
|
||||
Con::printf("Failed to open file '%s'.", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
U32 save_sz = bstream->getPosition();
|
||||
|
||||
if (!on_server)
|
||||
{
|
||||
f_stream->write((U32)CLIENT_CACHE_VERSION_CODE);
|
||||
f_stream->write(save_sz);
|
||||
f_stream->write(server_cache_CRC);
|
||||
f_stream->write((U32)CLIENT_CACHE_VERSION_CODE);
|
||||
}
|
||||
|
||||
f_stream->write(save_sz, bstream->getBuffer());
|
||||
|
||||
// zero out any leftover bytes short of a 4-byte multiple
|
||||
while ((save_sz % 4) != 0)
|
||||
{
|
||||
f_stream->write((U8)0);
|
||||
save_sz++;
|
||||
}
|
||||
|
||||
delete f_stream;
|
||||
}
|
||||
|
||||
if (!on_server)
|
||||
client_db_stream->clear();
|
||||
}
|
||||
|
||||
static bool afx_saved_db_cache = false;
|
||||
static U32 afx_saved_db_cache_CRC = 0xffffffff;
|
||||
|
||||
void GameConnection::resetDatablockCache()
|
||||
{
|
||||
afx_saved_db_cache = false;
|
||||
afx_saved_db_cache_CRC = 0xffffffff;
|
||||
}
|
||||
|
||||
DefineEngineFunction(resetDatablockCache, void, (),,"")
|
||||
{
|
||||
GameConnection::resetDatablockCache();
|
||||
}
|
||||
|
||||
DefineEngineFunction(isDatablockCacheSaved, bool, (),,"")
|
||||
{
|
||||
return afx_saved_db_cache;
|
||||
}
|
||||
|
||||
DefineEngineFunction(getDatablockCacheCRC, S32, (),,"")
|
||||
{
|
||||
return (S32)afx_saved_db_cache_CRC;
|
||||
}
|
||||
|
||||
DefineEngineFunction(extractDatablockCacheCRC, S32, (const char* fileName),,"")
|
||||
{
|
||||
FileStream f_stream;
|
||||
if (!f_stream.open(fileName, Torque::FS::File::Read))
|
||||
{
|
||||
Con::errorf("Failed to open file '%s'.", fileName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
U32 stream_sz = f_stream.getStreamSize();
|
||||
if (stream_sz < 4 * 32)
|
||||
{
|
||||
Con::errorf("File '%s' is not a valid datablock cache.", fileName);
|
||||
f_stream.close();
|
||||
return -1;
|
||||
}
|
||||
|
||||
U32 pre_code; f_stream.read(&pre_code);
|
||||
U32 save_sz; f_stream.read(&save_sz);
|
||||
U32 crc_code; f_stream.read(&crc_code);
|
||||
U32 post_code; f_stream.read(&post_code);
|
||||
|
||||
f_stream.close();
|
||||
|
||||
if (pre_code != post_code)
|
||||
{
|
||||
Con::errorf("File '%s' is not a valid datablock cache.", fileName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pre_code != (U32)CLIENT_CACHE_VERSION_CODE)
|
||||
{
|
||||
Con::errorf("Version of datablock cache file '%s' does not match version of running software.", fileName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (S32)crc_code;
|
||||
}
|
||||
|
||||
DefineEngineFunction(setDatablockCacheCRC, void, (U32 crc), , "")
|
||||
{
|
||||
GameConnection *conn = GameConnection::getConnectionToServer();
|
||||
if (!conn)
|
||||
return;
|
||||
|
||||
conn->setServerCacheCRC(crc);
|
||||
}
|
||||
|
||||
DefineEngineMethod(GameConnection, saveDatablockCache, void, (),, "")
|
||||
{
|
||||
if (GameConnection::serverCacheEnabled() && !afx_saved_db_cache)
|
||||
{
|
||||
// Save the datablocks to a cache file. An argument
|
||||
// of true indicates that this is a server save.
|
||||
object->saveDatablockCache(true);
|
||||
afx_saved_db_cache = true;
|
||||
afx_saved_db_cache_CRC = 0xffffffff;
|
||||
|
||||
static char filename_buffer[1024];
|
||||
String filename(Torque::Path::CleanSeparators(object->serverCacheFilename()));
|
||||
Con::expandScriptFilename(filename_buffer, sizeof(filename_buffer), filename.c_str());
|
||||
Torque::Path givenPath(Torque::Path::CompressPath(filename_buffer));
|
||||
Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(givenPath);
|
||||
if (fileRef == NULL)
|
||||
Con::errorf("saveDatablockCache() failed to get CRC for file '%s'.", filename.c_str());
|
||||
else
|
||||
afx_saved_db_cache_CRC = (S32)fileRef->getChecksum();
|
||||
}
|
||||
}
|
||||
|
||||
DefineEngineMethod(GameConnection, loadDatablockCache, void, (),, "")
|
||||
{
|
||||
if (GameConnection::clientCacheEnabled())
|
||||
{
|
||||
object->loadDatablockCache();
|
||||
}
|
||||
}
|
||||
|
||||
DefineEngineMethod(GameConnection, loadDatablockCache_Begin, bool, (),, "")
|
||||
{
|
||||
if (GameConnection::clientCacheEnabled())
|
||||
{
|
||||
return object->loadDatablockCache_Begin();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DefineEngineMethod(GameConnection, loadDatablockCache_Continue, bool, (),, "")
|
||||
{
|
||||
if (GameConnection::clientCacheEnabled())
|
||||
{
|
||||
return object->loadDatablockCache_Continue();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static char* afx_db_load_buf = 0;
|
||||
static U32 afx_db_load_buf_sz = 0;
|
||||
static BitStream* afx_db_load_bstream = 0;
|
||||
|
||||
void GameConnection::loadDatablockCache()
|
||||
{
|
||||
if (!loadDatablockCache_Begin())
|
||||
return;
|
||||
|
||||
while (loadDatablockCache_Continue())
|
||||
;
|
||||
}
|
||||
|
||||
bool GameConnection::loadDatablockCache_Begin()
|
||||
{
|
||||
if (!client_cache_filename || client_cache_filename[0] == '\0')
|
||||
{
|
||||
Con::errorf("No filename was specified for the client datablock cache.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// open cache file
|
||||
FileStream f_stream;
|
||||
if(!f_stream.open(client_cache_filename, Torque::FS::File::Read))
|
||||
{
|
||||
Con::errorf("Failed to open file '%s'.", client_cache_filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
// get file size
|
||||
U32 stream_sz = f_stream.getStreamSize();
|
||||
if (stream_sz <= 4*4)
|
||||
{
|
||||
Con::errorf("File '%s' is too small to be a valid datablock cache.", client_cache_filename);
|
||||
f_stream.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// load header data
|
||||
U32 pre_code; f_stream.read(&pre_code);
|
||||
U32 save_sz; f_stream.read(&save_sz);
|
||||
U32 crc_code; f_stream.read(&crc_code);
|
||||
U32 post_code; f_stream.read(&post_code);
|
||||
|
||||
// validate header info
|
||||
if (pre_code != post_code)
|
||||
{
|
||||
Con::errorf("File '%s' is not a valid datablock cache.", client_cache_filename);
|
||||
f_stream.close();
|
||||
return false;
|
||||
}
|
||||
if (pre_code != (U32)CLIENT_CACHE_VERSION_CODE)
|
||||
{
|
||||
Con::errorf("Version of datablock cache file '%s' does not match version of running software.", client_cache_filename);
|
||||
f_stream.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// allocated the in-memory buffer
|
||||
afx_db_load_buf_sz = stream_sz - (4*4);
|
||||
afx_db_load_buf = new char[afx_db_load_buf_sz];
|
||||
|
||||
// load data from file into memory
|
||||
if (!f_stream.read(stream_sz, afx_db_load_buf))
|
||||
{
|
||||
Con::errorf("Failed to read data from file '%s'.", client_cache_filename);
|
||||
f_stream.close();
|
||||
delete [] afx_db_load_buf;
|
||||
afx_db_load_buf = 0;
|
||||
afx_db_load_buf_sz = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// close file
|
||||
f_stream.close();
|
||||
|
||||
// At this point we have the whole cache in memory
|
||||
|
||||
// create a bitstream from the in-memory buffer
|
||||
afx_db_load_bstream = new BitStream(afx_db_load_buf, afx_db_load_buf_sz);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameConnection::loadDatablockCache_Continue()
|
||||
{
|
||||
if (!afx_db_load_bstream)
|
||||
return false;
|
||||
|
||||
// prevent repacking of datablocks during load
|
||||
BitStream* save_client_db_stream = client_db_stream;
|
||||
client_db_stream = 0;
|
||||
|
||||
bool all_finished = false;
|
||||
|
||||
// loop through at most 16 datablocks
|
||||
BitStream *bstream = afx_db_load_bstream;
|
||||
for (S32 i = 0; i < 16; i++)
|
||||
{
|
||||
S32 save_pos = bstream->getCurPos();
|
||||
if (!bstream->readFlag())
|
||||
{
|
||||
all_finished = true;
|
||||
break;
|
||||
}
|
||||
bstream->setCurPos(save_pos);
|
||||
SimDataBlockEvent evt;
|
||||
evt.unpack(this, bstream);
|
||||
evt.process(this);
|
||||
}
|
||||
|
||||
client_db_stream = save_client_db_stream;
|
||||
|
||||
if (all_finished)
|
||||
{
|
||||
delete afx_db_load_bstream;
|
||||
afx_db_load_bstream = 0;
|
||||
delete [] afx_db_load_buf;
|
||||
afx_db_load_buf = 0;
|
||||
afx_db_load_buf_sz = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _GAMECONNECTION_H_
|
||||
#define _GAMECONNECTION_H_
|
||||
|
||||
|
|
@ -55,6 +60,14 @@ class MoveList;
|
|||
struct Move;
|
||||
struct AuthInfo;
|
||||
|
||||
// To disable datablock caching, remove or comment out the AFX_CAP_DATABLOCK_CACHE define below.
|
||||
// Also, at a minimum, the following script preferences should be set to false:
|
||||
// $pref::Client::EnableDatablockCache = false; (in arcane.fx/client/defaults.cs)
|
||||
// $Pref::Server::EnableDatablockCache = false; (in arcane.fx/server/defaults.cs)
|
||||
// Alternatively, all script code marked with "DATABLOCK CACHE CODE" can be removed or
|
||||
// commented out.
|
||||
//
|
||||
#define AFX_CAP_DATABLOCK_CACHE
|
||||
const F32 MinCameraFov = 1.f; ///< min camera FOV
|
||||
const F32 MaxCameraFov = 179.f; ///< max camera FOV
|
||||
|
||||
|
|
@ -372,6 +385,62 @@ protected:
|
|||
DECLARE_CALLBACK( void, setLagIcon, (bool state) );
|
||||
DECLARE_CALLBACK( void, onDataBlocksDone, (U32 sequence) );
|
||||
DECLARE_CALLBACK( void, onFlash, (bool state) );
|
||||
|
||||
#ifdef TORQUE_AFX_ENABLED
|
||||
// GameConnection is modified to keep track of object selections which are used in
|
||||
// spell targeting. This code stores the current object selection as well as the
|
||||
// current rollover object beneath the cursor. The rollover object is treated as a
|
||||
// pending object selection and actual object selection is usually made by promoting
|
||||
// the rollover object to the current object selection.
|
||||
private:
|
||||
SimObjectPtr<SceneObject> mRolloverObj;
|
||||
SimObjectPtr<SceneObject> mPreSelectedObj;
|
||||
SimObjectPtr<SceneObject> mSelectedObj;
|
||||
bool mChangedSelectedObj;
|
||||
U32 mPreSelectTimestamp;
|
||||
protected:
|
||||
virtual void onDeleteNotify(SimObject*);
|
||||
public:
|
||||
void setRolloverObj(SceneObject*);
|
||||
SceneObject* getRolloverObj() { return mRolloverObj; }
|
||||
void setSelectedObj(SceneObject*, bool propagate_to_client=false);
|
||||
SceneObject* getSelectedObj() { return mSelectedObj; }
|
||||
void setPreSelectedObjFromRollover();
|
||||
void clearPreSelectedObj();
|
||||
void setSelectedObjFromPreSelected();
|
||||
// Flag is added to indicate when a client is fully connected or "zoned-in".
|
||||
// This information determines when AFX will startup active effects on a newly
|
||||
// added client.
|
||||
private:
|
||||
bool zoned_in;
|
||||
public:
|
||||
bool isZonedIn() const { return zoned_in; }
|
||||
void setZonedIn() { zoned_in = true; }
|
||||
#endif
|
||||
#ifdef AFX_CAP_DATABLOCK_CACHE
|
||||
private:
|
||||
static StringTableEntry server_cache_filename;
|
||||
static StringTableEntry client_cache_filename;
|
||||
static bool server_cache_on;
|
||||
static bool client_cache_on;
|
||||
BitStream* client_db_stream;
|
||||
U32 server_cache_CRC;
|
||||
public:
|
||||
void repackClientDatablock(BitStream*, S32 start_pos);
|
||||
void saveDatablockCache(bool on_server);
|
||||
void loadDatablockCache();
|
||||
bool loadDatablockCache_Begin();
|
||||
bool loadDatablockCache_Continue();
|
||||
void tempDisableStringBuffering(BitStream* bs) const;
|
||||
void restoreStringBuffering(BitStream* bs) const;
|
||||
void setServerCacheCRC(U32 crc) { server_cache_CRC = crc; }
|
||||
|
||||
static void resetDatablockCache();
|
||||
static bool serverCacheEnabled() { return server_cache_on; }
|
||||
static bool clientCacheEnabled() { return client_cache_on; }
|
||||
static const char* serverCacheFilename() { return server_cache_filename; }
|
||||
static const char* clientCacheFilename() { return client_cache_filename; }
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "core/dnet.h"
|
||||
#include "core/stream/bitStream.h"
|
||||
|
|
@ -136,6 +141,9 @@ void SimDataBlockEvent::notifyDelivered(NetConnection *conn, bool )
|
|||
|
||||
void SimDataBlockEvent::pack(NetConnection *conn, BitStream *bstream)
|
||||
{
|
||||
#ifdef AFX_CAP_DATABLOCK_CACHE
|
||||
((GameConnection *)conn)->tempDisableStringBuffering(bstream);
|
||||
#endif
|
||||
SimDataBlock* obj;
|
||||
Sim::findObject(id,obj);
|
||||
GameConnection *gc = (GameConnection *) conn;
|
||||
|
|
@ -157,10 +165,18 @@ void SimDataBlockEvent::pack(NetConnection *conn, BitStream *bstream)
|
|||
bstream->writeInt(classId ^ DebugChecksum, 32);
|
||||
#endif
|
||||
}
|
||||
#ifdef AFX_CAP_DATABLOCK_CACHE
|
||||
((GameConnection *)conn)->restoreStringBuffering(bstream);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SimDataBlockEvent::unpack(NetConnection *cptr, BitStream *bstream)
|
||||
{
|
||||
#ifdef AFX_CAP_DATABLOCK_CACHE
|
||||
// stash the stream position prior to unpacking
|
||||
S32 start_pos = bstream->getCurPos();
|
||||
((GameConnection *)cptr)->tempDisableStringBuffering(bstream);
|
||||
#endif
|
||||
if(bstream->readFlag())
|
||||
{
|
||||
mProcess = true;
|
||||
|
|
@ -215,6 +231,11 @@ void SimDataBlockEvent::unpack(NetConnection *cptr, BitStream *bstream)
|
|||
#endif
|
||||
|
||||
}
|
||||
#ifdef AFX_CAP_DATABLOCK_CACHE
|
||||
// rewind to stream position and then process raw bytes for caching
|
||||
((GameConnection *)cptr)->repackClientDatablock(bstream, start_pos);
|
||||
((GameConnection *)cptr)->restoreStringBuffering(bstream);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SimDataBlockEvent::write(NetConnection *cptr, BitStream *bstream)
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ ClientProcessList* ClientProcessList::smClientProcessList = NULL;
|
|||
ServerProcessList* ServerProcessList::smServerProcessList = NULL;
|
||||
static U32 gNetOrderNextId = 0;
|
||||
|
||||
DefineConsoleFunction( dumpProcessList, void, ( ), ,
|
||||
DefineEngineFunction( dumpProcessList, void, ( ), ,
|
||||
"Dumps all ProcessObjects in ServerProcessList and ClientProcessList to the console." )
|
||||
{
|
||||
Con::printf( "client process list:" );
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/gameBase/processList.h"
|
||||
|
||||
|
|
@ -27,10 +32,8 @@
|
|||
#include "platform/profiler.h"
|
||||
#include "console/consoleTypes.h"
|
||||
|
||||
#ifdef TORQUE_EXPERIMENTAL_EC
|
||||
#include "T3D/components/coreInterfaces.h"
|
||||
#include "T3D/components/component.h"
|
||||
#endif
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
ProcessObject::ProcessObject()
|
||||
|
|
@ -272,17 +275,30 @@ void ProcessList::advanceObjects()
|
|||
onTickObject(pobj);
|
||||
}
|
||||
|
||||
#ifdef TORQUE_EXPERIMENTAL_EC
|
||||
for (U32 i = 0; i < UpdateInterface::all.size(); i++)
|
||||
{
|
||||
UpdateInterface::all[i]->processTick();
|
||||
}
|
||||
#endif
|
||||
|
||||
mTotalTicks++;
|
||||
|
||||
PROFILE_END();
|
||||
}
|
||||
|
||||
ProcessObject* ProcessList::findNearestToEnd(Vector<ProcessObject*>& objs) const
|
||||
{
|
||||
if (objs.empty())
|
||||
return 0;
|
||||
|
||||
for (ProcessObject* obj = mHead.mProcessLink.prev; obj != &mHead; obj = obj->mProcessLink.prev)
|
||||
{
|
||||
for (S32 i = 0; i < objs.size(); i++)
|
||||
{
|
||||
if (obj == objs[i])
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _PROCESSLIST_H_
|
||||
#define _PROCESSLIST_H_
|
||||
|
||||
|
|
@ -188,6 +193,9 @@ protected:
|
|||
|
||||
PreTickSignal mPreTick;
|
||||
PostTickSignal mPostTick;
|
||||
// JTF: still needed?
|
||||
public:
|
||||
ProcessObject* findNearestToEnd(Vector<ProcessObject*>& objs) const;
|
||||
};
|
||||
|
||||
#endif // _PROCESSLIST_H_
|
||||
|
|
@ -37,10 +37,8 @@
|
|||
#include "T3D/gameBase/std/stdMoveList.h"
|
||||
#include "T3D/fx/cameraFXMgr.h"
|
||||
|
||||
#ifdef TORQUE_EXPERIMENTAL_EC
|
||||
#include "T3D/components/coreInterfaces.h"
|
||||
#include "T3D/components/component.h"
|
||||
#endif
|
||||
|
||||
MODULE_BEGIN( ProcessList )
|
||||
|
||||
|
|
@ -137,7 +135,6 @@ bool StdClientProcessList::advanceTime( SimTime timeDelta )
|
|||
obj = obj->mProcessLink.next;
|
||||
}
|
||||
|
||||
#ifdef TORQUE_EXPERIMENTAL_EC
|
||||
for (U32 i = 0; i < UpdateInterface::all.size(); i++)
|
||||
{
|
||||
Component *comp = dynamic_cast<Component*>(UpdateInterface::all[i]);
|
||||
|
|
@ -147,7 +144,6 @@ bool StdClientProcessList::advanceTime( SimTime timeDelta )
|
|||
|
||||
UpdateInterface::all[i]->interpolateTick(mLastDelta);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Inform objects of total elapsed delta so they can advance
|
||||
// client side animations.
|
||||
|
|
@ -163,7 +159,6 @@ bool StdClientProcessList::advanceTime( SimTime timeDelta )
|
|||
obj = obj->mProcessLink.next;
|
||||
}
|
||||
|
||||
#ifdef TORQUE_EXPERIMENTAL_EC
|
||||
for (U32 i = 0; i < UpdateInterface::all.size(); i++)
|
||||
{
|
||||
Component *comp = dynamic_cast<Component*>(UpdateInterface::all[i]);
|
||||
|
|
@ -176,7 +171,6 @@ bool StdClientProcessList::advanceTime( SimTime timeDelta )
|
|||
|
||||
UpdateInterface::all[i]->advanceTime(dt);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ static U32 sgServerQueryIndex = 0;
|
|||
//SERVER FUNCTIONS ONLY
|
||||
ConsoleFunctionGroupBegin( Containers, "Spatial query functions. <b>Server side only!</b>");
|
||||
|
||||
DefineConsoleFunction( containerFindFirst, const char*, (U32 typeMask, Point3F origin, Point3F size), , "(int mask, Point3F point, float x, float y, float z)"
|
||||
DefineEngineFunction( containerFindFirst, const char*, (U32 typeMask, Point3F origin, Point3F size), , "(int mask, Point3F point, float x, float y, float z)"
|
||||
"@brief Find objects matching the bitmask type within a box centered at point, with extents x, y, z.\n\n"
|
||||
"@returns The first object found, or an empty string if nothing was found. Thereafter, you can get more "
|
||||
"results using containerFindNext()."
|
||||
|
|
@ -146,7 +146,7 @@ DefineConsoleFunction( containerFindFirst, const char*, (U32 typeMask, Point3F o
|
|||
return buff;
|
||||
}
|
||||
|
||||
DefineConsoleFunction( containerFindNext, const char*, (), , "()"
|
||||
DefineEngineFunction( containerFindNext, const char*, (), , "()"
|
||||
"@brief Get more results from a previous call to containerFindFirst().\n\n"
|
||||
"@note You must call containerFindFirst() to begin the search.\n"
|
||||
"@returns The next object found, or an empty string if nothing else was found.\n"
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/groundPlane.h"
|
||||
|
||||
|
|
@ -39,7 +44,9 @@
|
|||
#include "T3D/physics/physicsPlugin.h"
|
||||
#include "T3D/physics/physicsBody.h"
|
||||
#include "T3D/physics/physicsCollision.h"
|
||||
|
||||
#ifdef TORQUE_AFX_ENABLED
|
||||
#include "afx/ce/afxZodiacMgr.h"
|
||||
#endif
|
||||
|
||||
/// Minimum square size allowed. This is a cheap way to limit the amount
|
||||
/// of geometry possibly generated by the GroundPlane (vertex buffers have a
|
||||
|
|
@ -77,6 +84,7 @@ GroundPlane::GroundPlane()
|
|||
mNetFlags.set( Ghostable | ScopeAlways );
|
||||
|
||||
mConvexList = new Convex;
|
||||
mTypeMask |= TerrainLikeObjectType;
|
||||
}
|
||||
|
||||
GroundPlane::~GroundPlane()
|
||||
|
|
@ -355,7 +363,9 @@ void GroundPlane::prepRenderImage( SceneRenderState* state )
|
|||
createGeometry( state->getCullingFrustum() );
|
||||
if( mVertexBuffer.isNull() )
|
||||
return;
|
||||
|
||||
#ifdef TORQUE_AFX_ENABLED
|
||||
afxZodiacMgr::renderGroundPlaneZodiacs(state, this);
|
||||
#endif
|
||||
// Add a render instance.
|
||||
|
||||
RenderPassManager* pass = state->getRenderPass();
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ void GuiMaterialPreview::setObjectModel(const char* modelName)
|
|||
|
||||
// Initialize camera values:
|
||||
mOrbitPos = mModel->getShape()->center;
|
||||
mMinOrbitDist = mModel->getShape()->radius;
|
||||
mMinOrbitDist = mModel->getShape()->mRadius;
|
||||
|
||||
lastRenderTime = Platform::getVirtualMilliseconds();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -367,7 +367,7 @@ void GuiObjectView::setObjectModel( const String& modelName )
|
|||
// Initialize camera values.
|
||||
|
||||
mOrbitPos = mModel->getShape()->center;
|
||||
mMinOrbitDist = mModel->getShape()->radius;
|
||||
mMinOrbitDist = mModel->getShape()->mRadius;
|
||||
|
||||
// Initialize animation.
|
||||
|
||||
|
|
|
|||
|
|
@ -320,8 +320,8 @@ Item::Item()
|
|||
mAtRest = true;
|
||||
mAtRestCounter = 0;
|
||||
mInLiquid = false;
|
||||
delta.warpTicks = 0;
|
||||
delta.dt = 1;
|
||||
mDelta.warpTicks = 0;
|
||||
mDelta.dt = 1;
|
||||
mCollisionObject = 0;
|
||||
mCollisionTimeout = 0;
|
||||
mPhysicsRep = NULL;
|
||||
|
|
@ -350,7 +350,7 @@ bool Item::onAdd()
|
|||
|
||||
if (mStatic)
|
||||
mAtRest = true;
|
||||
mObjToWorld.getColumn(3,&delta.pos);
|
||||
mObjToWorld.getColumn(3,&mDelta.pos);
|
||||
|
||||
// Setup the box for our convex object...
|
||||
mObjBox.getCenter(&mConvex.mCenter);
|
||||
|
|
@ -564,21 +564,21 @@ void Item::processTick(const Move* move)
|
|||
mCollisionObject = 0;
|
||||
|
||||
// Warp to catch up to server
|
||||
if (delta.warpTicks > 0)
|
||||
if (mDelta.warpTicks > 0)
|
||||
{
|
||||
delta.warpTicks--;
|
||||
mDelta.warpTicks--;
|
||||
|
||||
// Set new pos.
|
||||
MatrixF mat = mObjToWorld;
|
||||
mat.getColumn(3,&delta.pos);
|
||||
delta.pos += delta.warpOffset;
|
||||
mat.setColumn(3,delta.pos);
|
||||
mat.getColumn(3,&mDelta.pos);
|
||||
mDelta.pos += mDelta.warpOffset;
|
||||
mat.setColumn(3, mDelta.pos);
|
||||
Parent::setTransform(mat);
|
||||
|
||||
// Backstepping
|
||||
delta.posVec.x = -delta.warpOffset.x;
|
||||
delta.posVec.y = -delta.warpOffset.y;
|
||||
delta.posVec.z = -delta.warpOffset.z;
|
||||
mDelta.posVec.x = -mDelta.warpOffset.x;
|
||||
mDelta.posVec.y = -mDelta.warpOffset.y;
|
||||
mDelta.posVec.z = -mDelta.warpOffset.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -601,7 +601,7 @@ void Item::processTick(const Move* move)
|
|||
else
|
||||
{
|
||||
// Need to clear out last updatePos or warp interpolation
|
||||
delta.posVec.set(0,0,0);
|
||||
mDelta.posVec.set(0,0,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -613,11 +613,11 @@ void Item::interpolateTick(F32 dt)
|
|||
return;
|
||||
|
||||
// Client side interpolation
|
||||
Point3F pos = delta.pos + delta.posVec * dt;
|
||||
Point3F pos = mDelta.pos + mDelta.posVec * dt;
|
||||
MatrixF mat = mRenderObjToWorld;
|
||||
mat.setColumn(3,pos);
|
||||
setRenderTransform(mat);
|
||||
delta.dt = dt;
|
||||
mDelta.dt = dt;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -733,7 +733,7 @@ void Item::updatePos(const U32 /*mask*/, const F32 dt)
|
|||
// Try and move
|
||||
Point3F pos;
|
||||
mObjToWorld.getColumn(3,&pos);
|
||||
delta.posVec = pos;
|
||||
mDelta.posVec = pos;
|
||||
|
||||
bool contact = false;
|
||||
bool nonStatic = false;
|
||||
|
|
@ -891,9 +891,9 @@ void Item::updatePos(const U32 /*mask*/, const F32 dt)
|
|||
if (collisionList.getTime() < 1.0)
|
||||
{
|
||||
// Set to collision point
|
||||
F32 dt = time * collisionList.getTime();
|
||||
pos += mVelocity * dt;
|
||||
time -= dt;
|
||||
F32 cdt = time * collisionList.getTime();
|
||||
pos += mVelocity * cdt;
|
||||
time -= cdt;
|
||||
|
||||
// Pick the most resistant surface
|
||||
F32 bd = 0;
|
||||
|
|
@ -959,9 +959,9 @@ void Item::updatePos(const U32 /*mask*/, const F32 dt)
|
|||
|
||||
// If on the client, calculate delta for backstepping
|
||||
if (isGhost()) {
|
||||
delta.pos = pos;
|
||||
delta.posVec -= pos;
|
||||
delta.dt = 1;
|
||||
mDelta.pos = pos;
|
||||
mDelta.posVec -= pos;
|
||||
mDelta.dt = 1;
|
||||
}
|
||||
|
||||
// Update transform
|
||||
|
|
@ -1131,40 +1131,40 @@ void Item::unpackUpdate(NetConnection *connection, BitStream *stream)
|
|||
if (stream->readFlag() && isProperlyAdded()) {
|
||||
// Determin number of ticks to warp based on the average
|
||||
// of the client and server velocities.
|
||||
delta.warpOffset = pos - delta.pos;
|
||||
mDelta.warpOffset = pos - mDelta.pos;
|
||||
F32 as = (speed + mVelocity.len()) * 0.5f * TickSec;
|
||||
F32 dt = (as > 0.00001f) ? delta.warpOffset.len() / as: sMaxWarpTicks;
|
||||
delta.warpTicks = (S32)((dt > sMinWarpTicks)? getMax(mFloor(dt + 0.5f), 1.0f): 0.0f);
|
||||
F32 dt = (as > 0.00001f) ? mDelta.warpOffset.len() / as: sMaxWarpTicks;
|
||||
mDelta.warpTicks = (S32)((dt > sMinWarpTicks)? getMax(mFloor(dt + 0.5f), 1.0f): 0.0f);
|
||||
|
||||
if (delta.warpTicks)
|
||||
if (mDelta.warpTicks)
|
||||
{
|
||||
// Setup the warp to start on the next tick, only the
|
||||
// object's position is warped.
|
||||
if (delta.warpTicks > sMaxWarpTicks)
|
||||
delta.warpTicks = sMaxWarpTicks;
|
||||
delta.warpOffset /= (F32)delta.warpTicks;
|
||||
if (mDelta.warpTicks > sMaxWarpTicks)
|
||||
mDelta.warpTicks = sMaxWarpTicks;
|
||||
mDelta.warpOffset /= (F32)mDelta.warpTicks;
|
||||
}
|
||||
else {
|
||||
// Going to skip the warp, server and client are real close.
|
||||
// Adjust the frame interpolation to move smoothly to the
|
||||
// new position within the current tick.
|
||||
Point3F cp = delta.pos + delta.posVec * delta.dt;
|
||||
VectorF vec = delta.pos - cp;
|
||||
Point3F cp = mDelta.pos + mDelta.posVec * mDelta.dt;
|
||||
VectorF vec = mDelta.pos - cp;
|
||||
F32 vl = vec.len();
|
||||
if (vl) {
|
||||
F32 s = delta.posVec.len() / vl;
|
||||
delta.posVec = (cp - pos) * s;
|
||||
F32 s = mDelta.posVec.len() / vl;
|
||||
mDelta.posVec = (cp - pos) * s;
|
||||
}
|
||||
delta.pos = pos;
|
||||
mDelta.pos = pos;
|
||||
mat.setColumn(3,pos);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Set the item to the server position
|
||||
delta.warpTicks = 0;
|
||||
delta.posVec.set(0,0,0);
|
||||
delta.pos = pos;
|
||||
delta.dt = 0;
|
||||
mDelta.warpTicks = 0;
|
||||
mDelta.posVec.set(0,0,0);
|
||||
mDelta.pos = pos;
|
||||
mDelta.dt = 0;
|
||||
mat.setColumn(3,pos);
|
||||
}
|
||||
}
|
||||
|
|
@ -1209,7 +1209,7 @@ DefineEngineMethod( Item, isRotating, bool, (),,
|
|||
return object->isRotating();
|
||||
}
|
||||
|
||||
DefineEngineMethod( Item, setCollisionTimeout, bool, (S32 ignoreColObj),(NULL),
|
||||
DefineEngineMethod( Item, setCollisionTimeout, bool, (S32 ignoreColObj),,
|
||||
"@brief Temporarily disable collisions against a specific ShapeBase object.\n\n"
|
||||
|
||||
"This is useful to prevent a player from immediately picking up an Item they have "
|
||||
|
|
@ -1254,7 +1254,7 @@ DefineEngineMethod( Item, getLastStickyPos, const char*, (),,
|
|||
object->mStickyCollisionPos.y,
|
||||
object->mStickyCollisionPos.z);
|
||||
else
|
||||
dStrcpy(ret, "0 0 0");
|
||||
dStrcpy(ret, "0 0 0", bufSize);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1277,7 +1277,7 @@ DefineEngineMethod( Item, getLastStickyNormal, const char *, (),,
|
|||
object->mStickyCollisionNormal.y,
|
||||
object->mStickyCollisionNormal.z);
|
||||
else
|
||||
dStrcpy(ret, "0 0 0");
|
||||
dStrcpy(ret, "0 0 0", bufSize);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ class Item: public ShapeBase
|
|||
Point3F warpOffset;
|
||||
F32 dt;
|
||||
};
|
||||
StateDelta delta;
|
||||
StateDelta mDelta;
|
||||
|
||||
// Static attributes
|
||||
ItemData* mDataBlock;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "T3D/lightBase.h"
|
||||
|
||||
|
|
@ -73,6 +78,7 @@ LightBase::LightBase()
|
|||
mLight = LightManager::createLightInfo();
|
||||
|
||||
mFlareState.clear();
|
||||
mLocalRenderViz = false;
|
||||
}
|
||||
|
||||
LightBase::~LightBase()
|
||||
|
|
@ -206,7 +212,7 @@ void LightBase::prepRenderImage( SceneRenderState *state )
|
|||
|
||||
// If the light is selected or light visualization
|
||||
// is enabled then register the callback.
|
||||
if ( smRenderViz || isSelectedInEditor )
|
||||
if ( mLocalRenderViz || smRenderViz || isSelectedInEditor )
|
||||
{
|
||||
ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
|
||||
ri->renderDelegate.bind( this, &LightBase::_onRenderViz );
|
||||
|
|
@ -434,7 +440,7 @@ static ConsoleDocFragment _lbplayAnimation2(
|
|||
"void playAnimation(LightAnimData anim);"
|
||||
);
|
||||
|
||||
DefineConsoleMethod( LightBase, playAnimation, void, (const char * anim), (""), "( [LightAnimData anim] )\t"
|
||||
DefineEngineMethod( LightBase, playAnimation, void, (const char * anim), (""), "( [LightAnimData anim] )\t"
|
||||
"Plays a light animation on the light. If no LightAnimData is passed the "
|
||||
"existing one is played."
|
||||
"@hide")
|
||||
|
|
@ -478,7 +484,7 @@ void LightBase::playAnimation( LightAnimData *animData )
|
|||
}
|
||||
}
|
||||
|
||||
DefineConsoleMethod( LightBase, pauseAnimation, void, (), , "Stops the light animation." )
|
||||
DefineEngineMethod( LightBase, pauseAnimation, void, (), , "Stops the light animation." )
|
||||
{
|
||||
object->pauseAnimation();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _LIGHTBASE_H_
|
||||
#define _LIGHTBASE_H_
|
||||
|
||||
|
|
@ -132,6 +137,8 @@ public:
|
|||
virtual void pauseAnimation( void );
|
||||
virtual void playAnimation( void );
|
||||
virtual void playAnimation( LightAnimData *animData );
|
||||
protected:
|
||||
bool mLocalRenderViz;
|
||||
};
|
||||
|
||||
#endif // _LIGHTBASE_H_
|
||||
|
|
|
|||
|
|
@ -494,7 +494,7 @@ ConsoleDocFragment _SpawnSpherespawnObject1(
|
|||
"bool spawnObject(string additionalProps);"
|
||||
);
|
||||
|
||||
DefineConsoleMethod(SpawnSphere, spawnObject, S32, (String additionalProps), ,
|
||||
DefineEngineMethod(SpawnSphere, spawnObject, S32, (String additionalProps), ,
|
||||
"([string additionalProps]) Spawns the object based on the SpawnSphere's "
|
||||
"class, datablock, properties, and script settings. Allows you to pass in "
|
||||
"extra properties."
|
||||
|
|
|
|||
|
|
@ -20,11 +20,19 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _OBJECTTYPES_H_
|
||||
#define _OBJECTTYPES_H_
|
||||
|
||||
#include "platform/types.h"
|
||||
|
||||
// Uncomment the AFX_CAP_AFXMODEL_TYPE define below to enable a type flag
|
||||
// for afxModel objects.
|
||||
//#define AFX_CAP_AFXMODEL_TYPE
|
||||
/// Types used for SceneObject type masks (SceneObject::mTypeMask)
|
||||
///
|
||||
/// @note If a new object type is added, don't forget to add it to
|
||||
|
|
@ -149,6 +157,11 @@ enum SceneObjectTypes
|
|||
|
||||
EntityObjectType = BIT(23),
|
||||
/// @}
|
||||
InteriorLikeObjectType = BIT(24),
|
||||
TerrainLikeObjectType = BIT(25),
|
||||
#if defined(AFX_CAP_AFXMODEL_TYPE)
|
||||
afxModelObjectType = BIT(26)
|
||||
#endif
|
||||
};
|
||||
|
||||
enum SceneObjectTypeMasks : U32
|
||||
|
|
|
|||
|
|
@ -167,11 +167,11 @@ void OcclusionVolume::buildSilhouette( const SceneCameraState& cameraState, Vect
|
|||
|
||||
if( mTransformDirty )
|
||||
{
|
||||
const U32 numPoints = mPolyhedron.getNumPoints();
|
||||
const U32 numPolyPoints = mPolyhedron.getNumPoints();
|
||||
const PolyhedronType::PointType* points = getPolyhedron().getPoints();
|
||||
|
||||
mWSPoints.setSize( numPoints );
|
||||
for( U32 i = 0; i < numPoints; ++ i )
|
||||
mWSPoints.setSize(numPolyPoints);
|
||||
for( U32 i = 0; i < numPolyPoints; ++ i )
|
||||
{
|
||||
Point3F p = points[ i ];
|
||||
p.convolve( getScale() );
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "T3D/physicalZone.h"
|
||||
#include "core/stream/bitStream.h"
|
||||
#include "collision/boxConvex.h"
|
||||
|
|
@ -33,6 +38,8 @@
|
|||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
//#include "console/engineTypes.h"
|
||||
#include "sim/netConnection.h"
|
||||
IMPLEMENT_CO_NETOBJECT_V1(PhysicalZone);
|
||||
|
||||
ConsoleDocClass( PhysicalZone,
|
||||
|
|
@ -103,6 +110,10 @@ PhysicalZone::PhysicalZone()
|
|||
|
||||
mConvexList = new Convex;
|
||||
mActive = true;
|
||||
force_type = VECTOR;
|
||||
force_mag = 0.0f;
|
||||
orient_force = false;
|
||||
fade_amt = 1.0f;
|
||||
}
|
||||
|
||||
PhysicalZone::~PhysicalZone()
|
||||
|
|
@ -111,6 +122,16 @@ PhysicalZone::~PhysicalZone()
|
|||
mConvexList = NULL;
|
||||
}
|
||||
|
||||
|
||||
ImplementEnumType( PhysicalZone_ForceType, "Possible physical zone force types.\n" "@ingroup PhysicalZone\n\n" )
|
||||
{ PhysicalZone::VECTOR, "vector", "..." },
|
||||
{ PhysicalZone::SPHERICAL, "spherical", "..." },
|
||||
{ PhysicalZone::CYLINDRICAL, "cylindrical", "..." },
|
||||
// aliases
|
||||
{ PhysicalZone::SPHERICAL, "sphere", "..." },
|
||||
{ PhysicalZone::CYLINDRICAL, "cylinder", "..." },
|
||||
EndImplementEnumType;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void PhysicalZone::consoleInit()
|
||||
{
|
||||
|
|
@ -129,6 +150,10 @@ void PhysicalZone::initPersistFields()
|
|||
"point followed by three vectors representing the edges extending from the corner." );
|
||||
endGroup("Misc");
|
||||
|
||||
addGroup("AFX");
|
||||
addField("forceType", TYPEID<PhysicalZone::ForceType>(), Offset(force_type, PhysicalZone));
|
||||
addField("orientForce", TypeBool, Offset(orient_force, PhysicalZone));
|
||||
endGroup("AFX");
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
|
|
@ -158,6 +183,19 @@ bool PhysicalZone::onAdd()
|
|||
Polyhedron temp = mPolyhedron;
|
||||
setPolyhedron(temp);
|
||||
|
||||
switch (force_type)
|
||||
{
|
||||
case SPHERICAL:
|
||||
force_mag = mAppliedForce.magnitudeSafe();
|
||||
break;
|
||||
case CYLINDRICAL:
|
||||
{
|
||||
Point3F force_vec = mAppliedForce;
|
||||
force_vec.z = 0.0;
|
||||
force_mag = force_vec.magnitudeSafe();
|
||||
}
|
||||
break;
|
||||
}
|
||||
addToScene();
|
||||
|
||||
return true;
|
||||
|
|
@ -174,8 +212,10 @@ void PhysicalZone::onRemove()
|
|||
|
||||
void PhysicalZone::inspectPostApply()
|
||||
{
|
||||
setPolyhedron(mPolyhedron);
|
||||
Parent::inspectPostApply();
|
||||
|
||||
setPolyhedron(mPolyhedron);
|
||||
setMaskBits(PolyhedronMask | MoveMask | SettingsMask | FadeMask);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -191,7 +231,7 @@ void PhysicalZone::setTransform(const MatrixF & mat)
|
|||
mClippedList.setBaseTransform(base);
|
||||
|
||||
if (isServerObject())
|
||||
setMaskBits(InitialUpdateMask);
|
||||
setMaskBits(MoveMask);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -210,30 +250,87 @@ void PhysicalZone::prepRenderImage( SceneRenderState *state )
|
|||
}
|
||||
|
||||
|
||||
void PhysicalZone::renderObject( ObjectRenderInst *ri,
|
||||
SceneRenderState *state,
|
||||
BaseMatInstance *overrideMat )
|
||||
void PhysicalZone::renderObject(ObjectRenderInst *ri,
|
||||
SceneRenderState *state,
|
||||
BaseMatInstance *overrideMat)
|
||||
{
|
||||
if (overrideMat)
|
||||
return;
|
||||
|
||||
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setZReadWrite( true, false );
|
||||
desc.setBlend( true );
|
||||
desc.setCullMode( GFXCullNone );
|
||||
|
||||
desc.setZReadWrite(true, false);
|
||||
desc.setBlend(true);
|
||||
desc.setCullMode(GFXCullNone);
|
||||
|
||||
GFXTransformSaver saver;
|
||||
|
||||
GFXDrawUtil *drawer = GFX->getDrawUtil();
|
||||
|
||||
Point3F start = getBoxCenter();
|
||||
Box3F obb = mObjBox; //object bounding box
|
||||
|
||||
F32 baseForce = 10000; //roughly the ammount of force needed to push a player back as it walks into a zone. (used for visual scaling)
|
||||
|
||||
Point3F forceDir = getForce(&start);
|
||||
F32 forceLen = forceDir.len()/ baseForce;
|
||||
forceDir.normalizeSafe();
|
||||
ColorI guideCol = LinearColorF(mFabs(forceDir.x), mFabs(forceDir.y), mFabs(forceDir.z), 0.125).toColorI();
|
||||
|
||||
if (force_type == VECTOR)
|
||||
{
|
||||
Point3F endPos = start + (forceDir * mMax(forceLen,0.75f));
|
||||
drawer->drawArrow(desc, start, endPos, guideCol, 0.05f);
|
||||
}
|
||||
|
||||
MatrixF mat = getRenderTransform();
|
||||
mat.scale( getScale() );
|
||||
mat.scale(getScale());
|
||||
|
||||
GFX->multWorld(mat);
|
||||
start = obb.getCenter();
|
||||
|
||||
if (force_type == VECTOR)
|
||||
{
|
||||
drawer->drawPolyhedron(desc, mPolyhedron, ColorI(0, 255, 0, 45));
|
||||
}
|
||||
else if (force_type == SPHERICAL)
|
||||
{
|
||||
F32 rad = obb.getBoundingSphere().radius/ 2;
|
||||
drawer->drawSphere(desc, rad, start, ColorI(0, 255, 0, 45));
|
||||
|
||||
GFX->multWorld( mat );
|
||||
rad = (rad + (mAppliedForce.most() / baseForce))/2;
|
||||
desc.setFillModeWireframe();
|
||||
drawer->drawSphere(desc, rad, start, ColorI(0, 0, 255, 255));
|
||||
}
|
||||
else
|
||||
{
|
||||
Point3F bottomPos = start;
|
||||
bottomPos.z -= obb.len_z() / 2;
|
||||
|
||||
Point3F topPos = start;
|
||||
topPos.z += obb.len_z() / 2;
|
||||
F32 rad = obb.len_x() / 2;
|
||||
drawer->drawCylinder(desc, bottomPos, topPos, rad, ColorI(0, 255, 0, 45));
|
||||
|
||||
GFXDrawUtil *drawer = GFX->getDrawUtil();
|
||||
drawer->drawPolyhedron( desc, mPolyhedron, ColorI( 0, 255, 0, 45 ) );
|
||||
Point3F force_vec = mAppliedForce; //raw relative-applied force here as oposed to derived
|
||||
F32 hieght = (force_vec.z / baseForce);
|
||||
|
||||
if (force_vec.z<0)
|
||||
bottomPos.z = (bottomPos.z + hieght)/2;
|
||||
else
|
||||
topPos.z = (topPos.z + hieght) / 2;
|
||||
|
||||
if (force_vec.x > force_vec.y)
|
||||
rad = (rad + (force_vec.x / baseForce)) / 2;
|
||||
else
|
||||
rad = (rad + (force_vec.y / baseForce)) / 2;
|
||||
|
||||
|
||||
desc.setFillModeWireframe();
|
||||
drawer->drawCylinder(desc, bottomPos, topPos, rad, guideCol);
|
||||
}
|
||||
|
||||
desc.setFillModeWireframe();
|
||||
drawer->drawPolyhedron( desc, mPolyhedron, ColorI::BLACK );
|
||||
drawer->drawPolyhedron(desc, mPolyhedron, ColorI::BLACK);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
|
@ -242,39 +339,51 @@ U32 PhysicalZone::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
|
|||
U32 i;
|
||||
U32 retMask = Parent::packUpdate(con, mask, stream);
|
||||
|
||||
if (stream->writeFlag((mask & InitialUpdateMask) != 0)) {
|
||||
// Note that we don't really care about efficiency here, since this is an
|
||||
// edit-only ghost...
|
||||
mathWrite(*stream, mObjToWorld);
|
||||
mathWrite(*stream, mObjScale);
|
||||
|
||||
if (stream->writeFlag(mask & PolyhedronMask))
|
||||
{
|
||||
// Write the polyhedron
|
||||
stream->write(mPolyhedron.pointList.size());
|
||||
for (i = 0; i < mPolyhedron.pointList.size(); i++)
|
||||
mathWrite(*stream, mPolyhedron.pointList[i]);
|
||||
stream->write(mPolyhedron.mPointList.size());
|
||||
for (i = 0; i < mPolyhedron.mPointList.size(); i++)
|
||||
mathWrite(*stream, mPolyhedron.mPointList[i]);
|
||||
|
||||
stream->write(mPolyhedron.planeList.size());
|
||||
for (i = 0; i < mPolyhedron.planeList.size(); i++)
|
||||
mathWrite(*stream, mPolyhedron.planeList[i]);
|
||||
stream->write(mPolyhedron.mPlaneList.size());
|
||||
for (i = 0; i < mPolyhedron.mPlaneList.size(); i++)
|
||||
mathWrite(*stream, mPolyhedron.mPlaneList[i]);
|
||||
|
||||
stream->write(mPolyhedron.edgeList.size());
|
||||
for (i = 0; i < mPolyhedron.edgeList.size(); i++) {
|
||||
const Polyhedron::Edge& rEdge = mPolyhedron.edgeList[i];
|
||||
stream->write(mPolyhedron.mEdgeList.size());
|
||||
for (i = 0; i < mPolyhedron.mEdgeList.size(); i++) {
|
||||
const Polyhedron::Edge& rEdge = mPolyhedron.mEdgeList[i];
|
||||
|
||||
stream->write(rEdge.face[0]);
|
||||
stream->write(rEdge.face[1]);
|
||||
stream->write(rEdge.vertex[0]);
|
||||
stream->write(rEdge.vertex[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (stream->writeFlag(mask & MoveMask))
|
||||
{
|
||||
stream->writeAffineTransform(mObjToWorld);
|
||||
mathWrite(*stream, mObjScale);
|
||||
}
|
||||
|
||||
if (stream->writeFlag(mask & SettingsMask))
|
||||
{
|
||||
stream->write(mVelocityMod);
|
||||
stream->write(mGravityMod);
|
||||
mathWrite(*stream, mAppliedForce);
|
||||
stream->writeFlag(mActive);
|
||||
} else {
|
||||
stream->writeFlag(mActive);
|
||||
stream->writeInt(force_type, FORCE_TYPE_BITS);
|
||||
stream->writeFlag(orient_force);
|
||||
}
|
||||
|
||||
if (stream->writeFlag(mask & FadeMask))
|
||||
{
|
||||
U8 fade_byte = (U8)(fade_amt*255.0f);
|
||||
stream->write(fade_byte);
|
||||
}
|
||||
|
||||
stream->writeFlag(mActive);
|
||||
|
||||
return retMask;
|
||||
}
|
||||
|
||||
|
|
@ -282,31 +391,27 @@ void PhysicalZone::unpackUpdate(NetConnection* con, BitStream* stream)
|
|||
{
|
||||
Parent::unpackUpdate(con, stream);
|
||||
|
||||
if (stream->readFlag()) {
|
||||
bool new_ph = false;
|
||||
if (stream->readFlag()) // PolyhedronMask
|
||||
{
|
||||
U32 i, size;
|
||||
MatrixF temp;
|
||||
Point3F tempScale;
|
||||
Polyhedron tempPH;
|
||||
|
||||
// Transform
|
||||
mathRead(*stream, &temp);
|
||||
mathRead(*stream, &tempScale);
|
||||
|
||||
// Read the polyhedron
|
||||
stream->read(&size);
|
||||
tempPH.pointList.setSize(size);
|
||||
for (i = 0; i < tempPH.pointList.size(); i++)
|
||||
mathRead(*stream, &tempPH.pointList[i]);
|
||||
tempPH.mPointList.setSize(size);
|
||||
for (i = 0; i < tempPH.mPointList.size(); i++)
|
||||
mathRead(*stream, &tempPH.mPointList[i]);
|
||||
|
||||
stream->read(&size);
|
||||
tempPH.planeList.setSize(size);
|
||||
for (i = 0; i < tempPH.planeList.size(); i++)
|
||||
mathRead(*stream, &tempPH.planeList[i]);
|
||||
tempPH.mPlaneList.setSize(size);
|
||||
for (i = 0; i < tempPH.mPlaneList.size(); i++)
|
||||
mathRead(*stream, &tempPH.mPlaneList[i]);
|
||||
|
||||
stream->read(&size);
|
||||
tempPH.edgeList.setSize(size);
|
||||
for (i = 0; i < tempPH.edgeList.size(); i++) {
|
||||
Polyhedron::Edge& rEdge = tempPH.edgeList[i];
|
||||
tempPH.mEdgeList.setSize(size);
|
||||
for (i = 0; i < tempPH.mEdgeList.size(); i++) {
|
||||
Polyhedron::Edge& rEdge = tempPH.mEdgeList[i];
|
||||
|
||||
stream->read(&rEdge.face[0]);
|
||||
stream->read(&rEdge.face[1]);
|
||||
|
|
@ -314,17 +419,46 @@ void PhysicalZone::unpackUpdate(NetConnection* con, BitStream* stream)
|
|||
stream->read(&rEdge.vertex[1]);
|
||||
}
|
||||
|
||||
setPolyhedron(tempPH);
|
||||
new_ph = true;
|
||||
}
|
||||
|
||||
if (stream->readFlag()) // MoveMask
|
||||
{
|
||||
MatrixF temp;
|
||||
stream->readAffineTransform(&temp);
|
||||
|
||||
Point3F tempScale;
|
||||
mathRead(*stream, &tempScale);
|
||||
|
||||
//if (!new_ph)
|
||||
//{
|
||||
// Polyhedron rPolyhedron = mPolyhedron;
|
||||
// setPolyhedron(rPolyhedron);
|
||||
//}
|
||||
setScale(tempScale);
|
||||
setTransform(temp);
|
||||
}
|
||||
|
||||
if (stream->readFlag()) //SettingsMask
|
||||
{
|
||||
stream->read(&mVelocityMod);
|
||||
stream->read(&mGravityMod);
|
||||
mathRead(*stream, &mAppliedForce);
|
||||
|
||||
setPolyhedron(tempPH);
|
||||
setScale(tempScale);
|
||||
setTransform(temp);
|
||||
mActive = stream->readFlag();
|
||||
} else {
|
||||
mActive = stream->readFlag();
|
||||
force_type = stream->readInt(FORCE_TYPE_BITS); // AFX
|
||||
orient_force = stream->readFlag(); // AFX
|
||||
}
|
||||
|
||||
if (stream->readFlag()) //FadeMask
|
||||
{
|
||||
U8 fade_byte;
|
||||
stream->read(&fade_byte);
|
||||
fade_amt = ((F32)fade_byte)/255.0f;
|
||||
}
|
||||
else
|
||||
fade_amt = 1.0f;
|
||||
|
||||
mActive = stream->readFlag();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -333,12 +467,12 @@ void PhysicalZone::setPolyhedron(const Polyhedron& rPolyhedron)
|
|||
{
|
||||
mPolyhedron = rPolyhedron;
|
||||
|
||||
if (mPolyhedron.pointList.size() != 0) {
|
||||
if (mPolyhedron.mPointList.size() != 0) {
|
||||
mObjBox.minExtents.set(1e10, 1e10, 1e10);
|
||||
mObjBox.maxExtents.set(-1e10, -1e10, -1e10);
|
||||
for (U32 i = 0; i < mPolyhedron.pointList.size(); i++) {
|
||||
mObjBox.minExtents.setMin(mPolyhedron.pointList[i]);
|
||||
mObjBox.maxExtents.setMax(mPolyhedron.pointList[i]);
|
||||
for (U32 i = 0; i < mPolyhedron.mPointList.size(); i++) {
|
||||
mObjBox.minExtents.setMin(mPolyhedron.mPointList[i]);
|
||||
mObjBox.maxExtents.setMax(mPolyhedron.mPointList[i]);
|
||||
}
|
||||
} else {
|
||||
mObjBox.minExtents.set(-0.5, -0.5, -0.5);
|
||||
|
|
@ -349,7 +483,7 @@ void PhysicalZone::setPolyhedron(const Polyhedron& rPolyhedron)
|
|||
setTransform(xform);
|
||||
|
||||
mClippedList.clear();
|
||||
mClippedList.mPlaneList = mPolyhedron.planeList;
|
||||
mClippedList.mPlaneList = mPolyhedron.mPlaneList;
|
||||
|
||||
MatrixF base(true);
|
||||
base.scale(Point3F(1.0/mObjScale.x,
|
||||
|
|
@ -406,7 +540,7 @@ bool PhysicalZone::testObject(SceneObject* enter)
|
|||
// all. And whats the point of building a convex if no collision methods
|
||||
// are implemented?
|
||||
|
||||
if (mPolyhedron.pointList.size() == 0)
|
||||
if (mPolyhedron.mPointList.size() == 0)
|
||||
return false;
|
||||
|
||||
mClippedList.clear();
|
||||
|
|
@ -443,3 +577,104 @@ void PhysicalZone::deactivate()
|
|||
mActive = false;
|
||||
}
|
||||
|
||||
void PhysicalZone::onStaticModified(const char* slotName, const char*newValue)
|
||||
{
|
||||
if (dStricmp(slotName, "appliedForce") == 0 || dStricmp(slotName, "forceType") == 0)
|
||||
{
|
||||
switch (force_type)
|
||||
{
|
||||
case SPHERICAL:
|
||||
force_mag = mAppliedForce.magnitudeSafe();
|
||||
break;
|
||||
case CYLINDRICAL:
|
||||
{
|
||||
Point3F force_vec = mAppliedForce;
|
||||
force_vec.z = 0.0;
|
||||
force_mag = force_vec.magnitudeSafe();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Point3F& PhysicalZone::getForce(const Point3F* center) const
|
||||
{
|
||||
static Point3F force_vec;
|
||||
|
||||
if (force_type == VECTOR)
|
||||
{
|
||||
if (orient_force)
|
||||
{
|
||||
getTransform().mulV(mAppliedForce, &force_vec);
|
||||
force_vec *= fade_amt;
|
||||
return force_vec;
|
||||
}
|
||||
force_vec = mAppliedForce;
|
||||
force_vec *= fade_amt;
|
||||
return force_vec;
|
||||
}
|
||||
|
||||
if (!center)
|
||||
{
|
||||
force_vec.zero();
|
||||
return force_vec;
|
||||
}
|
||||
|
||||
if (force_type == SPHERICAL)
|
||||
{
|
||||
force_vec = *center - getPosition();
|
||||
force_vec.normalizeSafe();
|
||||
force_vec *= force_mag*fade_amt;
|
||||
return force_vec;
|
||||
}
|
||||
|
||||
if (orient_force)
|
||||
{
|
||||
force_vec = *center - getPosition();
|
||||
getWorldTransform().mulV(force_vec);
|
||||
force_vec.z = 0.0f;
|
||||
force_vec.normalizeSafe();
|
||||
force_vec *= force_mag;
|
||||
force_vec.z = mAppliedForce.z;
|
||||
getTransform().mulV(force_vec);
|
||||
force_vec *= fade_amt;
|
||||
return force_vec;
|
||||
}
|
||||
|
||||
force_vec = *center - getPosition();
|
||||
force_vec.z = 0.0f;
|
||||
force_vec.normalizeSafe();
|
||||
force_vec *= force_mag;
|
||||
force_vec *= fade_amt;
|
||||
return force_vec;
|
||||
}
|
||||
|
||||
bool PhysicalZone::isExcludedObject(SceneObject* obj) const
|
||||
{
|
||||
for (S32 i = 0; i < excluded_objects.size(); i++)
|
||||
if (excluded_objects[i] == obj)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void PhysicalZone::registerExcludedObject(SceneObject* obj)
|
||||
{
|
||||
if (isExcludedObject(obj))
|
||||
return;
|
||||
|
||||
excluded_objects.push_back(obj);
|
||||
setMaskBits(FadeMask);
|
||||
}
|
||||
|
||||
void PhysicalZone::unregisterExcludedObject(SceneObject* obj)
|
||||
{
|
||||
for (S32 i = 0; i < excluded_objects.size(); i++)
|
||||
if (excluded_objects[i] == obj)
|
||||
{
|
||||
excluded_objects.erase(i);
|
||||
setMaskBits(FadeMask);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#ifndef _H_PHYSICALZONE
|
||||
#define _H_PHYSICALZONE
|
||||
|
||||
|
|
@ -40,9 +45,14 @@ class PhysicalZone : public SceneObject
|
|||
{
|
||||
typedef SceneObject Parent;
|
||||
|
||||
enum UpdateMasks {
|
||||
enum UpdateMasks {
|
||||
ActiveMask = Parent::NextFreeMask << 0,
|
||||
NextFreeMask = Parent::NextFreeMask << 1
|
||||
SettingsMask = Parent::NextFreeMask << 1,
|
||||
FadeMask = Parent::NextFreeMask << 2,
|
||||
PolyhedronMask = Parent::NextFreeMask << 3,
|
||||
MoveMask = Parent::NextFreeMask << 4,
|
||||
ExclusionMask = Parent::NextFreeMask << 5,
|
||||
NextFreeMask = Parent::NextFreeMask << 6
|
||||
};
|
||||
|
||||
protected:
|
||||
|
|
@ -83,7 +93,10 @@ class PhysicalZone : public SceneObject
|
|||
|
||||
inline F32 getVelocityMod() const { return mVelocityMod; }
|
||||
inline F32 getGravityMod() const { return mGravityMod; }
|
||||
inline const Point3F& getForce() const { return mAppliedForce; }
|
||||
// the scene object is now passed in to getForce() where
|
||||
// it is needed to calculate the applied force when the
|
||||
// force is radial.
|
||||
const Point3F& getForce(const Point3F* center=0) const;
|
||||
|
||||
void setPolyhedron(const Polyhedron&);
|
||||
bool testObject(SceneObject*);
|
||||
|
|
@ -96,7 +109,25 @@ class PhysicalZone : public SceneObject
|
|||
void deactivate();
|
||||
inline bool isActive() const { return mActive; }
|
||||
|
||||
protected:
|
||||
friend class afxPhysicalZoneData;
|
||||
friend class afxEA_PhysicalZone;
|
||||
Vector<SceneObject*> excluded_objects;
|
||||
S32 force_type;
|
||||
F32 force_mag;
|
||||
bool orient_force;
|
||||
F32 fade_amt;
|
||||
void setFadeAmount(F32 amt) { fade_amt = amt; if (fade_amt < 1.0f) setMaskBits(FadeMask); }
|
||||
public:
|
||||
enum ForceType { VECTOR, SPHERICAL, CYLINDRICAL };
|
||||
enum { FORCE_TYPE_BITS = 2 };
|
||||
virtual void onStaticModified(const char* slotName, const char*newValue = NULL);
|
||||
bool isExcludedObject(SceneObject*) const;
|
||||
void registerExcludedObject(SceneObject*);
|
||||
void unregisterExcludedObject(SceneObject*);
|
||||
};
|
||||
|
||||
typedef PhysicalZone::ForceType PhysicalZone_ForceType;
|
||||
DefineEnumType( PhysicalZone_ForceType );
|
||||
#endif // _H_PHYSICALZONE
|
||||
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ void PhysicsDebrisData::unpackData(BitStream* stream)
|
|||
shapeName = stream->readSTString();
|
||||
}
|
||||
|
||||
DefineConsoleMethod( PhysicsDebrisData, preload, void, (), ,
|
||||
DefineEngineMethod( PhysicsDebrisData, preload, void, (), ,
|
||||
"@brief Loads some information to have readily available at simulation time.\n\n"
|
||||
"Forces generation of shaders, materials, and other data used by the %PhysicsDebris object. "
|
||||
"This function should be used while a level is loading in order to shorten "
|
||||
|
|
@ -358,7 +358,7 @@ bool PhysicsDebris::onAdd()
|
|||
}
|
||||
|
||||
// Setup our bounding box
|
||||
mObjBox = mDataBlock->shape->bounds;
|
||||
mObjBox = mDataBlock->shape->mBounds;
|
||||
resetWorldBox();
|
||||
|
||||
// Add it to the client scene.
|
||||
|
|
|
|||
|
|
@ -35,12 +35,11 @@
|
|||
#include "T3D/physics/physicsWorld.h"
|
||||
#include "core/util/tNamedFactory.h"
|
||||
|
||||
|
||||
PhysicsPlugin* PhysicsPlugin::smSingleton = NULL;
|
||||
PhysicsResetSignal PhysicsPlugin::smPhysicsResetSignal;
|
||||
bool PhysicsPlugin::smSinglePlayer = false;
|
||||
U32 PhysicsPlugin::smThreadCount = 2;
|
||||
|
||||
bool PhysicsPlugin::smGpuAccelerationAllowed = false;
|
||||
|
||||
String PhysicsPlugin::smServerWorldName( "server" );
|
||||
String PhysicsPlugin::smClientWorldName( "client" );
|
||||
|
|
@ -51,6 +50,10 @@ AFTER_MODULE_INIT( Sim )
|
|||
"@brief Informs the physics simulation if only a single player exists.\n\n"
|
||||
"If true, optimizations will be implemented to better cater to a single player environmnent.\n\n"
|
||||
"@ingroup Physics\n");
|
||||
Con::addVariable("$Physics::gpuAccelerationAllowed", TypeBool, &PhysicsPlugin::smGpuAccelerationAllowed,
|
||||
"@brief Informs the physics plugin if it is allowed to use gpu acceleration.\n\n"
|
||||
"Not all physics implemenations or gpus can support gpu acceleration, this simply informs the plugin if it is allowed to try and use it or not.\n\n"
|
||||
"@ingroup Physics\n");
|
||||
Con::addVariable( "$pref::Physics::threadCount", TypeS32, &PhysicsPlugin::smThreadCount,
|
||||
"@brief Number of threads to use in a single pass of the physics engine.\n\n"
|
||||
"Defaults to 2 if not set.\n\n"
|
||||
|
|
@ -124,31 +127,31 @@ void PhysicsPlugin::_debugDraw( SceneManager *graph, const SceneRenderState *sta
|
|||
world->onDebugDraw( state );
|
||||
}
|
||||
|
||||
DefineConsoleFunction( physicsPluginPresent, bool, (), , "physicsPluginPresent()"
|
||||
DefineEngineFunction( physicsPluginPresent, bool, (), , "physicsPluginPresent()"
|
||||
"@brief Returns true if a physics plugin exists and is initialized.\n\n"
|
||||
"@ingroup Physics" )
|
||||
{
|
||||
return PHYSICSMGR != NULL;
|
||||
}
|
||||
|
||||
DefineConsoleFunction( physicsInit, bool, (const char * library), ("default"), "physicsInit( [string library] )")
|
||||
DefineEngineFunction( physicsInit, bool, (const char * library), ("default"), "physicsInit( [string library] )")
|
||||
{
|
||||
return PhysicsPlugin::activate( library );
|
||||
}
|
||||
|
||||
DefineConsoleFunction( physicsDestroy, void, (), , "physicsDestroy()")
|
||||
DefineEngineFunction( physicsDestroy, void, (), , "physicsDestroy()")
|
||||
{
|
||||
if ( PHYSICSMGR )
|
||||
PHYSICSMGR->destroyPlugin();
|
||||
}
|
||||
|
||||
DefineConsoleFunction( physicsInitWorld, bool, (const char * worldName), , "physicsInitWorld( String worldName )")
|
||||
DefineEngineFunction( physicsInitWorld, bool, (const char * worldName), , "physicsInitWorld( String worldName )")
|
||||
{
|
||||
bool res = PHYSICSMGR && PHYSICSMGR->createWorld( String( worldName ) );
|
||||
return res;
|
||||
}
|
||||
|
||||
DefineConsoleFunction( physicsDestroyWorld, void, (const char * worldName), , "physicsDestroyWorld( String worldName )")
|
||||
DefineEngineFunction( physicsDestroyWorld, void, (const char * worldName), , "physicsDestroyWorld( String worldName )")
|
||||
{
|
||||
if ( PHYSICSMGR )
|
||||
PHYSICSMGR->destroyWorld( worldName );
|
||||
|
|
@ -157,19 +160,19 @@ DefineConsoleFunction( physicsDestroyWorld, void, (const char * worldName), , "p
|
|||
|
||||
// Control/query of the stop/started state
|
||||
// of the currently running simulation.
|
||||
DefineConsoleFunction( physicsStartSimulation, void, (const char * worldName), , "physicsStartSimulation( String worldName )")
|
||||
DefineEngineFunction( physicsStartSimulation, void, (const char * worldName), , "physicsStartSimulation( String worldName )")
|
||||
{
|
||||
if ( PHYSICSMGR )
|
||||
PHYSICSMGR->enableSimulation( String( worldName ), true );
|
||||
}
|
||||
|
||||
DefineConsoleFunction( physicsStopSimulation, void, (const char * worldName), , "physicsStopSimulation( String worldName )")
|
||||
DefineEngineFunction( physicsStopSimulation, void, (const char * worldName), , "physicsStopSimulation( String worldName )")
|
||||
{
|
||||
if ( PHYSICSMGR )
|
||||
PHYSICSMGR->enableSimulation( String( worldName ), false );
|
||||
}
|
||||
|
||||
DefineConsoleFunction( physicsSimulationEnabled, bool, (), , "physicsStopSimulation( String worldName )")
|
||||
DefineEngineFunction( physicsSimulationEnabled, bool, (), , "physicsStopSimulation( String worldName )")
|
||||
{
|
||||
return PHYSICSMGR && PHYSICSMGR->isSimulationEnabled();
|
||||
}
|
||||
|
|
@ -177,14 +180,14 @@ DefineConsoleFunction( physicsSimulationEnabled, bool, (), , "physicsStopSimulat
|
|||
// Used for slowing down time on the
|
||||
// physics simulation, and for pausing/restarting
|
||||
// the simulation.
|
||||
DefineConsoleFunction( physicsSetTimeScale, void, (F32 scale), , "physicsSetTimeScale( F32 scale )")
|
||||
DefineEngineFunction( physicsSetTimeScale, void, (F32 scale), , "physicsSetTimeScale( F32 scale )")
|
||||
{
|
||||
if ( PHYSICSMGR )
|
||||
PHYSICSMGR->setTimeScale( scale );
|
||||
}
|
||||
|
||||
// Get the currently set time scale.
|
||||
DefineConsoleFunction( physicsGetTimeScale, F32, (), , "physicsGetTimeScale()")
|
||||
DefineEngineFunction( physicsGetTimeScale, F32, (), , "physicsGetTimeScale()")
|
||||
{
|
||||
return PHYSICSMGR && PHYSICSMGR->getTimeScale();
|
||||
}
|
||||
|
|
@ -193,7 +196,7 @@ DefineConsoleFunction( physicsGetTimeScale, F32, (), , "physicsGetTimeScale()")
|
|||
// physics simulation that they should store
|
||||
// their current state for later restoration,
|
||||
// such as when the editor is closed.
|
||||
DefineConsoleFunction( physicsStoreState, void, (), , "physicsStoreState()")
|
||||
DefineEngineFunction( physicsStoreState, void, (), , "physicsStoreState()")
|
||||
{
|
||||
PhysicsPlugin::getPhysicsResetSignal().trigger( PhysicsResetEvent_Store );
|
||||
}
|
||||
|
|
@ -201,13 +204,13 @@ DefineConsoleFunction( physicsStoreState, void, (), , "physicsStoreState()")
|
|||
// Used to send a signal to objects in the
|
||||
// physics simulation that they should restore
|
||||
// their saved state, such as when the editor is opened.
|
||||
DefineConsoleFunction( physicsRestoreState, void, (), , "physicsRestoreState()")
|
||||
DefineEngineFunction( physicsRestoreState, void, (), , "physicsRestoreState()")
|
||||
{
|
||||
if ( PHYSICSMGR )
|
||||
PHYSICSMGR->reset();
|
||||
}
|
||||
|
||||
DefineConsoleFunction( physicsDebugDraw, void, (bool enable), , "physicsDebugDraw( bool enable )")
|
||||
DefineEngineFunction( physicsDebugDraw, void, (bool enable), , "physicsDebugDraw( bool enable )")
|
||||
{
|
||||
if ( PHYSICSMGR )
|
||||
PHYSICSMGR->enableDebugDraw( enable );
|
||||
|
|
|
|||
|
|
@ -96,6 +96,10 @@ public:
|
|||
/// @see PHYSICSPLUGIN
|
||||
static PhysicsPlugin* getSingleton() { return smSingleton; }
|
||||
|
||||
/// Allow gpu acceleration if supported
|
||||
static bool smGpuAccelerationAllowed;
|
||||
static bool gpuAccelerationAllowed() { return smGpuAccelerationAllowed; }
|
||||
|
||||
///
|
||||
static bool activate( const char *library );
|
||||
|
||||
|
|
|
|||
|
|
@ -308,10 +308,10 @@ bool PhysicsShapeData::preload( bool server, String &errorBuffer )
|
|||
{
|
||||
//no collision so we create a simple box collision shape from the shapes bounds and alert the user
|
||||
Con::warnf( "PhysicsShapeData::preload - No collision found for shape '%s', auto-creating one", shapeName );
|
||||
Point3F halfWidth = shape->bounds.getExtents() * 0.5f;
|
||||
Point3F halfWidth = shape->mBounds.getExtents() * 0.5f;
|
||||
colShape = PHYSICSMGR->createCollision();
|
||||
MatrixF centerXfm(true);
|
||||
centerXfm.setPosition(shape->bounds.getCenter());
|
||||
centerXfm.setPosition(shape->mBounds.getCenter());
|
||||
colShape->addBox(halfWidth, centerXfm);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -707,7 +707,7 @@ bool PhysicsShape::_createShape()
|
|||
return false;
|
||||
|
||||
// Set the world box.
|
||||
mObjBox = db->shape->bounds;
|
||||
mObjBox = db->shape->mBounds;
|
||||
resetWorldBox();
|
||||
|
||||
// If this is the server and its a client only simulation
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue