Merge branch 'development' of https://github.com/GarageGames/Torque3D into AIExtracts

Conflicts:
	Engine/source/T3D/aiPlayer.cpp
This commit is contained in:
Azaezel 2016-03-02 10:59:10 -06:00
commit 262cc4bac1
293 changed files with 11902 additions and 2097 deletions

View file

@ -564,6 +564,21 @@ bool AIPlayer::getAIMove(Move *movePtr)
}
}
Pose desiredPose = mPose;
if ( mSwimming )
desiredPose = SwimPose;
else if ( mAiPose == 1 && canCrouch() )
desiredPose = CrouchPose;
else if ( mAiPose == 2 && canProne() )
desiredPose = PronePose;
else if ( mAiPose == 3 && canSprint() )
desiredPose = SprintPose;
else if ( canStand() )
desiredPose = StandPose;
setPose( desiredPose );
// Replicate the trigger state into the move so that
// triggers can be controlled from scripts.
for( U32 i = 0; i < MaxTriggerKeys; i++ )
@ -592,12 +607,24 @@ bool AIPlayer::getAIMove(Move *movePtr)
return true;
}
void AIPlayer::updateMove(const Move* move)
void AIPlayer::updateMove(const Move* move)
{
if (!getControllingClient() && isGhost())
return;
Parent::updateMove(move);
}
void AIPlayer::setAiPose( S32 pose )
{
if (!getControllingClient() && isGhost())
return;
mAiPose = pose;
}
Parent::updateMove(move);
S32 AIPlayer::getAiPose()
{
return mAiPose;
}
/**
@ -1397,3 +1424,18 @@ DefineEngineMethod(AIPlayer, getTargetDistance, bool, (ShapeBase* obj, bool chec
{
return object->getTargetDistance(obj, checkEnabled);
}
DefineEngineMethod( AIPlayer, setAiPose, void, ( S32 pose ),,
"@brief Sets the AiPose for an AI object.\n"
"@param pose StandPose=0, CrouchPose=1, PronePose=2, SprintPose=3.\n"
"Uses the new AiPose variable from shapebase (as defined in its PlayerData datablock).\n")
{
object->setAiPose(pose);
}
DefineEngineMethod( AIPlayer, getAiPose, S32, (),,
"@brief Get the object's current AiPose.\n"
"@return StandPose=0, CrouchPose=1, PronePose=2, SprintPose=3.\n")
{
return object->getAiPose();
}

View file

@ -182,7 +182,9 @@ public:
void setMoveDestination( const Point3F &location, bool slowdown );
Point3F getMoveDestination() const { return mMoveDestination; }
void stopMove();
void setAiPose( S32 pose );
S32 getAiPose();
// Trigger sets/gets
void setMoveTrigger( U32 slot, const bool isSet = true );
bool getMoveTrigger( U32 slot ) const;

View file

@ -39,7 +39,7 @@
#endif
#ifndef _TSSHAPE_H_
#include "ts/TSShape.h"
#include "ts/tsShape.h"
#endif
#ifndef __RESOURCE_H__
#include "core/resource.h"

View file

@ -284,6 +284,7 @@ void DecalData::unpackData( BitStream *stream )
Parent::unpackData( stream );
stream->read( &lookupName );
assignName(lookupName);
stream->read( &size );
stream->read( &materialName );
_updateMaterial();

View file

@ -1744,3 +1744,48 @@ DefineEngineFunction( decalManagerRemoveDecal, bool, ( S32 decalID ),,
gDecalManager->removeDecal(inst);
return true;
}
DefineEngineFunction( decalManagerEditDecal, bool, ( S32 decalID, Point3F pos, Point3F normal, F32 rotAroundNormal, F32 decalScale ),,
"Edit specified decal of the decal manager.\n"
"@param decalID ID of the decal to edit.\n"
"@param pos World position for the decal.\n"
"@param normal Decal normal vector (if the decal was a tire lying flat on a "
"surface, this is the vector pointing in the direction of the axle).\n"
"@param rotAroundNormal Angle (in radians) to rotate this decal around its normal vector.\n"
"@param decalScale Scale factor applied to the decal.\n"
"@return Returns true if successful, false if decalID not found.\n"
"" )
{
DecalInstance *decalInstance = gDecalManager->getDecal( decalID );
if( !decalInstance )
return false;
//Internally we need Point3F tangent instead of the user friendly F32 rotAroundNormal
MatrixF mat( true );
MathUtils::getMatrixFromUpVector( normal, &mat );
AngAxisF rot( normal, rotAroundNormal );
MatrixF rotmat;
rot.setMatrix( &rotmat );
mat.mul( rotmat );
Point3F tangent;
mat.getColumn( 1, &tangent );
//if everything is unchanged just do nothing and return "everything is ok"
if ( pos.equal(decalInstance->mPosition) &&
normal.equal(decalInstance->mNormal) &&
tangent.equal(decalInstance->mTangent) &&
mFabs( decalInstance->mSize - (decalInstance->mDataBlock->size * decalScale) ) < POINT_EPSILON )
return true;
decalInstance->mPosition = pos;
decalInstance->mNormal = normal;
decalInstance->mTangent = tangent;
decalInstance->mSize = decalInstance->mDataBlock->size * decalScale;
gDecalManager->clipDecal( decalInstance, NULL, NULL);
gDecalManager->notifyDecalModified( decalInstance );
return true;
}

View file

@ -426,7 +426,7 @@ void fxFoliageReplicator::CreateFoliage(void)
Point3F MaxPoint( 0.5, 0.5, 0.5 );
// Check Host.
AssertFatal(isClientObject(), "Trying to create Foliage on Server, this is bad!")
AssertFatal(isClientObject(), "Trying to create Foliage on Server, this is bad!");
// Cannot continue without Foliage Texture!
if (dStrlen(mFieldData.mFoliageFile) == 0)
@ -1134,7 +1134,7 @@ void fxFoliageReplicator::ProcessQuadrant(fxFoliageQuadrantNode* pParentNode, fx
void fxFoliageReplicator::SyncFoliageReplicators(void)
{
// Check Host.
AssertFatal(isServerObject(), "We *MUST* be on server when Synchronising Foliage!")
AssertFatal(isServerObject(), "We *MUST* be on server when Synchronising Foliage!");
// Find the Replicator Set.
SimSet *fxFoliageSet = dynamic_cast<SimSet*>(Sim::findObject("fxFoliageSet"));
@ -1196,7 +1196,7 @@ void fxFoliageReplicator::DestroyFoliageItems()
void fxFoliageReplicator::DestroyFoliage(void)
{
// Check Host.
AssertFatal(isClientObject(), "Trying to destroy Foliage on Server, this is bad!")
AssertFatal(isClientObject(), "Trying to destroy Foliage on Server, this is bad!");
// Destroy Quad-tree.
mPotentialFoliageNodes = 0;

View file

@ -224,7 +224,7 @@ void fxShapeReplicator::CreateShapes(void)
}
// Check Shapes.
AssertFatal(mCurrentShapeCount==0,"Shapes already present, this should not be possible!")
AssertFatal(mCurrentShapeCount==0,"Shapes already present, this should not be possible!");
// Check that we have a shape...
if (!mFieldData.mShapeFile) return;

View file

@ -3173,18 +3173,21 @@ void Player::updateMove(const Move* move)
// Update the PlayerPose
Pose desiredPose = mPose;
if ( mSwimming )
desiredPose = SwimPose;
else if ( runSurface && move->trigger[sCrouchTrigger] && canCrouch() )
desiredPose = CrouchPose;
else if ( runSurface && move->trigger[sProneTrigger] && canProne() )
desiredPose = PronePose;
else if ( move->trigger[sSprintTrigger] && canSprint() )
desiredPose = SprintPose;
else if ( canStand() )
desiredPose = StandPose;
if ( !mIsAiControlled )
{
if ( mSwimming )
desiredPose = SwimPose;
else if ( runSurface && move->trigger[sCrouchTrigger] && canCrouch() )
desiredPose = CrouchPose;
else if ( runSurface && move->trigger[sProneTrigger] && canProne() )
desiredPose = PronePose;
else if ( move->trigger[sSprintTrigger] && canSprint() )
desiredPose = SprintPose;
else if ( canStand() )
desiredPose = StandPose;
setPose( desiredPose );
setPose( desiredPose );
}
}
@ -4659,9 +4662,9 @@ Point3F Player::_move( const F32 travelTime, Collision *outCol )
}
Point3F distance = end - start;
if (mFabs(distance.x) < mObjBox.len_x() &&
mFabs(distance.y) < mObjBox.len_y() &&
mFabs(distance.z) < mObjBox.len_z())
if (mFabs(distance.x) < mScaledBox.len_x() &&
mFabs(distance.y) < mScaledBox.len_y() &&
mFabs(distance.z) < mScaledBox.len_z())
{
// We can potentially early out of this. If there are no polys in the clipped polylist at our
// end position, then we can bail, and just set start = end;
@ -6186,6 +6189,10 @@ U32 Player::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
{
stream->writeFlag(mFalling);
stream->writeFlag(mSwimming);
stream->writeFlag(mJetting);
stream->writeInt(mPose, NumPoseBits);
stream->writeInt(mState,NumStateBits);
if (stream->writeFlag(mState == RecoverState))
stream->writeInt(mRecoverTicks,PlayerData::RecoverDelayBits);
@ -6282,7 +6289,11 @@ void Player::unpackUpdate(NetConnection *con, BitStream *stream)
if (stream->readFlag()) {
mPredictionCount = sMaxPredictionTicks;
mFalling = stream->readFlag();
mSwimming = stream->readFlag();
mJetting = stream->readFlag();
mPose = (Pose)(stream->readInt(NumPoseBits));
ActionState actionState = (ActionState)stream->readInt(NumStateBits);
if (stream->readFlag()) {
mRecoverTicks = stream->readInt(PlayerData::RecoverDelayBits);
@ -6873,31 +6884,13 @@ void Player::playFootstepSound( bool triggeredLeft, Material* contactMaterial, S
// Play default sound.
S32 sound = -1;
if( contactMaterial && contactMaterial->mFootstepSoundId != -1 )
if (contactMaterial && (contactMaterial->mImpactSoundId>-1 && contactMaterial->mImpactSoundId<PlayerData::MaxSoundOffsets))
sound = contactMaterial->mFootstepSoundId;
else if( contactObject && contactObject->getTypeMask() & VehicleObjectType )
sound = 2;
switch ( sound )
{
case 0: // Soft
SFX->playOnce( mDataBlock->sound[PlayerData::FootSoft], &footMat );
break;
case 1: // Hard
SFX->playOnce( mDataBlock->sound[PlayerData::FootHard], &footMat );
break;
case 2: // Metal
SFX->playOnce( mDataBlock->sound[PlayerData::FootMetal], &footMat );
break;
case 3: // Snow
SFX->playOnce( mDataBlock->sound[PlayerData::FootSnow], &footMat );
break;
/*
default: //Hard
SFX->playOnce( mDataBlock->sound[PlayerData::FootHard], &footMat );
break;
*/
}
if (sound>=0)
SFX->playOnce(mDataBlock->sound[sound], &footMat);
}
}
@ -6922,36 +6915,13 @@ void Player:: playImpactSound()
else
{
S32 sound = -1;
if( material && material->mImpactSoundId )
if (material && (material->mImpactSoundId>-1 && material->mImpactSoundId<PlayerData::MaxSoundOffsets))
sound = material->mImpactSoundId;
else if( rInfo.object->getTypeMask() & VehicleObjectType )
sound = 2; // Play metal;
switch( sound )
{
case 0:
//Soft
SFX->playOnce( mDataBlock->sound[ PlayerData::ImpactSoft ], &getTransform() );
break;
case 1:
//Hard
SFX->playOnce( mDataBlock->sound[ PlayerData::ImpactHard ], &getTransform() );
break;
case 2:
//Metal
SFX->playOnce( mDataBlock->sound[ PlayerData::ImpactMetal ], &getTransform() );
break;
case 3:
//Snow
SFX->playOnce( mDataBlock->sound[ PlayerData::ImpactSnow ], &getTransform() );
break;
/*
default:
//Hard
alxPlay(mDataBlock->sound[PlayerData::ImpactHard], &getTransform());
break;
*/
}
if (sound >= 0)
SFX->playOnce(mDataBlock->sound[PlayerData::ImpactStart + sound], &getTransform());
}
}
}

View file

@ -190,13 +190,15 @@ struct PlayerData: public ShapeBaseData {
FootHard,
FootMetal,
FootSnow,
MaxSoundOffsets,
FootShallowSplash,
FootWading,
FootUnderWater,
FootBubbles,
MoveBubbles,
WaterBreath,
ImpactSoft,
ImpactStart,
ImpactSoft = ImpactStart,
ImpactHard,
ImpactMetal,
ImpactSnow,

View file

@ -156,7 +156,7 @@ bool Rigid::resolveCollision(const Point3F& p, const Point3F &normal, Rigid* rig
return false;
// Compute impulse
F32 d, n = -nv * (1.0f + restitution * rigid->restitution);
F32 d, n = -nv * (2.0f + restitution * rigid->restitution);
Point3F a1,b1,c1;
mCross(r1,normal,&a1);
invWorldInertia.mulV(a1,&b1);
@ -173,7 +173,7 @@ bool Rigid::resolveCollision(const Point3F& p, const Point3F &normal, Rigid* rig
applyImpulse(r1,impulse);
impulse.neg();
applyImpulse(r2,impulse);
rigid->applyImpulse(r2, impulse);
return true;
}

View file

@ -879,6 +879,7 @@ IMPLEMENT_CALLBACK( ShapeBase, validateCameraFov, F32, (F32 fov), (fov),
ShapeBase::ShapeBase()
: mDataBlock( NULL ),
mIsAiControlled( false ),
mAiPose( 0 ),
mControllingObject( NULL ),
mMoveMotion( false ),
mShapeBaseMount( NULL ),

View file

@ -874,6 +874,7 @@ protected:
/// @name Physical Properties
/// @{
S32 mAiPose; ///< Current pose.
F32 mEnergy; ///< Current enery level.
F32 mRechargeRate; ///< Energy recharge rate (in units/tick).

View file

@ -91,6 +91,9 @@ ConsoleDocClass( TSStatic,
);
TSStatic::TSStatic()
:
cubeDescId( 0 ),
reflectorDesc( NULL )
{
mNetFlags.set(Ghostable | ScopeAlways);
@ -186,6 +189,11 @@ void TSStatic::initPersistFields()
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 ),
@ -292,6 +300,14 @@ bool TSStatic::onAdd()
addToScene();
if ( isClientObject() )
{
mCubeReflector.unregisterReflector();
if ( reflectorDesc )
mCubeReflector.registerReflector( this, reflectorDesc );
}
_updateShouldTick();
// Accumulation
@ -357,6 +373,16 @@ bool TSStatic::_createShape()
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;
}
@ -429,6 +455,8 @@ void TSStatic::onRemove()
mShapeInstance = NULL;
mAmbientThread = NULL;
if ( isClientObject() )
mCubeReflector.unregisterReflector();
Parent::onRemove();
}
@ -561,6 +589,12 @@ void TSStatic::prepRenderImage( SceneRenderState* state )
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
@ -577,6 +611,9 @@ void TSStatic::prepRenderImage( SceneRenderState* state )
rdata.setFadeOverride( 1.0f );
rdata.setOriginSort( mUseOriginSort );
if ( mCubeReflector.isEnabled() )
rdata.setCubemap( mCubeReflector.getCubemap() );
// Acculumation
rdata.setAccuTex(mAccuTex);
@ -604,6 +641,20 @@ void TSStatic::prepRenderImage( SceneRenderState* state )
mat.scale( mObjScale );
GFX->setWorldMatrix( mat );
if ( state->isDiffusePass() && mCubeReflector.isEnabled() && mCubeReflector.getOcclusionQuery() )
{
RenderPassManager *pass = state->getRenderPass();
OccluderRenderInst *ri = pass->allocInst<OccluderRenderInst>();
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)
{
@ -715,6 +766,10 @@ U32 TSStatic::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
if ( mLightPlugin )
retMask |= mLightPlugin->packUpdate(this, AdvancedStaticOptionsMask, con, mask, stream);
if( stream->writeFlag( reflectorDesc != NULL ) )
{
stream->writeRangedU32( reflectorDesc->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast );
}
return retMask;
}
@ -782,6 +837,11 @@ void TSStatic::unpackUpdate(NetConnection *con, BitStream *stream)
mLightPlugin->unpackUpdate(this, con, stream);
}
if( stream->readFlag() )
{
cubeDescId = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );
}
if ( isProperlyAdded() )
_updateShouldTick();
}

View file

@ -39,6 +39,10 @@
#include "ts/tsShape.h"
#endif
#ifndef _REFLECTOR_H_
#include "scene/reflector.h"
#endif
class TSShapeInstance;
class TSThread;
class TSStatic;
@ -147,6 +151,11 @@ protected:
/// Start or stop processing ticks depending on our state.
void _updateShouldTick();
String cubeDescName;
U32 cubeDescId;
ReflectorDesc *reflectorDesc;
CubeReflector mCubeReflector;
protected:
Convex *mConvexList;

View file

@ -202,6 +202,26 @@ DefineConsoleFunction( getRealTime, S32, (), , "()"
return Platform::getRealMilliseconds();
}
ConsoleFunction( getLocalTime, const char *, 1, 1, "Return the current local time as: weekday month day year hour min sec.\n\n"
"Local time is platform defined.")
{
Platform::LocalTime lt;
Platform::getLocalTime(lt);
static const U32 bufSize = 128;
char *retBuffer = Con::getReturnBuffer(bufSize);
dSprintf(retBuffer, bufSize, "%d %d %d %d %02d %02d %02d",
lt.weekday,
lt.month + 1,
lt.monthday,
lt.year + 1900,
lt.hour,
lt.min,
lt.sec);
return retBuffer;
}
ConsoleFunctionGroupEnd(Platform);
//-----------------------------------------------------------------------------

View file

@ -27,6 +27,7 @@
#include "console/consoleInternal.h"
#include "core/strings/stringUnit.h"
#include "console/engineAPI.h"
#include "core/stream/fileStream.h"
TCPObject *TCPObject::table[TCPObject::TableSize] = {0, };
@ -138,6 +139,15 @@ IMPLEMENT_CALLBACK(TCPObject, onLine, void, (const char* line), (line),
"@param line Data sent from the server.\n"
);
IMPLEMENT_CALLBACK(TCPObject, onPacket, bool, (const char* data), (data),
"@brief Called when we get a packet with no newlines or nulls (probably websocket).\n\n"
"@param data Data sent from the server.\n"
"@return true if script handled the packet.\n"
);
IMPLEMENT_CALLBACK(TCPObject, onEndReceive, void, (), (),
"@brief Called when we are done reading all lines.\n\n"
);
IMPLEMENT_CALLBACK(TCPObject, onDNSResolved, void, (),(),
"Called whenever the DNS has been resolved.\n"
);
@ -355,7 +365,7 @@ void TCPObject::onConnectFailed()
onConnectFailed_callback();
}
void TCPObject::finishLastLine()
bool TCPObject::finishLastLine()
{
if(mBufferSize)
{
@ -364,6 +374,25 @@ void TCPObject::finishLastLine()
dFree(mBuffer);
mBuffer = 0;
mBufferSize = 0;
return true;
}
return false;
}
bool TCPObject::isBufferEmpty()
{
return (mBufferSize <= 0);
}
void TCPObject::emptyBuffer()
{
if(mBufferSize)
{
dFree(mBuffer);
mBuffer = 0;
mBufferSize = 0;
}
}
@ -400,6 +429,25 @@ void TCPObject::send(const U8 *buffer, U32 len)
Net::sendtoSocket(mTag, buffer, S32(len));
}
bool TCPObject::sendFile(const char* fileName)
{
//Open the file for reading
FileStream readFile;
if(!readFile.open(fileName, Torque::FS::File::Read))
{
return false;
}
//Read each byte into our buffer
Vector<U8> buffer(readFile.getStreamSize());
readFile.read(buffer.size(), &buffer);
//Send the buffer
send(buffer.address(), buffer.size());
return true;
}
DefineEngineMethod(TCPObject, send, void, (const char *data),,
"@brief Transmits the data string to the connected computer.\n\n"
@ -421,6 +469,20 @@ DefineEngineMethod(TCPObject, send, void, (const char *data),,
object->send( (const U8*)data, dStrlen(data) );
}
DefineEngineMethod(TCPObject, sendFile, bool, (const char *fileName),,
"@brief Transmits the file in binary to the connected computer.\n\n"
"@param fileName The filename of the file to transfer.\n")
{
return object->sendFile(fileName);
}
DefineEngineMethod(TCPObject, finishLastLine, void, (),,
"@brief Eat the rest of the lines.\n")
{
object->finishLastLine();
}
DefineEngineMethod(TCPObject, listen, void, (U32 port),,
"@brief Start listening on the specified port for connections.\n\n"
@ -499,6 +561,29 @@ void processConnectedReceiveEvent(NetSocket sock, RawData incomingData)
size -= ret;
buffer += ret;
}
//If our buffer now has something in it then it's probably a web socket packet and lets handle it
if(!tcpo->isBufferEmpty())
{
//Copy all the data into a string (may be a quicker way of doing this)
U8 *data = (U8*)incomingData.data;
String temp;
for(S32 i = 0; i < incomingData.size; i++)
{
temp += data[i];
}
//Send the packet to script
bool handled = tcpo->onPacket_callback(temp);
//If the script did something with it, clear the buffer
if(handled)
{
tcpo->emptyBuffer();
}
}
tcpo->onEndReceive_callback();
}
void processConnectedAcceptEvent(NetSocket listeningPort, NetSocket newConnection, NetAddress originatingAddress)

View file

@ -36,6 +36,8 @@ public:
DECLARE_CALLBACK(void, onConnectionRequest, (const char* address, const char* ID));
DECLARE_CALLBACK(void, onLine, (const char* line));
DECLARE_CALLBACK(bool, onPacket, (const char* data));
DECLARE_CALLBACK(void, onEndReceive, ());
DECLARE_CALLBACK(void, onDNSResolved,());
DECLARE_CALLBACK(void, onDNSFailed, ());
DECLARE_CALLBACK(void, onConnected, ());
@ -60,7 +62,9 @@ public:
virtual ~TCPObject();
void parseLine(U8 *buffer, U32 *start, U32 bufferLen);
void finishLastLine();
bool finishLastLine();
bool isBufferEmpty();
void emptyBuffer();
static TCPObject *find(NetSocket tag);
@ -81,6 +85,12 @@ public:
bool processArguments(S32 argc, ConsoleValueRef *argv);
void send(const U8 *buffer, U32 bufferLen);
///Send an entire file over tcp
///@arg fileName Full path to file you want to send
///@return true if file was sent, false if not (file doesn't exist)
bool sendFile(const char* fileName);
void addToTable(NetSocket newTag);
void removeFromTable();

View file

@ -61,7 +61,7 @@ CodeBlock::CodeBlock()
CodeBlock::~CodeBlock()
{
// Make sure we aren't lingering in the current code block...
AssertFatal(smCurrentCodeBlock != this, "CodeBlock::~CodeBlock - Caught lingering in smCurrentCodeBlock!")
AssertFatal(smCurrentCodeBlock != this, "CodeBlock::~CodeBlock - Caught lingering in smCurrentCodeBlock!");
if(name)
removeFromCodeList();

View file

@ -25,6 +25,11 @@
#include "console/consoleInternal.h"
#include "console/engineAPI.h"
#include "console/ast.h"
#ifndef _CONSOLFUNCTIONS_H_
#include "console/consoleFunctions.h"
#endif
#include "core/strings/findMatch.h"
#include "core/strings/stringUnit.h"
#include "core/strings/unicode.h"
@ -32,7 +37,11 @@
#include "console/compiler.h"
#include "platform/platformInput.h"
#include "core/util/journal/journal.h"
#include "gfx/gfxEnums.h"
#include "core/util/uuid.h"
#include "core/color.h"
#include "math/mPoint3.h"
#include "math/mathTypes.h"
// This is a temporary hack to get tools using the library to
// link in this module which contains no other references.
@ -41,6 +50,132 @@ bool LinkConsoleFunctions = false;
// Buffer for expanding script filenames.
static char scriptFilenameBuffer[1024];
bool isInt(const char* str)
{
int len = dStrlen(str);
if(len <= 0)
return false;
// Ignore whitespace
int start = 0;
for(int i = start; i < len; i++)
if(str[i] != ' ')
{
start = i;
break;
}
for(int i = start; i < len; i++)
switch(str[i])
{
case '+': case '-':
if(i != 0)
return false;
break;
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0':
break;
case ' ': // ignore whitespace
for(int j = i+1; j < len; j++)
if(str[j] != ' ')
return false;
return true;
break;
default:
return false;
}
return true;
}
bool isFloat(const char* str, bool sciOk = false)
{
int len = dStrlen(str);
if(len <= 0)
return false;
// Ingore whitespace
int start = 0;
for(int i = start; i < len; i++)
if(str[i] != ' ')
{
start = i;
break;
}
bool seenDot = false;
int eLoc = -1;
for(int i = 0; i < len; i++)
switch(str[i])
{
case '+': case '-':
if(sciOk)
{
//Haven't found e or scientific notation symbol
if(eLoc == -1)
{
//only allowed in beginning
if(i != 0)
return false;
}
else
{
//if not right after the e
if(i != (eLoc + 1))
return false;
}
}
else
{
//only allowed in beginning
if(i != 0)
return false;
}
break;
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0':
break;
case 'e': case 'E':
if(!sciOk)
return false;
else
{
//already saw it so can't have 2
if(eLoc != -1)
return false;
eLoc = i;
}
break;
case '.':
if(seenDot | (sciOk && eLoc != -1))
return false;
seenDot = true;
break;
case ' ': // ignore whitespace
for(int j = i+1; j < len; j++)
if(str[j] != ' ')
return false;
return true;
break;
default:
return false;
}
return true;
}
bool isValidIP(const char* ip)
{
unsigned b1, b2, b3, b4;
unsigned char c;
int rc = dSscanf(ip, "%3u.%3u.%3u.%3u%c", &b1, &b2, &b3, &b4, &c);
if (rc != 4 && rc != 5) return false;
if ((b1 | b2 | b3 | b4) > 255) return false;
if (dStrspn(ip, "0123456789.") < dStrlen(ip)) return false;
return true;
}
bool isValidPort(U16 port)
{
return (port >= 0 && port <=65535);
}
//=============================================================================
// String Functions.
@ -235,6 +370,40 @@ DefineConsoleFunction( strlen, S32, ( const char* str ),,
return dStrlen( str );
}
//-----------------------------------------------------------------------------
DefineConsoleFunction( strlenskip, S32, ( const char* str, const char* first, const char* last ),,
"Calculate the length of a string in characters, skipping everything between and including first and last.\n"
"@param str A string.\n"
"@param first First character to look for to skip block of text.\n"
"@param last Second character to look for to skip block of text.\n"
"@return The length of the given string skipping blocks of text between characters.\n"
"@ingroup Strings" )
{
const UTF8* pos = str;
U32 size = 0;
U32 length = dStrlen(str);
bool count = true;
//loop through each character counting each character, skipping tags (anything with < followed by >)
for(U32 i = 0; i < length; i++, pos++)
{
if(count)
{
if(*pos == first[0])
count = false;
else
size++;
}
else
{
if(*pos == last[0])
count = true;
}
}
return S32(size);
}
//-----------------------------------------------------------------------------
DefineConsoleFunction( strstr, S32, ( const char* string, const char* substring ),,
@ -281,6 +450,33 @@ DefineConsoleFunction( strpos, S32, ( const char* haystack, const char* needle,
//-----------------------------------------------------------------------------
DefineConsoleFunction( strposr, S32, ( const char* haystack, const char* needle, S32 offset ), ( 0 ),
"Find the start of @a needle in @a haystack searching from right to left beginning at the given offset.\n"
"@param haystack The string to search.\n"
"@param needle The string to search for.\n"
"@return The index at which the first occurrence of @a needle was found in @a heystack or -1 if no match was found.\n\n"
"@tsexample\n"
"strposr( \"b ab\", \"b\", 1 ) // Returns 2.\n"
"@endtsexample\n"
"@ingroup Strings" )
{
U32 sublen = dStrlen( needle );
U32 strlen = dStrlen( haystack );
S32 start = strlen - offset;
if(start < 0 || start > strlen)
return -1;
if (start + sublen > strlen)
start = strlen - sublen;
for(; start >= 0; start--)
if(!dStrncmp(haystack + start, needle, sublen))
return start;
return -1;
}
//-----------------------------------------------------------------------------
DefineConsoleFunction( ltrim, const char*, ( const char* str ),,
"Remove leading whitespace from the string.\n"
"@param str A string.\n"
@ -627,6 +823,18 @@ DefineConsoleFunction( stripTrailingNumber, String, ( const char* str ),,
return String::GetTrailingNumber( str, suffix );
}
//-----------------------------------------------------------------------------
DefineConsoleFunction( getFirstNumber, String, ( const char* str ),,
"Get the first occuring number from @a str.\n"
"@param str The string from which to read out the first number.\n"
"@return String representation of the number or "" if no number.\n\n")
{
U32 start;
U32 end;
return String::GetFirstNumber(str, start, end);
}
//----------------------------------------------------------------
DefineConsoleFunction( isspace, bool, ( const char* str, S32 index ),,
@ -811,6 +1019,192 @@ DefineConsoleFunction( strrchrpos, S32, ( const char* str, const char* chr, S32
return index;
}
//----------------------------------------------------------------
DefineConsoleFunction(ColorFloatToInt, ColorI, (ColorF color), ,
"Convert from a float color to an integer color (0.0 - 1.0 to 0 to 255).\n"
"@param color Float color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha.\n"
"@return Converted color value (0 - 255)\n\n"
"@tsexample\n"
"ColorFloatToInt( \"0 0 1 0.5\" ) // Returns \"0 0 255 128\".\n"
"@endtsexample\n"
"@ingroup Strings")
{
return (ColorI)color;
}
DefineConsoleFunction(ColorIntToFloat, ColorF, (ColorI color), ,
"Convert from a integer color to an float color (0 to 255 to 0.0 - 1.0).\n"
"@param color Integer color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha.\n"
"@return Converted color value (0.0 - 1.0)\n\n"
"@tsexample\n"
"ColorIntToFloat( \"0 0 255 128\" ) // Returns \"0 0 1 0.5\".\n"
"@endtsexample\n"
"@ingroup Strings")
{
return (ColorF)color;
}
DefineConsoleFunction(ColorRGBToHEX, const char*, (ColorI color), ,
"Convert from a integer RGB (red, green, blue) color to hex color value (0 to 255 to 00 - FF).\n"
"@param color Integer color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha. It excepts an alpha, but keep in mind this will not be converted.\n"
"@return Hex color value (#000000 - #FFFFFF), alpha isn't handled/converted so it is only the RGB value\n\n"
"@tsexample\n"
"ColorRBGToHEX( \"0 0 255 128\" ) // Returns \"#0000FF\".\n"
"@endtsexample\n"
"@ingroup Strings")
{
return Con::getReturnBuffer(color.getHex());
}
DefineConsoleFunction(ColorRGBToHSB, const char*, (ColorI color), ,
"Convert from a integer RGB (red, green, blue) color to HSB (hue, saturation, brightness). HSB is also know as HSL or HSV as well, with the last letter standing for lightness or value.\n"
"@param color Integer color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha. It excepts an alpha, but keep in mind this will not be converted.\n"
"@return HSB color value, alpha isn't handled/converted so it is only the RGB value\n\n"
"@tsexample\n"
"ColorRBGToHSB( \"0 0 255 128\" ) // Returns \"240 100 100\".\n"
"@endtsexample\n"
"@ingroup Strings")
{
ColorI::Hsb hsb(color.getHSB());
String s(String::ToString(hsb.hue) + " " + String::ToString(hsb.sat) + " " + String::ToString(hsb.brightness));
return Con::getReturnBuffer(s);
}
DefineConsoleFunction(ColorHEXToRGB, ColorI, (const char* hex), ,
"Convert from a hex color value to an integer RGB (red, green, blue) color (00 - FF to 0 to 255).\n"
"@param hex Hex color value (#000000 - #FFFFFF) to be converted to an RGB (red, green, blue) value.\n"
"@return Integer color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha. Alpha isn't handled/converted so only pay attention to the RGB value\n\n"
"@tsexample\n"
"ColorHEXToRGB( \"#0000FF\" ) // Returns \"0 0 255 0\".\n"
"@endtsexample\n"
"@ingroup Strings")
{
S32 rgb = dAtoui(hex, 16);
ColorI color;
color.set(rgb & 0x000000FF, (rgb & 0x0000FF00) >> 8, (rgb & 0x00FF0000) >> 16);
return color;
}
DefineConsoleFunction(ColorHSBToRGB, ColorI, (Point3I hsb), ,
"Convert from a HSB (hue, saturation, brightness) to an integer RGB (red, green, blue) color. HSB is also know as HSL or HSV as well, with the last letter standing for lightness or value.\n"
"@param hsb HSB (hue, saturation, brightness) value to be converted.\n"
"@return Integer color value to be converted in the form \"R G B A\", where R is red, G is green, B is blue, and A is alpha. Alpha isn't handled/converted so only pay attention to the RGB value\n\n"
"@tsexample\n"
"ColorHSBToRGB( \"240 100 100\" ) // Returns \"0 0 255 0\".\n"
"@endtsexample\n"
"@ingroup Strings")
{
ColorI color;
color.set(ColorI::Hsb(hsb.x, hsb.y, hsb.z));
return color;
}
//----------------------------------------------------------------
DefineConsoleFunction( strToggleCaseToWords, const char*, ( const char* str ),,
"Parse a Toggle Case word into separate words.\n"
"@param str The string to parse.\n"
"@return new string space separated.\n\n"
"@tsexample\n"
"strToggleCaseToWords( \"HelloWorld\" ) // Returns \"Hello World\".\n"
"@endtsexample\n"
"@ingroup Strings" )
{
String newStr;
for(S32 i = 0; str[i]; i++)
{
//If capitol add a space
if(i != 0 && str[i] >= 65 && str[i] <= 90)
newStr += " ";
newStr += str[i];
}
return Con::getReturnBuffer(newStr);
}
//----------------------------------------------------------------
// Warning: isInt and isFloat are very 'strict' and might need to be adjusted to allow other values. //seanmc
DefineConsoleFunction( isInt, bool, ( const char* str),,
"Returns true if the string is an integer.\n"
"@param str The string to test.\n"
"@return true if @a str is an integer and false if not\n\n"
"@tsexample\n"
"isInt( \"13\" ) // Returns true.\n"
"@endtsexample\n"
"@ingroup Strings" )
{
return isInt(str);
}
//----------------------------------------------------------------
DefineConsoleFunction( isFloat, bool, ( const char* str, bool sciOk), (false),
"Returns true if the string is a float.\n"
"@param str The string to test.\n"
"@param sciOk Test for correct scientific notation and accept it (ex. 1.2e+14)"
"@return true if @a str is a float and false if not\n\n"
"@tsexample\n"
"isFloat( \"13.5\" ) // Returns true.\n"
"@endtsexample\n"
"@ingroup Strings" )
{
return isFloat(str, sciOk);
}
//----------------------------------------------------------------
DefineConsoleFunction( isValidPort, bool, ( const char* str),,
"Returns true if the string is a valid port number.\n"
"@param str The string to test.\n"
"@return true if @a str is a port and false if not\n\n"
"@tsexample\n"
"isValidPort( \"8080\" ) // Returns true.\n"
"@endtsexample\n"
"@ingroup Strings" )
{
if(isInt(str))
{
U16 port = dAtous(str);
return isValidPort(port);
}
else
return false;
}
//----------------------------------------------------------------
DefineConsoleFunction( isValidIP, bool, ( const char* str),,
"Returns true if the string is a valid ip address, excepts localhost.\n"
"@param str The string to test.\n"
"@return true if @a str is a valid ip address and false if not\n\n"
"@tsexample\n"
"isValidIP( \"localhost\" ) // Returns true.\n"
"@endtsexample\n"
"@ingroup Strings" )
{
if(dStrcmp(str, "localhost") == 0)
{
return true;
}
else
return isValidIP(str);
}
//----------------------------------------------------------------
// Torque won't normally add another string if it already exists with another casing,
// so this forces the addition. It should be called once near the start, such as in main.cs.
ConsoleFunction(addCaseSensitiveStrings,void,2,0,"[string1, string2, ...]"
"Adds case sensitive strings to the StringTable.")
{
for(int i = 1; i < argc; i++)
StringTable->insert(argv[i], true);
}
//=============================================================================
// Field Manipulators.
//=============================================================================
@ -829,6 +1223,7 @@ DefineConsoleFunction( getWord, const char*, ( const char* text, S32 index ),,
"@endtsexample\n\n"
"@see getWords\n"
"@see getWordCount\n"
"@see getToken\n"
"@see getField\n"
"@see getRecord\n"
"@ingroup FieldManip" )
@ -852,6 +1247,7 @@ DefineConsoleFunction( getWords, const char*, ( const char* text, S32 startIndex
"@endtsexample\n\n"
"@see getWord\n"
"@see getWordCount\n"
"@see getTokens\n"
"@see getFields\n"
"@see getRecords\n"
"@ingroup FieldManip" )
@ -876,6 +1272,7 @@ DefineConsoleFunction( setWord, const char*, ( const char* text, S32 index, cons
"setWord( \"a b c d\", 2, \"f\" ) // Returns \"a b f d\"\n"
"@endtsexample\n\n"
"@see getWord\n"
"@see setToken\n"
"@see setField\n"
"@see setRecord\n"
"@ingroup FieldManip" )
@ -895,6 +1292,7 @@ DefineConsoleFunction( removeWord, const char*, ( const char* text, S32 index ),
"@tsexample\n"
"removeWord( \"a b c d\", 2 ) // Returns \"a b d\"\n"
"@endtsexample\n\n"
"@see removeToken\n"
"@see removeField\n"
"@see removeRecord\n"
"@ingroup FieldManip" )
@ -912,6 +1310,7 @@ DefineConsoleFunction( getWordCount, S32, ( const char* text ),,
"@tsexample\n"
"getWordCount( \"a b c d e\" ) // Returns 5\n"
"@endtsexample\n\n"
"@see getTokenCount\n"
"@see getFieldCount\n"
"@see getRecordCount\n"
"@ingroup FieldManip" )
@ -921,6 +1320,49 @@ DefineConsoleFunction( getWordCount, S32, ( const char* text ),,
//-----------------------------------------------------------------------------
DefineEngineFunction( monthNumToStr, String, ( S32 num, bool abbreviate ), (false),
"@brief returns month as a word given a number or \"\" if number is bad"
"@return month as a word given a number or \"\" if number is bad"
"@ingroup FileSystem")
{
switch(num)
{
case 1: return abbreviate ? "Jan" : "January"; break;
case 2: return abbreviate ? "Feb" : "February"; break;
case 3: return abbreviate ? "Mar" : "March"; break;
case 4: return abbreviate ? "Apr" : "April"; break;
case 5: return "May"; break;
case 6: return abbreviate ? "Jun" : "June"; break;
case 7: return abbreviate ? "Jul" : "July"; break;
case 8: return abbreviate ? "Aug" : "August"; break;
case 9: return abbreviate ? "Sep" : "September"; break;
case 10: return abbreviate ? "Oct" : "October"; break;
case 11: return abbreviate ? "Nov" : "November"; break;
case 12: return abbreviate ? "Dec" : "December"; break;
default: return "";
}
}
DefineEngineFunction( weekdayNumToStr, String, ( S32 num, bool abbreviate ), (false),
"@brief returns weekday as a word given a number or \"\" if number is bad"
"@return weekday as a word given a number or \"\" if number is bad"
"@ingroup FileSystem")
{
switch(num)
{
case 0: return abbreviate ? "Sun" : "Sunday"; break;
case 1: return abbreviate ? "Mon" : "Monday"; break;
case 2: return abbreviate ? "Tue" : "Tuesday"; break;
case 3: return abbreviate ? "Wed" : "Wednesday"; break;
case 4: return abbreviate ? "Thu" : "Thursday"; break;
case 5: return abbreviate ? "Fri" : "Friday"; break;
case 6: return abbreviate ? "Sat" : "Saturday"; break;
default: return "";
}
}
//-----------------------------------------------------------------------------
DefineConsoleFunction( getField, const char*, ( const char* text, S32 index ),,
"Extract the field at the given @a index in the newline and/or tab separated list in @a text.\n"
"Fields in @a text must be separated by newlines and/or tabs.\n"
@ -1242,6 +1684,114 @@ DefineConsoleFunction( nextToken, const char*, ( const char* str1, const char* t
return ret;
}
//-----------------------------------------------------------------------------
DefineConsoleFunction( getToken, const char*, ( const char* text, const char* delimiters, S32 index ),,
"Extract the substring at the given @a index in the @a delimiters separated list in @a text.\n"
"@param text A @a delimiters list of substrings.\n"
"@param delimiters Character or characters that separate the list of substrings in @a text.\n"
"@param index The zero-based index of the substring to extract.\n"
"@return The substring at the given index or \"\" if the index is out of range.\n\n"
"@tsexample\n"
"getToken( \"a b c d\", \" \", 2 ) // Returns \"c\"\n"
"@endtsexample\n\n"
"@see getTokens\n"
"@see getTokenCount\n"
"@see getWord\n"
"@see getField\n"
"@see getRecord\n"
"@ingroup FieldManip" )
{
return Con::getReturnBuffer( StringUnit::getUnit(text, index, delimiters));
}
//-----------------------------------------------------------------------------
DefineConsoleFunction( getTokens, const char*, ( const char* text, const char* delimiters, S32 startIndex, S32 endIndex ), ( -1 ),
"Extract a range of substrings separated by @a delimiters at the given @a startIndex onwards thru @a endIndex.\n"
"@param text A @a delimiters list of substrings.\n"
"@param delimiters Character or characters that separate the list of substrings in @a text.\n"
"@param startIndex The zero-based index of the first substring to extract from @a text.\n"
"@param endIndex The zero-based index of the last substring to extract from @a text. If this is -1, all words beginning "
"with @a startIndex are extracted from @a text.\n"
"@return A string containing the specified range of substrings from @a text or \"\" if @a startIndex "
"is out of range or greater than @a endIndex.\n\n"
"@tsexample\n"
"getTokens( \"a b c d\", \" \", 1, 2, ) // Returns \"b c\"\n"
"@endtsexample\n\n"
"@see getToken\n"
"@see getTokenCount\n"
"@see getWords\n"
"@see getFields\n"
"@see getRecords\n"
"@ingroup FieldManip" )
{
if( endIndex < 0 )
endIndex = 1000000;
return Con::getReturnBuffer( StringUnit::getUnits( text, startIndex, endIndex, delimiters ) );
}
//-----------------------------------------------------------------------------
DefineConsoleFunction( setToken, const char*, ( const char* text, const char* delimiters, S32 index, const char* replacement ),,
"Replace the substring in @a text separated by @a delimiters at the given @a index with @a replacement.\n"
"@param text A @a delimiters list of substrings.\n"
"@param delimiters Character or characters that separate the list of substrings in @a text.\n"
"@param index The zero-based index of the substring to replace.\n"
"@param replacement The string with which to replace the substring.\n"
"@return A new string with the substring at the given @a index replaced by @a replacement or the original "
"string if @a index is out of range.\n\n"
"@tsexample\n"
"setToken( \"a b c d\", \" \", 2, \"f\" ) // Returns \"a b f d\"\n"
"@endtsexample\n\n"
"@see getToken\n"
"@see setWord\n"
"@see setField\n"
"@see setRecord\n"
"@ingroup FieldManip" )
{
return Con::getReturnBuffer( StringUnit::setUnit( text, index, replacement, delimiters) );
}
//-----------------------------------------------------------------------------
DefineConsoleFunction( removeToken, const char*, ( const char* text, const char* delimiters, S32 index ),,
"Remove the substring in @a text separated by @a delimiters at the given @a index.\n"
"@param text A @a delimiters list of substrings.\n"
"@param delimiters Character or characters that separate the list of substrings in @a text.\n"
"@param index The zero-based index of the word in @a text.\n"
"@return A new string with the substring at the given index removed or the original string if @a index is "
"out of range.\n\n"
"@tsexample\n"
"removeToken( \"a b c d\", \" \", 2 ) // Returns \"a b d\"\n"
"@endtsexample\n\n"
"@see removeWord\n"
"@see removeField\n"
"@see removeRecord\n"
"@ingroup FieldManip" )
{
return Con::getReturnBuffer( StringUnit::removeUnit( text, index, delimiters ) );
}
//-----------------------------------------------------------------------------
DefineConsoleFunction( getTokenCount, S32, ( const char* text, const char* delimiters),,
"Return the number of @a delimiters substrings in @a text.\n"
"@param text A @a delimiters list of substrings.\n"
"@param delimiters Character or characters that separate the list of substrings in @a text.\n"
"@return The number of @a delimiters substrings in @a text.\n\n"
"@tsexample\n"
"getTokenCount( \"a b c d e\", \" \" ) // Returns 5\n"
"@endtsexample\n\n"
"@see getWordCount\n"
"@see getFieldCount\n"
"@see getRecordCount\n"
"@ingroup FieldManip" )
{
return StringUnit::getUnitCount( text, delimiters );
}
//=============================================================================
// Tagged Strings.
//=============================================================================
@ -2597,3 +3147,10 @@ DefineEngineFunction( isToolBuild, bool, (),,
return false;
#endif
}
DefineEngineFunction( getMaxDynamicVerts, S32, (),,
"Get max number of allowable dynamic vertices in a single vertex buffer.\n\n"
"@return the max number of allowable dynamic vertices in a single vertex buffer" )
{
return MAX_DYNAMIC_VERTS / 2;
}

View file

@ -0,0 +1,16 @@
#ifndef _CONSOLFUNCTIONS_H_
#define _CONSOLFUNCTIONS_H_
#ifndef _STRINGFUNCTIONS_H_
#include "core/strings/stringFunctions.h"
#endif
bool isInt(const char* str);
bool isFloat(const char* str);
bool isValidIP(const char* ip);
bool isValidPort(U16 port);
#endif

View file

@ -48,7 +48,7 @@
#include "console/simObjectRef.h"
#endif
#ifndef TINYXML_INCLUDED
#include "tinyXML/tinyxml.h"
#include "tinyxml.h"
#endif
/// @file
@ -212,7 +212,7 @@ public:
///
/// @param conIdPtr Pointer to the static S32 console ID.
/// @param conTypeName Console type name.
AbstractClassRep( S32* conIdPtr, const char* typeName )
AbstractClassRep( S32* conIdPtr, const char* typeName )
: Parent( sizeof( void* ), conIdPtr, typeName )
{
VECTOR_SET_ASSOCIATION( mFieldList );
@ -323,13 +323,13 @@ public:
/// Return the namespace that contains the methods of this class.
Namespace* getNameSpace() const { return mNamespace; }
/// Return the AbstractClassRep of the class that this class is derived from.
AbstractClassRep* getParentClass() const { return parentClass; }
virtual AbstractClassRep* getContainerChildClass(const bool recurse) = 0;
virtual WriteCustomTamlSchema getCustomTamlSchema(void) = 0;
/// Return the size of instances of this class in bytes.
S32 getSizeof() const { return mClassSizeof; }
@ -396,7 +396,7 @@ protected:
Namespace * mNamespace;
/// @}
public:
bool mIsRenderEnabled;
@ -404,23 +404,23 @@ public:
bool isRenderEnabled() const { return mIsRenderEnabled; }
bool isSelectionEnabled() const { return mIsSelectionEnabled; }
/// @name Categories
/// @{
protected:
const char* mCategory;
const char* mDescription;
public:
/// Return the space separated category path for the class.
const char* getCategory() const { return mCategory; }
/// Return a short description string suitable for displaying in tooltips.
const char* getDescription() const { return mDescription; }
/// @}
/// @name Fields
@ -434,16 +434,12 @@ public:
/// This is a function pointer typedef to support optional writing for fields.
typedef bool(*WriteDataNotify)(void* obj, StringTableEntry pFieldName);
/// Allows the writing of a custom TAML schema.
typedef void(*WriteCustomTamlSchema)(const AbstractClassRep* pClassRep, TiXmlElement* pParentElement);
/// These are special field type values used to mark
/// groups and arrays in the field list.
/// @see Field::type
/// @see addArray, endArray
/// @see addGroup, endGroup
/// @see addGroup, endGroup
/// @see addGroup, endGroup
/// @see addGroup, endGroup
/// @see addDeprecatedField
enum ACRFieldTypes
{
@ -451,35 +447,35 @@ public:
/// types greater or equal to this one are not
/// console data types.
ARCFirstCustomField = 0xFFFFFFFB,
/// Marks the start of a fixed size array of fields.
/// @see addArray
StartArrayFieldType = 0xFFFFFFFB,
/// Marks the end of a fixed size array of fields.
/// @see endArray
EndArrayFieldType = 0xFFFFFFFC,
/// Marks the beginning of a group of fields.
/// @see addGroup
StartGroupFieldType = 0xFFFFFFFD,
/// Marks the beginning of a group of fields.
/// @see endGroup
EndGroupFieldType = 0xFFFFFFFE,
/// Marks a field that is depreciated and no
/// Marks a field that is depreciated and no
/// longer stores a value.
/// @see addDeprecatedField
DeprecatedFieldType = 0xFFFFFFFF
};
enum FieldFlags
{
FIELD_HideInInspectors = BIT( 0 ), ///< Do not show the field in inspectors.
};
struct Field
struct Field
{
Field()
: pFieldname( NULL ),
@ -525,10 +521,10 @@ public:
/// @name Console Type Interface
/// @{
virtual void* getNativeVariable() { return new ( AbstractClassRep* ); } // Any pointer-sized allocation will do.
virtual void deleteNativeVariable( void* var ) { delete reinterpret_cast< AbstractClassRep** >( var ); }
/// @}
/// @name Abstract Class Database
@ -571,122 +567,141 @@ extern AbstractClassRep::FieldList sg_tempFieldList;
/// @see AbtractClassRep
/// @see ConsoleObject
template< class T >
class ConcreteClassRep : public AbstractClassRep
class ConcreteAbstractClassRep : public AbstractClassRep
{
public:
static EnginePropertyTable _smPropertyTable;
static EnginePropertyTable& smPropertyTable;
ConcreteClassRep( const char* name,
const char* conTypeName,
S32* conTypeIdPtr,
S32 netClassGroupMask,
S32 netClassType,
S32 netEventDir,
AbstractClassRep* parent,
const char* ( *parentDesc )() )
: AbstractClassRep( conTypeIdPtr, conTypeName )
public:
virtual AbstractClassRep* getContainerChildClass(const bool recurse)
{
// Fetch container children type.
AbstractClassRep* pChildren = T::getContainerChildStaticClassRep();
if (!recurse || pChildren != NULL)
return pChildren;
// Fetch parent type.
AbstractClassRep* pParent = T::getParentStaticClassRep();
if (pParent == NULL)
return NULL;
// Get parent container children.
return pParent->getContainerChildClass(recurse);
}
virtual WriteCustomTamlSchema getCustomTamlSchema(void)
{
return T::getStaticWriteCustomTamlSchema();
}
static EnginePropertyTable _smPropertyTable;
static EnginePropertyTable& smPropertyTable;
ConcreteAbstractClassRep(const char* name,
const char* conTypeName,
S32* conTypeIdPtr,
S32 netClassGroupMask,
S32 netClassType,
S32 netEventDir,
AbstractClassRep* parent,
const char* (*parentDesc)())
: AbstractClassRep(conTypeIdPtr, conTypeName)
{
mClassName = StringTable->insert(name);
mCategory = T::__category();
mTypeInfo = _MAPTYPE< T >();
if (mTypeInfo)
const_cast< EngineTypeInfo* >(mTypeInfo)->mPropertyTable = &smPropertyTable;
if (&T::__description != parentDesc)
mDescription = T::__description();
// Clean up mClassId
for (U32 i = 0; i < NetClassGroupsCount; i++)
mClassId[i] = -1;
// Set properties for this ACR
mClassType = netClassType;
mClassGroupMask = netClassGroupMask;
mNetEventDir = netEventDir;
parentClass = parent;
mClassSizeof = sizeof(T);
// Finally, register ourselves.
registerClassRep(this);
};
/// Wrap constructor.
ConsoleObject* create() const { return NULL; }
/// Perform class specific initialization tasks.
///
/// Link namespaces, call initPersistFields() and consoleInit().
void init()
{
// Get handle to our parent class, if any, and ourselves (we are our parent's child).
AbstractClassRep *parent = T::getParentStaticClassRep();
AbstractClassRep *child = T::getStaticClassRep();
// If we got reps, then link those namespaces! (To get proper inheritance.)
if (parent && child)
Con::classLinkNamespaces(parent->getNameSpace(), child->getNameSpace());
// Finally, do any class specific initialization...
T::initPersistFields();
T::consoleInit();
// Let the base finish up.
AbstractClassRep::init();
}
/// @name Console Type Interface
/// @{
virtual void setData(void* dptr, S32 argc, const char** argv, const EnumTable* tbl, BitSet32 flag)
{
if (argc == 1)
{
mClassName = StringTable->insert( name );
mCategory = T::__category();
mTypeInfo = _MAPTYPE< T >();
if( mTypeInfo )
const_cast< EngineTypeInfo* >( mTypeInfo )->mPropertyTable = &smPropertyTable;
if( &T::__description != parentDesc )
mDescription = T::__description();
// Clean up mClassId
for(U32 i = 0; i < NetClassGroupsCount; i++)
mClassId[i] = -1;
// Set properties for this ACR
mClassType = netClassType;
mClassGroupMask = netClassGroupMask;
mNetEventDir = netEventDir;
parentClass = parent;
mClassSizeof = sizeof(T);
// Finally, register ourselves.
registerClassRep(this);
};
virtual AbstractClassRep* getContainerChildClass(const bool recurse)
{
// Fetch container children type.
AbstractClassRep* pChildren = T::getContainerChildStaticClassRep();
if (!recurse || pChildren != NULL)
return pChildren;
// Fetch parent type.
AbstractClassRep* pParent = T::getParentStaticClassRep();
if (pParent == NULL)
return NULL;
// Get parent container children.
return pParent->getContainerChildClass(recurse);
T** obj = (T**)dptr;
*obj = dynamic_cast< T* >(T::__findObject(argv[0]));
}
else
Con::errorf("Cannot set multiple args to a single ConsoleObject*.");
}
virtual const char* getData(void* dptr, const EnumTable* tbl, BitSet32 flag)
{
T** obj = (T**)dptr;
return Con::getReturnBuffer(T::__getObjectId(*obj));
}
virtual const char* getTypeClassName() { return mClassName; }
virtual const bool isDatablock() { return T::__smIsDatablock; };
virtual WriteCustomTamlSchema getCustomTamlSchema(void)
{
return T::getStaticWriteCustomTamlSchema();
}
/// Perform class specific initialization tasks.
///
/// Link namespaces, call initPersistFields() and consoleInit().
void init()
{
// Get handle to our parent class, if any, and ourselves (we are our parent's child).
AbstractClassRep *parent = T::getParentStaticClassRep();
AbstractClassRep *child = T::getStaticClassRep();
// If we got reps, then link those namespaces! (To get proper inheritance.)
if(parent && child)
Con::classLinkNamespaces(parent->getNameSpace(), child->getNameSpace());
// Finally, do any class specific initialization...
T::initPersistFields();
T::consoleInit();
// Let the base finish up.
AbstractClassRep::init();
}
/// Wrap constructor.
ConsoleObject* create() const { return new T; }
/// @name Console Type Interface
/// @{
virtual void setData( void* dptr, S32 argc, const char** argv, const EnumTable* tbl, BitSet32 flag )
{
if( argc == 1 )
{
T** obj = ( T** ) dptr;
*obj = dynamic_cast< T* >( T::__findObject( argv[ 0 ] ) );
}
else
Con::errorf( "Cannot set multiple args to a single ConsoleObject*.");
}
virtual const char* getData( void* dptr, const EnumTable* tbl, BitSet32 flag )
{
T** obj = ( T** ) dptr;
return Con::getReturnBuffer( T::__getObjectId( *obj ) );
}
virtual const char* getTypeClassName() { return mClassName; }
virtual const bool isDatablock() { return T::__smIsDatablock; };
/// @}
/// @}
};
template< class T >
class ConcreteClassRep : public ConcreteAbstractClassRep<T>
{
public:
ConcreteClassRep(const char* name,
const char* conTypeName,
S32* conTypeIdPtr,
S32 netClassGroupMask,
S32 netClassType,
S32 netEventDir,
AbstractClassRep* parent,
const char* (*parentDesc)())
: ConcreteAbstractClassRep<T>(name, conTypeName, conTypeIdPtr, netClassGroupMask, netClassType, netEventDir, parent, parentDesc)
{
}
/// Wrap constructor.
ConsoleObject* create() const { return new T; }
};
template< typename T > EnginePropertyTable ConcreteClassRep< T >::_smPropertyTable( 0, NULL );
template< typename T > EnginePropertyTable& ConcreteClassRep< T >::smPropertyTable = ConcreteClassRep< T >::_smPropertyTable;
template< typename T > EnginePropertyTable ConcreteAbstractClassRep< T >::_smPropertyTable(0, NULL);
template< typename T > EnginePropertyTable& ConcreteAbstractClassRep< T >::smPropertyTable = ConcreteAbstractClassRep< T >::_smPropertyTable;
//------------------------------------------------------------------------------
// Forward declaration of this function so it can be used in the class
@ -751,7 +766,7 @@ bool defaultProtectedWriteFn(void* obj, StringTableEntry pFieldName);
class ConsoleObject : public EngineObject
{
DECLARE_ABSTRACT_CLASS( ConsoleObject, EngineObject );
protected:
/// @deprecated This is disallowed.
@ -760,16 +775,25 @@ protected:
public:
ConsoleObject() {}
/// Get a reference to a field by name.
const AbstractClassRep::Field *findField(StringTableEntry fieldName) const;
/// Gets the ClassRep.
virtual AbstractClassRep* getClassRep() const;
#define DECLARE_ABSTRACT_CONOBJECT( className ) \
DECLARE_ABSTRACT_CLASS( className, Parent ); \
static S32 _smTypeId; \
static ConcreteAbstractClassRep< className > dynClassRep; \
static AbstractClassRep* getParentStaticClassRep(); \
static AbstractClassRep* getStaticClassRep(); \
static SimObjectRefConsoleBaseType< className > ptrRefType; \
virtual AbstractClassRep* getClassRep() const
/// Set the value of a field.
bool setField(const char *fieldName, const char *value);
public:
/// @name Object Creation
@ -799,11 +823,11 @@ public:
static void endGroup(const char* in_pGroupname);
/// Marks the start of a fixed size array of fields.
/// @see console_autodoc
/// @see console_autodoc
static void addArray( const char *arrayName, S32 count );
/// Marks the end of an array of fields.
/// @see console_autodoc
/// @see console_autodoc
static void endArray( const char *arrayName );
/// Register a complex field.
@ -928,16 +952,16 @@ public:
static bool removeField(const char* in_pFieldname);
/// @}
/// @name Logging
/// @{
/// Overload this in subclasses to change the message formatting.
/// @param fmt A printf style format string.
/// @param args A va_list containing the args passed ot a log function.
/// @note It is suggested that you use String::VToString.
virtual String _getLogMessage(const char* fmt, va_list args) const;
/// @}
public:
@ -946,16 +970,16 @@ public:
/// These functions will try to print out a message along the lines
/// of "ObjectClass - ObjectName(ObjectId) - formatted message"
/// @{
/// Logs with Con::printf.
void logMessage(const char* fmt, ...) const;
/// Logs with Con::warnf.
void logWarning(const char* fmt, ...) const;
/// Logs with Con::errorf.
void logError(const char* fmt, ...) const;
/// @}
/// Register dynamic fields in a subclass of ConsoleObject.
@ -1016,16 +1040,16 @@ public:
static const char* __category() { return ""; }
static const char* __description() { return ""; }
/// Subclasses of ConsoleObjects that are datablocks should redefine this static member variable
/// and set it to true.
static const bool __smIsDatablock = false;
/// @name Object IDs and lookup.
/// For a subclass hierarchy based on ConsoleObject to become functional for use as a console object type,
/// the hierarchy must implement a naming scheme and indexing function for looking up objects by name.
/// @{
static ConsoleObject* __findObject( const char* ) { return NULL; }
static const char* __getObjectId( ConsoleObject* ) { return ""; }
};
@ -1120,11 +1144,11 @@ inline bool& ConsoleObject::getDynamicGroupExpand()
static SimObjectRefConsoleBaseType< className > ptrRefType; \
static AbstractClassRep::WriteCustomTamlSchema getStaticWriteCustomTamlSchema(); \
static AbstractClassRep* getContainerChildStaticClassRep(); \
virtual AbstractClassRep* getClassRep() const
virtual AbstractClassRep* getClassRep() const
#define DECLARE_CATEGORY( string ) \
static const char* __category() { return string; }
#define DECLARE_DESCRIPTION( string ) \
static const char* __description() { return string; }
@ -1140,7 +1164,7 @@ inline bool& ConsoleObject::getDynamicGroupExpand()
AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \
ConcreteClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
#define IMPLEMENT_CONOBJECT_CHILDREN( className ) \
#define IMPLEMENT_CONOBJECT_CHILDREN( className ) \
IMPLEMENT_CLASS( className, NULL ) \
END_IMPLEMENT_CLASS; \
S32 className::_smTypeId; \
@ -1148,11 +1172,11 @@ inline bool& ConsoleObject::getDynamicGroupExpand()
AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
AbstractClassRep* className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); } \
AbstractClassRep* className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); } \
AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \
ConcreteClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
#define IMPLEMENT_CONOBJECT_SCHEMA( className, schema ) \
#define IMPLEMENT_CONOBJECT_SCHEMA( className, schema ) \
IMPLEMENT_CLASS( className, NULL ) \
END_IMPLEMENT_CLASS; \
S32 className::_smTypeId; \
@ -1164,7 +1188,7 @@ inline bool& ConsoleObject::getDynamicGroupExpand()
AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return schema; } \
ConcreteClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
#define IMPLEMENT_CONOBJECT_CHILDREN_SCHEMA( className, schema ) \
#define IMPLEMENT_CONOBJECT_CHILDREN_SCHEMA( className, schema ) \
IMPLEMENT_CLASS( className, NULL ) \
END_IMPLEMENT_CLASS; \
S32 className::_smTypeId; \
@ -1172,10 +1196,20 @@ inline bool& ConsoleObject::getDynamicGroupExpand()
AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
AbstractClassRep* className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); } \
AbstractClassRep* className::getContainerChildStaticClassRep() { return Children::getStaticClassRep(); } \
AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return schema; } \
ConcreteClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
#define IMPLEMENT_ABSTRACT_CONOBJECT( className ) \
IMPLEMENT_NONINSTANTIABLE_CLASS( className, NULL ) \
END_IMPLEMENT_CLASS; \
S32 className::_smTypeId; \
SimObjectRefConsoleBaseType< className > className::ptrRefType( "Type" #className "Ref" ); \
AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; } \
AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
ConcreteAbstractClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, 0, -1, 0, className::getParentStaticClassRep(), &Parent::__description )
#define IMPLEMENT_CO_NETOBJECT_V1( className ) \
IMPLEMENT_CLASS( className, NULL ) \
END_IMPLEMENT_CLASS; \
@ -1185,7 +1219,7 @@ inline bool& ConsoleObject::getDynamicGroupExpand()
AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
AbstractClassRep* className::getContainerChildStaticClassRep() { return NULL; } \
AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \
AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \
ConcreteClassRep<className> className::dynClassRep( #className, "Type" #className, &_smTypeId, NetClassGroupGameMask, NetClassTypeObject, 0, className::getParentStaticClassRep(), &Parent::__description )
#define IMPLEMENT_CO_DATABLOCK_V1( className ) \
@ -1197,9 +1231,9 @@ inline bool& ConsoleObject::getDynamicGroupExpand()
AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; } \
AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
AbstractClassRep* className::getContainerChildStaticClassRep() { return NULL; } \
AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \
AbstractClassRep::WriteCustomTamlSchema className::getStaticWriteCustomTamlSchema() { return NULL; } \
ConcreteClassRep<className> className::dynClassRep(#className, "Type" #className, &_smTypeId, NetClassGroupGameMask, NetClassTypeDataBlock, 0, className::getParentStaticClassRep(), &Parent::__description )
// Support for adding properties to classes CONOBJECT style.
#define PROPERTY_TABLE( className ) \
namespace { namespace _ ## className { \
@ -1209,13 +1243,13 @@ inline bool& ConsoleObject::getDynamicGroupExpand()
ConcreteClassRep< className >::smPropertyTable = _ ## className::_propTable; \
namespace { namespace _ ## className { \
EnginePropertyTable::Property _props[] = {
#define END_PROPERTY_TABLE \
{ NULL } \
}; \
EnginePropertyTable _propTable( sizeof( _props ) / sizeof( _props[ 0 ] ) - 1, _props ); \
} }
/// Add an auto-doc for a class.
#define ConsoleDocClass( className, docString ) \
CLASSDOC( className, docString )
@ -1225,7 +1259,7 @@ inline bool& ConsoleObject::getDynamicGroupExpand()
//------------------------------------------------------------------------------
// Protected field default get/set functions
//
// The reason for these functions is that it will save one branch per console
// The reason for these functions is that it will save one branch per console
// data request and script functions will still execute at the same speed as
// before the modifications to allow protected static fields. These will just
// inline and the code should be roughly the same size, and just as fast as

View file

@ -362,7 +362,7 @@ class EngineTypeInfo : public EngineExportScope
// them to retroactively install property tables. Will be removed
// when the console interop is removed and all classes are migrated
// to the new system.
template< typename T > friend class ConcreteClassRep;
template< typename T > friend class ConcreteAbstractClassRep;
protected:

View file

@ -30,6 +30,10 @@
#include "math/mPoint4.h"
#endif
#ifndef _ENGINEAPI_H_
#include "console/engineAPI.h"
#endif
class ColorI;
@ -121,9 +125,20 @@ class ColorI
U8 blue;
U8 alpha;
struct Hsb
{
Hsb() :hue(0), sat(0), brightness(0){};
Hsb(U32 h, U32 s, U32 b) :hue(h), sat(s), brightness(b){};
U32 hue; ///Hue
U32 sat; ///Saturation
U32 brightness; //Brightness/Value/Lightness
};
public:
ColorI() { }
ColorI(const ColorI& in_rCopy);
ColorI(const Hsb& color);
ColorI(const U8 in_r,
const U8 in_g,
const U8 in_b,
@ -132,6 +147,12 @@ class ColorI
ColorI( const char* pStockColorName );
void set(const Hsb& color);
void HSLtoRGB_Subfunction(U32& c, const F64& temp1, const F64& temp2, const F64& temp3);
void set(const String& hex);
void set(const U8 in_r,
const U8 in_g,
const U8 in_b,
@ -176,6 +197,11 @@ class ColorI
U16 get565() const;
U16 get4444() const;
Hsb getHSB() const;
String getHex() const;
S32 convertFromHex(const String& hex) const;
operator ColorF() const;
operator const U8*() const { return &red; }
@ -459,6 +485,174 @@ inline void ColorI::set(const ColorI& in_rCopy,
alpha = in_a;
}
inline void ColorI::set(const Hsb& color)
{
U32 r = 0;
U32 g = 0;
U32 b = 0;
F64 L = ((F64)color.brightness) / 100.0;
F64 S = ((F64)color.sat) / 100.0;
F64 H = ((F64)color.hue) / 360.0;
if (color.sat == 0)
{
r = color.brightness;
g = color.brightness;
b = color.brightness;
}
else
{
F64 temp1 = 0;
if (L < 0.50)
{
temp1 = L*(1 + S);
}
else
{
temp1 = L + S - (L*S);
}
F64 temp2 = 2.0*L - temp1;
F64 temp3 = 0;
for (S32 i = 0; i < 3; i++)
{
switch (i)
{
case 0: // red
{
temp3 = H + 0.33333;
if (temp3 > 1.0)
temp3 -= 1.0;
HSLtoRGB_Subfunction(r, temp1, temp2, temp3);
break;
}
case 1: // green
{
temp3 = H;
HSLtoRGB_Subfunction(g, temp1, temp2, temp3);
break;
}
case 2: // blue
{
temp3 = H - 0.33333;
if (temp3 < 0)
temp3 += 1;
HSLtoRGB_Subfunction(b, temp1, temp2, temp3);
break;
}
default:
{
}
}
}
}
red = (U32)((((F64)r) / 100) * 255);
green = (U32)((((F64)g) / 100) * 255);
blue = (U32)((((F64)b) / 100) * 255);
}
// This is a subfunction of HSLtoRGB
inline void ColorI::HSLtoRGB_Subfunction(U32& c, const F64& temp1, const F64& temp2, const F64& temp3)
{
if ((temp3 * 6.0) < 1.0)
c = (U32)((temp2 + (temp1 - temp2)*6.0*temp3)*100.0);
else
if ((temp3 * 2.0) < 1.0)
c = (U32)(temp1*100.0);
else
if ((temp3 * 3.0) < 2.0)
c = (U32)((temp2 + (temp1 - temp2)*(0.66666 - temp3)*6.0)*100.0);
else
c = (U32)(temp2*100.0);
return;
}
inline void ColorI::set(const String& hex)
{
String redString;
String greenString;
String blueString;
//if the prefix # was attached to hex
if (hex[0] == '#')
{
redString = hex.substr(1, 2);
greenString = hex.substr(3, 2);
blueString = hex.substr(5, 2);
}
else
{
// since there is no prefix attached to hex
redString = hex.substr(0, 2);
greenString = hex.substr(2, 2);
blueString = hex.substr(4, 2);
}
red = (U8)(convertFromHex(redString));
green = (U8)(convertFromHex(greenString));
blue = (U8)(convertFromHex(blueString));
}
inline S32 ColorI::convertFromHex(const String& hex) const
{
S32 hexValue = 0;
S32 a = 0;
S32 b = hex.length() - 1;
for (; b >= 0; a++, b--)
{
if (hex[b] >= '0' && hex[b] <= '9')
{
hexValue += (hex[b] - '0') * (1 << (a * 4));
}
else
{
switch (hex[b])
{
case 'A':
case 'a':
hexValue += 10 * (1 << (a * 4));
break;
case 'B':
case 'b':
hexValue += 11 * (1 << (a * 4));
break;
case 'C':
case 'c':
hexValue += 12 * (1 << (a * 4));
break;
case 'D':
case 'd':
hexValue += 13 * (1 << (a * 4));
break;
case 'E':
case 'e':
hexValue += 14 * (1 << (a * 4));
break;
case 'F':
case 'f':
hexValue += 15 * (1 << (a * 4));
break;
default:
Con::errorf("Error, invalid character '%c' in hex number", hex[a]);
break;
}
}
}
return hexValue;
}
inline ColorI::ColorI(const ColorI& in_rCopy)
{
red = in_rCopy.red;
@ -467,6 +661,11 @@ inline ColorI::ColorI(const ColorI& in_rCopy)
alpha = in_rCopy.alpha;
}
inline ColorI::ColorI(const Hsb& color)
{
set(color);
}
inline ColorI::ColorI(const U8 in_r,
const U8 in_g,
const U8 in_b,
@ -503,6 +702,7 @@ inline ColorI& ColorI::operator*=(const S32 in_mul)
inline ColorI& ColorI::operator/=(const S32 in_mul)
{
AssertFatal(in_mul != 0.0f, "Error, div by zero...");
red = red / in_mul;
green = green / in_mul;
blue = blue / in_mul;
@ -647,6 +847,91 @@ inline U16 ColorI::get4444() const
U16(U16(blue >> 4) << 0));
}
inline ColorI::Hsb ColorI::getHSB() const
{
F64 rPercent = ((F64)red) / 255;
F64 gPercent = ((F64)green) / 255;
F64 bPercent = ((F64)blue) / 255;
F64 maxColor = 0.0;
if ((rPercent >= gPercent) && (rPercent >= bPercent))
maxColor = rPercent;
if ((gPercent >= rPercent) && (gPercent >= bPercent))
maxColor = gPercent;
if ((bPercent >= rPercent) && (bPercent >= gPercent))
maxColor = bPercent;
F64 minColor = 0.0;
if ((rPercent <= gPercent) && (rPercent <= bPercent))
minColor = rPercent;
if ((gPercent <= rPercent) && (gPercent <= bPercent))
minColor = gPercent;
if ((bPercent <= rPercent) && (bPercent <= gPercent))
minColor = bPercent;
F64 H = 0.0;
F64 S = 0.0;
F64 B = 0.0;
B = (maxColor + minColor) / 2.0;
if (maxColor == minColor)
{
H = 0.0;
S = 0.0;
}
else
{
if (B < 0.50)
{
S = (maxColor - minColor) / (maxColor + minColor);
}
else
{
S = (maxColor - minColor) / (2.0 - maxColor - minColor);
}
if (maxColor == rPercent)
{
H = (gPercent - bPercent) / (maxColor - minColor);
}
if (maxColor == gPercent)
{
H = 2.0 + (bPercent - rPercent) / (maxColor - minColor);
}
if (maxColor == bPercent)
{
H = 4.0 + (rPercent - gPercent) / (maxColor - minColor);
}
}
ColorI::Hsb val;
val.sat = (U32)(S * 100);
val.brightness = (U32)(B * 100);
H = H*60.0;
if (H < 0.0)
H += 360.0;
val.hue = (U32)H;
return val;
}
inline String ColorI::getHex() const
{
char r[255];
dSprintf(r, sizeof(r), "%.2X", red);
String result(r);
char g[255];
dSprintf(g, sizeof(g), "%.2X", green);
result += g;
char b[255];
dSprintf(b, sizeof(b), "%.2X", blue);
result += b;
return result;
}
//-------------------------------------- INLINE CONVERSION OPERATORS
inline ColorF::operator ColorI() const
{

View file

@ -74,7 +74,7 @@ public:
void free(U32 id)
{
AssertFatal(id >= mIdBlockBase, "IdGenerator::alloc: invalid id, id does not belong to this IdGenerator.")
AssertFatal(id >= mIdBlockBase, "IdGenerator::alloc: invalid id, id does not belong to this IdGenerator.");
if(id == mNextId - 1)
{
mNextId--;

View file

@ -128,7 +128,7 @@ bool Stream::writeFormattedBuffer(const char *format, ...)
char buffer[4096];
va_list args;
va_start(args, format);
const S32 length = vsprintf(buffer, format, args);
const S32 length = dVsprintf(buffer, sizeof(buffer), format, args);
// Sanity!
AssertFatal(length <= sizeof(buffer), "writeFormattedBuffer - String format exceeded buffer size. This will cause corruption.");

View file

@ -152,11 +152,20 @@ inline U32 dAtoui(const char *str, U32 base = 10)
return strtoul(str, NULL, base);
}
inline U16 dAtous(const char *str, U32 base = 10)
{
return strtoul(str, NULL, base);
}
inline F32 dAtof(const char *str)
{
return strtof(str, NULL);
}
inline F64 dAtod(const char *str)
{
return strtod(str, NULL);
}
inline char dToupper(const char c)
{

View file

@ -1628,3 +1628,103 @@ String String::GetTrailingNumber(const char* str, S32& number)
return base.substr(0, p - base.c_str());
}
String String::GetFirstNumber(const char* str, U32& startPos, U32& endPos)
{
// Check for trivial strings
if (!str || !str[0])
return String::EmptyString;
// Find the number at the end of the string
String base(str);
const char* p = base.c_str();
const char* end = base.c_str() + base.length() - 1;
bool dec = false;
startPos = 0;
//Check if we are just a digit
if(p == end && isdigit(*p))
return base;
//Look for the first digit
while ((p != end) && (dIsspace(*p) || !isdigit(*p)))
{
p++;
startPos++;
}
//Handle if we are at the end and found nothing
if(p == end && !isdigit(*p))
return "";
//update our end position at least to the start of our number
endPos = startPos;
//Backup our ptr
const char* backup = p;
//Check for any negative or decimal values
if(startPos > 0)
{
p--;
startPos--;
if(*p == '.')
{
dec = true;
//ignore any duplicate periods
while ((p != base.c_str()) && (*p == '.'))
{
p--;
startPos--;
}
//Found a decimal lets still check for negative sign
if(startPos > 0)
{
p--;
startPos--;
if((*p != '-') && (*p != '_'))
{
startPos++;
p++;
}
}
}
else if((*p != '-') && (*p != '_'))
{
//go back to where we where cause no decimal or negative sign found
startPos++;
p++;
}
}
//Restore where we were
p = backup;
//look for the end of the digits
bool justFoundDec = false;
while (p != end)
{
if(*p == '.')
{
if(dec && !justFoundDec)
break;
else
{
dec = true;
justFoundDec = true;
}
}
else if(!isdigit(*p))
break;
else if(justFoundDec)
justFoundDec = false;
p++;
endPos++;
}
U32 len = (!isdigit(*p)) ? endPos - startPos : (endPos + 1) - startPos;
return base.substr(startPos, len);
}

View file

@ -191,6 +191,7 @@ public:
static String ToUpper(const String &string);
static String GetTrailingNumber(const char* str, S32& number);
static String GetFirstNumber(const char* str, U32& startPos, U32& endPos);
/// @}

View file

@ -120,8 +120,7 @@ inline void Swizzle<T, mapLength>::ToBuffer( void *destination, const void *sour
{
// TODO: OpenMP?
AssertFatal( size % ( sizeof( T ) * mapLength ) == 0, "Bad buffer size for swizzle, see docs." );
AssertFatal( destination != NULL, "Swizzle::ToBuffer - got a NULL destination pointer!" );
AssertFatal( source != NULL, "Swizzle::ToBuffer - got a NULL source pointer!" );
if (!destination || !source) return;
T *dest = reinterpret_cast<T *>( destination );
const T *src = reinterpret_cast<const T *>( source );

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,243 @@
//-----------------------------------------------------------------------------
// 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 _VolumetricFog_H_
#define _VolumetricFog_H_
#ifndef _SCENEOBJECT_H_
#include "scene/sceneObject.h"
#endif
#ifndef _MATTEXTURETARGET_H_
#include "materials/matTextureTarget.h"
#endif
#ifndef _GFXSHADER_H_
#include "gfx/gfxShader.h"
#endif
#ifndef _GFXTARGET_H_
#include "gfx/gfxTarget.h"
#endif
#ifndef _GFXVERTEXBUFFER_H_
#include "gfx/gfxVertexBuffer.h"
#endif
#ifndef _TSSHAPE_H_
#include "ts/tsShape.h"
#endif
#ifndef _POST_EFFECT_H_
#include "postFx/postEffect.h"
#endif
#include "gui/core/guiCanvas.h"
class VolumetricFogRTManager;
class VolumetricFog : public SceneObject
{
typedef SceneObject Parent;
// Maskbits for updating
enum
{
VolumetricFogMask = Parent::NextFreeMask,
FogColorMask = Parent::NextFreeMask << 1,
FogDensityMask = Parent::NextFreeMask << 2,
FogModulationMask = Parent::NextFreeMask << 3,
FogPostFXMask = Parent::NextFreeMask << 4,
FogShapeMask = Parent::NextFreeMask << 5,
NextFreeMask = Parent::NextFreeMask << 6
};
// Struct which holds the shape details
struct meshes
{
F32 det_size;
S32 sub_shape;
S32 obj_det;
U32 num_verts;
GFXVertexPNTT *verts;
Vector <GFXPrimitive> *piArray;
Vector <U32> *indices;
};
protected:
// Rendertargets;
GFXTextureTargetRef z_buf;
NamedTexTargetRef mPrepassTarget;
NamedTexTargetRef mDepthBufferTarget;
NamedTexTargetRef mFrontBufferTarget;
// Fog Modulation texture
GFXTexHandle mTexture;
// Shaders
GFXShaderRef mShader;
GFXShaderRef mPrePassShader;
GFXShaderRef mReflectionShader;
// Stateblocks
GFXStateBlockDesc descD;
GFXStateBlockDesc descF;
GFXStateBlockDesc desc_preD;
GFXStateBlockDesc desc_preF;
GFXStateBlockDesc desc_refl;
GFXStateBlockRef mStateblockD;
GFXStateBlockRef mStateblockF;
GFXStateBlockRef mStateblock_preD;
GFXStateBlockRef mStateblock_preF;
GFXStateBlockRef mStateblock_refl;
// Shaderconstants
GFXShaderConstBufferRef mShaderConsts;
GFXShaderConstHandle *mModelViewProjSC;
GFXShaderConstHandle *mFadeSizeSC;
GFXShaderConstHandle *mFogColorSC;
GFXShaderConstHandle *mFogDensitySC;
GFXShaderConstHandle *mPreBias;
GFXShaderConstHandle *mAccumTime;
GFXShaderConstHandle *mIsTexturedSC;
GFXShaderConstHandle *mModSpeedSC;
GFXShaderConstHandle *mModStrengthSC;
GFXShaderConstHandle *mViewPointSC;
GFXShaderConstHandle *mTexScaleSC;
GFXShaderConstHandle *mTexTilesSC;
GFXShaderConstBufferRef mPPShaderConsts;
GFXShaderConstHandle *mPPModelViewProjSC;
GFXShaderConstHandle *mAmbientColorSC;
GFXShaderConstBufferRef mReflShaderConsts;
GFXShaderConstHandle *mReflModelViewProjSC;
GFXShaderConstHandle *mReflFogColorSC;
GFXShaderConstHandle *mReflFogDensitySC;
GFXShaderConstHandle *mReflFogStrengthSC;
// Vertex and Prim. Buffer
GFXVertexBufferHandle<GFXVertexPNTT> mVB;
GFXPrimitiveBufferHandle mPB;
// Fog volume data;
StringTableEntry mShapeName;
ColorI mFogColor;
F32 mFogDensity;
bool mIgnoreWater;
bool mReflect;
Vector<meshes> det_size;
bool mShapeLoaded;
F32 mPixelSize;
F32 mFadeSize;
U32 mCurDetailLevel;
U32 mNumDetailLevels;
F32 mObjSize;
F32 mRadius;
OrientedBox3F ColBox;
VectorF mObjScale;
F32 mMinDisplaySize;
F32 mInvScale;
// Fog Modulation data
String mTextureName;
bool mIsTextured;
F32 mTexTiles;
F32 mStrength;
Point2F mSpeed1;
Point2F mSpeed2;
Point4F mSpeed;
Point2F mTexScale;
// Fog Rendering data
Point3F camPos;
Point2F mViewPoint;
F32 mFOV;
F32 viewDist;
bool mIsVBDirty;
bool mIsPBDirty;
bool mCamInFog;
bool mResizing;
PlatformWindow *mPlatformWindow;
// Reflections
F32 mFogReflStrength;
// PostFX
PostEffect *glowFX;
bool mUseGlow;
F32 mGlowStrength;
U8 mGlowing;
F32 mCurGlow;
bool mModifLightRays;
F32 mLightRayMod;
F32 mOldLightRayStrength;
GameConnection* conn;
U32 mCounter;
void ResizeRT(PlatformWindow *win, bool resize);
protected:
// Protected methods
bool onAdd();
void onRemove();
void handleResize(VolumetricFogRTManager *RTM, bool resize);
void handleCanvasResize(GuiCanvas* canvas);
bool LoadShape();
bool setupRenderer();
void InitTexture();
bool UpdateBuffers(U32 dl,bool force=true);
void processTick(const Move *move);
void _enterFog(ShapeBase *control);
void _leaveFog(ShapeBase *control);
public:
// Public methods
VolumetricFog();
~VolumetricFog();
static void initPersistFields();
virtual void inspectPostApply();
U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream);
void unpackUpdate(NetConnection *conn, BitStream *stream);
void prepRenderImage(SceneRenderState* state);
void render(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat);
void reflect_render(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat);
// Methods for modifying & networking various fog elements
// Used in script
void setFogColor(ColorF color);
void setFogColor(ColorI color);
void setFogDensity(F32 density);
void setFogModulation(F32 strength, Point2F speed1, Point2F speed2);
void setFogGlow(bool on_off, F32 strength);
void setFogLightray(bool on_off, F32 strength);
bool isInsideFog();
DECLARE_CONOBJECT(VolumetricFog);
DECLARE_CALLBACK(void, onEnterFog, (SimObjectId obj));
DECLARE_CALLBACK(void, onLeaveFog, (SimObjectId obj));
};
#endif

View file

@ -0,0 +1,299 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Volumetric Fog Rendertarget Manager
//
// Creates and maintains one set of rendertargets to be used by every
// VolumetricFog object in the scene.
//
// Will be loaded at startup end removed when ending game.
//
//-----------------------------------------------------------------------------
#include "VolumetricFogRTManager.h"
#include "core/module.h"
#include "scene/sceneManager.h"
#include "windowManager/platformWindowMgr.h"
#include "console/engineAPI.h"
#include "gui/core/guiCanvas.h"
MODULE_BEGIN(VolumetricFogRTManager)
MODULE_INIT_AFTER(Scene)
MODULE_SHUTDOWN_BEFORE(Scene)
MODULE_INIT
{
gVolumetricFogRTManager = new VolumetricFogRTManager;
gClientSceneGraph->addObjectToScene(gVolumetricFogRTManager);
}
MODULE_SHUTDOWN
{
gClientSceneGraph->removeObjectFromScene(gVolumetricFogRTManager);
SAFE_DELETE(gVolumetricFogRTManager);
}
MODULE_END;
ConsoleDocClass( VolumetricFogRTManager,
"@brief Creates and maintains one set of rendertargets to be used by every\n"
"VolumetricFog object in the scene.\n\n"
"Will be loaded at startup end removed when ending game.\n\n"
"Methods:\n"
" get() returns the currently loaded VolumetricFogRTManager, also accessible\n"
" through VFRTM define.\n"
" Init() Initializes the rendertargets, called when a VolumetricFog object is\n"
" added to the scene.\n"
" isInitialed() returns true if Rendertargets are present, false if not, then\n"
" Init() should be called to create the rendertargets.\n"
" setQuality(U32 Quality) Normally a rendertarget has the same size as the view,\n"
" with this method you can scale down the size of it.\n"
" Be aware that scaling down will introduce renderartefacts.\n"
"@ingroup Atmosphere"
);
VolumetricFogRTMResizeSignal VolumetricFogRTManager::smVolumetricFogRTMResizeSignal;
VolumetricFogRTManager *gVolumetricFogRTManager = NULL;
S32 VolumetricFogRTManager::mTargetScale = 1;
IMPLEMENT_CONOBJECT(VolumetricFogRTManager);
VolumetricFogRTManager::VolumetricFogRTManager()
{
setGlobalBounds();
mTypeMask |= EnvironmentObjectType;
mNetFlags.set(IsGhost);
mIsInitialized = false;
mNumFogObjects = 0;
}
VolumetricFogRTManager::~VolumetricFogRTManager()
{
if (mFrontTarget.isRegistered())
mFrontTarget.unregister();
if (mDepthTarget.isRegistered())
mDepthTarget.unregister();
if (mDepthBuffer.isValid())
mDepthBuffer->kill();
if (mFrontBuffer.isValid())
mFrontBuffer->kill();
}
void VolumetricFogRTManager::onSceneRemove()
{
if (mIsInitialized)
mPlatformWindow->getScreenResChangeSignal().remove(this, &VolumetricFogRTManager::ResizeRT);
}
void VolumetricFogRTManager::onRemove()
{
removeFromScene();
Parent::onRemove();
}
void VolumetricFogRTManager::consoleInit()
{
Con::addVariable("$pref::VolumetricFog::Quality", TypeS32, &mTargetScale,
"The scale of the rendertargets.\n"
"@ingroup Rendering\n");
}
bool VolumetricFogRTManager::Init()
{
if (mIsInitialized)
{
Con::errorf("VolumetricFogRTManager allready initialized!!");
return true;
}
GuiCanvas* cv = dynamic_cast<GuiCanvas*>(Sim::findObject("Canvas"));
if (cv == NULL)
{
Con::errorf("VolumetricFogRTManager::Init() - Canvas not found!!");
return false;
}
mPlatformWindow = cv->getPlatformWindow();
mPlatformWindow->getScreenResChangeSignal().notify(this,&VolumetricFogRTManager::ResizeRT);
if (mTargetScale < 1)
mTargetScale = 1;
mWidth = mFloor(mPlatformWindow->getClientExtent().x / mTargetScale);
mHeight = mPlatformWindow->getClientExtent().y;
mFullScreen = mPlatformWindow->isFullscreen();
if (!mFullScreen)
mHeight -= 20;//subtract caption bar from rendertarget size.
mHeight = mFloor(mHeight / mTargetScale);
mDepthBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F,
&GFXDefaultRenderTargetProfile, avar("%s() - mDepthBuffer (line %d)", __FUNCTION__, __LINE__));
if (!mDepthBuffer.isValid())
{
Con::errorf("VolumetricFogRTManager Fatal Error: Unable to create Depthbuffer");
return false;
}
if (!mDepthTarget.registerWithName("volfogdepth"))
{
Con::errorf("VolumetricFogRTManager Fatal Error : Unable to register Depthbuffer");
return false;
}
mDepthTarget.setTexture(mDepthBuffer);
mFrontBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F,
&GFXDefaultRenderTargetProfile, avar("%s() - mFrontBuffer (line %d)", __FUNCTION__, __LINE__));
if (!mFrontBuffer.isValid())
{
Con::errorf("VolumetricFogRTManager Fatal Error: Unable to create front buffer");
return false;
}
if (!mFrontTarget.registerWithName("volfogfront"))
{
Con::errorf("VolumetricFogRTManager Fatal Error : Unable to register Frontbuffer");
return false;
}
mFrontTarget.setTexture(mFrontBuffer);
Con::setVariable("$VolumetricFog::density", "0.0");
mIsInitialized = true;
return true;
}
U32 VolumetricFogRTManager::IncFogObjects()
{
mNumFogObjects++;
return mNumFogObjects;
}
U32 VolumetricFogRTManager::DecFogObjects()
{
if (mNumFogObjects > 0)
mNumFogObjects--;
return mNumFogObjects;
}
void VolumetricFogRTManager::ResizeRT(PlatformWindow* win,bool resize)
{
mFogHasAnswered = 0;
smVolumetricFogRTMResizeSignal.trigger(this, true);
}
void VolumetricFogRTManager::FogAnswered()
{
mFogHasAnswered++;
if (mFogHasAnswered == mNumFogObjects)
{
if (Resize())
smVolumetricFogRTMResizeSignal.trigger(this, false);
else
Con::errorf("VolumetricFogRTManager::FogAnswered - Error resizing rendertargets!");
}
}
bool VolumetricFogRTManager::Resize()
{
if (mTargetScale < 1)
mTargetScale = 1;
mWidth = mFloor(mPlatformWindow->getClientExtent().x / mTargetScale);
mHeight = mPlatformWindow->getClientExtent().y;
if (!mPlatformWindow->isFullscreen())
mHeight -= 20;//subtract caption bar from rendertarget size.
mHeight = mFloor(mHeight / mTargetScale);
if (mWidth < 16 || mHeight < 16)
return false;
if (mFrontTarget.isRegistered())
mFrontTarget.setTexture(NULL);
if (mDepthTarget.isRegistered())
mDepthTarget.setTexture(NULL);
if (mDepthBuffer.isValid())
mDepthBuffer->kill();
if (mFrontBuffer.isValid())
mFrontBuffer->kill();
mFrontBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F,
&GFXDefaultRenderTargetProfile, avar("%s() - mFrontBuffer (line %d)", __FUNCTION__, __LINE__));
if (!mFrontBuffer.isValid())
{
Con::errorf("VolumetricFogRTManager::Resize() Fatal Error: Unable to create front buffer");
return false;
}
mFrontTarget.setTexture(mFrontBuffer);
mDepthBuffer = GFXTexHandle(mWidth, mHeight, GFXFormatR32F,
&GFXDefaultRenderTargetProfile, avar("%s() - mDepthBuffer (line %d)", __FUNCTION__, __LINE__));
if (!mDepthBuffer.isValid())
{
Con::errorf("VolumetricFogRTManager::Resize() Fatal Error: Unable to create Depthbuffer");
return false;
}
mDepthTarget.setTexture(mDepthBuffer);
return true;
}
S32 VolumetricFogRTManager::setQuality(U32 Quality)
{
if (!mIsInitialized)
return (mTargetScale = Quality);
if (Quality < 1)
Quality = 1;
if (Quality == mTargetScale)
return mTargetScale;
mTargetScale = Quality;
mFogHasAnswered = 0;
smVolumetricFogRTMResizeSignal.trigger(this, true);
return mTargetScale;
}
VolumetricFogRTManager* VolumetricFogRTManager::get()
{
return gVolumetricFogRTManager;
}
DefineConsoleFunction(SetFogVolumeQuality, S32, (U32 new_quality), ,
"@brief Resizes the rendertargets of the Volumetric Fog object.\n"
"@params new_quality new quality for the rendertargets 1 = full size, 2 = halfsize, 3 = 1/3, 4 = 1/4 ...")
{
if (VFRTM == NULL)
return -1;
return VFRTM->setQuality(new_quality);
}

View file

@ -0,0 +1,92 @@
//-----------------------------------------------------------------------------
// 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 _VolumetricFogRTManager_H_
#define _VolumetricFogRTManager_H_
#ifndef _SCENEOBJECT_H_
#include "scene/sceneObject.h"
#endif
#ifndef _MATTEXTURETARGET_H_
#include "materials/matTextureTarget.h"
#endif
#ifndef _GFXTARGET_H_
#include "gfx/gfxTarget.h"
#endif
#ifndef _SIGNAL_H_
#include "core/util/tSignal.h"
#endif
class VolumetricFogRTManager;
typedef Signal<void(VolumetricFogRTManager *VolumetricFogRTManager, bool resize)> VolumetricFogRTMResizeSignal;
#define VFRTM VolumetricFogRTManager::get()
class VolumetricFogRTManager : public SceneObject
{
public:
typedef SceneObject Parent;
protected:
GFXTexHandle mDepthBuffer;
GFXTexHandle mFrontBuffer;
NamedTexTarget mDepthTarget;
NamedTexTarget mFrontTarget;
PlatformWindow* mPlatformWindow;
static S32 mTargetScale;
bool mIsInitialized;
U32 mNumFogObjects;
U32 mFogHasAnswered;
U32 mWidth;
U32 mHeight;
bool mFullScreen;
void onRemove();
void onSceneRemove();
void ResizeRT(PlatformWindow *win, bool resize);
static VolumetricFogRTMResizeSignal smVolumetricFogRTMResizeSignal;
public:
VolumetricFogRTManager();
~VolumetricFogRTManager();
static VolumetricFogRTManager *get();
bool Init();
bool IsInitialized() { return mIsInitialized; }
static void consoleInit();
static VolumetricFogRTMResizeSignal& getVolumetricFogRTMResizeSignal() { return smVolumetricFogRTMResizeSignal; }
void FogAnswered();
S32 setQuality(U32 Quality);
bool Resize();
U32 IncFogObjects();
U32 DecFogObjects();
DECLARE_CONOBJECT(VolumetricFogRTManager);
};
extern VolumetricFogRTManager* gVolumetricFogRTManager;
#endif

View file

@ -141,7 +141,7 @@ bool BasicClouds::onAdd()
GFXStateBlockDesc desc;
desc.setCullMode( GFXCullNone );
desc.setBlend( true );
desc.setZReadWrite( false, false );
desc.setZReadWrite( true, false );
desc.samplersDefined = true;
desc.samplers[0].addressModeU = GFXAddressWrap;
desc.samplers[0].addressModeV = GFXAddressWrap;

View file

@ -161,7 +161,7 @@ bool CloudLayer::onAdd()
GFXStateBlockDesc desc;
desc.setCullMode( GFXCullNone );
desc.setBlend( true );
desc.setZReadWrite( false, false );
desc.setZReadWrite( true, false );
desc.samplersDefined = true;
desc.samplers[0].addressModeU = GFXAddressWrap;
desc.samplers[0].addressModeV = GFXAddressWrap;

View file

@ -732,7 +732,7 @@ void DecalRoad::prepRenderImage( SceneRenderState* state )
MathUtils::getZBiasProjectionMatrix( gDecalBias, frustum, tempMat );
coreRI.projection = tempMat;
coreRI.type = RenderPassManager::RIT_Decal;
coreRI.type = RenderPassManager::RIT_DecalRoad;
coreRI.vertBuff = &mVB;
coreRI.primBuff = &mPB;
coreRI.matInst = matInst;

View file

@ -955,12 +955,21 @@ void ScatterSky::_render( ObjectRenderInst *ri, SceneRenderState *state, BaseMat
Point3F camPos2 = state->getCameraPosition();
MatrixF xfm(true);
xfm.setPosition(camPos2 - Point3F( 0, 0, mZOffset));
GFX->multWorld(xfm);
MatrixF xform(proj);//GFX->getProjectionMatrix());
xform *= GFX->getViewMatrix();
xform *= GFX->getWorldMatrix();
if(state->isReflectPass())
{
static MatrixF rotMat(EulerF(0.0, 0.0, M_PI_F));
xform.mul(rotMat);
rotMat.set(EulerF(M_PI_F, 0.0, 0.0));
xform.mul(rotMat);
}
xform.setPosition(xform.getPosition() - Point3F(0, 0, mZOffset));
mShaderConsts->setSafe( mModelViewProjSC, xform );
mShaderConsts->setSafe( mMiscSC, miscParams );
mShaderConsts->setSafe( mSphereRadiiSC, sphereRadii );

View file

@ -599,7 +599,8 @@ void SkyBox::_initMaterial()
// We want to disable culling and z write.
GFXStateBlockDesc desc;
desc.setCullMode( GFXCullCW );
desc.setCullMode( GFXCullNone );
desc.setBlend( true );
desc.setZReadWrite( true, false );
mMatInstance->addStateBlockDesc( desc );

View file

@ -402,7 +402,7 @@ void TimeOfDay::_getSunColor( ColorF *outColor ) const
//simple check
if ( mColorTargets[0].elevation != 0.0f )
{
AssertFatal(0, "TimeOfDay::GetColor() - First elevation must be 0.0 radians")
AssertFatal(0, "TimeOfDay::GetColor() - First elevation must be 0.0 radians");
outColor->set(1.0f, 1.0f, 1.0f);
//mBandMod = 1.0f;
//mCurrentBandColor = color;
@ -411,7 +411,7 @@ void TimeOfDay::_getSunColor( ColorF *outColor ) const
if ( mColorTargets[mColorTargets.size()-1].elevation != M_PI_F )
{
AssertFatal(0, "Celestails::GetColor() - Last elevation must be PI")
AssertFatal(0, "Celestails::GetColor() - Last elevation must be PI");
outColor->set(1.0f, 1.0f, 1.0f);
//mBandMod = 1.0f;
//mCurrentBandColor = color;

View file

@ -87,9 +87,11 @@ void GFXD3D9CardProfiler::setupCardCapabilities()
bool canDoFourStageDetailBlend = ( caps.TextureOpCaps & D3DTEXOPCAPS_SUBTRACT ) &&
( caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP ) &&
( caps.MaxTextureBlendStages > 3 );
bool canDoIndependentMrtBitDepth = (caps.PrimitiveMiscCaps & D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS ? 1 : 0 );
setCapability( "lerpDetailBlend", canDoLERPDetailBlend );
setCapability( "fourStageDetailBlend", canDoFourStageDetailBlend );
setCapability( "independentMrtBitDepth", canDoIndependentMrtBitDepth);
}
bool GFXD3D9CardProfiler::_queryCardCap(const String &query, U32 &foundResult)

View file

@ -731,7 +731,8 @@ void GFXD3D9Device::setShader( GFXShader *shader, bool force )
//-----------------------------------------------------------------------------
GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer( U32 numIndices,
U32 numPrimitives,
GFXBufferType bufferType )
GFXBufferType bufferType,
void* data )
{
// Allocate a buffer to return
GFXD3D9PrimitiveBuffer * res = new GFXD3D9PrimitiveBuffer(this, numIndices, numPrimitives, bufferType);
@ -741,12 +742,13 @@ GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer( U32 numIndices,
D3DPOOL pool = D3DPOOL_DEFAULT;
// Assumptions:
// - static buffers are write once, use many
// - static buffers are write rarely, use many
// - dynamic buffers are write many, use many
// - volatile buffers are write once, use once
// You may never read from a buffer.
switch(bufferType)
{
case GFXBufferTypeImmutable:
case GFXBufferTypeStatic:
pool = isD3D9Ex() ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
break;
@ -781,6 +783,14 @@ GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer( U32 numIndices,
D3D9Assert(mD3DDevice->CreateIndexBuffer( sizeof(U16) * numIndices , usage, GFXD3D9IndexFormat[GFXIndexFormat16], pool, &res->ib, 0),
"Failed to allocate an index buffer.");
}
if(data)
{
void* dest;
res->lock(0, numIndices, &dest);
dMemcpy(dest, data, sizeof(U16) * numIndices);
res->unlock();
}
return res;
}
@ -791,7 +801,8 @@ GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer( U32 numIndices,
GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer( U32 numVerts,
const GFXVertexFormat *vertexFormat,
U32 vertSize,
GFXBufferType bufferType )
GFXBufferType bufferType,
void* data)
{
PROFILE_SCOPE( GFXD3D9Device_allocVertexBuffer );
@ -808,7 +819,7 @@ GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer( U32 numVerts,
res->mNumVerts = 0;
// Assumptions:
// - static buffers are write once, use many
// - static buffers are write rarely, use many
// - dynamic buffers are write many, use many
// - volatile buffers are write once, use once
// You may never read from a buffer.
@ -850,6 +861,15 @@ GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer( U32 numVerts,
}
res->mNumVerts = numVerts;
if(data)
{
void* dest;
res->lock(0, numVerts, &dest);
dMemcpy(dest, data, vertSize * numVerts);
res->unlock();
}
return res;
}

View file

@ -298,10 +298,12 @@ public:
virtual GFXVertexBuffer* allocVertexBuffer( U32 numVerts,
const GFXVertexFormat *vertexFormat,
U32 vertSize,
GFXBufferType bufferType );
GFXBufferType bufferType,
void* data = NULL );
virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices,
U32 numPrimitives,
GFXBufferType bufferType );
GFXBufferType bufferType,
void* data = NULL );
virtual void deallocVertexBuffer( GFXD3D9VertexBuffer *vertBuff );
virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat );
virtual void setVertexDecl( const GFXVertexDecl *decl );

View file

@ -31,6 +31,7 @@ void GFXD3D9PrimitiveBuffer::lock(U32 indexStart, U32 indexEnd, void **indexPtr)
U32 flags=0;
switch(mBufferType)
{
case GFXBufferTypeImmutable:
case GFXBufferTypeStatic:
// flags |= D3DLOCK_DISCARD;
break;

View file

@ -31,6 +31,9 @@
#include "gfx/gfxDebugEvent.h"
#include "windowManager/win32/win32Window.h"
#ifndef _GFXDEVICE_H_
#include "gfx/gfxDevice.h"
#endif
GFXPCD3D9TextureTarget::GFXPCD3D9TextureTarget()
: mTargetSize( Point2I::Zero ),
@ -451,6 +454,7 @@ void GFXPCD3D9WindowTarget::createAdditionalSwapChain()
void GFXPCD3D9WindowTarget::resetMode()
{
GFX->beginReset();
mWindow->setSuppressReset(true);
if (mSwapChain)
@ -509,6 +513,7 @@ void GFXPCD3D9WindowTarget::zombify()
void GFXPCD3D9WindowTarget::resurrect()
{
GFX->beginReset();
if(mImplicit)
{
setImplicitSwapChain();

View file

@ -276,14 +276,16 @@ GFXNullDevice::~GFXNullDevice()
GFXVertexBuffer *GFXNullDevice::allocVertexBuffer( U32 numVerts,
const GFXVertexFormat *vertexFormat,
U32 vertSize,
GFXBufferType bufferType )
GFXBufferType bufferType,
void* data )
{
return new GFXNullVertexBuffer(GFX, numVerts, vertexFormat, vertSize, bufferType);
}
GFXPrimitiveBuffer *GFXNullDevice::allocPrimitiveBuffer( U32 numIndices,
U32 numPrimitives,
GFXBufferType bufferType)
GFXBufferType bufferType,
void* data )
{
return new GFXNullPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType);
}

View file

@ -115,10 +115,12 @@ protected:
virtual GFXVertexBuffer *allocVertexBuffer( U32 numVerts,
const GFXVertexFormat *vertexFormat,
U32 vertSize,
GFXBufferType bufferType );
GFXBufferType bufferType,
void* data = NULL );
virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices,
U32 numPrimitives,
GFXBufferType bufferType );
GFXBufferType bufferType,
void* data = NULL );
virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat ) { return NULL; }
virtual void setVertexDecl( const GFXVertexDecl *decl ) { }

View file

@ -326,7 +326,7 @@ void GBitmap::allocateBitmap(const U32 in_width, const U32 in_height, const bool
mNumMipLevels++;
allocPixels += currWidth * currHeight * mBytesPerPixel;
} while (currWidth != 1 || currHeight != 1);
} while (currWidth != 1 && currHeight != 1);
}
AssertFatal(mNumMipLevels <= c_maxMipLevels, "GBitmap::allocateBitmap: too many miplevels");

View file

@ -483,7 +483,7 @@ static bool sReadTGA(Stream &stream, GBitmap *bitmap)
static bool sWriteTGA(GBitmap *bitmap, Stream &stream, U32 compressionLevel)
{
AssertISV(false, "GBitmap::writeTGA - doesn't support writing tga files!")
AssertISV(false, "GBitmap::writeTGA - doesn't support writing tga files!");
return false;
}

View file

@ -148,7 +148,7 @@ GFXDevice::GFXDevice()
mGlobalAmbientColor = ColorF(0.0f, 0.0f, 0.0f, 1.0f);
mLightMaterialDirty = false;
dMemset(&mCurrentLightMaterial, NULL, sizeof(GFXLightMaterial));
dMemset(&mCurrentLightMaterial, 0, sizeof(GFXLightMaterial));
// State block
mStateBlockDirty = false;

View file

@ -302,6 +302,7 @@ protected:
/// This will allow querying to see if a device is initialized and ready to
/// have operations performed on it.
bool mInitialized;
bool mReset;
/// This is called before this, or any other device, is deleted in the global destroy()
/// method. It allows the device to clean up anything while everything is still valid.
@ -326,6 +327,10 @@ public:
/// @see endScene
bool canCurrentlyRender() const { return mCanCurrentlyRender; }
bool recentlyReset(){ return mReset; }
void beginReset(){ mReset = true; }
void finalizeReset(){ mReset = false; }
void setAllowRender( bool render ) { mAllowRender = render; }
inline bool allowRender() const { return mAllowRender; }
@ -637,7 +642,8 @@ protected:
virtual GFXVertexBuffer *allocVertexBuffer( U32 numVerts,
const GFXVertexFormat *vertexFormat,
U32 vertSize,
GFXBufferType bufferType ) = 0;
GFXBufferType bufferType,
void* data = NULL ) = 0;
/// Called from GFXVertexFormat to allocate the hardware
/// specific vertex declaration for rendering.
@ -674,7 +680,8 @@ protected:
/// @note All index buffers use unsigned 16-bit indices.
virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices,
U32 numPrimitives,
GFXBufferType bufferType ) = 0;
GFXBufferType bufferType,
void* data = NULL ) = 0;
/// @}

View file

@ -526,10 +526,10 @@ void GFXDrawUtil::drawRectFill( const Point2F &upperLeft, const Point2F &lowerRi
F32 ulOffset = 0.5f - mDevice->getFillConventionOffset();
verts[0].point.set( upperLeft.x+nw.x+ulOffset, upperLeft.y+nw.y+ulOffset, 0.0f );
verts[1].point.set( lowerRight.x+ne.x, upperLeft.y+ne.y+ulOffset, 0.0f );
verts[2].point.set( upperLeft.x-ne.x+ulOffset, lowerRight.y-ne.y, 0.0f );
verts[3].point.set( lowerRight.x-nw.x, lowerRight.y-nw.y, 0.0f );
verts[0].point.set( upperLeft.x + nw.x + ulOffset, upperLeft.y + nw.y + ulOffset, 0.0f);
verts[1].point.set( lowerRight.x + ne.x + ulOffset, upperLeft.y + ne.y + ulOffset, 0.0f);
verts[2].point.set( upperLeft.x - ne.x + ulOffset, lowerRight.y - ne.y + ulOffset, 0.0f);
verts[3].point.set( lowerRight.x - nw.x + ulOffset, lowerRight.y - nw.y + ulOffset, 0.0f);
for (S32 i=0; i<4; i++)
verts[i].color = color;

View file

@ -39,8 +39,8 @@
enum GFXBufferType
{
GFXBufferTypeStatic, ///< Static vertex buffers are created and filled one time.
///< incur a performance penalty. Resizing a static vertex buffer is not
GFXBufferTypeStatic, ///< Static vertex buffers are created and rarely updated.
///< Updating might incur a performance penalty. Resizing a static vertex buffer is not
///< allowed.
GFXBufferTypeDynamic, ///< Dynamic vertex buffers are meant for vertices that can be changed
///< often. Vertices written into dynamic vertex buffers will remain valid
@ -48,7 +48,8 @@ enum GFXBufferType
///< allowed.
GFXBufferTypeVolatile, ///< Volatile vertex or index buffers are meant for vertices or indices that are essentially
///< only used once. They can be resized without any performance penalty.
GFXBufferTypeImmutable, ///< Immutable buffers must specify the data when creating the buffer. Cannot be modified.
GFXBufferType_COUNT ///< Number of buffer types.
};

View file

@ -80,3 +80,16 @@ void GFXPrimitiveBufferHandle::set(GFXDevice *theDevice, U32 indexCount, U32 pri
getPointer()->mDebugCreationPath = desc;
#endif
}
//-----------------------------------------------------------------------------
// immutable
//-----------------------------------------------------------------------------
void GFXPrimitiveBufferHandle::immutable(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, void* data, String desc)
{
StrongRefPtr<GFXPrimitiveBuffer>::operator=( theDevice->allocPrimitiveBuffer(indexCount, primitiveCount, GFXBufferTypeImmutable, data) );
#ifdef TORQUE_DEBUG
if( desc.isNotEmpty() )
getPointer()->mDebugCreationPath = desc;
#endif
}

View file

@ -140,6 +140,8 @@ public:
}
void set(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, GFXBufferType bufferType, String desc = String::EmptyString );
void immutable(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, void* data, String desc = String::EmptyString );
void lock(U16 **indexBuffer, GFXPrimitive **primitiveBuffer = NULL, U32 indexStart = 0, U32 indexEnd = 0)
{

View file

@ -1099,7 +1099,7 @@ void GFXTextureManager::_validateTexParams( const U32 width, const U32 height,
currHeight = 1;
inOutNumMips++;
} while ( currWidth != 1 || currHeight != 1 );
} while ( currWidth != 1 && currHeight != 1 );
}
}
}

View file

@ -143,6 +143,11 @@ public:
init();
}
~GLCircularVolatileBuffer()
{
glDeleteBuffers(1, &mBufferName);
}
void init()
{
glGenBuffers(1, &mBufferName);
@ -290,4 +295,4 @@ protected:
};
#endif
#endif

View file

@ -355,23 +355,47 @@ GFXPrimitiveBuffer* GFXGLDevice::findVolatilePBO(U32 numIndices, U32 numPrimitiv
GFXVertexBuffer *GFXGLDevice::allocVertexBuffer( U32 numVerts,
const GFXVertexFormat *vertexFormat,
U32 vertSize,
GFXBufferType bufferType )
GFXBufferType bufferType,
void* data )
{
if(bufferType == GFXBufferTypeVolatile)
return findVolatileVBO(numVerts, vertexFormat, vertSize);
GFXGLVertexBuffer* buf = new GFXGLVertexBuffer( GFX, numVerts, vertexFormat, vertSize, bufferType );
buf->registerResourceWithDevice(this);
buf->registerResourceWithDevice(this);
if(data)
{
void* dest;
buf->lock(0, numVerts, &dest);
dMemcpy(dest, data, vertSize * numVerts);
buf->unlock();
}
return buf;
}
GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType )
GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data )
{
GFXPrimitiveBuffer* buf;
if(bufferType == GFXBufferTypeVolatile)
return findVolatilePBO(numIndices, numPrimitives);
GFXGLPrimitiveBuffer* buf = new GFXGLPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType);
buf->registerResourceWithDevice(this);
{
buf = findVolatilePBO(numIndices, numPrimitives);
}
else
{
buf = new GFXGLPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType);
buf->registerResourceWithDevice(this);
}
if(data)
{
void* dest;
buf->lock(0, numIndices, &dest);
dMemcpy(dest, data, sizeof(U16) * numIndices);
buf->unlock();
}
return buf;
}

View file

@ -173,8 +173,9 @@ protected:
virtual GFXVertexBuffer *allocVertexBuffer( U32 numVerts,
const GFXVertexFormat *vertexFormat,
U32 vertSize,
GFXBufferType bufferType );
virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType );
GFXBufferType bufferType,
void* data = NULL);
virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data = NULL );
// NOTE: The GL device doesn't need a vertex declaration at
// this time, but we need to return something to keep the system

View file

@ -45,6 +45,7 @@ void GFXGLEnumTranslate::init()
GFXGLBufferType[GFXBufferTypeStatic] = GL_STATIC_DRAW;
GFXGLBufferType[GFXBufferTypeDynamic] = GL_DYNAMIC_DRAW;
GFXGLBufferType[GFXBufferTypeVolatile] = GL_STREAM_DRAW;
GFXGLBufferType[GFXBufferTypeImmutable] = GL_STATIC_DRAW;
// Primitives
GFXGLPrimType[GFXPointList] = GL_POINTS;

View file

@ -107,6 +107,14 @@ void GFXGLStateBlock::activate(const GFXGLStateBlock* oldState)
if(STATE_CHANGE(blendOp))
glBlendEquation(GFXGLBlendOp[mDesc.blendOp]);
if (mDesc.separateAlphaBlendEnable == true)
{
if (STATE_CHANGE(separateAlphaBlendSrc) || STATE_CHANGE(separateAlphaBlendDest))
glBlendFuncSeparate(GFXGLBlend[mDesc.blendSrc], GFXGLBlend[mDesc.blendDest], GFXGLBlend[mDesc.separateAlphaBlendSrc], GFXGLBlend[mDesc.separateAlphaBlendDest]);
if (STATE_CHANGE(separateAlphaBlendOp))
glBlendEquationSeparate(GFXGLBlendOp[mDesc.blendOp], GFXGLBlendOp[mDesc.separateAlphaBlendOp]);
}
// Color write masks
if(STATE_CHANGE(colorWriteRed) || STATE_CHANGE(colorWriteBlue) || STATE_CHANGE(colorWriteGreen) || STATE_CHANGE(colorWriteAlpha))
glColorMask(mDesc.colorWriteRed, mDesc.colorWriteBlue, mDesc.colorWriteGreen, mDesc.colorWriteAlpha);

View file

@ -163,6 +163,10 @@ void _GFXGLTextureTargetFBOImpl::applyState()
PRESERVE_FRAMEBUFFER();
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
bool drawbufs[16];
int bufsize = 0;
for (int i = 0; i < 16; i++)
drawbufs[i] = false;
bool hasColor = false;
for(int i = 0; i < GFXGL->getNumRenderTargets(); ++i)
{
@ -200,6 +204,20 @@ void _GFXGLTextureTargetFBOImpl::applyState()
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
}
GLenum *buf = new GLenum[bufsize];
int count = 0;
for (int i = 0; i < bufsize; i++)
{
if (drawbufs[i])
{
buf[count] = GL_COLOR_ATTACHMENT0 + i;
count++;
}
}
glDrawBuffers(bufsize, buf);
delete[] buf;
CHECK_FRAMEBUFFER_STATUS();
}
@ -260,7 +278,10 @@ GFXGLTextureTarget::GFXGLTextureTarget() : mCopyFboSrc(0), mCopyFboDst(0)
GFXGLTextureTarget::~GFXGLTextureTarget()
{
GFXTextureManager::removeEventDelegate( this, &GFXGLTextureTarget::_onTextureEvent );
GFXTextureManager::removeEventDelegate(this, &GFXGLTextureTarget::_onTextureEvent);
glDeleteFramebuffers(1, &mCopyFboSrc);
glDeleteFramebuffers(1, &mCopyFboDst);
}
const Point2I GFXGLTextureTarget::getSize()

View file

@ -42,6 +42,14 @@ GFXGLWindowTarget::GFXGLWindowTarget(PlatformWindow *win, GFXDevice *d)
win->appEvent.notify(this, &GFXGLWindowTarget::_onAppSignal);
}
GFXGLWindowTarget::~GFXGLWindowTarget()
{
if(glIsFramebuffer(mCopyFBO))
{
glDeleteFramebuffers(1, &mCopyFBO);
}
}
void GFXGLWindowTarget::resetMode()
{
if(mWindow->getVideoMode().fullScreen != mWindow->isFullscreen())
@ -49,6 +57,7 @@ void GFXGLWindowTarget::resetMode()
_teardownCurrentMode();
_setupNewMode();
}
GFX->beginReset();
}
void GFXGLWindowTarget::_onAppSignal(WindowId wnd, S32 event)

View file

@ -30,6 +30,8 @@ class GFXGLWindowTarget : public GFXWindowTarget
public:
GFXGLWindowTarget(PlatformWindow *win, GFXDevice *d);
~GFXGLWindowTarget();
const Point2I getSize()
{
return mWindow->getClientExtent();
@ -64,4 +66,4 @@ private:
void _WindowPresent();
};
#endif
#endif

View file

@ -83,6 +83,10 @@ void GFXGLDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
);
SDL_ClearError();
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GLContext tempContext = SDL_GL_CreateContext( tempWindow );
if( !tempContext )
{

View file

@ -29,6 +29,7 @@ namespace GL
{
void gglPerformBinds()
{
glewExperimental = GL_TRUE;
GLenum err = glewInit();
AssertFatal(GLEW_OK == err, avar("Error: %s\n", glewGetErrorString(err)) );
}

View file

@ -24,7 +24,13 @@
#define T_GL_H
#include "GL/glew.h"
#if defined (TORQUE_OS_WIN)
// This doesn't work on Mesa drivers.
#define gglHasExtension(EXTENSION) GLEW_##EXTENSION
#else
// Slower but reliably detects extensions on Mesa.
#define gglHasExtension(EXTENSION) glewGetExtension("GL_" # EXTENSION)
#endif
#endif

View file

@ -132,6 +132,11 @@ void DebugDrawer::setupStateBlocks()
d.setZReadWrite(false);
mRenderZOffSB = GFX->createStateBlock(d);
d.setCullMode(GFXCullCCW);
d.setZReadWrite(true, false);
d.setBlend(true);
mRenderAlpha = GFX->createStateBlock(d);
}
void DebugDrawer::render()
@ -158,10 +163,13 @@ void DebugDrawer::render()
// Set up the state block...
GFXStateBlockRef currSB;
if(p->useZ)
if(p->type==DebugPrim::Capsule){
currSB = mRenderAlpha;
}else if(p->useZ){
currSB = mRenderZOnSB;
else
}else{
currSB = mRenderZOffSB;
}
GFX->setStateBlock( currSB );
Point3F d;
@ -180,6 +188,47 @@ void DebugDrawer::render()
PrimBuild::end();
break;
case DebugPrim::DirectionLine:
{
const static F32 ARROW_LENGTH = 0.2f, ARROW_RADIUS = 0.035f, CYLINDER_RADIUS = 0.008f;
Point3F &start = p->a, &end = p->b;
Point3F direction = end - start;
F32 length = direction.len();
if( length>ARROW_LENGTH ){
//cylinder with arrow on end
direction *= (1.0f/length);
Point3F baseArrow = end - (direction*ARROW_LENGTH);
GFX->getDrawUtil()->drawCone(currSB->getDesc(), baseArrow, end, ARROW_RADIUS, p->color);
GFX->getDrawUtil()->drawCylinder(currSB->getDesc(), start, baseArrow, CYLINDER_RADIUS, p->color);
}else if( length>0 ){
//short, so just draw arrow
GFX->getDrawUtil()->drawCone(currSB->getDesc(), start, end, ARROW_RADIUS, p->color);
}
}
break;
case DebugPrim::Capsule:
GFX->getDrawUtil()->drawCapsule(currSB->getDesc(), p->a, p->b.x, p->b.y, p->color);
break;
case DebugPrim::OutlinedText:
{
GFXTransformSaver saver;
Point3F result;
if (MathUtils::mProjectWorldToScreen(p->a, &result, GFX->getViewport(), GFX->getWorldMatrix(), GFX->getProjectionMatrix()))
{
GFX->setClipRect(GFX->getViewport());
Point2I where = Point2I(result.x, result.y);
GFX->getDrawUtil()->setBitmapModulation(p->color2);
GFX->getDrawUtil()->drawText(mFont, Point2I(where.x-1, where.y), p->mText);
GFX->getDrawUtil()->drawText(mFont, Point2I(where.x+1, where.y), p->mText);
GFX->getDrawUtil()->drawText(mFont, Point2I(where.x, where.y-1), p->mText);
GFX->getDrawUtil()->drawText(mFont, Point2I(where.x, where.y+1), p->mText);
GFX->getDrawUtil()->setBitmapModulation(p->color);
GFX->getDrawUtil()->drawText(mFont, where, p->mText);
}
}
break;
case DebugPrim::Box:
d = p->a - p->b;
GFX->getDrawUtil()->drawCube(currSB->getDesc(), d * 0.5, (p->a + p->b) * 0.5, p->color);
@ -262,6 +311,63 @@ void DebugDrawer::drawLine(const Point3F &a, const Point3F &b, const ColorF &col
mHead = n;
}
void DebugDrawer::drawCapsule(const Point3F &a, const F32 &radius, const F32 &height, const ColorF &color)
{
if(isFrozen || !isDrawing)
return;
DebugPrim *n = mPrimChunker.alloc();
n->useZ = true;
n->dieTime = 0;
n->a = a;
n->b.x = radius;
n->b.y = height;
n->color = color;
n->type = DebugPrim::Capsule;
n->next = mHead;
mHead = n;
}
void DebugDrawer::drawDirectionLine(const Point3F &a, const Point3F &b, const ColorF &color)
{
if(isFrozen || !isDrawing)
return;
DebugPrim *n = mPrimChunker.alloc();
n->useZ = true;
n->dieTime = 0;
n->a = a;
n->b = b;
n->color = color;
n->type = DebugPrim::DirectionLine;
n->next = mHead;
mHead = n;
}
void DebugDrawer::drawOutlinedText(const Point3F& pos, const String& text, const ColorF &color, const ColorF &colorOutline)
{
if(isFrozen || !isDrawing)
return;
DebugPrim *n = mPrimChunker.alloc();
n->useZ = false;
n->dieTime = 0;
n->a = pos;
n->color = color;
n->color2 = colorOutline;
dStrncpy(n->mText, text.c_str(), 256);
n->type = DebugPrim::OutlinedText;
n->next = mHead;
mHead = n;
}
void DebugDrawer::drawTri(const Point3F &a, const Point3F &b, const Point3F &c, const ColorF &color)
{
if(isFrozen || !isDrawing)

View file

@ -124,7 +124,10 @@ public:
void drawLine(const Point3F &a, const Point3F &b, const ColorF &color = ColorF(1.0f,1.0f,1.0f));
void drawTri(const Point3F &a, const Point3F &b, const Point3F &c, const ColorF &color = ColorF(1.0f,1.0f,1.0f));
void drawText(const Point3F& pos, const String& text, const ColorF &color = ColorF(1.0f,1.0f,1.0f));
void drawCapsule(const Point3F &a, const F32 &radius, const F32 &height, const ColorF &color = ColorF(1.0f, 1.0f, 1.0f));
void drawDirectionLine(const Point3F &a, const Point3F &b, const ColorF &color = ColorF(1.0f, 1.0f, 1.0f));
void drawOutlinedText(const Point3F& pos, const String& text, const ColorF &color = ColorF(1.0f, 1.0f, 1.0f), const ColorF &colorOutline = ColorF(0.0f, 0.0f, 0.0f));
/// Render a wireframe view of the given polyhedron.
void drawPolyhedron( const AnyPolyhedron& polyhedron, const ColorF& color = ColorF( 1.f, 1.f, 1.f ) );
@ -161,6 +164,7 @@ private:
{
/// Color used for this primitive.
ColorF color;
ColorF color2;
/// Points used to store positional data. Exact semantics determined by type.
Point3F a, b, c;
@ -168,7 +172,10 @@ private:
Tri,
Box,
Line,
Text
Text,
DirectionLine,
OutlinedText,
Capsule,
} type; ///< Type of the primitive. The meanings of a,b,c are determined by this.
SimTime dieTime; ///< Time at which we should remove this from the list.
@ -188,6 +195,7 @@ private:
GFXStateBlockRef mRenderZOffSB;
GFXStateBlockRef mRenderZOnSB;
GFXStateBlockRef mRenderAlpha;
Resource<GFont> mFont;

View file

@ -39,13 +39,13 @@ ColorF colorAlpha(0.0f, 0.0f, 0.0f, 0.0f);
ColorF colorAlphaW(1.0f, 1.0f, 1.0f, 0.0f);
ColorI GuiColorPickerCtrl::mColorRange[7] = {
ColorI(255,0,0), // Red
ColorI(255,0,255), // Pink
ColorI(0,0,255), // Blue
ColorI(0,255,255), // Light blue
ColorI(0,255,0), // Green
ColorI(255,255,0), // Yellow
ColorI(255,0,0), // Red
ColorI(255,0,0), // Red
ColorI(255,0,255), // Pink
ColorI(0,0,255), // Blue
ColorI(0,255,255), // Light blue
ColorI(0,255,0), // Green
ColorI(255,255,0), // Yellow
ColorI(255,0,0), // Red
};
/// @}
@ -57,7 +57,6 @@ ConsoleDocClass( GuiColorPickerCtrl,
"@internal"
);
//--------------------------------------------------------------------------
GuiColorPickerCtrl::GuiColorPickerCtrl()
{
setExtent(140, 30);
@ -70,44 +69,50 @@ GuiColorPickerCtrl::GuiColorPickerCtrl()
mPositionChanged = false;
mSelectorGap = 1;
mActionOnMove = false;
mShowReticle = true;
mShowReticle = true;
mSelectColor = false;
mSetColor = mSetColor.BLACK;
mBitmap = NULL;
}
//--------------------------------------------------------------------------
GuiColorPickerCtrl::~GuiColorPickerCtrl()
{
if (mBitmap)
{
delete mBitmap;
mBitmap = NULL;
}
}
ImplementEnumType( GuiColorPickMode,
"\n\n"
"@ingroup GuiUtil"
"@internal" )
{ GuiColorPickerCtrl::pPallet, "Pallete" },
{ GuiColorPickerCtrl::pHorizColorRange, "HorizColor"},
{ GuiColorPickerCtrl::pVertColorRange, "VertColor" },
{ GuiColorPickerCtrl::pHorizColorBrightnessRange, "HorizBrightnessColor"},
{ GuiColorPickerCtrl::pVertColorBrightnessRange, "VertBrightnessColor" },
{ GuiColorPickerCtrl::pBlendColorRange, "BlendColor"},
{ GuiColorPickerCtrl::pHorizAlphaRange, "HorizAlpha"},
{ GuiColorPickerCtrl::pVertAlphaRange, "VertAlpha" },
{ GuiColorPickerCtrl::pDropperBackground, "Dropper" },
{ GuiColorPickerCtrl::pPallet, "Pallete" },
{ GuiColorPickerCtrl::pHorizColorRange, "HorizColor"},
{ GuiColorPickerCtrl::pVertColorRange, "VertColor" },
{ GuiColorPickerCtrl::pHorizColorBrightnessRange, "HorizBrightnessColor" },
{ GuiColorPickerCtrl::pVertColorBrightnessRange, "VertBrightnessColor" },
{ GuiColorPickerCtrl::pBlendColorRange, "BlendColor" },
{ GuiColorPickerCtrl::pHorizAlphaRange, "HorizAlpha" },
{ GuiColorPickerCtrl::pVertAlphaRange, "VertAlpha" },
{ GuiColorPickerCtrl::pDropperBackground, "Dropper" },
EndImplementEnumType;
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::initPersistFields()
{
addGroup("ColorPicker");
addField("baseColor", TypeColorF, Offset(mBaseColor, GuiColorPickerCtrl));
addField("pickColor", TypeColorF, Offset(mPickColor, GuiColorPickerCtrl));
addField("selectorGap", TypeS32, Offset(mSelectorGap, GuiColorPickerCtrl));
addField("displayMode", TYPEID< PickMode >(), Offset(mDisplayMode, GuiColorPickerCtrl) );
addField("actionOnMove", TypeBool,Offset(mActionOnMove, GuiColorPickerCtrl));
addField("showReticle", TypeBool, Offset(mShowReticle, GuiColorPickerCtrl));
endGroup("ColorPicker");
Parent::initPersistFields();
}
//--------------------------------------------------------------------------
// Function to draw a box which can have 4 different colors in each corner blended together
void GuiColorPickerCtrl::drawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, ColorF &c3, ColorF &c4)
{
@ -119,54 +124,54 @@ void GuiColorPickerCtrl::drawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, Col
//A couple of checks to determine if color blend
if(c1 == colorWhite && c3 == colorAlpha && c4 == colorBlack)
{
//Color
PrimBuild::begin( GFXTriangleFan, 4 );
PrimBuild::color( c2 );
PrimBuild::vertex2i( r, t );
//Color
PrimBuild::begin(GFXTriangleFan, 4);
PrimBuild::color( c2 );
PrimBuild::vertex2i( r, t );
PrimBuild::color( c2 );
PrimBuild::vertex2i( r, b );
PrimBuild::color( c2 );
PrimBuild::vertex2i( r, b );
PrimBuild::color( c2 );
PrimBuild::vertex2i( l, b );
PrimBuild::color( c2 );
PrimBuild::vertex2i( l, b );
PrimBuild::color( c2 );
PrimBuild::vertex2i( l, t );
PrimBuild::end();
PrimBuild::color( c2 );
PrimBuild::vertex2i( l, t );
PrimBuild::end();
//White
PrimBuild::begin( GFXTriangleFan, 4 );
PrimBuild::color( colorAlphaW );
PrimBuild::vertex2i( r, t );
//White
PrimBuild::begin( GFXTriangleFan, 4 );
PrimBuild::color( colorAlphaW );
PrimBuild::vertex2i( r, t );
PrimBuild::color( colorAlphaW );
PrimBuild::vertex2i( r, b );
PrimBuild::color( colorAlphaW );
PrimBuild::vertex2i( r, b );
PrimBuild::color( c1 );
PrimBuild::vertex2i( l, b );
PrimBuild::color( c1 );
PrimBuild::vertex2i( l, b );
PrimBuild::color( c1 );
PrimBuild::vertex2i( l, t );
PrimBuild::end();
PrimBuild::color( c1 );
PrimBuild::vertex2i( l, t );
PrimBuild::end();
//Black
PrimBuild::begin( GFXTriangleFan, 4 );
PrimBuild::color( c3 );
PrimBuild::vertex2i( r, t );
//Black
PrimBuild::begin( GFXTriangleFan, 4 );
PrimBuild::color( c3 );
PrimBuild::vertex2i( r, t );
PrimBuild::color( c4 );
PrimBuild::vertex2i( r, b );
PrimBuild::color( c4 );
PrimBuild::vertex2i( r, b );
PrimBuild::color( c4 );
PrimBuild::vertex2i( l, b );
PrimBuild::color( c4 );
PrimBuild::vertex2i( l, b );
PrimBuild::color( c3 );
PrimBuild::vertex2i( l, t );
PrimBuild::end();
PrimBuild::color( c3 );
PrimBuild::vertex2i( l, t );
PrimBuild::end();
}
else
{
PrimBuild::begin( GFXTriangleFan, 4 );
PrimBuild::begin( GFXTriangleFan, 4 );
PrimBuild::color( c1 );
PrimBuild::vertex2i( l, t );
@ -233,31 +238,29 @@ void GuiColorPickerCtrl::drawBlendRangeBox(RectI &bounds, bool vertical, U8 numC
void GuiColorPickerCtrl::drawSelector(RectI &bounds, Point2I &selectorPos, SelectorMode mode)
{
if( !mShowReticle )
return;
if( !mShowReticle )
return;
U16 sMax = mSelectorGap*2;
switch (mode)
{
case sVertical:
// Now draw the vertical selector
// Up -> Pos
if (selectorPos.y != bounds.point.y+1)
GFX->getDrawUtil()->drawLine(selectorPos.x, bounds.point.y, selectorPos.x, selectorPos.y-sMax-1, colorWhiteBlend);
// Down -> Pos
if (selectorPos.y != bounds.point.y+bounds.extent.y)
GFX->getDrawUtil()->drawLine(selectorPos.x, selectorPos.y + sMax, selectorPos.x, bounds.point.y + bounds.extent.y, colorWhiteBlend);
break;
case sHorizontal:
// Now draw the horizontal selector
// Left -> Pos
if (selectorPos.x != bounds.point.x)
U16 sMax = mSelectorGap*2;
switch (mode)
{
case sVertical:
// Now draw the vertical selector Up -> Pos
if (selectorPos.y != bounds.point.y+1)
GFX->getDrawUtil()->drawLine(selectorPos.x, bounds.point.y, selectorPos.x, selectorPos.y-sMax-1, colorWhiteBlend);
// Down -> Pos
if (selectorPos.y != bounds.point.y+bounds.extent.y)
GFX->getDrawUtil()->drawLine(selectorPos.x, selectorPos.y + sMax, selectorPos.x, bounds.point.y + bounds.extent.y, colorWhiteBlend);
break;
case sHorizontal:
// Now draw the horizontal selector Left -> Pos
if (selectorPos.x != bounds.point.x)
GFX->getDrawUtil()->drawLine(bounds.point.x, selectorPos.y-1, selectorPos.x-sMax, selectorPos.y-1, colorWhiteBlend);
// Right -> Pos
if (selectorPos.x != bounds.point.x)
// Right -> Pos
if (selectorPos.x != bounds.point.x)
GFX->getDrawUtil()->drawLine(bounds.point.x+mSelectorPos.x+sMax, selectorPos.y-1, bounds.point.x + bounds.extent.x, selectorPos.y-1, colorWhiteBlend);
break;
}
break;
}
}
//--------------------------------------------------------------------------
@ -269,10 +272,10 @@ void GuiColorPickerCtrl::renderColorBox(RectI &bounds)
pickerBounds.point.y = bounds.point.y+1;
pickerBounds.extent.x = bounds.extent.x-1;
pickerBounds.extent.y = bounds.extent.y-1;
if (mProfile->mBorder)
GFX->getDrawUtil()->drawRect(bounds, mProfile->mBorderColor);
Point2I selectorPos = Point2I(bounds.point.x+mSelectorPos.x+1, bounds.point.y+mSelectorPos.y+1);
// Draw color box differently depending on mode
@ -338,56 +341,169 @@ void GuiColorPickerCtrl::onRender(Point2I offset, const RectI& updateRect)
desc.setZReadWrite(false);
desc.zWriteEnable = false;
desc.setCullMode(GFXCullNone);
mStateBlock = GFX->createStateBlock( desc );
mStateBlock = GFX->createStateBlock(desc);
}
RectI boundsRect(offset, getExtent());
RectI boundsRect(offset, getExtent());
renderColorBox(boundsRect);
if (mPositionChanged)
if (mPositionChanged || mBitmap == NULL)
{
bool nullBitmap = false;
if (mPositionChanged == false && mBitmap == NULL)
nullBitmap = true;
mPositionChanged = false;
Point2I extent = getRoot()->getExtent();
// If we are anything but a pallete, change the pick color
if (mDisplayMode != pPallet)
{
Point2I resolution = getRoot()->getExtent();
U32 buf_x = offset.x + mSelectorPos.x + 1;
U32 buf_y = resolution.y - ( extent.y - ( offset.y + mSelectorPos.y + 1 ) );
U32 buf_y = resolution.y - (extent.y - (offset.y + mSelectorPos.y + 1));
GFXTexHandle bb( resolution.x,
resolution.y,
GFXFormatR8G8B8A8, &GFXDefaultRenderTargetProfile, avar("%s() - bb (line %d)", __FUNCTION__, __LINE__) );
Point2I tmpPt( buf_x, buf_y );
GFXTexHandle bb( resolution.x, resolution.y, GFXFormatR8G8B8A8, &GFXDefaultRenderTargetProfile, avar("%s() - bb (line %d)", __FUNCTION__, __LINE__) );
Point2I tmpPt(buf_x, buf_y);
GFXTarget *targ = GFX->getActiveRenderTarget();
targ->resolveTo( bb );
GBitmap bmp( bb.getWidth(), bb.getHeight() );
targ->resolveTo(bb);
bb.copyToBmp( &bmp );
//bmp.writePNGDebug( "foo.png" );
if (mBitmap)
{
delete mBitmap;
mBitmap = NULL;
}
ColorI tmp;
bmp.getColor( buf_x, buf_y, tmp );
mBitmap = new GBitmap(bb.getWidth(), bb.getHeight());
mPickColor = (ColorF)tmp;
bb.copyToBmp(mBitmap);
// Now do onAction() if we are allowed
if (mActionOnMove)
onAction();
if (!nullBitmap)
{
if (mSelectColor)
{
Point2I pos = findColor(mSetColor, offset, resolution, *mBitmap);
mSetColor = mSetColor.BLACK;
mSelectColor = false;
setSelectorPos(pos);
}
else
{
ColorI tmp;
mBitmap->getColor(buf_x, buf_y, tmp);
mPickColor = (ColorF)tmp;
// Now do onAction() if we are allowed
if (mActionOnMove)
onAction();
}
}
}
}
//render the children
renderChildControls( offset, updateRect);
renderChildControls(offset, updateRect);
}
void GuiColorPickerCtrl::setSelectorPos(const ColorF & color)
{
if (mBitmap && !mPositionChanged)
{
Point2I resolution = getRoot() ? getRoot()->getExtent() : Point2I(1024, 768);
RectI rect(getGlobalBounds());
Point2I pos = findColor(color, rect.point, resolution, *mBitmap);
mSetColor = mSetColor.BLACK;
mSelectColor = false;
setSelectorPos(pos);
}
else
{
mSetColor = color;
mSelectColor = true;
mPositionChanged = true;
}
}
Point2I GuiColorPickerCtrl::findColor(const ColorF & color, const Point2I& offset, const Point2I& resolution, GBitmap& bmp)
{
RectI rect;
Point2I ext = getExtent();
if (mDisplayMode != pDropperBackground)
{
ext.x -= 3;
ext.y -= 2;
rect = RectI(Point2I(1, 1), ext);
}
else
{
rect = RectI(Point2I(0, 0), ext);
}
Point2I closestPos(-1, -1);
/* Debugging
char filename[256];
dSprintf( filename, 256, "%s.%s", "colorPickerTest", "png" );
// Open up the file on disk.
FileStream fs;
if ( !fs.open( filename, Torque::FS::File::Write ) )
Con::errorf( "GuiObjectView::saveAsImage() - Failed to open output file '%s'!", filename );
else
{
// Write it and close.
bmp.writeBitmap( "png", fs );
fs.close();
}
*/
ColorI tmp;
U32 buf_x;
U32 buf_y;
ColorF curColor;
F32 val(10000.0f);
F32 closestVal(10000.0f);
bool closestSet = false;
for (S32 x = rect.point.x; x <= rect.extent.x; x++)
{
for (S32 y = rect.point.y; y <= rect.extent.y; y++)
{
buf_x = offset.x + x + 1;
buf_y = (resolution.y - (offset.y + y + 1));
buf_y = resolution.y - buf_y;
//Get the color at that position
bmp.getColor(buf_x, buf_y, tmp);
curColor = (ColorF)tmp;
//Evaluate how close the color is to our desired color
val = mFabs(color.red - curColor.red) + mFabs(color.green - curColor.green) + mFabs(color.blue - curColor.blue);
if (!closestSet)
{
closestVal = val;
closestPos.set(x, y);
closestSet = true;
}
else if (val < closestVal)
{
closestVal = val;
closestPos.set(x, y);
}
}
}
return closestPos;
}
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::setSelectorPos(const Point2I &pos)
{
Point2I extent = getExtent();
@ -432,7 +548,6 @@ void GuiColorPickerCtrl::setSelectorPos(const Point2I &pos)
}
}
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::onMouseDown(const GuiEvent &event)
{
if (!mActive)
@ -445,14 +560,14 @@ void GuiColorPickerCtrl::onMouseDown(const GuiEvent &event)
if (mProfile->mCanKeyFocus)
setFirstResponder();
if (mActive && (mDisplayMode != pDropperBackground))
if (mActive && (mDisplayMode != pDropperBackground))
onAction();
// Update the picker cross position
if (mDisplayMode != pPallet)
setSelectorPos(globalToLocalCoord(event.mousePoint));
setSelectorPos(globalToLocalCoord(event.mousePoint));
mMouseDown = true;
}
@ -468,10 +583,8 @@ void GuiColorPickerCtrl::onMouseDragged(const GuiEvent &event)
if( !mActionOnMove )
execAltConsoleCallback();
}
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::onMouseMove(const GuiEvent &event)
{
// Only for dropper mode
@ -479,45 +592,40 @@ void GuiColorPickerCtrl::onMouseMove(const GuiEvent &event)
setSelectorPos(globalToLocalCoord(event.mousePoint));
}
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::onMouseEnter(const GuiEvent &event)
{
mMouseOver = true;
}
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::onMouseLeave(const GuiEvent &)
{
// Reset state
mMouseOver = false;
}
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::onMouseUp(const GuiEvent &)
{
//if we released the mouse within this control, perform the action
if (mActive && mMouseDown && (mDisplayMode != pDropperBackground))
if (mActive && mMouseDown && (mDisplayMode != pDropperBackground))
mMouseDown = false;
if (mActive && (mDisplayMode == pDropperBackground))
if (mActive && (mDisplayMode == pDropperBackground))
{
// In a dropper, the alt command executes the mouse up action (to signal stopping)
execAltConsoleCallback();
}
mouseUnlock();
}
//--------------------------------------------------------------------------
const char *GuiColorPickerCtrl::getScriptValue()
{
static char temp[256];
ColorF color = getValue();
dSprintf(temp,256,"%f %f %f %f",color.red, color.green, color.blue, color.alpha);
return temp;
dSprintf( temp, 256, "%f %f %f %f", color.red, color.green, color.blue, color.alpha );
return temp;
}
//--------------------------------------------------------------------------
void GuiColorPickerCtrl::setScriptValue(const char *value)
{
ColorF newValue;
@ -537,5 +645,12 @@ DefineConsoleMethod(GuiColorPickerCtrl, setSelectorPos, void, (Point2I newPos),
DefineConsoleMethod(GuiColorPickerCtrl, updateColor, void, (), , "Forces update of pick color")
{
object->updateColor();
object->updateColor();
}
DefineEngineMethod(GuiColorPickerCtrl, setSelectorColor, void, (ColorF color), ,
"Sets the current position of the selector based on a color.n"
"@param color Color to look for.n")
{
object->setSelectorPos(color);
}

View file

@ -59,29 +59,28 @@ class GuiColorPickerCtrl : public GuiControl
public:
enum PickMode
{
pPallet = 0, ///< We just have a solid color; We just act like a pallet
pHorizColorRange, ///< We have a range of base colors going horizontally
pVertColorRange, ///< We have a range of base colors going vertically
pPallet = 0, ///< We just have a solid color; We just act like a pallet
pHorizColorRange, ///< We have a range of base colors going horizontally
pVertColorRange, ///< We have a range of base colors going vertically
pHorizColorBrightnessRange, ///< HorizColorRange with brightness
pVertColorBrightnessRange, ///< VertColorRange with brightness
pBlendColorRange, ///< We have a box which shows a range in brightness of the color
pHorizAlphaRange, ///< We have a box which shows a range in alpha going horizontally
pVertAlphaRange, ///< We have a box which shows a range in alpha going vertically
pDropperBackground ///< The control does not draw anything; Only does something when you click, or move the mouse (when active)
pVertColorBrightnessRange, ///< VertColorRange with brightness
pBlendColorRange, ///< We have a box which shows a range in brightness of the color
pHorizAlphaRange, ///< We have a box which shows a range in alpha going horizontally
pVertAlphaRange, ///< We have a box which shows a range in alpha going vertically
pDropperBackground ///< The control does not draw anything; Only does something when you click, or move the mouse (when active)
};
enum SelectorMode
{
sHorizontal = 0, ///< Horizontal selector with small gap
sVertical, ///< Vertical selector with small gap
sHorizontal = 0, ///< Horizontal selector with small gap
sVertical, ///< Vertical selector with small gap
};
protected:
/// @name Core Rendering functions
/// @{
void renderColorBox(RectI &bounds); ///< Function that draws the actual color box
void drawSelector(RectI &bounds, Point2I &selectorPos, SelectorMode mode); ///< Function that draws the selection indicator
void renderColorBox(RectI &bounds); ///< Function that draws the actual color box
void drawSelector(RectI &bounds, Point2I &selectorPos, SelectorMode mode); /// < Function that draws the selection indicator
void drawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, ColorF &c3, ColorF &c4);
void drawBlendRangeBox(RectI &bounds, bool vertical, U8 numColors, ColorI *colors);
/// @}
@ -98,7 +97,11 @@ class GuiColorPickerCtrl : public GuiControl
bool mMouseDown; ///< Mouse button down?
bool mActionOnMove; ///< Perform onAction() when position has changed?
bool mSelectColor;
ColorF mSetColor;
GBitmap* mBitmap;
Point2I findColor(const ColorF & color, const Point2I& offset, const Point2I& resolution, GBitmap& bmp);
S32 mSelectorGap; ///< The half-way "gap" between the selector pos and where the selector is allowed to draw.
@ -107,12 +110,13 @@ class GuiColorPickerCtrl : public GuiControl
static ColorI mColorRange[7]; ///< Color range for pHorizColorRange and pVertColorRange
/// @}
public:
public:
DECLARE_CONOBJECT(GuiColorPickerCtrl);
DECLARE_CATEGORY( "Gui Editor" );
GuiColorPickerCtrl();
~GuiColorPickerCtrl();
static void initPersistFields();
void onRender(Point2I offset, const RectI &updateRect);
@ -122,18 +126,19 @@ class GuiColorPickerCtrl : public GuiControl
/// NOTE: setValue only sets baseColor, since setting pickColor wouldn't be useful
void setValue(ColorF &value) {mBaseColor = value;}
/// NOTE: getValue() returns baseColor if pallet (since pallet controls can't "pick" colours themselves)
ColorF getValue() {return mDisplayMode == pPallet ? mBaseColor : mPickColor;}
ColorF getValue() { return mDisplayMode == pPallet ? mBaseColor : mPickColor; }
const char *getScriptValue();
void setScriptValue(const char *value);
void updateColor() {mPositionChanged = true;}
/// @}
/// @name Selector Functions
/// @{
void setSelectorPos(const Point2I &pos); ///< Set new pos (in local coords)
void setSelectorPos(const ColorF & color);
Point2I getSelectorPos() {return mSelectorPos;}
/// @}
/// @name Input Events
/// @{
void onMouseDown(const GuiEvent &);

View file

@ -128,6 +128,8 @@ GuiTextEditCtrl::GuiTextEditCtrl()
mActive = true;
mTextValid = true;
mTextOffsetReset = true;
mHistoryDirty = false;
@ -1252,14 +1254,16 @@ void GuiTextEditCtrl::onLoseFirstResponder()
Parent::onLoseFirstResponder();
}
void GuiTextEditCtrl::onRender(Point2I offset, const RectI &updateRect)
void GuiTextEditCtrl::onRender( Point2I offset, const RectI &updateRect )
{
RectI ctrlRect( offset, getExtent() );
//if opaque, fill the update rect with the fill color
if ( mProfile->mOpaque )
{
if(isFirstResponder())
if ( !mTextValid )
GFX->getDrawUtil()->drawRectFill( ctrlRect, mProfile->mFillColorERR );
else if ( isFirstResponder() )
GFX->getDrawUtil()->drawRectFill( ctrlRect, mProfile->mFillColorHL );
else
GFX->getDrawUtil()->drawRectFill( ctrlRect, mProfile->mFillColor );
@ -1267,7 +1271,11 @@ void GuiTextEditCtrl::onRender(Point2I offset, const RectI &updateRect)
//if there's a border, draw the border
if ( mProfile->mBorder )
{
renderBorder( ctrlRect, mProfile );
if ( !mTextValid )
GFX->getDrawUtil()->drawRectFill( ctrlRect, mProfile->mFillColorERR );
}
drawText( ctrlRect, isFirstResponder() );
}
@ -1490,7 +1498,25 @@ void GuiTextEditCtrl::drawText( const RectI &drawRect, bool isFocused )
bool GuiTextEditCtrl::hasText()
{
return (mTextBuffer.length());
return ( mTextBuffer.length() );
}
void GuiTextEditCtrl::invalidText(bool playSound)
{
mTextValid = false;
if ( playSound )
playDeniedSound();
}
void GuiTextEditCtrl::validText()
{
mTextValid = true;
}
bool GuiTextEditCtrl::isValidText()
{
return mTextValid;
}
void GuiTextEditCtrl::playDeniedSound()
@ -1520,27 +1546,29 @@ void GuiTextEditCtrl::handleCharInput( U16 ascii )
//see if it's a number field
if ( mProfile->mNumbersOnly )
{
if ( ascii == '-')
{
//a minus sign only exists at the beginning, and only a single minus sign
if ( mCursorPos != 0 && !isAllTextSelected() )
{
playDeniedSound();
return;
}
if (ascii == '-')
{
//a minus sign only exists at the beginning, and only a single minus sign
if (mCursorPos != 0 && !isAllTextSelected())
{
invalidText();
return;
}
if ( mInsertOn && ( mTextBuffer.getChar(0) == '-' ) )
{
playDeniedSound();
return;
}
}
// BJTODO: This is probably not unicode safe.
else if ( ascii != '.' && (ascii < '0' || ascii > '9') )
{
playDeniedSound();
return;
}
if (mInsertOn && (mTextBuffer.getChar(0) == '-'))
{
invalidText();
return;
}
}
// BJTODO: This is probably not unicode safe.
else if (ascii != '.' && (ascii < '0' || ascii > '9'))
{
invalidText();
return;
}
else
validText();
}
//save the current state
@ -1748,3 +1776,24 @@ DefineEngineMethod( GuiTextEditCtrl, forceValidateText, void, (),,
{
object->forceValidateText();
}
DefineEngineMethod(GuiTextEditCtrl, invalidText, void, (bool playSound), (true),
"@brief Trigger the invalid sound and make the box red.nn"
"@param playSound Play the invalid text sound or not.n")
{
object->invalidText(playSound);
}
DefineEngineMethod(GuiTextEditCtrl, validText, void, (), ,
"@brief Restores the box to normal color.nn")
{
object->validText();
}
DefineEngineMethod(GuiTextEditCtrl, isValidText, bool, (), ,
"@brief Returns if the text is set to valid or not.n"
"@Return true if text is set to valid, false if not.nn")
{
return object->isValidText();
}

View file

@ -93,6 +93,8 @@ protected:
void playDeniedSound();
void execConsoleCallback();
bool mTextValid;
virtual void handleCharInput( U16 ascii );
S32 findNextWord();
@ -119,6 +121,10 @@ public:
S32 getCursorPos() { return( mCursorPos ); }
void setCursorPos( const S32 newPos );
void invalidText(bool playSound = true);
void validText();
bool isValidText();
bool isAllTextSelected();
void selectAllText();
void clearSelectedText();

View file

@ -321,8 +321,11 @@ void GuiCanvas::setWindowTitle(const char *newTitle)
mPlatformWindow->setCaption(newTitle);
}
CanvasSizeChangeSignal GuiCanvas::smCanvasSizeChangeSignal;
void GuiCanvas::handleResize( WindowId did, S32 width, S32 height )
{
getCanvasSizeChangeSignal().trigger(this);
if (Journal::IsPlaying() && mPlatformWindow)
{
mPlatformWindow->lockSize(false);

View file

@ -33,6 +33,10 @@
#include "platform/platformInput.h"
#endif
#ifndef _SIGNAL_H_
#include "core/util/tSignal.h"
#endif
#include "component/interfaces/IProcessInput.h"
#include "windowManager/platformWindowMgr.h"
#include "gfx/gfxFence.h"
@ -74,6 +78,8 @@
/// screen will be painted normally. If you are making an animated GuiControl
/// you need to add your control to the dirty areas of the canvas.
///
class guiCanvas;
typedef Signal<void(GuiCanvas* canvas)> CanvasSizeChangeSignal;
class GuiCanvas : public GuiControl, public IProcessInput
{
@ -183,6 +189,8 @@ protected:
virtual void setupFences();
void checkLockMouseMove( const GuiEvent& event );
//Signal used to let others know this canvas has changed size.
static CanvasSizeChangeSignal smCanvasSizeChangeSignal;
GuiControl *mMenuBarCtrl;
@ -200,6 +208,8 @@ public:
static void initPersistFields();
static CanvasSizeChangeSignal& getCanvasSizeChangeSignal() { return smCanvasSizeChangeSignal; }
/// @name Rendering methods
///
/// @{

View file

@ -175,6 +175,9 @@ ImplementEnumType( GuiHorizontalSizing,
{ GuiControl::horizResizeLeft, "left" },
{ GuiControl::horizResizeCenter, "center" },
{ GuiControl::horizResizeRelative, "relative" },
{ GuiControl::horizResizeAspectLeft, "aspectLeft" },
{ GuiControl::horizResizeAspectRight, "aspectRight" },
{ GuiControl::horizResizeAspectCenter, "aspectCenter" },
{ GuiControl::horizResizeWindowRelative, "windowRelative" }
EndImplementEnumType;
@ -186,6 +189,9 @@ ImplementEnumType( GuiVerticalSizing,
{ GuiControl::vertResizeTop, "top" },
{ GuiControl::vertResizeCenter, "center" },
{ GuiControl::vertResizeRelative, "relative" },
{ GuiControl::vertResizeAspectTop, "aspectTop" },
{ GuiControl::vertResizeAspectBottom, "aspectBottom" },
{ GuiControl::vertResizeAspectCenter, "aspectCenter" },
{ GuiControl::vertResizeWindowRelative, "windowRelative" }
EndImplementEnumType;
@ -1370,6 +1376,36 @@ void GuiControl::parentResized(const RectI &oldParentRect, const RectI &newParen
newPosition.x = newLeft;
newExtent.x = newWidth;
}
else if (mHorizSizing == horizResizeAspectLeft && oldParentRect.extent.x != 0)
{
S32 newLeft = mRoundToNearest((F32(newPosition.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x));
S32 newWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y));
newPosition.x = newLeft;
newExtent.x = newWidth;
}
else if (mHorizSizing == horizResizeAspectRight && oldParentRect.extent.x != 0)
{
S32 newLeft = mRoundToNearest((F32(newPosition.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x));
S32 newWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); //origional aspect ratio corrected width
S32 rWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); //parent aspect ratio relative width
S32 offset = rWidth - newWidth; // account for change in relative width
newLeft += offset;
newPosition.x = newLeft;
newExtent.x = newWidth;
}
else if (mHorizSizing == horizResizeAspectCenter && oldParentRect.extent.x != 0)
{
S32 newLeft = mRoundToNearest((F32(newPosition.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x));
S32 newWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); //origional aspect ratio corrected width
S32 rWidth = mRoundToNearest((F32(newExtent.x) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); //parent aspect ratio relative width
S32 offset = rWidth - newWidth; // account for change in relative width
newLeft += offset/2;
newPosition.x = newLeft;
newExtent.x = newWidth;
}
if (mVertSizing == vertResizeCenter)
newPosition.y = (newParentRect.extent.y - getHeight()) >> 1;
@ -1385,6 +1421,36 @@ void GuiControl::parentResized(const RectI &oldParentRect, const RectI &newParen
newPosition.y = newTop;
newExtent.y = newHeight;
}
else if (mVertSizing == vertResizeAspectTop && oldParentRect.extent.y != 0)
{
S32 newTop = mRoundToNearest((F32(newPosition.y) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y));
S32 newHeight = mRoundToNearest((F32(newExtent.y) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x));
newPosition.y = newTop;
newExtent.y = newHeight;
}
else if (mVertSizing == vertResizeAspectBottom && oldParentRect.extent.y != 0)
{
S32 newTop = mRoundToNearest((F32(newPosition.y) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y));
S32 newHeight = mRoundToNearest((F32(newExtent.y) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); //origional aspect ratio corrected hieght
S32 rHeight = mRoundToNearest((F32(newExtent.y) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); //parent aspect ratio relative hieght
S32 offset = rHeight - newHeight; // account for change in relative hieght
newTop += offset;
newPosition.y = newTop;
newExtent.y = newHeight;
}
else if (mVertSizing == vertResizeAspectCenter && oldParentRect.extent.y != 0)
{
S32 newTop = mRoundToNearest((F32(newPosition.y) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y));
S32 newHeight = mRoundToNearest((F32(newExtent.y) / F32(oldParentRect.extent.x)) * F32(newParentRect.extent.x)); //origional aspect ratio corrected hieght
S32 rHeight = mRoundToNearest((F32(newExtent.y) / F32(oldParentRect.extent.y)) * F32(newParentRect.extent.y)); //parent aspect ratio relative hieght
S32 offset = rHeight - newHeight; // account for change in relative hieght
newTop += offset / 2;
newPosition.y = newTop;
newExtent.y = newHeight;
}
// Resizing Re factor [9/18/2006]
// Only resize if our minExtent is satisfied with it.

View file

@ -121,6 +121,9 @@ class GuiControl : public SimGroup
horizResizeLeft, ///< fixed on the right and width
horizResizeCenter,
horizResizeRelative, ///< resize relative
horizResizeAspectLeft, ///< resize relative to height delta (offset Left)
horizResizeAspectRight, ///< resize relative to height delta (offset Right)
horizResizeAspectCenter, ///< resize relative to height delta (Centered)
horizResizeWindowRelative ///< resize window relative
};
enum vertSizingOptions
@ -130,6 +133,9 @@ class GuiControl : public SimGroup
vertResizeTop, ///< fixed in height and on the bottom
vertResizeCenter,
vertResizeRelative, ///< resize relative
vertResizeAspectTop, ///< resize relative to width delta (offset Left)
vertResizeAspectBottom, ///< resize relative to width delta (offset Right)
vertResizeAspectCenter, ///< resize relative to width delta Centered)
vertResizeWindowRelative ///< resize window relative
};

View file

@ -269,6 +269,7 @@ GuiControlProfile::GuiControlProfile(void) :
mFillColor(255,0,255,255),
mFillColorHL(255,0,255,255),
mFillColorNA(255,0,255,255),
mFillColorERR(255,0,0,255),
mFillColorSEL(255,0,255,255),
mBorderColor(255,0,255,255),
mBorderColorHL(255,0,255,255),
@ -334,6 +335,7 @@ GuiControlProfile::GuiControlProfile(void) :
mFillColor = def->mFillColor;
mFillColorHL = def->mFillColorHL;
mFillColorNA = def->mFillColorNA;
mFillColorERR = def->mFillColorERR;
mFillColorSEL = def->mFillColorSEL;
mBorder = def->mBorder;
@ -398,6 +400,7 @@ void GuiControlProfile::initPersistFields()
addField("fillColor", TypeColorI, Offset(mFillColor, GuiControlProfile));
addField("fillColorHL", TypeColorI, Offset(mFillColorHL, GuiControlProfile));
addField("fillColorNA", TypeColorI, Offset(mFillColorNA, GuiControlProfile));
addField("fillColorERR", TypeColorI, Offset(mFillColorERR, GuiControlProfile));
addField("fillColorSEL", TypeColorI, Offset(mFillColorSEL, GuiControlProfile));
addField("border", TypeS32, Offset(mBorder, GuiControlProfile),
"Border type (0=no border)." );

View file

@ -385,6 +385,7 @@ public:
ColorI mFillColor; ///< Fill color, this is used to fill the bounds of the control if it is opaque
ColorI mFillColorHL; ///< This is used instead of mFillColor if the object is highlighted
ColorI mFillColorNA; ///< This is used instead of mFillColor if the object is not active or disabled
ColorI mFillColorERR; ///< This is used instead of mFillColor if the object has an error or is invalid
ColorI mFillColorSEL; ///< This is used instead of mFillColor if the object is selected
S32 mBorder; ///< For most controls, if mBorder is > 0 a border will be drawn, some controls use this to draw different types of borders however @see guiDefaultControlRender.cc

View file

@ -2810,7 +2810,7 @@ void WorldEditor::clearSelection()
void WorldEditor::selectObject( SimObject *obj )
{
if ( mSelectionLocked || !mSelected )
if ( mSelectionLocked || !mSelected || !obj )
return;
// Don't check isSelectionEnabled of SceneObjects here as we
@ -2833,7 +2833,7 @@ void WorldEditor::selectObject( const char* obj )
void WorldEditor::unselectObject( SimObject *obj )
{
if ( mSelectionLocked || !mSelected )
if ( mSelectionLocked || !mSelected || !obj )
return;
if ( !objClassIgnored( obj ) && mSelected->objInSet( obj ) )

View file

@ -318,6 +318,8 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
const U32 numPrims = curEntry.numPrims;
const U32 numVerts = curEntry.vertBuffer->mNumVerts;
ShadowMapParams *lsp = curLightInfo->getExtended<ShadowMapParams>();
// Skip lights which won't affect the scene.
if ( !curLightMat || curLightInfo->getBrightness() <= 0.001f )
continue;
@ -329,15 +331,12 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
mShadowManager->setLightShadowMap( curEntry.shadowMap );
mShadowManager->setLightDynamicShadowMap( curEntry.dynamicShadowMap );
// Let the shadow know we're about to render from it.
if ( curEntry.shadowMap )
curEntry.shadowMap->preLightRender();
if ( curEntry.dynamicShadowMap ) curEntry.dynamicShadowMap->preLightRender();
// Set geometry
GFX->setVertexBuffer( curEntry.vertBuffer );
GFX->setPrimitiveBuffer( curEntry.primBuffer );
lsp->getOcclusionQuery()->begin();
// Render the material passes
while( curLightMat->matInstance->setupPass( state, sgData ) )
{
@ -352,10 +351,7 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
GFX->drawPrimitive(GFXTriangleList, 0, numPrims);
}
// Tell it we're done rendering.
if ( curEntry.shadowMap )
curEntry.shadowMap->postLightRender();
if ( curEntry.dynamicShadowMap ) curEntry.dynamicShadowMap->postLightRender();
lsp->getOcclusionQuery()->end();
}
// Set NULL for active shadow map (so nothing gets confused)

View file

@ -105,7 +105,7 @@ void AdvancedLightManager::activate( SceneManager *sceneManager )
// we prefer the floating point format if it works.
Vector<GFXFormat> formats;
formats.push_back( GFXFormatR16G16B16A16F );
formats.push_back( GFXFormatR16G16B16A16 );
//formats.push_back( GFXFormatR16G16B16A16 );
GFXFormat blendTargetFormat = GFX->selectSupportedFormat( &GFXDefaultRenderTargetProfile,
formats,
true,

View file

@ -156,8 +156,8 @@ void DeferredRTLightingFeatGLSL::processPix( Vector<ShaderComponent*> &component
oneOverTargetSize->constSortPos = cspPass;
}
meta->addStatement( new GenOp( " float id_NL_Att, id_specular;\r\n float3 id_lightcolor;\r\n" ) );
meta->addStatement( new GenOp( avar( " %s(tex2D(@, @ + float2(0.0, @.y)), id_lightcolor, id_NL_Att, id_specular);\r\n",
meta->addStatement( new GenOp( " float id_NL_Att, id_specular;\r\n vec3 id_lightcolor;\r\n" ) );
meta->addStatement( new GenOp( avar( " %s(tex2D(@, @ + vec2(0.0, @.y)), id_lightcolor, id_NL_Att, id_specular);\r\n",
unconditionLightInfo.c_str() ), lightInfoBuffer, uvScene, oneOverTargetSize ) );
meta->addStatement( new GenOp(" @ = lerp(@, id_lightcolor, 0.5);\r\n", d_lightcolor, d_lightcolor ) );
@ -167,7 +167,7 @@ void DeferredRTLightingFeatGLSL::processPix( Vector<ShaderComponent*> &component
// This is kind of weak sauce
if( !fd.features[MFT_VertLit] && !fd.features[MFT_ToneMap] && !fd.features[MFT_LightMap] && !fd.features[MFT_SubSurface] )
meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(@, 1.0)", d_lightcolor ), Material::Mul ) ) );
meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(@, 1.0)", d_lightcolor ), Material::Mul ) ) );
output = meta;
}
@ -311,7 +311,7 @@ void DeferredBumpFeatGLSL::processPix( Vector<ShaderComponent*> &componentList,
meta->addStatement( new GenOp( " @.xy += @.xy * @;\r\n", bumpNorm, detailBump, detailBumpScale ) );
}
// This var is read from GBufferConditionerHLSL and
// This var is read from GBufferConditionerGLSL and
// used in the prepass output.
//
// By using the 'half' type here we get a bunch of partial
@ -533,11 +533,13 @@ void DeferredPixelSpecularGLSL::processPix( Vector<ShaderComponent*> &component
specPow->constSortPos = cspPotentialPrimitive;
}
Var *specStrength = new Var;
specStrength->setType( "float" );
specStrength->setName( "specularStrength" );
specStrength->uniform = true;
specStrength->constSortPos = cspPotentialPrimitive;
Var *specStrength = (Var*)LangElement::find( "specularStrength" );
if (!specStrength)
{
specStrength = new Var( "specularStrength", "float" );
specStrength->uniform = true;
specStrength->constSortPos = cspPotentialPrimitive;
}
Var *lightInfoSamp = (Var *)LangElement::find( "lightInfoSample" );
Var *d_specular = (Var*)LangElement::find( "d_specular" );
@ -555,10 +557,10 @@ void DeferredPixelSpecularGLSL::processPix( Vector<ShaderComponent*> &component
meta->addStatement(new GenOp(" @ = clamp( lerp( @, @ * @, @.a), 0, 1);\r\n", d_specular, d_specular, accuSpecular, d_specular, accuPlc));
}
// (a^m)^n = a^(m*n)
meta->addStatement( new GenOp( " @ = pow( abs(@), max((@ / AL_ConstantSpecularPower),1.0f)) * @;\r\n",
meta->addStatement( new GenOp( " @ = pow( abs(@), max((@ / AL_ConstantSpecularPower),1.0f)) * @;\r\n",
specDecl, d_specular, specPow, specStrength ) );
LangElement *specMul = new GenOp( "float4( @.rgb, 0 ) * @", specCol, specular );
LangElement *specMul = new GenOp( "vec4( @.rgb, 0 ) * @", specCol, specular );
LangElement *final = specMul;
// We we have a normal map then mask the specular
@ -682,10 +684,10 @@ void DeferredMinnaertGLSL::processPix( Vector<ShaderComponent*> &componentList,
Var *d_NL_Att = (Var*)LangElement::find( "d_NL_Att" );
meta->addStatement( new GenOp( avar( " float4 normalDepth = %s(@, @);\r\n", unconditionPrePassMethod.c_str() ), prepassBuffer, uvScene ) );
meta->addStatement( new GenOp( avar( " vec4 normalDepth = %s(@, @);\r\n", unconditionPrePassMethod.c_str() ), prepassBuffer, uvScene ) );
meta->addStatement( new GenOp( " float vDotN = dot(normalDepth.xyz, @);\r\n", wsViewVec ) );
meta->addStatement( new GenOp( " float Minnaert = pow( @, @) * pow(vDotN, 1.0 - @);\r\n", d_NL_Att, minnaertConstant, minnaertConstant ) );
meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(Minnaert, Minnaert, Minnaert, 1.0)" ), Material::Mul ) ) );
meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(Minnaert, Minnaert, Minnaert, 1.0)" ), Material::Mul ) ) );
output = meta;
}
@ -713,7 +715,7 @@ void DeferredSubSurfaceGLSL::processPix( Vector<ShaderComponent*> &componentLis
MultiLine *meta = new MultiLine;
meta->addStatement( new GenOp( " float subLamb = smoothstep(-@.a, 1.0, @) - smoothstep(0.0, 1.0, @);\r\n", subSurfaceParams, d_NL_Att, d_NL_Att ) );
meta->addStatement( new GenOp( " subLamb = max(0.0, subLamb);\r\n" ) );
meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "float4(@ + (subLamb * @.rgb), 1.0)", d_lightcolor, subSurfaceParams ), Material::Mul ) ) );
meta->addStatement( new GenOp( " @;\r\n", assignColor( new GenOp( "vec4(@ + (subLamb * @.rgb), 1.0)", d_lightcolor, subSurfaceParams ), Material::Mul ) ) );
output = meta;
}

View file

@ -0,0 +1,190 @@
//-----------------------------------------------------------------------------
// 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 "lighting/advanced/glsl/deferredShadingFeaturesGLSL.h"
#include "lighting/advanced/advancedLightBinManager.h"
#include "shaderGen/langElement.h"
#include "shaderGen/shaderOp.h"
#include "shaderGen/conditionerFeature.h"
#include "renderInstance/renderPrePassMgr.h"
#include "materials/processedMaterial.h"
#include "materials/materialFeatureTypes.h"
//****************************************************************************
// Deferred Shading Features
//****************************************************************************
// Specular Map -> Blue of Material Buffer ( greyscaled )
// Gloss Map (Alpha Channel of Specular Map) -> Alpha ( Spec Power ) of Material Info Buffer.
void DeferredSpecMapGLSL::processPix( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd )
{
// Get the texture coord.
Var *texCoord = getInTexCoord( "texCoord", "vec2", true, componentList );
// search for color var
Var *material = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
MultiLine * meta = new MultiLine;
if ( !material )
{
// create color var
material = new Var;
material->setType( "vec4" );
material->setName( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
material->setStructName("OUT");
}
// create texture var
Var *specularMap = new Var;
specularMap->setType( "sampler2D" );
specularMap->setName( "specularMap" );
specularMap->uniform = true;
specularMap->sampler = true;
specularMap->constNum = Var::getTexUnitNum();
LangElement *texOp = new GenOp( "tex2D(@, @)", specularMap, texCoord );
//matinfo.g slot reserved for AO later
meta->addStatement(new GenOp(" @.g = 1.0;\r\n", material));
meta->addStatement(new GenOp(" @.b = dot(tex2D(@, @).rgb, vec3(0.3, 0.59, 0.11));\r\n", material, specularMap, texCoord));
meta->addStatement(new GenOp(" @.a = tex2D(@, @).a;\r\n", material, specularMap, texCoord));
output = meta;
}
ShaderFeature::Resources DeferredSpecMapGLSL::getResources( const MaterialFeatureData &fd )
{
Resources res;
res.numTex = 1;
res.numTexReg = 1;
return res;
}
void DeferredSpecMapGLSL::setTexData( Material::StageData &stageDat,
const MaterialFeatureData &fd,
RenderPassData &passData,
U32 &texIndex )
{
GFXTextureObject *tex = stageDat.getTex( MFT_SpecularMap );
if ( tex )
{
passData.mTexType[ texIndex ] = Material::Standard;
passData.mSamplerNames[ texIndex ] = "specularMap";
passData.mTexSlot[ texIndex++ ].texObject = tex;
}
}
void DeferredSpecMapGLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
MultiLine *meta = new MultiLine;
getOutTexCoord( "texCoord",
"vec2",
true,
fd.features[MFT_TexAnim],
meta,
componentList );
output = meta;
}
// Material Info Flags -> Red ( Flags ) of Material Info Buffer.
void DeferredMatInfoFlagsGLSL::processPix( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd )
{
MultiLine *meta = new MultiLine;
// search for material var
Var *material = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
if ( !material )
{
// create material var
material = new Var;
material->setType( "vec4" );
material->setName( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
material->setStructName("OUT");
}
Var *matInfoFlags = new Var;
matInfoFlags->setType( "float" );
matInfoFlags->setName( "matInfoFlags" );
matInfoFlags->uniform = true;
matInfoFlags->constSortPos = cspPotentialPrimitive;
meta->addStatement(output = new GenOp(" @.r = @;\r\n", material, matInfoFlags));
output = meta;
}
// Spec Strength -> Blue Channel of Material Info Buffer.
// Spec Power -> Alpha Channel ( of Material Info Buffer.
void DeferredSpecVarsGLSL::processPix( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd )
{
// search for material var
Var *material = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
if ( !material )
{
// create material var
material = new Var;
material->setType( "vec4" );
material->setName( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
material->setStructName("OUT");
}
Var *specStrength = new Var;
specStrength->setType( "float" );
specStrength->setName( "specularStrength" );
specStrength->uniform = true;
specStrength->constSortPos = cspPotentialPrimitive;
Var *specPower = new Var;
specPower->setType("float");
specPower->setName("specularPower");
specPower->uniform = true;
specPower->constSortPos = cspPotentialPrimitive;
MultiLine *meta = new MultiLine;
//matinfo.g slot reserved for AO later
meta->addStatement(new GenOp(" @.g = 1.0;\r\n", material));
meta->addStatement(new GenOp(" @.a = @/128;\r\n", material, specPower));
meta->addStatement(new GenOp(" @.b = @/5;\r\n", material, specStrength));
output = meta;
}
// Black -> Blue and Alpha of Color Buffer (representing no specular)
void DeferredEmptySpecGLSL::processPix( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd )
{
// search for material var
Var *material = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
if ( !material )
{
// create material var
material = new Var;
material->setType( "vec4" );
material->setName( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
material->setStructName("OUT");
}
MultiLine * meta = new MultiLine;
//matinfo.g slot reserved for AO later
meta->addStatement(new GenOp(" @.g = 1.0;\r\n", material));
meta->addStatement(new GenOp(" @.ba = vec2(0.0);\r\n", material));
output = meta;
}

View file

@ -0,0 +1,85 @@
//-----------------------------------------------------------------------------
// 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 _DEFERREDSHADINGGLSL_H_
#define _DEFERREDSHADINGGLSL_H_
#include "shaderGen/GLSL/shaderFeatureGLSL.h"
#include "shaderGen/GLSL/bumpGLSL.h"
#include "shaderGen/GLSL/pixSpecularGLSL.h"
// Specular Outputs
class DeferredSpecMapGLSL : public ShaderFeatureGLSL
{
public:
virtual String getName() { return "Deferred Shading: Specular Map"; }
virtual void processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd );
virtual Resources getResources( const MaterialFeatureData &fd );
// Sets textures and texture flags for current pass
virtual void setTexData( Material::StageData &stageDat,
const MaterialFeatureData &fd,
RenderPassData &passData,
U32 &texIndex );
virtual void processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd );
};
class DeferredMatInfoFlagsGLSL : public ShaderFeatureGLSL
{
public:
virtual String getName() { return "Deferred Shading: Mat Info Flags"; }
virtual void processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd );
virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return ShaderFeature::RenderTarget2; }
};
class DeferredSpecVarsGLSL : public ShaderFeatureGLSL
{
public:
virtual String getName() { return "Deferred Shading: Specular Explicit Numbers"; }
virtual void processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd );
virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return ShaderFeature::RenderTarget2; }
};
class DeferredEmptySpecGLSL : public ShaderFeatureGLSL
{
public:
virtual String getName() { return "Deferred Shading: Empty Specular"; }
virtual void processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd );
virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return ShaderFeature::RenderTarget2; }
};
#endif

View file

@ -170,7 +170,7 @@ void GBufferConditionerGLSL::processPix( Vector<ShaderComponent*> &componentLis
if ( fd.features[ MFT_IsTranslucentZWrite ] )
{
alphaVal = new Var( "outAlpha", "float" );
meta->addStatement( new GenOp( " @ = col.a; // MFT_IsTranslucentZWrite\r\n", new DecOp( alphaVal ) ) );
meta->addStatement( new GenOp( " @ = OUT_col1.a; // MFT_IsTranslucentZWrite\r\n", new DecOp( alphaVal ) ) );
}
// If using interlaced normals, invert the normal
@ -397,7 +397,7 @@ Var* GBufferConditionerGLSL::_unconditionInput( Var *conditionedInput, MultiLine
// Recover depth from encoding
if(mNormalStorageType != CartesianXYZ)
{
const U64 maxValPerChannel = 1 << mBitsPerChannel;
const U64 maxValPerChannel = (U64)1 << mBitsPerChannel;
meta->addStatement( new GenOp( " \r\n // Decode depth\r\n" ) );
meta->addStatement( new GenOp( avar( " @.w = dot( @.zw, float2(1.0, 1.0/%llu.0));\r\n", maxValPerChannel - 1 ),
retVar, conditionedInput ) );

View file

@ -227,7 +227,7 @@ void DeferredBumpFeatHLSL::processVert( Vector<ShaderComponent*> &componentLis
const bool useTexAnim = fd.features[MFT_TexAnim];
// Make sure there are texcoords
if( !fd.features[MFT_Parallax] && !fd.features[MFT_DiffuseMap] )
if( !fd.features[MFT_Parallax] && !fd.features[MFT_DiffuseMap])
{
getOutTexCoord( "texCoord",
@ -532,11 +532,13 @@ void DeferredPixelSpecularHLSL::processPix( Vector<ShaderComponent*> &component
specPow->constSortPos = cspPotentialPrimitive;
}
Var *specStrength = new Var;
specStrength->setType( "float" );
specStrength->setName( "specularStrength" );
specStrength->uniform = true;
specStrength->constSortPos = cspPotentialPrimitive;
Var *specStrength = (Var*)LangElement::find( "specularStrength" );
if (!specStrength)
{
specStrength = new Var( "specularStrength", "float" );
specStrength->uniform = true;
specStrength->constSortPos = cspPotentialPrimitive;
}
Var *lightInfoSamp = (Var *)LangElement::find( "lightInfoSample" );
Var *d_specular = (Var*)LangElement::find( "d_specular" );
@ -556,7 +558,7 @@ void DeferredPixelSpecularHLSL::processPix( Vector<ShaderComponent*> &component
// (a^m)^n = a^(m*n)
meta->addStatement( new GenOp( " @ = pow( abs(@), max((@ / AL_ConstantSpecularPower),1.0f)) * @;\r\n",
specDecl, d_specular, specPow, specStrength ) );
specDecl, d_specular, specPow, specStrength));
LangElement *specMul = new GenOp( "float4( @.rgb, 0 ) * @", specCol, specular );
LangElement *final = specMul;

View file

@ -0,0 +1,187 @@
//-----------------------------------------------------------------------------
// 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 "lighting/advanced/hlsl/deferredShadingFeaturesHLSL.h"
#include "lighting/advanced/advancedLightBinManager.h"
#include "shaderGen/langElement.h"
#include "shaderGen/shaderOp.h"
#include "shaderGen/conditionerFeature.h"
#include "renderInstance/renderPrePassMgr.h"
#include "materials/processedMaterial.h"
#include "materials/materialFeatureTypes.h"
//****************************************************************************
// Deferred Shading Features
//****************************************************************************
// Specular Map -> Blue of Material Buffer ( greyscaled )
// Gloss Map (Alpha Channel of Specular Map) -> Alpha ( Spec Power ) of Material Info Buffer.
void DeferredSpecMapHLSL::processPix( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd )
{
// Get the texture coord.
Var *texCoord = getInTexCoord( "texCoord", "float2", true, componentList );
// search for color var
Var *material = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
MultiLine * meta = new MultiLine;
if ( !material )
{
// create color var
material = new Var;
material->setType( "fragout" );
material->setName( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
material->setStructName( "OUT" );
}
// create texture var
Var *specularMap = new Var;
specularMap->setType( "sampler2D" );
specularMap->setName( "specularMap" );
specularMap->uniform = true;
specularMap->sampler = true;
specularMap->constNum = Var::getTexUnitNum();
LangElement *texOp = new GenOp( "tex2D(@, @)", specularMap, texCoord );
//matinfo.g slot reserved for AO later
meta->addStatement(new GenOp(" @.g = 1.0;\r\n", material));
meta->addStatement(new GenOp(" @.b = dot(tex2D(@, @).rgb, float3(0.3, 0.59, 0.11));\r\n", material, specularMap, texCoord));
meta->addStatement(new GenOp(" @.a = tex2D(@, @).a;\r\n", material, specularMap, texCoord));
output = meta;
}
ShaderFeature::Resources DeferredSpecMapHLSL::getResources( const MaterialFeatureData &fd )
{
Resources res;
res.numTex = 1;
res.numTexReg = 1;
return res;
}
void DeferredSpecMapHLSL::setTexData( Material::StageData &stageDat,
const MaterialFeatureData &fd,
RenderPassData &passData,
U32 &texIndex )
{
GFXTextureObject *tex = stageDat.getTex( MFT_SpecularMap );
if ( tex )
{
passData.mTexType[ texIndex ] = Material::Standard;
passData.mSamplerNames[ texIndex ] = "specularMap";
passData.mTexSlot[ texIndex++ ].texObject = tex;
}
}
void DeferredSpecMapHLSL::processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd )
{
MultiLine *meta = new MultiLine;
getOutTexCoord( "texCoord",
"float2",
true,
fd.features[MFT_TexAnim],
meta,
componentList );
output = meta;
}
// Material Info Flags -> Red ( Flags ) of Material Info Buffer.
void DeferredMatInfoFlagsHLSL::processPix( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd )
{
// search for material var
Var *material = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
if ( !material )
{
// create material var
material = new Var;
material->setType( "fragout" );
material->setName( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
material->setStructName( "OUT" );
}
Var *matInfoFlags = new Var;
matInfoFlags->setType( "float" );
matInfoFlags->setName( "matInfoFlags" );
matInfoFlags->uniform = true;
matInfoFlags->constSortPos = cspPotentialPrimitive;
output = new GenOp( " @.r = @;\r\n", material, matInfoFlags );
}
// Spec Strength -> Blue Channel of Material Info Buffer.
// Spec Power -> Alpha Channel ( of Material Info Buffer.
void DeferredSpecVarsHLSL::processPix( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd )
{
// search for material var
Var *material = (Var*) LangElement::find( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
if ( !material )
{
// create material var
material = new Var;
material->setType( "fragout" );
material->setName( getOutputTargetVarName(ShaderFeature::RenderTarget2) );
material->setStructName( "OUT" );
}
Var *specStrength = new Var;
specStrength->setType( "float" );
specStrength->setName( "specularStrength" );
specStrength->uniform = true;
specStrength->constSortPos = cspPotentialPrimitive;
Var *specPower = new Var;
specPower->setType( "float" );
specPower->setName( "specularPower" );
specPower->uniform = true;
specPower->constSortPos = cspPotentialPrimitive;
MultiLine * meta = new MultiLine;
//matinfo.g slot reserved for AO later
meta->addStatement(new GenOp(" @.g = 1.0;\r\n", material));
meta->addStatement(new GenOp(" @.a = @/128;\r\n", material, specPower));
meta->addStatement(new GenOp(" @.b = @/5;\r\n", material, specStrength));
output = meta;
}
// Black -> Blue and Alpha of matinfo Buffer (representing no specular), White->G (representing No AO)
void DeferredEmptySpecHLSL::processPix( Vector<ShaderComponent*> &componentList, const MaterialFeatureData &fd )
{
// search for material var
Var *material = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::RenderTarget2));
if (!material)
{
// create color var
material = new Var;
material->setType("fragout");
material->setName(getOutputTargetVarName(ShaderFeature::RenderTarget2));
material->setStructName("OUT");
}
MultiLine * meta = new MultiLine;
//matinfo.g slot reserved for AO later
meta->addStatement(new GenOp(" @.g = 1.0;\r\n", material));
meta->addStatement(new GenOp(" @.ba = 0.0;\r\n", material));
output = meta;
}

View file

@ -0,0 +1,84 @@
//-----------------------------------------------------------------------------
// 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 _DEFERREDSHADINGHLSL_H_
#define _DEFERREDSHADINGHLSL_H_
#include "shaderGen/HLSL/shaderFeatureHLSL.h"
#include "shaderGen/HLSL/bumpHLSL.h"
#include "shaderGen/HLSL/pixSpecularHLSL.h"
// Specular Outputs
class DeferredSpecMapHLSL : public ShaderFeatureHLSL
{
public:
virtual String getName() { return "Deferred Shading: Specular Map"; }
virtual void processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd );
virtual Resources getResources( const MaterialFeatureData &fd );
// Sets textures and texture flags for current pass
virtual void setTexData( Material::StageData &stageDat,
const MaterialFeatureData &fd,
RenderPassData &passData,
U32 &texIndex );
virtual void processVert( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd );
};
class DeferredMatInfoFlagsHLSL : public ShaderFeatureHLSL
{
public:
virtual String getName() { return "Deferred Shading: Mat Info Flags"; }
virtual void processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd );
virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return ShaderFeature::RenderTarget2; }
};
class DeferredSpecVarsHLSL : public ShaderFeatureHLSL
{
public:
virtual String getName() { return "Deferred Shading: Specular Explicit Numbers"; }
virtual void processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd );
virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return ShaderFeature::RenderTarget2; }
};
class DeferredEmptySpecHLSL : public ShaderFeatureHLSL
{
public:
virtual String getName() { return "Deferred Shading: Empty Specular"; }
virtual void processPix( Vector<ShaderComponent*> &componentList,
const MaterialFeatureData &fd );
virtual U32 getOutputTargets( const MaterialFeatureData &fd ) const { return ShaderFeature::RenderTarget2; }
};
#endif

View file

@ -170,7 +170,7 @@ void GBufferConditionerHLSL::processPix( Vector<ShaderComponent*> &componentLis
if ( fd.features[ MFT_IsTranslucentZWrite ] )
{
alphaVal = new Var( "outAlpha", "float" );
meta->addStatement( new GenOp( " @ = OUT.col.a; // MFT_IsTranslucentZWrite\r\n", new DecOp( alphaVal ) ) );
meta->addStatement( new GenOp( " @ = OUT.col1.a; // MFT_IsTranslucentZWrite\r\n", new DecOp( alphaVal ) ) );
}
// If using interlaced normals, invert the normal

View file

@ -89,8 +89,6 @@ LightShadowMap::LightShadowMap( LightInfo *light )
mLastUpdate( 0 ),
mLastCull( 0 ),
mIsViewDependent( false ),
mVizQuery( NULL ),
mWasOccluded( false ),
mLastScreenSize( 0.0f ),
mLastPriority( 0.0f ),
mIsDynamic( false )
@ -98,9 +96,7 @@ LightShadowMap::LightShadowMap( LightInfo *light )
GFXTextureManager::addEventDelegate( this, &LightShadowMap::_onTextureEvent );
mTarget = GFX->allocRenderToTextureTarget();
mVizQuery = GFX->createOcclusionQuery();
smShadowMaps.push_back(this);
smShadowMaps.push_back( this );
mStaticRefreshTimer = PlatformTimer::create();
mDynamicRefreshTimer = PlatformTimer::create();
}
@ -108,8 +104,9 @@ LightShadowMap::LightShadowMap( LightInfo *light )
LightShadowMap::~LightShadowMap()
{
mTarget = NULL;
SAFE_DELETE( mVizQuery );
SAFE_DELETE(mStaticRefreshTimer);
SAFE_DELETE(mDynamicRefreshTimer);
releaseTextures();
smShadowMaps.remove( this );
@ -334,23 +331,6 @@ void LightShadowMap::render( RenderPassManager* renderPass,
mLastUpdate = Sim::getCurrentTime();
}
void LightShadowMap::preLightRender()
{
PROFILE_SCOPE( LightShadowMap_prepLightRender );
if ( mVizQuery )
{
mWasOccluded = mVizQuery->getStatus( true ) == GFXOcclusionQuery::Occluded;
mVizQuery->begin();
}
}
void LightShadowMap::postLightRender()
{
if ( mVizQuery )
mVizQuery->end();
}
BaseMatInstance* LightShadowMap::getShadowMaterial( BaseMatInstance *inMat ) const
{
// See if we have an existing material hook.
@ -610,11 +590,14 @@ ShadowMapParams::ShadowMapParams( LightInfo *light )
shadowSoftness = 0.15f;
fadeStartDist = 0.0f;
lastSplitTerrainOnly = false;
mQuery = GFX->createOcclusionQuery();
_validate();
}
ShadowMapParams::~ShadowMapParams()
{
SAFE_DELETE( mQuery );
SAFE_DELETE( mShadowMap );
SAFE_DELETE( mDynamicShadowMap );
}

View file

@ -47,6 +47,9 @@
#ifndef _GFXSHADER_H_
#include "gfx/gfxShader.h"
#endif
#ifndef _GFXOCCLUSIONQUERY_H_
#include "gfx/gfxOcclusionQuery.h"
#endif
#ifndef _PLATFORM_PLATFORMTIMER_H_
#include "platform/platformTimer.h"
#endif
@ -61,7 +64,6 @@ struct SceneData;
class GFXShaderConstBuffer;
class GFXShaderConstHandle;
class GFXShader;
class GFXOcclusionQuery;
class LightManager;
class RenderPassManager;
@ -169,12 +171,6 @@ public:
bool isViewDependent() const { return mIsViewDependent; }
bool wasOccluded() const { return mWasOccluded; }
void preLightRender();
void postLightRender();
void updatePriority( const SceneRenderState *state, U32 currTimeMs );
F32 getLastScreenSize() const { return mLastScreenSize; }
@ -257,15 +253,6 @@ protected:
/// The time this shadow was last culled and prioritized.
U32 mLastCull;
/// The shadow occlusion query used when the light is
/// rendered to determine if any pixel of it is visible.
GFXOcclusionQuery *mVizQuery;
/// If true the light was occluded by geometry the
/// last frame it was updated.
//the last frame.
bool mWasOccluded;
F32 mLastScreenSize;
F32 mLastPriority;
@ -325,6 +312,8 @@ public:
bool hasCookieTex() const { return cookie.isNotEmpty(); }
GFXOcclusionQuery* getOcclusionQuery() const { return mQuery; }
GFXTextureObject* getCookieTex();
GFXCubemap* getCookieCubeTex();
@ -339,6 +328,7 @@ protected:
///
LightShadowMap *mShadowMap;
LightShadowMap *mDynamicShadowMap;
GFXOcclusionQuery* mQuery;
LightInfo *mLight;

View file

@ -174,12 +174,12 @@ void ShadowMapPass::render( SceneManager *sceneManager,
continue;
// --- Static Shadow Map ---
LightShadowMap *lsm = params->getOrCreateShadowMap();
LightShadowMap *dlsm = params->getOrCreateShadowMap(true);
LightShadowMap *lsm = params->getOrCreateShadowMap();
LightShadowMap *dlsm = params->getOrCreateShadowMap(true);
// First check the visiblity query... if it wasn't
// visible skip it.
if (lsm->wasOccluded() || dlsm->wasOccluded())
if(params->getOcclusionQuery()->getStatus(true) == GFXOcclusionQuery::Occluded)
continue;
// Any shadow that is visible is counted as being
@ -187,9 +187,9 @@ void ShadowMapPass::render( SceneManager *sceneManager,
++smActiveShadowMaps;
// Do a priority update for this shadow.
lsm->updatePriority(diffuseState, currTime);
lsm->updatePriority(diffuseState, currTime);
shadowMaps.push_back(lsm);
shadowMaps.push_back(lsm);
// --- Dynamic Shadow Map ---
@ -198,7 +198,7 @@ void ShadowMapPass::render( SceneManager *sceneManager,
++smActiveShadowMaps;
// Do a priority update for this shadow.
dlsm->updatePriority(diffuseState, currTime);
dlsm->updatePriority(diffuseState, currTime);
shadowMaps.push_back( dlsm );
}
@ -306,4 +306,4 @@ void DynamicShadowRenderPassManager::addInst( RenderInst *inst )
}
Parent::addInst(inst);
}
}

View file

@ -47,9 +47,16 @@ bool NamedTexTarget::registerWithName( const String &name )
}
// Make sure the target name isn't empty or already taken.
if ( name.isEmpty() || smTargets.contains( name ) )
if ( name.isEmpty())
{
Con::errorf("NamedTexTarget::registerWithName( const String &name ) No name given!");
return false;
}
if (smTargets.contains( name ) )
{
Con::errorf("NamedTexTarget::registerWithName( %s ) Already used!", name.c_str());
return false;
}
mName = name;
mIsRegistered = true;
smTargets.insert( mName, this );

View file

@ -162,6 +162,9 @@ Material::Material()
mSeqFramePerSec[i] = 0.0f;
mSeqSegSize[i] = 0.0f;
// Deferred Shading
mMatInfoFlags[i] = 0.0f;
}
dMemset(mCellIndex, 0, sizeof(mCellIndex));
@ -170,6 +173,9 @@ Material::Material()
dMemset(mNormalMapAtlas, 0, sizeof(mNormalMapAtlas));
dMemset(mUseAnisotropic, 0, sizeof(mUseAnisotropic));
// Deferred Shading : Metalness
dMemset(mUseMetalness, 0, sizeof(mUseMetalness));
mImposterLimits = Point4F::Zero;
mDoubleSided = false;
@ -204,6 +210,9 @@ Material::Material()
mDirectSoundOcclusion = 1.f;
mReverbSoundOcclusion = 1.0;
// Deferred Shading
mIsSky = false;
}
void Material::initPersistFields()
@ -289,10 +298,7 @@ void Material::initPersistFields()
addField( "useAnisotropic", TypeBool, Offset(mUseAnisotropic, Material), MAX_STAGES,
"Use anisotropic filtering for the textures of this stage." );
addField("envMap", TypeImageFilename, Offset(mEnvMapFilename, Material), MAX_STAGES,
"The name of an environment map cube map to apply to this material." );
addField("vertLit", TypeBool, Offset(mVertLit, Material), MAX_STAGES,
"If true the vertex color is used for lighting." );
@ -379,9 +385,6 @@ void Material::initPersistFields()
addProtectedField("bumpTex", TypeImageFilename, Offset(mNormalMapFilename, Material),
defaultProtectedSetNotEmptyFn, emptyStringProtectedGetFn, MAX_STAGES,
"For backwards compatibility.\n@see normalMap\n");
addProtectedField("envTex", TypeImageFilename, Offset(mEnvMapFilename, Material),
defaultProtectedSetNotEmptyFn, emptyStringProtectedGetFn, MAX_STAGES,
"For backwards compatibility.\n@see envMap\n");
addProtectedField("colorMultiply", TypeColorF, Offset(mDiffuse, Material),
defaultProtectedSetNotEmptyFn, emptyStringProtectedGetFn, MAX_STAGES,
"For backwards compatibility.\n@see diffuseColor\n");
@ -417,6 +420,9 @@ void Material::initPersistFields()
addField("dynamicCubemap", TypeBool, Offset(mDynamicCubemap, Material),
"Enables the material to use the dynamic cubemap from the ShapeBase object its applied to." );
addField("isSky", TypeBool, Offset(mIsSky, Material),
"Sky support. Alters draw dimensions." );
addGroup( "Behavioral" );
addField( "showFootprints", TypeBool, Offset( mShowFootprints, Material ),

View file

@ -221,8 +221,6 @@ public:
/// The strength scalar for the detail normal map.
F32 mDetailNormalMapStrength[MAX_STAGES];
FileName mEnvMapFilename[MAX_STAGES];
/// This color is the diffuse color of the material
/// or if it has a texture it is multiplied against
/// the diffuse texture color.
@ -287,12 +285,18 @@ public:
/// If the stage should use anisotropic filtering.
bool mUseAnisotropic[MAX_STAGES];
// Deferred Shading: Metalness
bool mUseMetalness[MAX_STAGES];
bool mDoubleSided;
String mCubemapName;
CubemapData* mCubemapData;
bool mDynamicCubemap;
// Deferred Shading
bool mIsSky;
F32 mMatInfoFlags[MAX_STAGES];
bool mTranslucent;
BlendOp mTranslucentBlendOp;
bool mTranslucentZWrite;

View file

@ -46,6 +46,7 @@ ImplementFeatureType( MFT_AlphaTest, MFG_Texture, 7.0f, true );
ImplementFeatureType( MFT_SpecularMap, MFG_Texture, 8.0f, true );
ImplementFeatureType( MFT_NormalMap, MFG_Texture, 9.0f, true );
ImplementFeatureType( MFT_DetailNormalMap, MFG_Texture, 10.0f, true );
ImplementFeatureType( MFT_Imposter, U32(-1), -1, true );
ImplementFeatureType( MFT_AccuMap, MFG_PreLighting, 2.0f, true );
@ -55,10 +56,9 @@ ImplementFeatureType( MFT_LightMap, MFG_Lighting, 4.0f, true );
ImplementFeatureType( MFT_ToneMap, MFG_Lighting, 5.0f, true );
ImplementFeatureType( MFT_VertLitTone, MFG_Lighting, 6.0f, false );
ImplementFeatureType( MFT_VertLit, MFG_Lighting, 7.0f, true );
ImplementFeatureType( MFT_EnvMap, MFG_Lighting, 8.0f, true );
ImplementFeatureType( MFT_CubeMap, MFG_Lighting, 9.0f, true );
ImplementFeatureType( MFT_PixSpecular, MFG_Lighting, 10.0f, true );
ImplementFeatureType( MFT_MinnaertShading, MFG_Lighting, 12.0f, true );
ImplementFeatureType( MFT_PixSpecular, MFG_Lighting, 9.0f, true );
ImplementFeatureType( MFT_MinnaertShading, MFG_Lighting, 10.0f, true );
ImplementFeatureType( MFT_CubeMap, MFG_Lighting, 11.0f, true );
ImplementFeatureType( MFT_GlowMask, MFG_PostLighting, 1.0f, true );
ImplementFeatureType( MFT_Visibility, MFG_PostLighting, 2.0f, true );
@ -84,6 +84,8 @@ ImplementFeatureType( MFT_NormalsOut, MFG_PreLighting, 1.0f, false );
ImplementFeatureType( MFT_LightbufferMRT, MFG_PreLighting, 1.0f, false );
ImplementFeatureType( MFT_RenderTarget1_Zero, MFG_PreTexture, 1.0f, false );
ImplementFeatureType( MFT_RenderTarget2_Zero, MFG_PreTexture, 1.0f, false );
ImplementFeatureType( MFT_RenderTarget3_Zero, MFG_PreTexture, 1.0f, false );
ImplementFeatureType( MFT_Foliage, MFG_PreTransform, 1.0f, false );
@ -91,4 +93,13 @@ ImplementFeatureType( MFT_ParticleNormal, MFG_PreTransform, 2.0f, false );
ImplementFeatureType( MFT_ForwardShading, U32(-1), -1, true );
ImplementFeatureType( MFT_ImposterVert, MFG_PreTransform, 1.0, false );
ImplementFeatureType( MFT_ImposterVert, MFG_PreTransform, 1.0, false );
// Deferred Shading
ImplementFeatureType( MFT_isDeferred, U32(-1), -1, true );
ImplementFeatureType( MFT_SkyBox, MFG_Transform, 1.0f, true );
ImplementFeatureType( MFT_DeferredEmptySpec, MFG_Texture, 8.01f, false );
ImplementFeatureType( MFT_DeferredSpecMap, MFG_Texture, 8.2f, false );
ImplementFeatureType( MFT_DeferredSpecVars, MFG_Texture, 8.5f, false );
ImplementFeatureType( MFT_DeferredMatInfoFlags, MFG_Texture, 8.7f, false );

View file

@ -94,6 +94,7 @@ DeclareFeatureType( MFT_OverlayMap );
DeclareFeatureType( MFT_DetailMap );
DeclareFeatureType( MFT_DiffuseColor );
DeclareFeatureType( MFT_DetailNormalMap );
DeclareFeatureType( MFT_Imposter );
DeclareFeatureType( MFT_AccuMap );
DeclareFeatureType( MFT_AccuScale );
@ -120,7 +121,6 @@ DeclareFeatureType( MFT_ToneMap );
DeclareFeatureType( MFT_VertLit );
DeclareFeatureType( MFT_VertLitTone );
DeclareFeatureType( MFT_EnvMap );
DeclareFeatureType( MFT_CubeMap );
DeclareFeatureType( MFT_PixSpecular );
DeclareFeatureType( MFT_SpecularMap );
@ -157,8 +157,10 @@ DeclareFeatureType( MFT_InterlacedPrePass );
/// to the second render-target
DeclareFeatureType( MFT_LightbufferMRT );
/// This feature outputs black to RenderTarget1
/// This feature outputs black to RenderTarget3
DeclareFeatureType( MFT_RenderTarget1_Zero );
DeclareFeatureType( MFT_RenderTarget2_Zero );
DeclareFeatureType( MFT_RenderTarget3_Zero );
DeclareFeatureType( MFT_Foliage );
@ -178,4 +180,11 @@ DeclareFeatureType( MFT_ForwardShading );
DeclareFeatureType( MFT_ImposterVert );
// Deferred Shading
DeclareFeatureType( MFT_isDeferred );
DeclareFeatureType( MFT_SkyBox );
DeclareFeatureType( MFT_DeferredSpecMap );
DeclareFeatureType( MFT_DeferredSpecVars );
DeclareFeatureType( MFT_DeferredMatInfoFlags );
DeclareFeatureType( MFT_DeferredEmptySpec );
#endif // _MATERIALFEATURETYPES_H_

View file

@ -455,14 +455,6 @@ void ProcessedMaterial::_setStageData()
if(!mStages[i].getTex( MFT_SpecularMap ))
mMaterial->logError("Failed to load specular map %s for stage %i", _getTexturePath(mMaterial->mSpecularMapFilename[i]).c_str(), i);
}
// EnironmentMap
if( mMaterial->mEnvMapFilename[i].isNotEmpty() )
{
mStages[i].setTex( MFT_EnvMap, _createTexture( mMaterial->mEnvMapFilename[i], &GFXDefaultStaticDiffuseProfile ) );
if(!mStages[i].getTex( MFT_EnvMap ))
mMaterial->logError("Failed to load environment map %s for stage %i", _getTexturePath(mMaterial->mEnvMapFilename[i]).c_str(), i);
}
}
mMaterial->mCubemapData = dynamic_cast<CubemapData*>(Sim::findObject( mMaterial->mCubemapName ));

View file

@ -106,6 +106,9 @@ void ShaderConstHandles::init( GFXShader *shader, CustomMaterial* mat /*=NULL*/
for (S32 i = 0; i < Material::MAX_TEX_PER_PASS; ++i)
mTexHandlesSC[i] = shader->getShaderConstHandle(mat->mSamplerNames[i]);
}
// Deferred Shading
mMatInfoFlagsSC = shader->getShaderConstHandle(ShaderGenVars::matInfoFlags);
}
///
@ -208,28 +211,6 @@ bool ProcessedShaderMaterial::init( const FeatureSet &features,
mInstancingState = new InstancingState();
mInstancingState->setFormat( &_getRPD( 0 )->shader->mInstancingFormat, mVertexFormat );
}
// Check for a RenderTexTargetBin assignment
// *IMPORTANT NOTE*
// This is a temporary solution for getting diffuse mapping working with tex targets for standard materials
// It should be removed once this is done properly, at that time the sAllowTextureTargetAssignment should also be removed
// from Material (it is necessary for catching shadow maps/post effect this shouldn't be applied to)
if (Material::sAllowTextureTargetAssignment)
if (mMaterial && mMaterial->mDiffuseMapFilename[0].isNotEmpty() && mMaterial->mDiffuseMapFilename[0].substr( 0, 1 ).equal("#"))
{
String texTargetBufferName = mMaterial->mDiffuseMapFilename[0].substr(1, mMaterial->mDiffuseMapFilename[0].length() - 1);
NamedTexTarget *texTarget = NamedTexTarget::find( texTargetBufferName );
RenderPassData* rpd = getPass(0);
if (rpd)
{
rpd->mTexSlot[0].texTarget = texTarget;
rpd->mTexType[0] = Material::TexTarget;
rpd->mSamplerNames[0] = "diffuseMap";
}
}
return true;
}
@ -353,11 +334,18 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum,
fd.features.addFeature( MFT_VertLit );
// cubemaps only available on stage 0 for now - bramage
if ( stageNum < 1 &&
if ( stageNum < 1 && mMaterial->isTranslucent() &&
( ( mMaterial->mCubemapData && mMaterial->mCubemapData->mCubemap ) ||
mMaterial->mDynamicCubemap ) )
fd.features.addFeature( MFT_CubeMap );
{
fd.features.addFeature( MFT_CubeMap );
}
if (mMaterial->mIsSky)
{
fd.features.addFeature(MFT_CubeMap);
fd.features.addFeature(MFT_SkyBox);
}
fd.features.addFeature( MFT_Visibility );
if ( lastStage &&
@ -428,7 +416,6 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum,
if ( mMaterial->mAccuEnabled[stageNum] )
{
fd.features.addFeature( MFT_AccuMap );
mHasAccumulation = true;
}
@ -441,19 +428,7 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum,
fd.features.removeFeature( MFT_AccuMap );
mHasAccumulation = false;
}
// if we still have the AccuMap feature, we add all accu constant features
if ( fd.features[ MFT_AccuMap ] ) {
// add the dependencies of the accu map
fd.features.addFeature( MFT_AccuScale );
fd.features.addFeature( MFT_AccuDirection );
fd.features.addFeature( MFT_AccuStrength );
fd.features.addFeature( MFT_AccuCoverage );
fd.features.addFeature( MFT_AccuSpecular );
// now remove some features that are not compatible with this
fd.features.removeFeature( MFT_UseInstancing );
}
// Without a base texture use the diffuse color
// feature to ensure some sort of output.
if (!fd.features[MFT_DiffuseMap])
@ -1175,7 +1150,12 @@ void ProcessedShaderMaterial::_setShaderConstants(SceneRenderState * state, cons
0.0f, 0.0f ); // TODO: Wrap mode flags?
shaderConsts->setSafe(handles->mBumpAtlasTileSC, atlasTileParams);
}
// Deferred Shading: Determine Material Info Flags
S32 matInfoFlags =
(mMaterial->mEmissive[stageNum] ? 1 : 0);
mMaterial->mMatInfoFlags[stageNum] = matInfoFlags / 255.0f;
shaderConsts->setSafe(handles->mMatInfoFlagsSC, mMaterial->mMatInfoFlags[stageNum]);
if( handles->mAccuScaleSC->isValid() )
shaderConsts->set( handles->mAccuScaleSC, mMaterial->mAccuScale[stageNum] );
if( handles->mAccuDirectionSC->isValid() )

View file

@ -87,6 +87,9 @@ public:
GFXShaderConstHandle *mImposterUVs;
GFXShaderConstHandle *mImposterLimits;
// Deferred Shading : Material Info Flags
GFXShaderConstHandle* mMatInfoFlagsSC;
GFXShaderConstHandle* mTexHandlesSC[Material::MAX_TEX_PER_PASS];
GFXShaderConstHandle* mRTParamsSC[TEXTURE_STAGE_COUNT];

Some files were not shown because too many files have changed in this diff Show more