2016-05-14 05:00:02 +00:00
//-----------------------------------------------------------------------------
// 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 "platform/platform.h"
# include "console/consoleTypes.h"
2016-05-29 05:58:02 +00:00
# include "T3D/components/render/meshComponent.h"
2016-05-14 05:00:02 +00:00
# include "core/util/safeDelete.h"
# include "core/resourceManager.h"
# include "core/stream/fileStream.h"
# include "console/consoleTypes.h"
# include "console/consoleObject.h"
# include "core/stream/bitStream.h"
# include "sim/netConnection.h"
# include "gfx/gfxTransformSaver.h"
# include "console/engineAPI.h"
# include "lighting/lightQuery.h"
# include "scene/sceneManager.h"
# include "gfx/bitmap/ddsFile.h"
# include "gfx/gfxTextureManager.h"
# include "materials/materialFeatureTypes.h"
# include "renderInstance/renderImposterMgr.h"
# include "util/imposterCapture.h"
# include "gfx/sim/debugDraw.h"
# include "gfx/gfxDrawUtil.h"
# include "materials/materialManager.h"
# include "materials/matInstance.h"
# include "core/strings/findMatch.h"
2016-05-26 06:37:14 +00:00
# include "T3D/components/render/meshComponent_ScriptBinding.h"
2016-05-14 05:00:02 +00:00
2018-01-28 20:57:02 +00:00
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 ;
2016-05-14 05:00:02 +00:00
//////////////////////////////////////////////////////////////////////////
// Constructor/Destructor
//////////////////////////////////////////////////////////////////////////
2018-02-04 22:21:07 +00:00
MeshComponent : : MeshComponent ( ) : Component ( ) , mShape ( nullptr ) , mRenderMode ( Individual )
2016-05-14 05:00:02 +00:00
{
mFriendlyName = " Mesh Component " ;
mComponentType = " Render " ;
mDescription = getDescriptionText ( " Causes the object to render a non-animating 3d shape using the file provided. " ) ;
mNetworked = true ;
2018-01-28 20:57:02 +00:00
mShapeName = StringTable - > EmptyString ( ) ;
mShapeAsset = StringTable - > EmptyString ( ) ;
2016-05-14 05:00:02 +00:00
2018-01-28 20:57:02 +00:00
mMeshAsset = StringTable - > EmptyString ( ) ;
mMeshAssetId = StringTable - > EmptyString ( ) ;
2016-05-14 05:00:02 +00:00
2018-01-28 20:57:02 +00:00
mInterfaceData = new MeshRenderSystemInterface ( ) ;
2016-05-14 05:00:02 +00:00
2018-01-28 20:57:02 +00:00
mRenderMode = Individual ;
}
2016-05-14 05:00:02 +00:00
2018-01-28 20:57:02 +00:00
MeshComponent : : ~ MeshComponent ( )
{
if ( mInterfaceData )
SAFE_DELETE ( mInterfaceData ) ;
2016-05-14 05:00:02 +00:00
}
2018-01-28 20:57:02 +00:00
IMPLEMENT_CO_NETOBJECT_V1 ( MeshComponent ) ;
//==========================================================================================
2016-05-14 05:00:02 +00:00
bool MeshComponent : : onAdd ( )
{
if ( ! Parent : : onAdd ( ) )
return false ;
// Register for the resource change signal.
ResourceManager : : get ( ) . getChangedSignal ( ) . notify ( this , & MeshComponent : : _onResourceChanged ) ;
return true ;
}
void MeshComponent : : onComponentAdd ( )
{
Parent : : onComponentAdd ( ) ;
2018-01-28 20:57:02 +00:00
if ( isClientObject ( ) )
mInterfaceData - > mIsClient = true ;
// if (mInterfaceData != nullptr)
// mInterfaceData->mIsClient = isClientObject();
2016-05-14 05:00:02 +00:00
//get the default shape, if any
updateShape ( ) ;
}
void MeshComponent : : onRemove ( )
{
Parent : : onRemove ( ) ;
}
void MeshComponent : : onComponentRemove ( )
{
if ( mOwner )
{
Point3F pos = mOwner - > getPosition ( ) ; //store our center pos
mOwner - > setObjectBox ( Box3F ( Point3F ( - 1 , - 1 , - 1 ) , Point3F ( 1 , 1 , 1 ) ) ) ;
mOwner - > setPosition ( pos ) ;
}
Parent : : onComponentRemove ( ) ;
}
void MeshComponent : : initPersistFields ( )
{
Parent : : initPersistFields ( ) ;
2018-01-28 20:57:02 +00:00
addGroup ( " Rendering " ) ;
addField ( " BatchingMode " , TypeBatchingMode , Offset ( mRenderMode , MeshComponent ) ,
" The mode of batching this shape should be rendered with. " ) ;
endGroup ( " Rendering " ) ;
2016-05-14 05:00:02 +00:00
//create a hook to our internal variables
addGroup ( " Model " ) ;
2018-01-28 20:57:02 +00:00
addProtectedField ( " MeshAsset " , TypeShapeAssetPtr , Offset ( mShapeAsset , MeshComponent ) , & _setMesh , & defaultProtectedGetFn ,
2016-05-14 05:00:02 +00:00
" The asset Id used for the mesh. " , AbstractClassRep : : FieldFlags : : FIELD_ComponentInspectors ) ;
endGroup ( " Model " ) ;
}
bool MeshComponent : : _setMesh ( void * object , const char * index , const char * data )
{
MeshComponent * rbI = static_cast < MeshComponent * > ( object ) ;
// Sanity!
AssertFatal ( data ! = NULL , " Cannot use a NULL asset Id. " ) ;
return rbI - > setMeshAsset ( data ) ;
}
bool MeshComponent : : _setShape ( void * object , const char * index , const char * data )
{
MeshComponent * rbI = static_cast < MeshComponent * > ( object ) ;
rbI - > mShapeName = StringTable - > insert ( data ) ;
rbI - > updateShape ( ) ; //make sure we force the update to resize the owner bounds
rbI - > setMaskBits ( ShapeMask ) ;
return true ;
}
bool MeshComponent : : setMeshAsset ( const char * assetName )
{
// Fetch the asset Id.
2018-01-28 20:57:02 +00:00
if ( mInterfaceData = = nullptr )
return false ;
2016-05-14 05:00:02 +00:00
mMeshAssetId = StringTable - > insert ( assetName ) ;
2016-06-07 02:20:00 +00:00
mMeshAsset = mMeshAssetId ;
2016-05-14 05:00:02 +00:00
if ( mMeshAsset . isNull ( ) )
{
Con : : errorf ( " [MeshComponent] Failed to load mesh asset. " ) ;
return false ;
}
mShapeName = mMeshAssetId ;
mShapeAsset = mShapeName ;
updateShape ( ) ; //make sure we force the update to resize the owner bounds
setMaskBits ( ShapeMask ) ;
return true ;
}
2018-01-28 20:57:02 +00:00
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 ( ) - > bounds . minExtents ;
max = mMeshAsset - > getShape ( ) - > bounds . 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 ) ;
}
2016-05-14 05:00:02 +00:00
void MeshComponent : : _onResourceChanged ( const Torque : : Path & path )
{
2018-01-28 20:57:02 +00:00
if ( mInterfaceData = = nullptr )
return ;
String filePath ;
if ( mMeshAsset )
filePath = Torque : : Path ( mMeshAsset - > getShapeFilename ( ) ) ;
if ( ! mMeshAsset | | path ! = Torque : : Path ( mMeshAsset - > getShapeFilename ( ) ) )
2016-05-14 05:00:02 +00:00
return ;
updateShape ( ) ;
setMaskBits ( ShapeMask ) ;
}
void MeshComponent : : inspectPostApply ( )
{
Parent : : inspectPostApply ( ) ;
}
U32 MeshComponent : : packUpdate ( NetConnection * con , U32 mask , BitStream * stream )
{
U32 retMask = Parent : : packUpdate ( con , mask , stream ) ;
if ( ! mOwner | | con - > getGhostIndex ( mOwner ) = = - 1 )
{
stream - > writeFlag ( false ) ;
stream - > writeFlag ( false ) ;
if ( mask & ShapeMask )
retMask | = ShapeMask ;
if ( mask & MaterialMask )
retMask | = MaterialMask ;
return retMask ;
}
if ( stream - > writeFlag ( mask & ShapeMask ) )
{
stream - > writeString ( mShapeName ) ;
2018-01-28 20:57:02 +00:00
stream - > writeInt ( mRenderMode , 8 ) ;
2016-05-14 05:00:02 +00:00
}
if ( stream - > writeFlag ( mask & MaterialMask ) )
{
stream - > writeInt ( mChangingMaterials . size ( ) , 16 ) ;
for ( U32 i = 0 ; i < mChangingMaterials . size ( ) ; i + + )
{
stream - > writeInt ( mChangingMaterials [ i ] . slot , 16 ) ;
2016-05-29 05:58:02 +00:00
2018-01-28 20:57:02 +00:00
NetStringHandle matNameStr = mChangingMaterials [ i ] . assetId . c_str ( ) ;
2016-05-29 05:58:02 +00:00
con - > packNetStringHandleU ( stream , matNameStr ) ;
2016-05-14 05:00:02 +00:00
}
mChangingMaterials . clear ( ) ;
}
return retMask ;
}
void MeshComponent : : unpackUpdate ( NetConnection * con , BitStream * stream )
{
Parent : : unpackUpdate ( con , stream ) ;
if ( stream - > readFlag ( ) )
{
mShapeName = stream - > readSTString ( ) ;
2018-01-28 20:57:02 +00:00
mRenderMode = ( RenderMode ) stream - > readInt ( 8 ) ;
2016-05-14 05:00:02 +00:00
setMeshAsset ( mShapeName ) ;
updateShape ( ) ;
}
if ( stream - > readFlag ( ) )
{
mChangingMaterials . clear ( ) ;
U32 materialCount = stream - > readInt ( 16 ) ;
for ( U32 i = 0 ; i < materialCount ; i + + )
{
matMap newMatMap ;
newMatMap . slot = stream - > readInt ( 16 ) ;
2018-01-28 20:57:02 +00:00
newMatMap . assetId = String ( con - > unpackNetStringHandleU ( stream ) . getString ( ) ) ;
//do the lookup, now
newMatMap . matAsset = AssetDatabase . acquireAsset < MaterialAsset > ( newMatMap . assetId ) ;
2016-05-14 05:00:02 +00:00
mChangingMaterials . push_back ( newMatMap ) ;
}
updateMaterials ( ) ;
}
}
void MeshComponent : : prepRenderImage ( SceneRenderState * state )
{
2018-01-28 20:57:02 +00:00
/*if (!mEnabled || !mOwner || !mShapeInstance)
2016-05-14 05:00:02 +00:00
return ;
Point3F cameraOffset ;
mOwner - > getRenderTransform ( ) . getColumn ( 3 , & cameraOffset ) ;
cameraOffset - = state - > getDiffuseCameraPosition ( ) ;
F32 dist = cameraOffset . len ( ) ;
if ( dist < 0.01f )
dist = 0.01f ;
Point3F objScale = getOwner ( ) - > getScale ( ) ;
F32 invScale = ( 1.0f / getMax ( getMax ( objScale . x , objScale . y ) , objScale . z ) ) ;
mShapeInstance - > setDetailFromDistance ( state , dist * invScale ) ;
if ( mShapeInstance - > getCurrentDetail ( ) < 0 )
return ;
GFXTransformSaver saver ;
// Set up our TS render state.
TSRenderState rdata ;
rdata . setSceneState ( state ) ;
rdata . setFadeOverride ( 1.0f ) ;
rdata . setOriginSort ( false ) ;
// We might have some forward lit materials
// so pass down a query to gather lights.
LightQuery query ;
query . init ( mOwner - > getWorldSphere ( ) ) ;
rdata . setLightQuery ( & query ) ;
MatrixF mat = mOwner - > getRenderTransform ( ) ;
2018-01-28 20:57:02 +00:00
if ( mOwner - > isMounted ( ) )
2016-05-14 05:00:02 +00:00
{
2018-01-28 20:57:02 +00:00
MatrixF wrldPos = mOwner - > getWorldTransform ( ) ;
Point3F wrldPosPos = wrldPos . getPosition ( ) ;
2016-05-14 05:00:02 +00:00
2018-01-28 20:57:02 +00:00
Point3F mntPs = mat . getPosition ( ) ;
EulerF mntRt = RotationF ( mat ) . asEulerF ( ) ;
2016-05-14 05:00:02 +00:00
2018-01-28 20:57:02 +00:00
bool tr = true ;
2016-05-14 05:00:02 +00:00
}
2018-01-28 20:57:02 +00:00
mat . scale ( objScale ) ;
GFX - > setWorldMatrix ( mat ) ;
mShapeInstance - > render ( rdata ) ; */
2016-05-14 05:00:02 +00:00
}
void MeshComponent : : updateMaterials ( )
{
2018-01-28 20:57:02 +00:00
if ( mChangingMaterials . empty ( ) | | ! mMeshAsset - > getShape ( ) )
2016-05-14 05:00:02 +00:00
return ;
2018-01-28 20:57:02 +00:00
TSMaterialList * pMatList = mInterfaceData - > mShapeInstance - > getMaterialList ( ) ;
2016-05-14 05:00:02 +00:00
pMatList - > setTextureLookupPath ( getShapeResource ( ) . getPath ( ) . getPath ( ) ) ;
const Vector < String > & materialNames = pMatList - > getMaterialNameList ( ) ;
for ( S32 i = 0 ; i < materialNames . size ( ) ; i + + )
{
for ( U32 m = 0 ; m < mChangingMaterials . size ( ) ; m + + )
{
if ( mChangingMaterials [ m ] . slot = = i )
{
2018-01-28 20:57:02 +00:00
//Fetch the actual material asset
pMatList - > renameMaterial ( i , mChangingMaterials [ m ] . matAsset - > getMaterialDefinitionName ( ) ) ;
2016-05-14 05:00:02 +00:00
}
}
mChangingMaterials . clear ( ) ;
}
// Initialize the material instances
2018-01-28 20:57:02 +00:00
mInterfaceData - > mShapeInstance - > initMaterialList ( ) ;
2016-05-14 05:00:02 +00:00
}
MatrixF MeshComponent : : getNodeTransform ( S32 nodeIdx )
{
2018-01-28 20:57:02 +00:00
if ( mInterfaceData ! = nullptr & & mMeshAsset - > getShape ( ) )
2016-05-14 05:00:02 +00:00
{
S32 nodeCount = getShape ( ) - > nodes . size ( ) ;
if ( nodeIdx > = 0 & & nodeIdx < nodeCount )
{
//animate();
2018-01-28 20:57:02 +00:00
MatrixF nodeTransform = mInterfaceData - > mShapeInstance - > mNodeTransforms [ nodeIdx ] ;
const Point3F & scale = mOwner - > getScale ( ) ;
// 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 ) ;
2016-05-14 05:00:02 +00:00
2018-01-28 20:57:02 +00:00
return finalTransform ;
2016-05-14 05:00:02 +00:00
}
}
return MatrixF : : Identity ;
}
S32 MeshComponent : : getNodeByName ( String nodeName )
{
2018-01-28 20:57:02 +00:00
if ( mMeshAsset - > getShape ( ) )
2016-05-14 05:00:02 +00:00
{
S32 nodeIdx = getShape ( ) - > findNode ( nodeName ) ;
return nodeIdx ;
}
return - 1 ;
}
bool MeshComponent : : castRayRendered ( const Point3F & start , const Point3F & end , RayInfo * info )
{
return false ;
}
void MeshComponent : : mountObjectToNode ( SceneObject * objB , String node , MatrixF txfm )
{
const char * test ;
test = node . c_str ( ) ;
if ( dIsdigit ( test [ 0 ] ) )
{
getOwner ( ) - > mountObject ( objB , dAtoi ( node ) , txfm ) ;
}
else
{
if ( TSShape * shape = getShape ( ) )
{
S32 idx = shape - > findNode ( node ) ;
getOwner ( ) - > mountObject ( objB , idx , txfm ) ;
}
}
}
void MeshComponent : : onDynamicModified ( const char * slotName , const char * newValue )
{
if ( FindMatch : : isMatch ( " materialslot* " , slotName , false ) )
{
if ( ! getShape ( ) )
return ;
S32 slot = - 1 ;
String outStr ( String : : GetTrailingNumber ( slotName , slot ) ) ;
if ( slot = = - 1 )
return ;
2018-01-28 20:57:02 +00:00
//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 ;
2016-05-14 05:00:02 +00:00
bool found = false ;
for ( U32 i = 0 ; i < mChangingMaterials . size ( ) ; i + + )
{
if ( mChangingMaterials [ i ] . slot = = slot )
{
2018-01-28 20:57:02 +00:00
mChangingMaterials [ i ] . matAsset = matAsset ;
mChangingMaterials [ i ] . assetId = newValue ;
2016-05-14 05:00:02 +00:00
found = true ;
}
}
if ( ! found )
{
matMap newMatMap ;
newMatMap . slot = slot ;
2018-01-28 20:57:02 +00:00
newMatMap . matAsset = matAsset ;
newMatMap . assetId = newValue ;
2016-05-14 05:00:02 +00:00
mChangingMaterials . push_back ( newMatMap ) ;
}
setMaskBits ( MaterialMask ) ;
}
Parent : : onDynamicModified ( slotName , newValue ) ;
}
2018-01-28 20:57:02 +00:00
void MeshComponent : : changeMaterial ( U32 slot , MaterialAsset * newMat )
2016-05-14 05:00:02 +00:00
{
char fieldName [ 512 ] ;
//update our respective field
dSprintf ( fieldName , 512 , " materialSlot%d " , slot ) ;
2018-01-28 20:57:02 +00:00
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 ;
2016-05-14 05:00:02 +00:00
}
void MeshComponent : : onInspect ( )
{
}
void MeshComponent : : onEndInspect ( )
{
2018-01-28 20:57:02 +00:00
}
void MeshComponent : : ownerTransformSet ( MatrixF * mat )
{
if ( mInterfaceData ! = nullptr )
{
MatrixF newTransform = * mat ;
mInterfaceData - > mTransform = newTransform ;
}
2016-05-14 05:00:02 +00:00
}