2015-10-13 20:19:36 +00:00
//-----------------------------------------------------------------------------
// 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_ASSET_H_
# include "ShapeAsset.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 ( ShapeAsset ) ;
2018-01-28 20:48:02 +00:00
ConsoleType ( assetIdString , TypeShapeAssetPtr , String , ASSET_ID_FIELD_PREFIX )
2015-10-13 20:19:36 +00:00
//-----------------------------------------------------------------------------
ConsoleGetType ( TypeShapeAssetPtr )
{
// Fetch asset Id.
2018-01-28 20:48:02 +00:00
return * ( ( StringTableEntry * ) dptr ) ;
2015-10-13 20:19:36 +00:00
}
//-----------------------------------------------------------------------------
ConsoleSetType ( TypeShapeAssetPtr )
{
// Was a single argument specified?
if ( argc = = 1 )
{
// Yes, so fetch field value.
const char * pFieldValue = argv [ 0 ] ;
2018-01-28 20:48:02 +00:00
// Fetch asset Id.
StringTableEntry * assetId = ( StringTableEntry * ) ( dptr ) ;
2015-10-13 20:19:36 +00:00
2018-01-28 20:48:02 +00:00
// Update asset value.
* assetId = StringTable - > insert ( pFieldValue ) ;
2015-10-13 20:19:36 +00:00
return ;
}
// Warn.
2018-01-28 20:48:02 +00:00
Con : : warnf ( " (TypeAssetId) - Cannot set multiple args to a single asset. " ) ;
2015-10-13 20:19:36 +00:00
}
//-----------------------------------------------------------------------------
2018-01-28 20:48:02 +00:00
ShapeAsset : : ShapeAsset ( )
2015-10-13 20:19:36 +00:00
{
}
//-----------------------------------------------------------------------------
ShapeAsset : : ~ ShapeAsset ( )
{
}
//-----------------------------------------------------------------------------
void ShapeAsset : : initPersistFields ( )
{
// Call parent.
Parent : : initPersistFields ( ) ;
2019-05-04 16:49:42 +00:00
addProtectedField ( " fileName " , TypeAssetLooseFilePath , Offset ( mFileName , ShapeAsset ) ,
& setShapeFile , & getShapeFile , " Path to the shape file we want to render " ) ;
2018-01-28 20:48:02 +00:00
}
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 ) ;
}
2015-10-13 20:19:36 +00:00
}
void ShapeAsset : : initializeAsset ( )
{
// Call parent.
Parent : : initializeAsset ( ) ;
2019-05-04 16:49:42 +00:00
if ( mFileName = = StringTable - > EmptyString ( ) )
return ;
ResourceManager : : get ( ) . getChangedSignal ( ) . notify ( this , & ShapeAsset : : _onResourceChanged ) ;
loadShape ( ) ;
}
void ShapeAsset : : setShapeFile ( const char * pShapeFile )
{
// Sanity!
AssertFatal ( pShapeFile ! = NULL , " Cannot use a NULL shape file. " ) ;
// Fetch image file.
pShapeFile = StringTable - > insert ( pShapeFile ) ;
// Ignore no change,
if ( pShapeFile = = mFileName )
return ;
// Update.
mFileName = getOwned ( ) ? expandAssetFilePath ( pShapeFile ) : StringTable - > insert ( pShapeFile ) ;
// Refresh the asset.
refreshAsset ( ) ;
}
void ShapeAsset : : _onResourceChanged ( const Torque : : Path & path )
{
if ( path ! = Torque : : Path ( mFileName ) )
2015-10-13 20:19:36 +00:00
return ;
loadShape ( ) ;
}
bool ShapeAsset : : loadShape ( )
{
2018-01-28 20:48:02 +00:00
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 " ) )
{
2019-05-04 16:49:42 +00:00
mMaterialAssetIds . push_front ( assetDependenciesItr - > value ) ;
2018-01-28 20:48:02 +00:00
//Force the asset to become initialized if it hasn't been already
AssetPtr < MaterialAsset > matAsset = assetDependenciesItr - > value ;
2019-05-04 16:49:42 +00:00
mMaterialAssets . push_front ( matAsset ) ;
2018-01-28 20:48:02 +00:00
}
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 + + ;
}
}
2015-10-13 20:19:36 +00:00
mShape = ResourceManager : : get ( ) . load ( mFileName ) ;
if ( ! mShape )
{
Con : : errorf ( " StaticMesh::updateShape : failed to load shape file! " ) ;
return false ; //if it failed to load, bail out
}
2018-02-04 20:31:28 +00:00
bool hasBlends = false ;
2018-01-28 20:48:02 +00:00
//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
2018-02-04 20:31:28 +00:00
for ( S32 i = mAnimationAssets . size ( ) - 1 ; i > = 0 ; - - i )
2018-01-28 20:48:02 +00:00
{
2018-02-04 20:31:28 +00:00
String srcName = mAnimationAssets [ i ] - > getAnimationName ( ) ;
2018-01-28 20:48:02 +00:00
String srcPath ( mAnimationAssets [ i ] - > getAnimationFilename ( ) ) ;
2018-02-04 20:31:28 +00:00
//SplitSequencePathAndName(srcPath, srcName);
2018-01-28 20:48:02 +00:00
2018-02-04 20:31:28 +00:00
if ( ! mShape - > addSequence ( srcPath , srcName , srcName ,
2018-01-28 20:48:02 +00:00
mAnimationAssets [ i ] - > getStartFrame ( ) , mAnimationAssets [ i ] - > getEndFrame ( ) , mAnimationAssets [ i ] - > getPadRotation ( ) , mAnimationAssets [ i ] - > getPadTransforms ( ) ) )
return false ;
2018-02-04 20:31:28 +00:00
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 ;
}
}
}
2018-01-28 20:48:02 +00:00
}
2019-05-04 16:49:42 +00:00
onShapeChanged . trigger ( this ) ;
2015-10-13 20:19:36 +00:00
return true ;
}
//------------------------------------------------------------------------------
void ShapeAsset : : copyTo ( SimObject * object )
{
// Call to parent.
Parent : : copyTo ( object ) ;
2016-06-07 02:20:00 +00:00
}
void ShapeAsset : : onAssetRefresh ( void )
{
2018-01-28 20:48:02 +00:00
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 ;
2015-10-13 20:19:36 +00:00
}