Merge branch 'development' into ConvexProxies

This commit is contained in:
Areloch 2018-12-09 15:34:12 -06:00 committed by GitHub
commit bb30de04f7
2803 changed files with 195958 additions and 224299 deletions

View file

@ -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() );

View file

@ -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 );

View file

@ -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.

View file

@ -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;

View file

@ -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

View file

@ -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);
}

View file

@ -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)

View file

@ -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();
}
//-----------------------------------------------------------------------------

View file

@ -43,11 +43,6 @@ class ExampleAsset : public AssetBase
{
typedef AssetBase Parent;
AssetManager* mpOwningAssetManager;
bool mAssetInitialized;
AssetDefinition* mpAssetDefinition;
U32 mAcquireReferenceCount;
public:
ExampleAsset();
virtual ~ExampleAsset();

View 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;
}

View 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_

View file

@ -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;
}

View file

@ -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_

View 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();
}

View 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

View 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);
}

View 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_

View 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;
}

View 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_

View 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;
}

View 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_

View 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();
}

View 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_

View 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);
}

View 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_

View 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)
{
}

View 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_

View file

@ -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;
}

View file

@ -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

View 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)
{
}

View 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_

View 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;
}

View 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

View file

@ -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;

View file

@ -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());
}*/
}
}
}
}

View 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;
}

View 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

View file

@ -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);

View file

@ -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.")
{

View file

@ -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()

View file

@ -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.")
{

View file

@ -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]);

View file

@ -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")
{

View file

@ -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

View file

@ -30,6 +30,10 @@ StateMachine::StateMachine()
mStartingState = "";
mCurCreateState = NULL;
mStateMachineFile = StringTable->EmptyString();
mCurCreateState = nullptr;
}
StateMachine::~StateMachine()

View file

@ -158,6 +158,8 @@ public:
{
if (index <= mFields.size())
return mFields[index];
return StateField(); //return a blank one
}
Signal< void(StateMachine*, S32 stateIdx) > onStateChanged;

View file

@ -57,7 +57,6 @@ StateMachineComponent::StateMachineComponent() : Component()
//doesn't need to be networked
mNetworked = false;
mNetFlags.clear();
}
StateMachineComponent::~StateMachineComponent()

View file

@ -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;

View file

@ -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];

View file

@ -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;
}
}

View file

@ -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

View file

@ -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);
}

View file

@ -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(&center);
info->appliedForce += pz->getForce(&center);
}
}

View file

@ -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;

View file

@ -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 );

View file

@ -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() );

View file

@ -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; }
};

View file

@ -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 );

View file

@ -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 &currentBatch = 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

View file

@ -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(); }

View file

@ -213,7 +213,7 @@ void RenderShapeExample::createShape()
}
// Update the bounding box
mObjBox = mShape->bounds;
mObjBox = mShape->mBounds;
resetWorldBox();
setRenderTransform(mObjToWorld);

View file

@ -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() );

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);
}

View file

@ -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.
};

View file

@ -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
}

View file

@ -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

View file

@ -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();

View file

@ -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:

View file

@ -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 );
}

View file

@ -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 )

View file

@ -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); }
};

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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:" );

View file

@ -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;
}

View file

@ -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_

View file

@ -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;
}

View file

@ -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"

View file

@ -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();

View file

@ -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();
}

View file

@ -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.

View file

@ -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;
}

View file

@ -88,7 +88,7 @@ class Item: public ShapeBase
Point3F warpOffset;
F32 dt;
};
StateDelta delta;
StateDelta mDelta;
// Static attributes
ItemData* mDataBlock;

View file

@ -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();
}

View file

@ -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_

View file

@ -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."

View file

@ -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

View file

@ -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() );

View file

@ -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;
}
}

View file

@ -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

View file

@ -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.

View file

@ -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 );

View file

@ -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 );

View file

@ -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