diff --git a/Engine/source/T3D/groundPlane.cpp b/Engine/source/T3D/groundPlane.cpp index bb8f82503..5e23a28ce 100644 --- a/Engine/source/T3D/groundPlane.cpp +++ b/Engine/source/T3D/groundPlane.cpp @@ -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" @@ -40,6 +45,7 @@ #include "T3D/physics/physicsBody.h" #include "T3D/physics/physicsCollision.h" +#include "afx/ce/afxZodiacMgr.h" /// 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 +83,7 @@ GroundPlane::GroundPlane() mNetFlags.set( Ghostable | ScopeAlways ); mConvexList = new Convex; + mTypeMask |= TerrainLikeObjectType; } GroundPlane::~GroundPlane() @@ -356,6 +363,7 @@ void GroundPlane::prepRenderImage( SceneRenderState* state ) if( mVertexBuffer.isNull() ) return; + afxZodiacMgr::renderGroundPlaneZodiacs(state, this); // Add a render instance. RenderPassManager* pass = state->getRenderPass(); diff --git a/Engine/source/T3D/objectTypes.h b/Engine/source/T3D/objectTypes.h index 8c9b3c84c..c27479b7f 100644 --- a/Engine/source/T3D/objectTypes.h +++ b/Engine/source/T3D/objectTypes.h @@ -20,6 +20,10 @@ // 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_ @@ -149,6 +153,8 @@ enum SceneObjectTypes EntityObjectType = BIT(23), /// @} + InteriorLikeObjectType = BIT(24), + TerrainLikeObjectType = BIT(25), }; enum SceneObjectTypeMasks : U32 diff --git a/Engine/source/T3D/tsStatic.cpp b/Engine/source/T3D/tsStatic.cpp index 84b3b0797..84b07566f 100644 --- a/Engine/source/T3D/tsStatic.cpp +++ b/Engine/source/T3D/tsStatic.cpp @@ -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/tsStatic.h" @@ -54,6 +59,8 @@ using namespace Torque; extern bool gEditingMission; +#include "afx/ce/afxZodiacMgr.h" + IMPLEMENT_CO_NETOBJECT_V1(TSStatic); ConsoleDocClass( TSStatic, @@ -124,6 +131,12 @@ TSStatic::TSStatic() mCollisionType = CollisionMesh; mDecalType = CollisionMesh; + + mIgnoreZodiacs = false; + mHasGradients = false; + mInvertGradientRange = false; + mGradientRangeUser.set(0.0f, 180.0f); + afxZodiacData::convertGradientRangeFromDegrees(mGradientRange, mGradientRangeUser); } TSStatic::~TSStatic() @@ -222,6 +235,12 @@ void TSStatic::initPersistFields() endGroup("Debug"); + addGroup("AFX"); + addField("ignoreZodiacs", TypeBool, Offset(mIgnoreZodiacs, TSStatic)); + addField("useGradientRange", TypeBool, Offset(mHasGradients, TSStatic)); + addField("gradientRange", TypePoint2F, Offset(mGradientRangeUser, TSStatic)); + addField("invertGradientRange", TypeBool, Offset(mInvertGradientRange, TSStatic)); + endGroup("AFX"); Parent::initPersistFields(); } @@ -323,6 +342,8 @@ bool TSStatic::_createShape() { // Cleanup before we create. mCollisionDetails.clear(); + mDecalDetails.clear(); + mDecalDetailsPtr = 0; mLOSDetails.clear(); SAFE_DELETE( mPhysicsRep ); SAFE_DELETE( mShapeInstance ); @@ -396,11 +417,29 @@ void TSStatic::prepCollision() // Cleanup any old collision data mCollisionDetails.clear(); + mDecalDetails.clear(); + mDecalDetailsPtr = 0; mLOSDetails.clear(); mConvexList->nukeList(); if ( mCollisionType == CollisionMesh || mCollisionType == VisibleMesh ) + { mShape->findColDetails( mCollisionType == VisibleMesh, &mCollisionDetails, &mLOSDetails ); + if ( mDecalType == mCollisionType ) + { + mDecalDetailsPtr = &mCollisionDetails; + } + else if ( mDecalType == CollisionMesh || mDecalType == VisibleMesh ) + { + mShape->findColDetails( mDecalType == VisibleMesh, &mDecalDetails, 0 ); + mDecalDetailsPtr = &mDecalDetails; + } + } + else if ( mDecalType == CollisionMesh || mDecalType == VisibleMesh ) + { + mShape->findColDetails( mDecalType == VisibleMesh, &mDecalDetails, 0 ); + mDecalDetailsPtr = &mDecalDetails; + } _updatePhysics(); } @@ -681,6 +720,8 @@ void TSStatic::prepRenderImage( SceneRenderState* state ) } mShapeInstance->render( rdata ); + if (!mIgnoreZodiacs && mDecalDetailsPtr != 0) + afxZodiacMgr::renderPolysoupZodiacs(state, this); if ( mRenderNormalScalar > 0 ) { ObjectRenderInst *ri = state->getRenderPass()->allocInst(); @@ -786,6 +827,13 @@ U32 TSStatic::packUpdate(NetConnection *con, U32 mask, BitStream *stream) stream->write(mInvertAlphaFade); } + stream->writeFlag(mIgnoreZodiacs); + if (stream->writeFlag(mHasGradients)) + { + stream->writeFlag(mInvertGradientRange); + stream->write(mGradientRange.x); + stream->write(mGradientRange.y); + } if ( mLightPlugin ) retMask |= mLightPlugin->packUpdate(this, AdvancedStaticOptionsMask, con, mask, stream); @@ -870,6 +918,14 @@ void TSStatic::unpackUpdate(NetConnection *con, BitStream *stream) stream->read(&mInvertAlphaFade); } + mIgnoreZodiacs = stream->readFlag(); + mHasGradients = stream->readFlag(); + if (mHasGradients) + { + mInvertGradientRange = stream->readFlag(); + stream->read(&mGradientRange.x); + stream->read(&mGradientRange.y); + } if ( mLightPlugin ) { mLightPlugin->unpackUpdate(this, con, stream); @@ -882,6 +938,7 @@ void TSStatic::unpackUpdate(NetConnection *con, BitStream *stream) if ( isProperlyAdded() ) _updateShouldTick(); + set_special_typing(); } //---------------------------------------------------------------------------- @@ -992,6 +1049,11 @@ bool TSStatic::buildPolyList(PolyListContext context, AbstractPolyList* polyList polyList->addBox( mObjBox ); else if ( meshType == VisibleMesh ) mShapeInstance->buildPolyList( polyList, 0 ); + else if (context == PLC_Decal && mDecalDetailsPtr != 0) + { + for ( U32 i = 0; i < mDecalDetailsPtr->size(); i++ ) + mShapeInstance->buildPolyListOpcode( (*mDecalDetailsPtr)[i], polyList, box ); + } else { // Everything else is done from the collision meshes @@ -1324,3 +1386,22 @@ DefineEngineMethod( TSStatic, getModelFile, const char *, (),, { return object->getShapeFileName(); } + +void TSStatic::set_special_typing() +{ + if (mCollisionType == VisibleMesh || mCollisionType == CollisionMesh) + mTypeMask |= InteriorLikeObjectType; + else + mTypeMask &= ~InteriorLikeObjectType; +} + +void TSStatic::onStaticModified(const char* slotName, const char*newValue) +{ + if (slotName == afxZodiacData::GradientRangeSlot) + { + afxZodiacData::convertGradientRangeFromDegrees(mGradientRange, mGradientRangeUser); + return; + } + + set_special_typing(); +} diff --git a/Engine/source/T3D/tsStatic.cpp.orig b/Engine/source/T3D/tsStatic.cpp.orig deleted file mode 100644 index 11848499e..000000000 --- a/Engine/source/T3D/tsStatic.cpp.orig +++ /dev/null @@ -1,1330 +0,0 @@ -//----------------------------------------------------------------------------- -// 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 "T3D/tsStatic.h" - -#include "core/resourceManager.h" -#include "core/stream/bitStream.h" -#include "scene/sceneRenderState.h" -#include "scene/sceneManager.h" -#include "scene/sceneObjectLightingPlugin.h" -#include "lighting/lightManager.h" -#include "math/mathIO.h" -#include "ts/tsShapeInstance.h" -#include "ts/tsMaterialList.h" -#include "console/consoleTypes.h" -#include "T3D/shapeBase.h" -#include "sim/netConnection.h" -#include "gfx/gfxDevice.h" -#include "gfx/gfxTransformSaver.h" -#include "ts/tsRenderState.h" -#include "collision/boxConvex.h" -#include "T3D/physics/physicsPlugin.h" -#include "T3D/physics/physicsBody.h" -#include "T3D/physics/physicsCollision.h" -#include "materials/materialDefinition.h" -#include "materials/materialManager.h" -#include "materials/matInstance.h" -#include "materials/materialFeatureData.h" -#include "materials/materialFeatureTypes.h" -#include "console/engineAPI.h" -#include "T3D/accumulationVolume.h" - -using namespace Torque; - -extern bool gEditingMission; - -IMPLEMENT_CO_NETOBJECT_V1(TSStatic); - -ConsoleDocClass( TSStatic, - "@brief A static object derived from a 3D model file and placed within the game world.\n\n" - - "TSStatic is the most basic 3D shape in Torque. Unlike StaticShape it doesn't make use of " - "a datablock. It derrives directly from SceneObject. This makes TSStatic extremely light " - "weight, which is why the Tools use this class when you want to drop in a DTS or DAE object.\n\n" - - "While a TSStatic doesn't provide any motion -- it stays were you initally put it -- it does allow for " - "a single ambient animation sequence to play when the object is first added to the scene.\n\n" - - "@tsexample\n" - "new TSStatic(Team1Base) {\n" - " shapeName = \"art/shapes/desertStructures/station01.dts\";\n" - " playAmbient = \"1\";\n" - " receiveSunLight = \"1\";\n" - " receiveLMLighting = \"1\";\n" - " useCustomAmbientLighting = \"0\";\n" - " customAmbientLighting = \"0 0 0 1\";\n" - " collisionType = \"Visible Mesh\";\n" - " decalType = \"Collision Mesh\";\n" - " allowPlayerStep = \"1\";\n" - " renderNormals = \"0\";\n" - " forceDetail = \"-1\";\n" - " position = \"315.18 -180.418 244.313\";\n" - " rotation = \"0 0 1 195.952\";\n" - " scale = \"1 1 1\";\n" - " isRenderEnabled = \"true\";\n" - " canSaveDynamicFields = \"1\";\n" - "};\n" - "@endtsexample\n" - - "@ingroup gameObjects\n" -); - -TSStatic::TSStatic() -: - cubeDescId( 0 ), - reflectorDesc( NULL ) -{ - mNetFlags.set(Ghostable | ScopeAlways); - - mTypeMask |= StaticObjectType | StaticShapeObjectType; - - mShapeName = ""; - mShapeInstance = NULL; - - mPlayAmbient = true; - mAmbientThread = NULL; - - mAllowPlayerStep = false; - - mConvexList = new Convex; - - mRenderNormalScalar = 0; - mForceDetail = -1; - - mMeshCulling = false; - mUseOriginSort = false; - - mUseAlphaFade = false; - mAlphaFadeStart = 100.0f; - mAlphaFadeEnd = 150.0f; - mInvertAlphaFade = false; - mAlphaFade = 1.0f; - mPhysicsRep = NULL; - - mCollisionType = CollisionMesh; - mDecalType = CollisionMesh; -} - -TSStatic::~TSStatic() -{ - delete mConvexList; - mConvexList = NULL; -} - -ImplementEnumType( TSMeshType, - "Type of mesh data available in a shape.\n" - "@ingroup gameObjects" ) - { TSStatic::None, "None", "No mesh data." }, - { TSStatic::Bounds, "Bounds", "Bounding box of the shape." }, - { TSStatic::CollisionMesh, "Collision Mesh", "Specifically desingated \"collision\" meshes." }, - { TSStatic::VisibleMesh, "Visible Mesh", "Rendered mesh polygons." }, -EndImplementEnumType; - - -void TSStatic::initPersistFields() -{ - addGroup("Media"); - - addField("shapeName", TypeShapeFilename, Offset( mShapeName, TSStatic ), - "%Path and filename of the model file (.DTS, .DAE) to use for this TSStatic." ); - - addProtectedField( "skin", TypeRealString, Offset( mAppliedSkinName, TSStatic ), &_setFieldSkin, &_getFieldSkin, - "@brief The skin applied to the shape.\n\n" - - "'Skinning' the shape effectively renames the material targets, allowing " - "different materials to be used on different instances of the same model.\n\n" - - "Any material targets that start with the old skin name have that part " - "of the name replaced with the new skin name. The initial old skin name is " - "\"base\". For example, if a new skin of \"blue\" was applied to a model " - "that had material targets base_body and face, the new targets " - "would be blue_body and face. Note that face was not " - "renamed since it did not start with the old skin name of \"base\".\n\n" - - "To support models that do not use the default \"base\" naming convention, " - "you can also specify the part of the name to replace in the skin field " - "itself. For example, if a model had a material target called shapemat, " - "we could apply a new skin \"shape=blue\", and the material target would be " - "renamed to bluemat (note \"shape\" has been replaced with \"blue\").\n\n" - - "Multiple skin updates can also be applied at the same time by separating " - "them with a semicolon. For example: \"base=blue;face=happy_face\".\n\n" - - "Material targets are only renamed if an existing Material maps to that " - "name, or if there is a diffuse texture in the model folder with the same " - "name as the new target.\n\n" ); - - endGroup("Media"); - - addGroup("Rendering"); - - addField( "playAmbient", TypeBool, Offset( mPlayAmbient, TSStatic ), - "Enables automatic playing of the animation sequence named \"ambient\" (if it exists) when the TSStatic is loaded."); - addField( "meshCulling", TypeBool, Offset( mMeshCulling, TSStatic ), - "Enables detailed culling of meshes within the TSStatic. Should only be used " - "with large complex shapes like buildings which contain many submeshes." ); - addField( "originSort", TypeBool, Offset( mUseOriginSort, TSStatic ), - "Enables translucent sorting of the TSStatic by its origin instead of the bounds." ); - - endGroup("Rendering"); - - addGroup( "Reflection" ); - addField( "cubeReflectorDesc", TypeRealString, Offset( cubeDescName, TSStatic ), - "References a ReflectorDesc datablock that defines performance and quality properties for dynamic reflections.\n"); - endGroup( "Reflection" ); - - addGroup("Collision"); - - addField( "collisionType", TypeTSMeshType, Offset( mCollisionType, TSStatic ), - "The type of mesh data to use for collision queries." ); - addField( "decalType", TypeTSMeshType, Offset( mDecalType, TSStatic ), - "The type of mesh data used to clip decal polygons against." ); - addField( "allowPlayerStep", TypeBool, Offset( mAllowPlayerStep, TSStatic ), - "@brief Allow a Player to walk up sloping polygons in the TSStatic (based on the collisionType).\n\n" - "When set to false, the slightest bump will stop the player from walking on top of the object.\n"); - - endGroup("Collision"); - - addGroup( "AlphaFade" ); - addField( "alphaFadeEnable", TypeBool, Offset(mUseAlphaFade, TSStatic), "Turn on/off Alpha Fade" ); - addField( "alphaFadeStart", TypeF32, Offset(mAlphaFadeStart, TSStatic), "Distance of start Alpha Fade" ); - addField( "alphaFadeEnd", TypeF32, Offset(mAlphaFadeEnd, TSStatic), "Distance of end Alpha Fade" ); - addField( "alphaFadeInverse", TypeBool, Offset(mInvertAlphaFade, TSStatic), "Invert Alpha Fade's Start & End Distance" ); - endGroup( "AlphaFade" ); - - addGroup("Debug"); - - addField( "renderNormals", TypeF32, Offset( mRenderNormalScalar, TSStatic ), - "Debug rendering mode shows the normals for each point in the TSStatic's mesh." ); - addField( "forceDetail", TypeS32, Offset( mForceDetail, TSStatic ), - "Forces rendering to a particular detail level." ); - - endGroup("Debug"); - - Parent::initPersistFields(); -} - -bool TSStatic::_setFieldSkin( void *object, const char *index, const char *data ) -{ - TSStatic *ts = static_cast( object ); - if ( ts ) - ts->setSkinName( data ); - return false; -} - -const char *TSStatic::_getFieldSkin( void *object, const char *data ) -{ - TSStatic *ts = static_cast( object ); - return ts ? ts->mSkinNameHandle.getString() : ""; -} - -void TSStatic::inspectPostApply() -{ - // Apply any transformations set in the editor - Parent::inspectPostApply(); - - if(isServerObject()) - { - setMaskBits(AdvancedStaticOptionsMask); - prepCollision(); - } - - _updateShouldTick(); -} - -bool TSStatic::onAdd() -{ - PROFILE_SCOPE(TSStatic_onAdd); - - if ( isServerObject() ) - { - // Handle the old "usePolysoup" field - SimFieldDictionary* fieldDict = getFieldDictionary(); - - if ( fieldDict ) - { - StringTableEntry slotName = StringTable->insert( "usePolysoup" ); - - SimFieldDictionary::Entry * entry = fieldDict->findDynamicField( slotName ); - - if ( entry ) - { - // Was "usePolysoup" set? - bool usePolysoup = dAtob( entry->value ); - - // "usePolysoup" maps to the new VisibleMesh type - if ( usePolysoup ) - mCollisionType = VisibleMesh; - - // Remove the field in favor on the new "collisionType" field - fieldDict->setFieldValue( slotName, "" ); - } - } - } - - if ( !Parent::onAdd() ) - return false; - - // Setup the shape. - if ( !_createShape() ) - { - Con::errorf( "TSStatic::onAdd() - Shape creation failed!" ); - return false; - } - - setRenderTransform(mObjToWorld); - - // Register for the resource change signal. - ResourceManager::get().getChangedSignal().notify( this, &TSStatic::_onResourceChanged ); - - addToScene(); - - if ( isClientObject() ) - { - mCubeReflector.unregisterReflector(); - - if ( reflectorDesc ) - mCubeReflector.registerReflector( this, reflectorDesc ); - } - - _updateShouldTick(); - - // Accumulation and environment mapping - if (isClientObject() && mShapeInstance) - { - AccumulationVolume::addObject(this); - } - - return true; -} - -bool TSStatic::_createShape() -{ - // Cleanup before we create. - mCollisionDetails.clear(); - mLOSDetails.clear(); - SAFE_DELETE( mPhysicsRep ); - SAFE_DELETE( mShapeInstance ); - mAmbientThread = NULL; - mShape = NULL; - - if (!mShapeName || mShapeName[0] == '\0') - { - Con::errorf( "TSStatic::_createShape() - No shape name!" ); - return false; - } - - mShapeHash = _StringTable::hashString(mShapeName); - - mShape = ResourceManager::get().load(mShapeName); - if ( bool(mShape) == false ) - { - Con::errorf( "TSStatic::_createShape() - Unable to load shape: %s", mShapeName ); - return false; - } - - if ( isClientObject() && - !mShape->preloadMaterialList(mShape.getPath()) && - NetConnection::filesWereDownloaded() ) - return false; - - mObjBox = mShape->bounds; - resetWorldBox(); - - mShapeInstance = new TSShapeInstance( mShape, isClientObject() ); - - if( isGhost() ) - { - // Reapply the current skin - mAppliedSkinName = ""; - reSkin(); - } - - prepCollision(); - - // Find the "ambient" animation if it exists - S32 ambientSeq = mShape->findSequence("ambient"); - - if ( ambientSeq > -1 && !mAmbientThread ) - mAmbientThread = mShapeInstance->addThread(); - - if ( mAmbientThread ) - mShapeInstance->setSequence( mAmbientThread, ambientSeq, 0); - - // Resolve CubeReflectorDesc. - if ( cubeDescName.isNotEmpty() ) - { - Sim::findObject( cubeDescName, reflectorDesc ); - } - else if( cubeDescId > 0 ) - { - Sim::findObject( cubeDescId, reflectorDesc ); - } - - return true; -} - -void TSStatic::prepCollision() -{ - // Let the client know that the collision was updated - setMaskBits( UpdateCollisionMask ); - - // Allow the ShapeInstance to prep its collision if it hasn't already - if ( mShapeInstance ) - mShapeInstance->prepCollision(); - - // Cleanup any old collision data - mCollisionDetails.clear(); - mLOSDetails.clear(); - mConvexList->nukeList(); - - if ( mCollisionType == CollisionMesh || mCollisionType == VisibleMesh ) - mShape->findColDetails( mCollisionType == VisibleMesh, &mCollisionDetails, &mLOSDetails ); - - _updatePhysics(); -} - -void TSStatic::_updatePhysics() -{ - SAFE_DELETE( mPhysicsRep ); - - if ( !PHYSICSMGR || mCollisionType == None ) - return; - - PhysicsCollision *colShape = NULL; - if ( mCollisionType == Bounds ) - { - MatrixF offset( true ); - offset.setPosition( mShape->center ); - colShape = PHYSICSMGR->createCollision(); - colShape->addBox( getObjBox().getExtents() * 0.5f * mObjScale, offset ); - } - else - colShape = mShape->buildColShape( mCollisionType == VisibleMesh, getScale() ); - - if ( colShape ) - { - PhysicsWorld *world = PHYSICSMGR->getWorld( isServerObject() ? "server" : "client" ); - mPhysicsRep = PHYSICSMGR->createBody(); - mPhysicsRep->init( colShape, 0, 0, this, world ); - mPhysicsRep->setTransform( getTransform() ); - } -} - -void TSStatic::onRemove() -{ - SAFE_DELETE( mPhysicsRep ); - - // Accumulation - if ( isClientObject() && mShapeInstance ) - { - if ( mShapeInstance->hasAccumulation() ) - AccumulationVolume::removeObject(this); - } - - mConvexList->nukeList(); - - removeFromScene(); - - // Remove the resource change signal. - ResourceManager::get().getChangedSignal().remove( this, &TSStatic::_onResourceChanged ); - - delete mShapeInstance; - mShapeInstance = NULL; - - mAmbientThread = NULL; - if ( isClientObject() ) - mCubeReflector.unregisterReflector(); - - Parent::onRemove(); -} - -void TSStatic::_onResourceChanged( const Torque::Path &path ) -{ - if ( path != Path( mShapeName ) ) - return; - - _createShape(); - _updateShouldTick(); -} - -void TSStatic::setSkinName( const char *name ) -{ - if ( !isGhost() ) - { - if ( name[0] != '\0' ) - { - // Use tags for better network performance - // Should be a tag, but we'll convert to one if it isn't. - if ( name[0] == StringTagPrefixByte ) - mSkinNameHandle = NetStringHandle( U32(dAtoi(name + 1)) ); - else - mSkinNameHandle = NetStringHandle( name ); - } - else - mSkinNameHandle = NetStringHandle(); - - setMaskBits( SkinMask ); - } -} - -void TSStatic::reSkin() -{ - if ( isGhost() && mShapeInstance && mSkinNameHandle.isValidString() ) - { - Vector skins; - String(mSkinNameHandle.getString()).split( ";", skins ); - - for (S32 i = 0; i < skins.size(); i++) - { - String oldSkin( mAppliedSkinName.c_str() ); - String newSkin( skins[i] ); - - // Check if the skin handle contains an explicit "old" base string. This - // allows all models to support skinning, even if they don't follow the - // "base_xxx" material naming convention. - S32 split = newSkin.find( '=' ); // "old=new" format skin? - if ( split != String::NPos ) - { - oldSkin = newSkin.substr( 0, split ); - newSkin = newSkin.erase( 0, split+1 ); - } - - mShapeInstance->reSkin( newSkin, oldSkin ); - mAppliedSkinName = newSkin; - } - } -} - -void TSStatic::processTick( const Move *move ) -{ - if ( isServerObject() && mPlayAmbient && mAmbientThread ) - mShapeInstance->advanceTime( TickSec, mAmbientThread ); - - if ( isMounted() ) - { - MatrixF mat( true ); - mMount.object->getMountTransform(mMount.node, mMount.xfm, &mat ); - setTransform( mat ); - } -} - -void TSStatic::interpolateTick( F32 delta ) -{ -} - -void TSStatic::advanceTime( F32 dt ) -{ - if ( mPlayAmbient && mAmbientThread ) - mShapeInstance->advanceTime( dt, mAmbientThread ); - - if ( isMounted() ) - { - MatrixF mat( true ); - mMount.object->getRenderMountTransform( dt, mMount.node, mMount.xfm, &mat ); - setRenderTransform( mat ); - } -} - -void TSStatic::_updateShouldTick() -{ - bool shouldTick = (mPlayAmbient && mAmbientThread) || isMounted(); - - if ( isTicking() != shouldTick ) - setProcessTick( shouldTick ); -} - -void TSStatic::prepRenderImage( SceneRenderState* state ) -{ - if( !mShapeInstance ) - return; - - Point3F cameraOffset; - getRenderTransform().getColumn(3,&cameraOffset); - cameraOffset -= state->getDiffuseCameraPosition(); - F32 dist = cameraOffset.len(); - if (dist < 0.01f) - dist = 0.01f; - - if (mUseAlphaFade) - { - mAlphaFade = 1.0f; - if ((mAlphaFadeStart < mAlphaFadeEnd) && mAlphaFadeStart > 0.1f) - { - if (mInvertAlphaFade) - { - if (dist <= mAlphaFadeStart) - { - return; - } - if (dist < mAlphaFadeEnd) - { - mAlphaFade = ((dist - mAlphaFadeStart) / (mAlphaFadeEnd - mAlphaFadeStart)); - } - } - else - { - if (dist >= mAlphaFadeEnd) - { - return; - } - if (dist > mAlphaFadeStart) - { - mAlphaFade -= ((dist - mAlphaFadeStart) / (mAlphaFadeEnd - mAlphaFadeStart)); - } - } - } - } - - F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z)); - - // If we're currently rendering our own reflection we - // don't want to render ourselves into it. - if ( mCubeReflector.isRendering() ) - return; - - - if ( mForceDetail == -1 ) - mShapeInstance->setDetailFromDistance( state, dist * invScale ); - else - mShapeInstance->setCurrentDetail( mForceDetail ); - - if ( mShapeInstance->getCurrentDetail() < 0 ) - return; - - GFXTransformSaver saver; - - // Set up our TS render state. - TSRenderState rdata; - rdata.setSceneState( state ); - rdata.setFadeOverride( 1.0f ); - rdata.setOriginSort( mUseOriginSort ); - - if ( mCubeReflector.isEnabled() ) - rdata.setCubemap( mCubeReflector.getCubemap() ); - - // Acculumation - rdata.setAccuTex(mAccuTex); - - // If we have submesh culling enabled then prepare - // the object space frustum to pass to the shape. - Frustum culler; - if ( mMeshCulling ) - { - culler = state->getCullingFrustum(); - MatrixF xfm( true ); - xfm.scale( Point3F::One / getScale() ); - xfm.mul( getRenderWorldTransform() ); - xfm.mul( culler.getTransform() ); - culler.setTransform( xfm ); - rdata.setCuller( &culler ); - } - - // We might have some forward lit materials - // so pass down a query to gather lights. - LightQuery query; - query.init( getWorldSphere() ); - rdata.setLightQuery( &query ); - - MatrixF mat = getRenderTransform(); - mat.scale( mObjScale ); - GFX->setWorldMatrix( mat ); - - if ( state->isDiffusePass() && mCubeReflector.isEnabled() && mCubeReflector.getOcclusionQuery() ) - { - RenderPassManager *pass = state->getRenderPass(); - OccluderRenderInst *ri = pass->allocInst(); - - ri->type = RenderPassManager::RIT_Occluder; - ri->query = mCubeReflector.getOcclusionQuery(); - mObjToWorld.mulP( mObjBox.getCenter(), &ri->position ); - ri->scale.set( mObjBox.getExtents() ); - ri->orientation = pass->allocUniqueXform( mObjToWorld ); - ri->isSphere = false; - state->getRenderPass()->addInst( ri ); - } - - mShapeInstance->animate(); - if(mShapeInstance) - { - if (mUseAlphaFade) - { - mShapeInstance->setAlphaAlways(mAlphaFade); - S32 s = mShapeInstance->mMeshObjects.size(); - - for(S32 x = 0; x < s; x++) - { - mShapeInstance->mMeshObjects[x].visible = mAlphaFade; - } - } - } - mShapeInstance->render( rdata ); - - if ( mRenderNormalScalar > 0 ) - { - ObjectRenderInst *ri = state->getRenderPass()->allocInst(); - ri->renderDelegate.bind( this, &TSStatic::_renderNormals ); - ri->type = RenderPassManager::RIT_Editor; - state->getRenderPass()->addInst( ri ); - } -} - -void TSStatic::_renderNormals( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ) -{ - PROFILE_SCOPE( TSStatic_RenderNormals ); - - GFXTransformSaver saver; - - MatrixF mat = getRenderTransform(); - mat.scale( mObjScale ); - GFX->multWorld( mat ); - - S32 dl = mShapeInstance->getCurrentDetail(); - mShapeInstance->renderDebugNormals( mRenderNormalScalar, dl ); -} - -void TSStatic::onScaleChanged() -{ - Parent::onScaleChanged(); - - if ( mPhysicsRep ) - { - // If the editor is enabled delay the scale operation - // by a few milliseconds so that we're not rebuilding - // during an active scale drag operation. - if ( gEditingMission ) - mPhysicsRep->queueCallback( 500, Delegate( this, &TSStatic::_updatePhysics ) ); - else - _updatePhysics(); - } - - setMaskBits( ScaleMask ); -} - -void TSStatic::setTransform(const MatrixF & mat) -{ - Parent::setTransform(mat); - if ( !isMounted() ) - setMaskBits( TransformMask ); - - if ( mPhysicsRep ) - mPhysicsRep->setTransform( mat ); - - // Accumulation - if ( isClientObject() && mShapeInstance ) - { - if ( mShapeInstance->hasAccumulation() ) - AccumulationVolume::updateObject(this); - } - - // Since this is a static it's render transform changes 1 - // to 1 with it's collision transform... no interpolation. - setRenderTransform(mat); -} - -U32 TSStatic::packUpdate(NetConnection *con, U32 mask, BitStream *stream) -{ - U32 retMask = Parent::packUpdate(con, mask, stream); - - if ( stream->writeFlag( mask & TransformMask ) ) - mathWrite( *stream, getTransform() ); - - if ( stream->writeFlag( mask & ScaleMask ) ) - { - // Only write one bit if the scale is one. - if ( stream->writeFlag( mObjScale != Point3F::One ) ) - mathWrite( *stream, mObjScale ); - } - - if ( stream->writeFlag( mask & UpdateCollisionMask ) ) - stream->write( (U32)mCollisionType ); - - if ( stream->writeFlag( mask & SkinMask ) ) - con->packNetStringHandleU( stream, mSkinNameHandle ); - - if (stream->writeFlag(mask & AdvancedStaticOptionsMask)) - { - stream->writeString(mShapeName); - stream->write((U32)mDecalType); - - stream->writeFlag(mAllowPlayerStep); - stream->writeFlag(mMeshCulling); - stream->writeFlag(mUseOriginSort); - - stream->write(mRenderNormalScalar); - - stream->write(mForceDetail); - - stream->writeFlag(mPlayAmbient); - } - - if ( stream->writeFlag(mUseAlphaFade) ) - { - stream->write(mAlphaFadeStart); - stream->write(mAlphaFadeEnd); - stream->write(mInvertAlphaFade); - } - - if ( mLightPlugin ) - retMask |= mLightPlugin->packUpdate(this, AdvancedStaticOptionsMask, con, mask, stream); - - if( stream->writeFlag( reflectorDesc != NULL ) ) - { - stream->writeRangedU32( reflectorDesc->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast ); - } - return retMask; -} - -void TSStatic::unpackUpdate(NetConnection *con, BitStream *stream) -{ - Parent::unpackUpdate(con, stream); - - if ( stream->readFlag() ) // TransformMask - { - MatrixF mat; - mathRead( *stream, &mat ); - setTransform(mat); - setRenderTransform(mat); - } - - if ( stream->readFlag() ) // ScaleMask - { - if ( stream->readFlag() ) - { - VectorF scale; - mathRead( *stream, &scale ); - setScale( scale ); - } - else - setScale( Point3F::One ); - } - - if ( stream->readFlag() ) // UpdateCollisionMask - { - U32 collisionType = CollisionMesh; - - stream->read( &collisionType ); - - // Handle it if we have changed CollisionType's - if ( (MeshType)collisionType != mCollisionType ) - { - mCollisionType = (MeshType)collisionType; - - if ( isProperlyAdded() && mShapeInstance ) - prepCollision(); - } - } - - if (stream->readFlag()) // SkinMask - { - NetStringHandle skinDesiredNameHandle = con->unpackNetStringHandleU(stream);; - if (mSkinNameHandle != skinDesiredNameHandle) - { - mSkinNameHandle = skinDesiredNameHandle; - reSkin(); - } - } - - if (stream->readFlag()) // AdvancedStaticOptionsMask - { - mShapeName = stream->readSTString(); - - stream->read((U32*)&mDecalType); - - mAllowPlayerStep = stream->readFlag(); - mMeshCulling = stream->readFlag(); - mUseOriginSort = stream->readFlag(); - - stream->read(&mRenderNormalScalar); - - stream->read(&mForceDetail); - mPlayAmbient = stream->readFlag(); - } - - mUseAlphaFade = stream->readFlag(); - if (mUseAlphaFade) - { - stream->read(&mAlphaFadeStart); - stream->read(&mAlphaFadeEnd); - stream->read(&mInvertAlphaFade); - } - - if ( mLightPlugin ) - { - mLightPlugin->unpackUpdate(this, con, stream); - } - - if( stream->readFlag() ) - { - cubeDescId = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast ); - } - - if ( isProperlyAdded() ) - _updateShouldTick(); -} - -//---------------------------------------------------------------------------- -bool TSStatic::castRay(const Point3F &start, const Point3F &end, RayInfo* info) -{ - if ( mCollisionType == None ) - return false; - - if ( !mShapeInstance ) - return false; - - if ( mCollisionType == Bounds ) - { - F32 fst; - if (!mObjBox.collideLine(start, end, &fst, &info->normal)) - return false; - - info->t = fst; - info->object = this; - info->point.interpolate( start, end, fst ); - info->material = NULL; - return true; - } - else - { - RayInfo shortest = *info; - RayInfo localInfo; - shortest.t = 1e8f; - localInfo.generateTexCoord = info->generateTexCoord; - - for ( U32 i = 0; i < mLOSDetails.size(); i++ ) - { - mShapeInstance->animate( mLOSDetails[i] ); - - if ( mShapeInstance->castRayOpcode( mLOSDetails[i], start, end, &localInfo ) ) - { - localInfo.object = this; - - if (localInfo.t < shortest.t) - shortest = localInfo; - } - } - - if (shortest.object == this) - { - // Copy out the shortest time... - *info = shortest; - return true; - } - } - - return false; -} - -bool TSStatic::castRayRendered(const Point3F &start, const Point3F &end, RayInfo *info) -{ - if ( !mShapeInstance ) - return false; - - // Cast the ray against the currently visible detail - RayInfo localInfo; - bool res = mShapeInstance->castRayOpcode( mShapeInstance->getCurrentDetail(), start, end, &localInfo ); - - if ( res ) - { - *info = localInfo; - info->object = this; - return true; - } - - return false; -} - -bool TSStatic::buildPolyList(PolyListContext context, AbstractPolyList* polyList, const Box3F &box, const SphereF &) -{ - if ( !mShapeInstance ) - return false; - - // This is safe to set even if we're not outputing - polyList->setTransform( &mObjToWorld, mObjScale ); - polyList->setObject( this ); - - if ( context == PLC_Export ) - { - // Use highest detail level - S32 dl = 0; - - // Try to call on the client so we can export materials - if ( isServerObject() && getClientObject() ) - dynamic_cast(getClientObject())->mShapeInstance->buildPolyList( polyList, dl ); - else - mShapeInstance->buildPolyList( polyList, dl ); - } - else if ( context == PLC_Selection ) - { - // Use the last rendered detail level - S32 dl = mShapeInstance->getCurrentDetail(); - mShapeInstance->buildPolyListOpcode( dl, polyList, box ); - } - else - { - // Figure out the mesh type we're looking for. - MeshType meshType = ( context == PLC_Decal ) ? mDecalType : mCollisionType; - - if ( meshType == None ) - return false; - else if ( meshType == Bounds ) - polyList->addBox( mObjBox ); - else if ( meshType == VisibleMesh ) - mShapeInstance->buildPolyList( polyList, 0 ); - else - { - // Everything else is done from the collision meshes - // which may be built from either the visual mesh or - // special collision geometry. - for ( U32 i = 0; i < mCollisionDetails.size(); i++ ) - mShapeInstance->buildPolyListOpcode( mCollisionDetails[i], polyList, box ); - } - } - - return true; -} - -void TSStatic::buildConvex(const Box3F& box, Convex* convex) -{ - if ( mCollisionType == None ) - return; - - if ( mShapeInstance == NULL ) - return; - - // These should really come out of a pool - mConvexList->collectGarbage(); - - if ( mCollisionType == Bounds ) - { - // Just return a box convex for the entire shape... - Convex* cc = 0; - CollisionWorkingList& wl = convex->getWorkingList(); - for (CollisionWorkingList* itr = wl.wLink.mNext; itr != &wl; itr = itr->wLink.mNext) - { - if (itr->mConvex->getType() == BoxConvexType && - itr->mConvex->getObject() == this) - { - cc = itr->mConvex; - break; - } - } - if (cc) - return; - - // Create a new convex. - BoxConvex* cp = new BoxConvex; - mConvexList->registerObject(cp); - convex->addToWorkingList(cp); - cp->init(this); - - mObjBox.getCenter(&cp->mCenter); - cp->mSize.x = mObjBox.len_x() / 2.0f; - cp->mSize.y = mObjBox.len_y() / 2.0f; - cp->mSize.z = mObjBox.len_z() / 2.0f; - } - else // CollisionMesh || VisibleMesh - { - TSStaticPolysoupConvex::smCurObject = this; - - for (U32 i = 0; i < mCollisionDetails.size(); i++) - mShapeInstance->buildConvexOpcode( mObjToWorld, mObjScale, mCollisionDetails[i], box, convex, mConvexList ); - - TSStaticPolysoupConvex::smCurObject = NULL; - } -} - -SceneObject* TSStaticPolysoupConvex::smCurObject = NULL; - -TSStaticPolysoupConvex::TSStaticPolysoupConvex() -: box( 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f ), - normal( 0.0f, 0.0f, 0.0f, 0.0f ), - idx( 0 ), - mesh( NULL ) -{ - mType = TSPolysoupConvexType; - - for ( U32 i = 0; i < 4; ++i ) - { - verts[i].set( 0.0f, 0.0f, 0.0f ); - } -} - -Point3F TSStaticPolysoupConvex::support(const VectorF& vec) const -{ - F32 bestDot = mDot( verts[0], vec ); - - const Point3F *bestP = &verts[0]; - for(S32 i=1; i<4; i++) - { - F32 newD = mDot(verts[i], vec); - if(newD > bestDot) - { - bestDot = newD; - bestP = &verts[i]; - } - } - - return *bestP; -} - -Box3F TSStaticPolysoupConvex::getBoundingBox() const -{ - Box3F wbox = box; - wbox.minExtents.convolve( mObject->getScale() ); - wbox.maxExtents.convolve( mObject->getScale() ); - mObject->getTransform().mul(wbox); - return wbox; -} - -Box3F TSStaticPolysoupConvex::getBoundingBox(const MatrixF& mat, const Point3F& scale) const -{ - AssertISV(false, "TSStaticPolysoupConvex::getBoundingBox(m,p) - Not implemented. -- XEA"); - return box; -} - -void TSStaticPolysoupConvex::getPolyList(AbstractPolyList *list) -{ - // Transform the list into object space and set the pointer to the object - MatrixF i( mObject->getTransform() ); - Point3F iS( mObject->getScale() ); - list->setTransform(&i, iS); - list->setObject(mObject); - - // Add only the original collision triangle - S32 base = list->addPoint(verts[0]); - list->addPoint(verts[2]); - list->addPoint(verts[1]); - - list->begin(0, (U32)idx ^ (uintptr_t)mesh); - list->vertex(base + 2); - list->vertex(base + 1); - list->vertex(base + 0); - list->plane(base + 0, base + 1, base + 2); - list->end(); -} - -void TSStaticPolysoupConvex::getFeatures(const MatrixF& mat,const VectorF& n, ConvexFeature* cf) -{ - cf->material = 0; - cf->object = mObject; - - // For a tetrahedron this is pretty easy... first - // convert everything into world space. - Point3F tverts[4]; - mat.mulP(verts[0], &tverts[0]); - mat.mulP(verts[1], &tverts[1]); - mat.mulP(verts[2], &tverts[2]); - mat.mulP(verts[3], &tverts[3]); - - // points... - S32 firstVert = cf->mVertexList.size(); - cf->mVertexList.increment(); cf->mVertexList.last() = tverts[0]; - cf->mVertexList.increment(); cf->mVertexList.last() = tverts[1]; - cf->mVertexList.increment(); cf->mVertexList.last() = tverts[2]; - cf->mVertexList.increment(); cf->mVertexList.last() = tverts[3]; - - // edges... - cf->mEdgeList.increment(); - cf->mEdgeList.last().vertex[0] = firstVert+0; - cf->mEdgeList.last().vertex[1] = firstVert+1; - - cf->mEdgeList.increment(); - cf->mEdgeList.last().vertex[0] = firstVert+1; - cf->mEdgeList.last().vertex[1] = firstVert+2; - - cf->mEdgeList.increment(); - cf->mEdgeList.last().vertex[0] = firstVert+2; - cf->mEdgeList.last().vertex[1] = firstVert+0; - - cf->mEdgeList.increment(); - cf->mEdgeList.last().vertex[0] = firstVert+3; - cf->mEdgeList.last().vertex[1] = firstVert+0; - - cf->mEdgeList.increment(); - cf->mEdgeList.last().vertex[0] = firstVert+3; - cf->mEdgeList.last().vertex[1] = firstVert+1; - - cf->mEdgeList.increment(); - cf->mEdgeList.last().vertex[0] = firstVert+3; - cf->mEdgeList.last().vertex[1] = firstVert+2; - - // triangles... - cf->mFaceList.increment(); - cf->mFaceList.last().normal = PlaneF(tverts[2], tverts[1], tverts[0]); - cf->mFaceList.last().vertex[0] = firstVert+2; - cf->mFaceList.last().vertex[1] = firstVert+1; - cf->mFaceList.last().vertex[2] = firstVert+0; - - cf->mFaceList.increment(); - cf->mFaceList.last().normal = PlaneF(tverts[1], tverts[0], tverts[3]); - cf->mFaceList.last().vertex[0] = firstVert+1; - cf->mFaceList.last().vertex[1] = firstVert+0; - cf->mFaceList.last().vertex[2] = firstVert+3; - - cf->mFaceList.increment(); - cf->mFaceList.last().normal = PlaneF(tverts[2], tverts[1], tverts[3]); - cf->mFaceList.last().vertex[0] = firstVert+2; - cf->mFaceList.last().vertex[1] = firstVert+1; - cf->mFaceList.last().vertex[2] = firstVert+3; - - cf->mFaceList.increment(); - cf->mFaceList.last().normal = PlaneF(tverts[0], tverts[2], tverts[3]); - cf->mFaceList.last().vertex[0] = firstVert+0; - cf->mFaceList.last().vertex[1] = firstVert+2; - cf->mFaceList.last().vertex[2] = firstVert+3; - - // All done! -} - -void TSStatic::onMount( SceneObject *obj, S32 node ) -{ - Parent::onMount(obj, node); - _updateShouldTick(); -} - -void TSStatic::onUnmount( SceneObject *obj, S32 node ) -{ - Parent::onUnmount( obj, node ); - setMaskBits( TransformMask ); - _updateShouldTick(); -} - -//------------------------------------------------------------------------ -//These functions are duplicated in tsStatic and shapeBase. -//They each function a little differently; but achieve the same purpose of gathering -//target names/counts without polluting simObject. - -DefineEngineMethod( TSStatic, getTargetName, const char*, ( S32 index ),(0), - "Get the name of the indexed shape material.\n" - "@param index index of the material to get (valid range is 0 - getTargetCount()-1).\n" - "@return the name of the indexed material.\n" - "@see getTargetCount()\n") -{ - TSStatic *obj = dynamic_cast< TSStatic* > ( object ); - if(obj) - { - // Try to use the client object (so we get the reskinned targets in the Material Editor) - if ((TSStatic*)obj->getClientObject()) - obj = (TSStatic*)obj->getClientObject(); - - return obj->getShapeInstance()->getTargetName(index); - } - - return ""; -} - -DefineEngineMethod( TSStatic, getTargetCount, S32,(),, - "Get the number of materials in the shape.\n" - "@return the number of materials in the shape.\n" - "@see getTargetName()\n") -{ - TSStatic *obj = dynamic_cast< TSStatic* > ( object ); - if(obj) - { - // Try to use the client object (so we get the reskinned targets in the Material Editor) - if ((TSStatic*)obj->getClientObject()) - obj = (TSStatic*)obj->getClientObject(); - - return obj->getShapeInstance()->getTargetCount(); - } - - return -1; -} - -// This method is able to change materials per map to with others. The material that is being replaced is being mapped to -// unmapped_mat as a part of this transition - -DefineEngineMethod( TSStatic, changeMaterial, void, ( const char* mapTo, Material* oldMat, Material* newMat ),("",nullAsType(),nullAsType()), - "@brief Change one of the materials on the shape.\n\n" - - "This method changes materials per mapTo with others. The material that " - "is being replaced is mapped to unmapped_mat as a part of this transition.\n" - - "@note Warning, right now this only sort of works. It doesn't do a live " - "update like it should.\n" - - "@param mapTo the name of the material target to remap (from getTargetName)\n" - "@param oldMat the old Material that was mapped \n" - "@param newMat the new Material to map\n\n" - - "@tsexample\n" - "// remap the first material in the shape\n" - "%mapTo = %obj.getTargetName( 0 );\n" - "%obj.changeMaterial( %mapTo, 0, MyMaterial );\n" - "@endtsexample\n" ) -{ - // if no valid new material, theres no reason for doing this - if( !newMat ) - { - Con::errorf("TSShape::changeMaterial failed: New material does not exist!"); - return; - } - - TSMaterialList* shapeMaterialList = object->getShape()->materialList; - - // Check the mapTo name exists for this shape - S32 matIndex = shapeMaterialList->getMaterialNameList().find_next(String(mapTo)); - if (matIndex < 0) - { - Con::errorf("TSShape::changeMaterial failed: Invalid mapTo name '%s'", mapTo); - return; - } - - // Lets remap the old material off, so as to let room for our current material room to claim its spot - if( oldMat ) - oldMat->mMapTo = String("unmapped_mat"); - - newMat->mMapTo = mapTo; - - // Map the material by name in the matmgr - MATMGR->mapMaterial( mapTo, newMat->getName() ); - - // Replace instances with the new material being traded in. Lets make sure that we only - // target the specific targets per inst, this is actually doing more than we thought - delete shapeMaterialList->mMatInstList[matIndex]; - shapeMaterialList->mMatInstList[matIndex] = newMat->createMatInstance(); - - // Finish up preparing the material instances for rendering - const GFXVertexFormat *flags = getGFXVertexFormat(); - FeatureSet features = MATMGR->getDefaultFeatures(); - shapeMaterialList->getMaterialInst(matIndex)->init(features, flags); -} - -DefineEngineMethod( TSStatic, getModelFile, const char *, (),, - "@brief Get the model filename used by this shape.\n\n" - - "@return the shape filename\n\n" - "@tsexample\n" - "// Acquire the model filename used on this shape.\n" - "%modelFilename = %obj.getModelFile();\n" - "@endtsexample\n" - ) -{ -<<<<<<< HEAD - return object->getShapeFileName(); -======= - return object->getShapeFileName(); ->>>>>>> garagegames/development -} diff --git a/Engine/source/T3D/tsStatic.h b/Engine/source/T3D/tsStatic.h index db1ff138c..40e89c0fc 100644 --- a/Engine/source/T3D/tsStatic.h +++ b/Engine/source/T3D/tsStatic.h @@ -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 _TSSTATIC_H_ #define _TSSTATIC_H_ @@ -236,6 +241,19 @@ public: const Vector& getLOSDetails() const { return mLOSDetails; } +private: + virtual void onStaticModified(const char* slotName, const char*newValue = NULL); +protected: + Vector mDecalDetails; + Vector* mDecalDetailsPtr; +public: + bool mIgnoreZodiacs; + bool mHasGradients; + bool mInvertGradientRange; + Point2F mGradientRangeUser; + Point2F mGradientRange; +private: + void set_special_typing(); }; typedef TSStatic::MeshType TSMeshType; diff --git a/Engine/source/environment/meshRoad.cpp b/Engine/source/environment/meshRoad.cpp index 7fef4a217..fc1619afb 100644 --- a/Engine/source/environment/meshRoad.cpp +++ b/Engine/source/environment/meshRoad.cpp @@ -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 "environment/meshRoad.h" @@ -52,6 +57,8 @@ #include "T3D/physics/physicsCollision.h" #include "environment/nodeListManager.h" +#include "afx/ce/afxZodiacMgr.h" + #define MIN_METERS_PER_SEGMENT 1.0f #define MIN_NODE_DEPTH 0.25f #define MAX_NODE_DEPTH 50.0f @@ -620,6 +627,7 @@ MeshRoad::MeshRoad() mMatInst[Top] = NULL; mMatInst[Bottom] = NULL; mMatInst[Side] = NULL; + mTypeMask |= TerrainLikeObjectType; } MeshRoad::~MeshRoad() @@ -821,6 +829,7 @@ void MeshRoad::prepRenderImage( SceneRenderState* state ) // otherwise obey the smShowRoad flag if ( smShowRoad || !smEditorOpen ) { + afxZodiacMgr::renderMeshRoadZodiacs(state, this); MeshRenderInst coreRI; coreRI.clear(); coreRI.objectToWorld = &MatrixF::Identity; @@ -1379,6 +1388,11 @@ bool MeshRoad::buildSegmentPolyList( AbstractPolyList* polyList, U32 startSegIdx ddraw->setLastTTL( 0 ); } + if (buildPolyList_TopSurfaceOnly) + { + offset += 4; + continue; + } // Left Face polyList->begin( 0,0 ); @@ -2454,3 +2468,16 @@ DefineEngineMethod( MeshRoad, postApply, void, (),, { object->inspectPostApply(); } +bool MeshRoad::buildPolyList_TopSurfaceOnly = false; + +bool MeshRoad::buildTopPolyList(PolyListContext plc, AbstractPolyList* polyList) +{ + static Box3F box_prox; static SphereF ball_prox; + + buildPolyList_TopSurfaceOnly = true; + bool result = buildPolyList(plc, polyList, box_prox, ball_prox); + buildPolyList_TopSurfaceOnly = false; + + return result; +} + diff --git a/Engine/source/environment/meshRoad.h b/Engine/source/environment/meshRoad.h index ed47984b1..06157b343 100644 --- a/Engine/source/environment/meshRoad.h +++ b/Engine/source/environment/meshRoad.h @@ -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 _MESHROAD_H_ #define _MESHROAD_H_ @@ -560,6 +565,10 @@ protected: Convex* mConvexList; Vector mDebugConvex; PhysicsBody *mPhysicsRep; +private: + static bool buildPolyList_TopSurfaceOnly; +public: + bool buildTopPolyList(PolyListContext, AbstractPolyList*); };