diff --git a/Engine/source/T3D/AI/AIAimTarget.cpp b/Engine/source/T3D/AI/AIAimTarget.cpp index 35c7d927e..86ea7145b 100644 --- a/Engine/source/T3D/AI/AIAimTarget.cpp +++ b/Engine/source/T3D/AI/AIAimTarget.cpp @@ -194,7 +194,9 @@ DefineEngineMethod(AIController, getAimObject, S32, (), , "@see setAimObject()\n") { - SceneObject* obj = dynamic_cast(object->getAim()->mObj.getPointer()); + SceneObject* obj = NULL; + if (object->getAim()) + obj = dynamic_cast(object->getAim()->mObj.getPointer()); return obj ? obj->getId() : -1; } diff --git a/Engine/source/T3D/AI/AIController.cpp b/Engine/source/T3D/AI/AIController.cpp index 8ace880f1..d38eb4bfd 100644 --- a/Engine/source/T3D/AI/AIController.cpp +++ b/Engine/source/T3D/AI/AIController.cpp @@ -70,7 +70,12 @@ bool AIController::setControllerDataProperty(void* obj, const char* index, const void AIController::setGoal(AIInfo* targ) { - if (mGoal) { delete(mGoal); mGoal = NULL; } + if (mGoal) + { + if (mGoal->mObj.isValid() && targ->mObj.isValid() && mGoal->mObj == targ->mObj) + return; + delete(mGoal); mGoal = NULL; + } if (targ->mObj.isValid()) { @@ -86,26 +91,58 @@ void AIController::setGoal(AIInfo* targ) void AIController::setGoal(Point3F loc, F32 rad) { - if (mGoal) delete(mGoal); + if (mGoal) + { + if (mGoal->mPosSet && mGoal->getPosition() == loc) + { + mGoal->mRadius = rad; + return; + } + delete(mGoal); + } mGoal = new AIGoal(this, loc, rad); } void AIController::setGoal(SimObjectPtr objIn, F32 rad) { - if (mGoal) delete(mGoal); + if (mGoal) + { + if (mGoal->mObj.isValid() && objIn.isValid() && mGoal->mObj == objIn) + { + mGoal->mRadius = rad; + return; + } + delete(mGoal); + } mGoal = new AIGoal(this, objIn, rad); } void AIController::setAim(Point3F loc, F32 rad, Point3F offset) { - if (mAimTarget) delete(mAimTarget); + if (mAimTarget) + { + if (mAimTarget->mPosSet && mAimTarget->getPosition() == loc) + { + mAimTarget->mAimOffset = offset; + return; + } + delete(mAimTarget); + } mAimTarget = new AIAimTarget(this, loc, rad); mAimTarget->mAimOffset = offset; } void AIController::setAim(SimObjectPtr objIn, F32 rad, Point3F offset) { - if (mAimTarget) delete(mAimTarget); + if (mAimTarget) + { + if (mAimTarget->mObj.isValid() && objIn.isValid() && mAimTarget->mObj == objIn) + { + mAimTarget->mAimOffset = offset; + return; + } + delete(mAimTarget); + } mAimTarget = new AIAimTarget(this, objIn, rad); mAimTarget->mAimOffset = offset; } diff --git a/Engine/source/T3D/AI/AIController.h b/Engine/source/T3D/AI/AIController.h index dcc46f661..fdd9eb9df 100644 --- a/Engine/source/T3D/AI/AIController.h +++ b/Engine/source/T3D/AI/AIController.h @@ -70,8 +70,24 @@ public: private: AICover* mCover; public: - void setCover(Point3F loc, F32 rad = 0.0f) { delete(mCover); mCover = new AICover(this, loc, rad); } - void setCover(SimObjectPtr objIn, F32 rad = 0.0f) { delete(mCover); mCover = new AICover(this, objIn, rad); } + void setCover(Point3F loc, F32 rad = 0.0f) + { + if (mCover && mCover->mPosSet && mCover->getPosition() == loc) + { + mCover->mRadius = rad; + return; + } + delete(mCover); mCover = new AICover(this, loc, rad); + } + void setCover(SimObjectPtr objIn, F32 rad = 0.0f) + { + if (mCover && mCover->mObj == objIn) + { + mCover->mRadius = rad; + return; + } + delete(mCover); mCover = new AICover(this, objIn, rad); + } AICover* getCover() { return mCover; } bool findCover(const Point3F& from, F32 radius); void clearCover(); diff --git a/Engine/source/T3D/SubScene.cpp b/Engine/source/T3D/SubScene.cpp index effda500f..798d42ace 100644 --- a/Engine/source/T3D/SubScene.cpp +++ b/Engine/source/T3D/SubScene.cpp @@ -225,7 +225,16 @@ bool SubScene::evaluateCondition() Con::setBoolVariable(resVar.c_str(), false); String command = resVar + "=" + mLoadIf + ";"; - Con::evaluatef(command.c_str()); + StringTableEntry objectName = getName(); + if (objectName != NULL) + objectName = getIdString(); + + StringTableEntry groupName = getGroup() ? getGroup()->getName() : NULL; + if (groupName != NULL) + groupName = getGroup()->getIdString(); + + String context = String::ToString("%s\nGroup: %s, Object: %s", getFilename(), groupName, objectName); + Con::evaluate(command.c_str(), false, context.c_str()); return Con::getBoolVariable(resVar.c_str()); } return true; diff --git a/Engine/source/T3D/assets/assetImporter.cpp b/Engine/source/T3D/assets/assetImporter.cpp index a807bbc0f..ec0fd1f89 100644 --- a/Engine/source/T3D/assets/assetImporter.cpp +++ b/Engine/source/T3D/assets/assetImporter.cpp @@ -3003,7 +3003,7 @@ Torque::Path AssetImporter::importMaterialAsset(AssetImportObject* assetItem) if (hasRoughness) { - newMat->mInvertRoughness[0] = true; + newMat->mInvertRoughness[0] = false; } newAsset->addObject(newMat); diff --git a/Engine/source/T3D/missionMarker.cpp b/Engine/source/T3D/missionMarker.cpp index 69ae9ab81..a3e380951 100644 --- a/Engine/source/T3D/missionMarker.cpp +++ b/Engine/source/T3D/missionMarker.cpp @@ -367,7 +367,17 @@ bool SpawnSphere::testCondition() String resVar = getIdString() + String(".result"); Con::setBoolVariable(resVar.c_str(), false); String command = resVar + "=" + mSpawnIf + ";"; - Con::evaluatef(command.c_str()); + + StringTableEntry objectName = getName(); + if (objectName != NULL) + objectName = getIdString(); + + StringTableEntry groupName = getGroup() ? getGroup()->getName() : NULL; + if (groupName != NULL) + groupName = getGroup()->getIdString(); + + String context = String::ToString("%s\nGroup: %s, Object: %s", getFilename(), groupName, objectName); + Con::evaluate(command.c_str(), false, context.c_str()); if (Con::getBoolVariable(resVar.c_str()) == 1) { return true; diff --git a/Engine/source/T3D/shapeBase.cpp b/Engine/source/T3D/shapeBase.cpp index 729271fae..96fadaf6e 100644 --- a/Engine/source/T3D/shapeBase.cpp +++ b/Engine/source/T3D/shapeBase.cpp @@ -975,6 +975,7 @@ ShapeBase::ShapeBase() mMoveMotion( false ), mShapeBaseMount( NULL ), mShapeInstance( NULL ), + mCubeReflector(NULL), mConvexList( new Convex ), mEnergy( 0.0f ), mRechargeRate( 0.0f ), @@ -1053,6 +1054,12 @@ ShapeBase::~ShapeBase() mShapeInstance = NULL; } + if (mCubeReflector) + { + mCubeReflector->unregisterReflector(); + SAFE_DELETE(mCubeReflector); + } + CollisionTimeout* ptr = mTimeoutList; while (ptr) { CollisionTimeout* cur = ptr; @@ -1173,7 +1180,11 @@ void ShapeBase::onRemove() if ( isClientObject() ) { - mCubeReflector.unregisterReflector(); + if (mCubeReflector) + { + mCubeReflector->unregisterReflector(); + SAFE_DELETE(mCubeReflector); + } } } @@ -1349,11 +1360,17 @@ bool ShapeBase::onNewDataBlock( GameBaseData *dptr, bool reload ) mLightPlugin->reset(); if ( isClientObject() ) - { - mCubeReflector.unregisterReflector(); - - if ( mDataBlock->reflectorDesc ) - mCubeReflector.registerReflector( this, mDataBlock->reflectorDesc ); + { + if (mCubeReflector) + { + mCubeReflector->unregisterReflector(); + SAFE_DELETE(mCubeReflector); + } + if (mDataBlock->reflectorDesc) + { + mCubeReflector = new CubeReflector(); + mCubeReflector->registerReflector(this, mDataBlock->reflectorDesc); + } } return true; @@ -2681,7 +2698,7 @@ void ShapeBase::_prepRenderImage( SceneRenderState *state, // If we're currently rendering our own reflection we // don't want to render ourselves into it. - if ( mCubeReflector.isRendering() ) + if (mCubeReflector && mCubeReflector->isRendering()) return; // We force all the shapes to use the highest detail @@ -2785,8 +2802,8 @@ void ShapeBase::prepBatchRender(SceneRenderState* state, S32 mountedImageIndex ) // Set up our TS render state. TSRenderState rdata; rdata.setSceneState( state ); - if ( mCubeReflector.isEnabled() ) - rdata.setCubemap( mCubeReflector.getCubemap() ); + if (mCubeReflector && mCubeReflector->isEnabled()) + rdata.setCubemap( mCubeReflector->getCubemap() ); rdata.setFadeOverride( (1.0f - mCloakLevel) * mFadeVal ); // We might have some forward lit materials @@ -2810,14 +2827,14 @@ void ShapeBase::prepBatchRender(SceneRenderState* state, S32 mountedImageIndex ) mat.scale( mObjScale ); GFX->setWorldMatrix( mat ); - if ( state->isDiffusePass() && mCubeReflector.isEnabled() && mCubeReflector.getOcclusionQuery() ) + if ( state->isDiffusePass() && mCubeReflector && mCubeReflector->isEnabled() && mCubeReflector->getOcclusionQuery() ) { RenderPassManager *pass = state->getRenderPass(); OccluderRenderInst *ri = pass->allocInst(); ri->type = RenderPassManager::RIT_Occluder; - ri->query = mCubeReflector.getOcclusionQuery(); + ri->query = mCubeReflector->getOcclusionQuery(); mObjToWorld.mulP( mObjBox.getCenter(), &ri->position ); ri->scale.set( mObjBox.getExtents() ); ri->orientation = pass->allocUniqueXform( mObjToWorld ); diff --git a/Engine/source/T3D/shapeBase.h b/Engine/source/T3D/shapeBase.h index a8807a026..71967bbe1 100644 --- a/Engine/source/T3D/shapeBase.h +++ b/Engine/source/T3D/shapeBase.h @@ -1207,7 +1207,7 @@ public: static F32 sFullCorrectionDistance; static F32 sCloakSpeed; // Time to cloak, in seconds - CubeReflector mCubeReflector; + CubeReflector* mCubeReflector; /// @name Initialization /// @{ diff --git a/Engine/source/T3D/trigger.cpp b/Engine/source/T3D/trigger.cpp index 9df293ba5..2558c45d5 100644 --- a/Engine/source/T3D/trigger.cpp +++ b/Engine/source/T3D/trigger.cpp @@ -28,6 +28,7 @@ #include "console/engineAPI.h" #include "collision/boxConvex.h" #include "console/script.h" +#include "console/consoleInternal.h" #include "core/stream/bitStream.h" #include "math/mathIO.h" @@ -172,8 +173,9 @@ Trigger::Trigger() mPhysicsRep = NULL; mTripOnce = false; + mTripped = false; mTrippedBy = 0xFFFFFFFF; - mTripIf = ""; + mTripIf.clear(); //Default up a basic square Point3F vecs[3] = { Point3F(1.0, 0.0, 0.0), @@ -704,7 +706,17 @@ bool Trigger::testCondition() String resVar = getIdString() + String(".result"); Con::setBoolVariable(resVar.c_str(), false); String command = resVar + "=" + mTripIf + ";"; - Con::evaluatef(command.c_str()); + + StringTableEntry objectName = getName(); + if (objectName != NULL) + objectName = getIdString(); + + StringTableEntry groupName = getGroup() ? getGroup()->getName() : NULL; + if (groupName != NULL) + groupName = getGroup()->getIdString(); + + String context = String::ToString("%s\nGroup: %s, Object: %s", getFilename(), groupName, objectName); + Con::evaluate(command.c_str(), false, context.c_str()); if (Con::getBoolVariable(resVar.c_str()) == 1) { return true; @@ -738,11 +750,11 @@ void Trigger::potentialEnterObject(GameBase* enter) mObjects.push_back(enter); deleteNotify(enter); - if(evalCmD(&mEnterCommand)) + if(isServerObject() && evalCmD(&mEnterCommand)) { String command = String("%obj = ") + enter->getIdString() + ";"; command = command + String("%this = ") + getIdString() + ";" + mEnterCommand; - Con::evaluate(command.c_str()); + Con::evaluate(command.c_str(), false, Con::getCurrentScriptModulePath()); } if( mDataBlock && testTrippable() && testCondition()) @@ -787,11 +799,11 @@ void Trigger::processTick(const Move* move) mObjects.erase(i); clearNotify(remove); - if (evalCmD(&mLeaveCommand)) + if (isServerObject() && evalCmD(&mLeaveCommand)) { String command = String("%obj = ") + remove->getIdString() + ";"; command = command + String("%this = ") + getIdString() + ";" + mLeaveCommand; - Con::evaluate(command.c_str()); + Con::evaluate(command.c_str(), false, Con::getCurrentScriptModulePath()); } if (testTrippable() && testCondition()) mDataBlock->onLeaveTrigger_callback( this, remove ); @@ -799,8 +811,19 @@ void Trigger::processTick(const Move* move) } } - if (evalCmD(&mTickCommand)) - Con::evaluate(mTickCommand.c_str()); + if (isServerObject() && evalCmD(&mTickCommand)) + { + StringTableEntry objectName = getName(); + if (objectName != NULL) + objectName = getIdString(); + + StringTableEntry groupName = getGroup() ? getGroup()->getName() : NULL; + if (groupName != NULL) + groupName = getGroup()->getIdString(); + + String context = String::ToString("%s\nGroup: %s, Object: %s", getFilename(), groupName, objectName); + Con::evaluate(mTickCommand.c_str(), false, context); + } if (mObjects.size() != 0 && testTrippable() && testCondition()) mDataBlock->onTickTrigger_callback( this ); diff --git a/Engine/source/T3D/tsStatic.cpp b/Engine/source/T3D/tsStatic.cpp index 329485b4f..c244d25c3 100644 --- a/Engine/source/T3D/tsStatic.cpp +++ b/Engine/source/T3D/tsStatic.cpp @@ -109,7 +109,8 @@ F32 TSStatic::smStaticObjectUnfadeableSize = 75; TSStatic::TSStatic() : cubeDescId(0), - reflectorDesc(NULL) + reflectorDesc(NULL), + mCubeReflector(NULL) { mNetFlags.set(Ghostable | ScopeAlways); @@ -159,6 +160,11 @@ TSStatic::~TSStatic() delete mConvexList; mConvexList = NULL; mShapeAsset.unregisterRefreshNotify(); + if (mCubeReflector) + { + mCubeReflector->unregisterReflector(); + SAFE_DELETE(mCubeReflector); + } } ImplementEnumType(TSMeshType, @@ -361,10 +367,17 @@ bool TSStatic::onAdd() if (isClientObject()) { - mCubeReflector.unregisterReflector(); + if (mCubeReflector) + { + mCubeReflector->unregisterReflector(); + SAFE_DELETE(mCubeReflector); + } if (reflectorDesc) - mCubeReflector.registerReflector(this, reflectorDesc); + { + mCubeReflector = new CubeReflector(); + mCubeReflector->registerReflector(this, reflectorDesc); + } } _updateShouldTick(); @@ -594,8 +607,11 @@ void TSStatic::onRemove() mShapeInstance = NULL; mAmbientThread = NULL; - if (isClientObject()) - mCubeReflector.unregisterReflector(); + if (isClientObject() && mCubeReflector) + { + mCubeReflector->unregisterReflector(); + SAFE_DELETE(mCubeReflector); + } Parent::onRemove(); } @@ -780,7 +796,7 @@ void TSStatic::prepRenderImage(SceneRenderState* state) // If we're currently rendering our own reflection we // don't want to render ourselves into it. - if (mCubeReflector.isRendering()) + if (mCubeReflector && mCubeReflector->isRendering()) return; @@ -800,8 +816,8 @@ void TSStatic::prepRenderImage(SceneRenderState* state) rdata.setFadeOverride(1.0f); rdata.setOriginSort(mUseOriginSort); - if (mCubeReflector.isEnabled()) - rdata.setCubemap(mCubeReflector.getCubemap()); + if (mCubeReflector && mCubeReflector->isEnabled()) + rdata.setCubemap(mCubeReflector->getCubemap()); // Acculumation rdata.setAccuTex(mAccuTex); @@ -830,13 +846,13 @@ void TSStatic::prepRenderImage(SceneRenderState* state) mat.scale(mObjScale); GFX->setWorldMatrix(mat); - if (state->isDiffusePass() && mCubeReflector.isEnabled() && mCubeReflector.getOcclusionQuery()) + if (state->isDiffusePass() && mCubeReflector && mCubeReflector->isEnabled() && mCubeReflector->getOcclusionQuery()) { RenderPassManager* pass = state->getRenderPass(); OccluderRenderInst* ri = pass->allocInst(); ri->type = RenderPassManager::RIT_Occluder; - ri->query = mCubeReflector.getOcclusionQuery(); + ri->query = mCubeReflector->getOcclusionQuery(); mObjToWorld.mulP(mObjBox.getCenter(), &ri->position); ri->scale.set(mObjBox.getExtents()); ri->orientation = pass->allocUniqueXform(mObjToWorld); diff --git a/Engine/source/T3D/tsStatic.h b/Engine/source/T3D/tsStatic.h index 150aa59cf..7ab21ba0a 100644 --- a/Engine/source/T3D/tsStatic.h +++ b/Engine/source/T3D/tsStatic.h @@ -184,7 +184,7 @@ protected: String cubeDescName; U32 cubeDescId; ReflectorDesc* reflectorDesc; - CubeReflector mCubeReflector; + CubeReflector* mCubeReflector; void onAssetRefreshed(AssetPtrBase* pAssetPtrBase) override { diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index 77f1e78c2..5da712e5d 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -2367,8 +2367,7 @@ DefineEngineFunction( exec, bool, ( const char* fileName, bool noCalls, bool jou DefineEngineFunction( eval, const char*, ( const char* consoleString, bool echo ), (false), "eval(consoleString)") { - Con::EvalResult returnValue = Con::evaluate(consoleString, echo, NULL); - + Con::EvalResult returnValue = Con::evaluate(consoleString, echo, Platform::makeRelativePathName(Con::getCurrentScriptModulePath(), NULL)); return Con::getReturnBuffer(returnValue.value.getString()); } diff --git a/Engine/source/console/torquescript/astNodes.cpp b/Engine/source/console/torquescript/astNodes.cpp index 6fd28bc58..c20a0b975 100644 --- a/Engine/source/console/torquescript/astNodes.cpp +++ b/Engine/source/console/torquescript/astNodes.cpp @@ -59,7 +59,8 @@ inline FuncVars* getFuncVars(S32 lineNumber) { if (gFuncVars == &gGlobalScopeFuncVars) { - const char* str = avar("Attemping to use local variable in global scope. File: %s Line: %d", CodeBlock::smCurrentParser->getCurrentFile(), lineNumber); + const char* lineTxt = CodeBlock::smCurrentLineText; + const char* str = avar("Attemping to use local variable in global scope. File: %s\nLine Num: %d\nLine: \"%s\"", CodeBlock::smCurrentParser->getCurrentFile(), lineNumber, lineTxt); scriptErrorHandler(str); } return gFuncVars; diff --git a/Engine/source/console/torquescript/codeBlock.cpp b/Engine/source/console/torquescript/codeBlock.cpp index 5a4bdb30a..2696ca054 100644 --- a/Engine/source/console/torquescript/codeBlock.cpp +++ b/Engine/source/console/torquescript/codeBlock.cpp @@ -35,6 +35,7 @@ using namespace Compiler; bool CodeBlock::smInFunction = false; CodeBlock * CodeBlock::smCodeBlockList = NULL; +const char* CodeBlock::smCurrentLineText = "\0"; TorqueScriptParser *CodeBlock::smCurrentParser = NULL; extern FuncVars gEvalFuncVars; @@ -578,6 +579,7 @@ Con::EvalResult CodeBlock::compileExec(StringTableEntry fileName, const char *in consoleAllocReset(); name = fileName; + smCurrentLineText = inString; if (fileName) { @@ -609,7 +611,7 @@ Con::EvalResult CodeBlock::compileExec(StringTableEntry fileName, const char *in Script::gStatementList = NULL; // we are an eval compile if we don't have a file name associated (no exec) - gIsEvalCompile = fileName == NULL; + gIsEvalCompile = fileName == NULL || setFrame == 0; gFuncVars = gIsEvalCompile ? &gEvalFuncVars : &gGlobalScopeFuncVars; // Set up the parser. @@ -623,6 +625,7 @@ Con::EvalResult CodeBlock::compileExec(StringTableEntry fileName, const char *in if (!Script::gStatementList) { + smCurrentLineText = "\0"; delete this; return Con::EvalResult(Con::getVariable("$ScriptError")); } @@ -668,7 +671,10 @@ Con::EvalResult CodeBlock::compileExec(StringTableEntry fileName, const char *in Con::warnf(ConsoleLogEntry::General, "precompile size mismatch, precompile: %d compile: %d", codeSize, lastIp); // repurpose argc as local register counter for global state - return (exec(0, fileName, NULL, localRegisterCount, 0, noCalls, NULL, setFrame)); + Con::EvalResult execResult = (exec(0, fileName, NULL, localRegisterCount, 0, noCalls, NULL, setFrame)); + + smCurrentLineText = "\0"; + return execResult; } //------------------------------------------------------------------------- diff --git a/Engine/source/console/torquescript/codeBlock.h b/Engine/source/console/torquescript/codeBlock.h index b9d7dd207..33404d9a6 100644 --- a/Engine/source/console/torquescript/codeBlock.h +++ b/Engine/source/console/torquescript/codeBlock.h @@ -61,6 +61,7 @@ private: public: static bool smInFunction; static TorqueScriptParser * smCurrentParser; + static const char* smCurrentLineText; static CodeBlock *getCodeBlockList() { diff --git a/Engine/source/console/torquescript/compiler.cpp b/Engine/source/console/torquescript/compiler.cpp index 51bf7c0c5..206f7d679 100644 --- a/Engine/source/console/torquescript/compiler.cpp +++ b/Engine/source/console/torquescript/compiler.cpp @@ -160,7 +160,16 @@ S32 FuncVars::assign(StringTableEntry var, TypeReq currentType, S32 lineNumber, if (found->second.isConstant) { - const char* str = avar("Script Warning: Reassigning variable %s when it is a constant. File: %s Line : %d", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber); + const char* lineText = CodeBlock::smCurrentLineText; + + String codeString = CodeBlock::smCurrentLineText; + Vector splitLines; + codeString.split("\n", splitLines); + + if (lineNumber > 0 && splitLines.size() > lineNumber) + lineText = splitLines[lineNumber - 1].c_str(); + + const char* str = avar("Script Warning: Reassigning variable %s when it is a constant. File: %s\nLine Num: %d\nLine: \"%s\"", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber, lineText); scriptErrorHandler(str); } return found->second.reg; @@ -179,7 +188,16 @@ S32 FuncVars::lookup(StringTableEntry var, S32 lineNumber) if (found == vars.end()) { - const char* str = avar("Script Warning: Variable %s referenced before used when compiling script. File: %s Line: %d", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber); + const char* lineText = CodeBlock::smCurrentLineText; + + String codeString = CodeBlock::smCurrentLineText; + Vector splitLines; + codeString.split("\n", splitLines); + + if (lineNumber > 0 && splitLines.size() > lineNumber) + lineText = splitLines[lineNumber - 1].c_str(); + + const char* str = avar("Script Warning: Variable %s referenced before used when compiling script. File: %s\nLine Num: %d\nLine: \"%s\"", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber, lineText); scriptErrorHandler(str); return assign(var, TypeReqString, lineNumber, false); @@ -194,7 +212,16 @@ TypeReq FuncVars::lookupType(StringTableEntry var, S32 lineNumber) if (found == vars.end()) { - const char* str = avar("Script Warning: Variable %s referenced before used when compiling script. File: %s Line: %d", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber); + const char* lineText = CodeBlock::smCurrentLineText; + + String codeString = CodeBlock::smCurrentLineText; + Vector splitLines; + codeString.split("\n", splitLines); + + if (lineNumber > 0 && splitLines.size() > lineNumber) + lineText = splitLines[lineNumber-1].c_str(); + + const char* str = avar("Script Warning: Variable %s referenced before used when compiling script. File: %s\nLine Num: %d\nLine: \"%s\"", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber, lineText); scriptErrorHandler(str); assign(var, TypeReqString, lineNumber, false); diff --git a/Engine/source/console/torquescript/runtime.cpp b/Engine/source/console/torquescript/runtime.cpp index 45c3249ee..1f0db44d3 100644 --- a/Engine/source/console/torquescript/runtime.cpp +++ b/Engine/source/console/torquescript/runtime.cpp @@ -38,8 +38,10 @@ namespace TorqueScript if (fileName) fileName = StringTable->insert(fileName); + bool fileExec = Torque::FS::IsFile(fileName); + CodeBlock* newCodeBlock = new CodeBlock(); - return (newCodeBlock->compileExec(fileName, string, false, fileName ? -1 : 0)); + return (newCodeBlock->compileExec(fileName, string, false, fileExec ? -1 : 0)); } Con::EvalResult TorqueScriptRuntime::evaluate(const char* script, S32 frame, bool echo, const char* fileName) diff --git a/Engine/source/gfx/gFont.cpp b/Engine/source/gfx/gFont.cpp index 05a3f55ac..a4d349af1 100644 --- a/Engine/source/gfx/gFont.cpp +++ b/Engine/source/gfx/gFont.cpp @@ -705,10 +705,8 @@ bool GFont::read(Stream& io_rStream) delete bmp; return false; }*/ - U32 len; - io_rStream.read(&len); - if (!bmp->readBitmapStream("png", io_rStream, len)) + if (!bmp->readBitmapStream("png", io_rStream, U32_MAX)) { delete bmp; return false; diff --git a/Engine/source/gfx/gl/gfxGLDevice.cpp b/Engine/source/gfx/gl/gfxGLDevice.cpp index 8019f21bf..8ec644b8a 100644 --- a/Engine/source/gfx/gl/gfxGLDevice.cpp +++ b/Engine/source/gfx/gl/gfxGLDevice.cpp @@ -91,19 +91,74 @@ void loadGLExtensions(void *context) GL::gglPerformExtensionBinds(context); } -void STDCALL glDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, - const GLchar *message, const void *userParam) +void APIENTRY glDebugCallback( + GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam) { - // JTH [11/24/2016]: This is a temporary fix so that we do not get spammed for redundant fbo changes. - // This only happens on Intel cards. This should be looked into sometime in the near future. - if (dStrStartsWith(message, "API_ID_REDUNDANT_FBO")) + // Ignore non-significant notifications (optional) + if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) return; + + const char* srcStr = "UNKNOWN"; + const char* typeStr = "UNKNOWN"; + const char* sevStr = "UNKNOWN"; + + switch (source) + { + case GL_DEBUG_SOURCE_API: srcStr = "API"; break; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: srcStr = "WINDOW"; break; + case GL_DEBUG_SOURCE_SHADER_COMPILER: srcStr = "SHADER"; break; + case GL_DEBUG_SOURCE_THIRD_PARTY: srcStr = "THIRD_PARTY"; break; + case GL_DEBUG_SOURCE_APPLICATION: srcStr = "APP"; break; + case GL_DEBUG_SOURCE_OTHER: srcStr = "OTHER"; break; + } + + switch (type) + { + case GL_DEBUG_TYPE_ERROR: typeStr = "ERROR"; break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: typeStr = "DEPRECATED"; break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: typeStr = "UNDEFINED"; break; + case GL_DEBUG_TYPE_PORTABILITY: typeStr = "PORTABILITY"; break; + case GL_DEBUG_TYPE_PERFORMANCE: typeStr = "PERFORMANCE"; break; + case GL_DEBUG_TYPE_MARKER: typeStr = "MARKER"; break; + case GL_DEBUG_TYPE_PUSH_GROUP: typeStr = "PUSH"; break; + case GL_DEBUG_TYPE_POP_GROUP: typeStr = "POP"; break; + case GL_DEBUG_TYPE_OTHER: typeStr = "OTHER"; break; + } + + switch (severity) + { + case GL_DEBUG_SEVERITY_HIGH: sevStr = "HIGH"; break; + case GL_DEBUG_SEVERITY_MEDIUM: sevStr = "MEDIUM"; break; + case GL_DEBUG_SEVERITY_LOW: sevStr = "LOW"; break; + case GL_DEBUG_SEVERITY_NOTIFICATION: sevStr = "NOTIFY"; break; + } + + // Filter known noisy IDs here if needed + // Example: + // if (id == 131185) return; + if (severity == GL_DEBUG_SEVERITY_HIGH) - Con::errorf("OPENGL: %s", message); + { + Con::errorf("OPENGL [%s][%s][%s][%u]: %s", + sevStr, srcStr, typeStr, id, message); + AssertFatal(false, "OpenGL HIGH severity error."); + } else if (severity == GL_DEBUG_SEVERITY_MEDIUM) - Con::warnf("OPENGL: %s", message); - else if (severity == GL_DEBUG_SEVERITY_LOW) - Con::printf("OPENGL: %s", message); + { + Con::warnf("OPENGL [%s][%s][%s][%u]: %s", + sevStr, srcStr, typeStr, id, message); + } + else + { + Con::printf("OPENGL [%s][%s][%s][%u]: %s", + sevStr, srcStr, typeStr, id, message); + } } void STDCALL glAmdDebugCallback(GLuint id, GLenum category, GLenum severity, GLsizei length, @@ -157,27 +212,34 @@ void GFXGLDevice::initGLState() #endif #if TORQUE_DEBUG - if( gglHasExtension(ARB_debug_output) ) - { - glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallbackARB(glDebugCallback, NULL); - glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); - GLuint unusedIds = 0; - glDebugMessageControlARB(GL_DONT_CARE, - GL_DONT_CARE, - GL_DONT_CARE, - 0, - &unusedIds, - GL_TRUE); - } - else if(gglHasExtension(AMD_debug_output)) - { - glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallbackAMD(glAmdDebugCallback, NULL); - //glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); - GLuint unusedIds = 0; - glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0,&unusedIds, GL_TRUE); - } + +bool debugInitialized = false; +int flags; +glGetIntegerv(GL_CONTEXT_FLAGS, &flags); +if (flags & GL_CONTEXT_FLAG_DEBUG_BIT) +{ + glEnable(GL_DEBUG_OUTPUT); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + + glDebugMessageCallback(glDebugCallback, nullptr); + + glDebugMessageControl( + GL_DONT_CARE, + GL_DONT_CARE, + GL_DONT_CARE, + 0, + nullptr, + GL_TRUE); + + Con::printf("OpenGL debug output enabled."); + debugInitialized = true; +} + +if (!debugInitialized) +{ + Con::warnf("OpenGL debug output NOT available."); +} + #endif PlatformGL::setVSync(smEnableVSync); diff --git a/Engine/source/gfx/gl/gfxGLTextureManager.cpp b/Engine/source/gfx/gl/gfxGLTextureManager.cpp index ca0a958f3..c6c73fbee 100644 --- a/Engine/source/gfx/gl/gfxGLTextureManager.cpp +++ b/Engine/source/gfx/gl/gfxGLTextureManager.cpp @@ -175,7 +175,7 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex, //calculate num mipmaps if(retTex->mMipLevels == 0) retTex->mMipLevels = getMaxMipmaps(width, height, 1); - + glTexParameteri(binding, GL_TEXTURE_MAX_LEVEL, retTex->mMipLevels-1 ); bool hasTexStorage = false; @@ -364,34 +364,83 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex, // loadTexture - GBitmap //----------------------------------------------------------------------------- -static void _textureUpload(const S32 width, const S32 height,const S32 bytesPerPixel,const GFXGLTextureObject* texture, const GFXFormat fmt, const U8* data,const S32 mip=0, const U32 face = 0, Swizzle *pSwizzle = NULL) +static void _textureUpload( + const S32 width, + const S32 height, + const S32 bytesPerPixel, + const GFXGLTextureObject* texture, + const GFXFormat fmt, + const U8* data, + const S32 mip = 0, + const U32 face = 0, + Swizzle* pSwizzle = NULL) { - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture->getBuffer()); - U32 bufSize = width * height * bytesPerPixel; - glBufferData(GL_PIXEL_UNPACK_BUFFER, bufSize, NULL, GL_STREAM_DRAW); + const GLenum target = texture->getBinding(); - if(pSwizzle) - { - PROFILE_SCOPE(Swizzle32_Upload); - U8* pboMemory = (U8*)dMalloc(bufSize); - pSwizzle->ToBuffer(pboMemory, data, bufSize); - glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, bufSize, pboMemory); - dFree(pboMemory); - } - else - { - PROFILE_SCOPE(SwizzleNull_Upload); - glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, bufSize, data); - } + // Save pixel store state + GLint prevUnpackAlign; + glGetIntegerv(GL_UNPACK_ALIGNMENT, &prevUnpackAlign); - if(texture->getBinding() == GL_TEXTURE_CUBE_MAP) - glTexSubImage2D(GFXGLFaceType[face], mip, 0, 0, width, height, GFXGLTextureFormat[fmt], GFXGLTextureType[fmt], NULL); - else if (texture->getBinding() == GL_TEXTURE_2D) - glTexSubImage2D(texture->getBinding(), mip, 0, 0, width, height, GFXGLTextureFormat[fmt], GFXGLTextureType[fmt], NULL); - else - glTexSubImage1D(texture->getBinding(), mip, 0, (width > 1 ? width : height), GFXGLTextureFormat[fmt], GFXGLTextureType[fmt], NULL); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + const U32 bufSize = width * height * bytesPerPixel; + + const U8* uploadPtr = data; + U8* tempBuffer = nullptr; + + if (pSwizzle) + { + tempBuffer = (U8*)dMalloc(bufSize); + pSwizzle->ToBuffer(tempBuffer, data, bufSize); + uploadPtr = tempBuffer; + } + + if (target == GL_TEXTURE_CUBE_MAP) + { + glTexSubImage2D( + GFXGLFaceType[face], + mip, + 0, 0, + width, height, + GFXGLTextureFormat[fmt], + GFXGLTextureType[fmt], + uploadPtr + ); + } + else if (target == GL_TEXTURE_2D) + { + glTexSubImage2D( + GL_TEXTURE_2D, + mip, + 0, 0, + width, height, + GFXGLTextureFormat[fmt], + GFXGLTextureType[fmt], + uploadPtr + ); + } + else if (target == GL_TEXTURE_1D) + { + glTexSubImage1D( + GL_TEXTURE_1D, + mip, + 0, + width, + GFXGLTextureFormat[fmt], + GFXGLTextureType[fmt], + uploadPtr + ); + } + + if (tempBuffer) + dFree(tempBuffer); + + // Restore state + glPixelStorei(GL_UNPACK_ALIGNMENT, prevUnpackAlign); + +#ifdef TORQUE_DEBUG + glCheckErrors(); +#endif } bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, GBitmap *pDL) diff --git a/Engine/source/gfx/gl/gfxGLTextureObject.cpp b/Engine/source/gfx/gl/gfxGLTextureObject.cpp index 651059d34..81ca6fa9d 100644 --- a/Engine/source/gfx/gl/gfxGLTextureObject.cpp +++ b/Engine/source/gfx/gl/gfxGLTextureObject.cpp @@ -102,36 +102,79 @@ GFXLockedRect* GFXGLTextureObject::lock(U32 mipLevel /*= 0*/, RectI* inRect /*= void GFXGLTextureObject::unlock(U32 mipLevel /*= 0*/, U32 faceIndex /*= 0*/) { - if(!mLockedRect.bits) - return; + if (!mLockedRect.bits) + return; - // I know this is in unlock, but in GL we actually do our submission in unlock. - PROFILE_SCOPE(GFXGLTextureObject_lockRT); + PROFILE_SCOPE(GFXGLTextureObject_unlock); - PRESERVE_TEXTURE(mBinding); - glBindTexture(mBinding, mHandle); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mBuffer); - glBufferData(GL_PIXEL_UNPACK_BUFFER, (mLockedRectRect.extent.x + 1) * (mLockedRectRect.extent.y + 1) * mBytesPerTexel, mFrameAllocatorPtr, GL_STREAM_DRAW); - S32 z = getDepth(); - if (mBinding == GL_TEXTURE_3D) - glTexSubImage3D(mBinding, mipLevel, mLockedRectRect.point.x, mLockedRectRect.point.y, z, - mLockedRectRect.extent.x, mLockedRectRect.extent.y, z, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], NULL); - else if(mBinding == GL_TEXTURE_2D) - glTexSubImage2D(mBinding, mipLevel, mLockedRectRect.point.x, mLockedRectRect.point.y, - mLockedRectRect.extent.x, mLockedRectRect.extent.y, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], NULL); - else if(mBinding == GL_TEXTURE_1D) - glTexSubImage1D(mBinding, mipLevel, (mLockedRectRect.point.x > 1 ? mLockedRectRect.point.x : mLockedRectRect.point.y), - (mLockedRectRect.extent.x > 1 ? mLockedRectRect.extent.x : mLockedRectRect.extent.y), GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], NULL); + PRESERVE_TEXTURE(mBinding); + glBindTexture(mBinding, mHandle); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + // --- Save pixel store state --- + GLint prevUnpackAlign; + glGetIntegerv(GL_UNPACK_ALIGNMENT, &prevUnpackAlign); - mLockedRect.bits = NULL; -#if TORQUE_DEBUG - AssertFatal(mFrameAllocatorMarkGuard == FrameAllocator::getWaterMark(), ""); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + const U32 width = mLockedRectRect.extent.x; + const U32 height = mLockedRectRect.extent.y; + const U32 depth = getDepth(); + + if (mBinding == GL_TEXTURE_3D) + { + glTexSubImage3D( + mBinding, + mipLevel, + mLockedRectRect.point.x, + mLockedRectRect.point.y, + 0, + width, + height, + depth, + GFXGLTextureFormat[mFormat], + GFXGLTextureType[mFormat], + mLockedRect.bits + ); + } + else if (mBinding == GL_TEXTURE_2D) + { + glTexSubImage2D( + mBinding, + mipLevel, + mLockedRectRect.point.x, + mLockedRectRect.point.y, + width, + height, + GFXGLTextureFormat[mFormat], + GFXGLTextureType[mFormat], + mLockedRect.bits + ); + } + else if (mBinding == GL_TEXTURE_1D) + { + glTexSubImage1D( + mBinding, + mipLevel, + mLockedRectRect.point.x, + width, + GFXGLTextureFormat[mFormat], + GFXGLTextureType[mFormat], + mLockedRect.bits + ); + } + + // --- Restore state --- + glPixelStorei(GL_UNPACK_ALIGNMENT, prevUnpackAlign); + + mLockedRect.bits = NULL; + + FrameAllocator::setWaterMark(mFrameAllocatorMark); + mFrameAllocatorMark = 0; + mFrameAllocatorPtr = NULL; + +#ifdef TORQUE_DEBUG + glCheckErrors(); #endif - FrameAllocator::setWaterMark(mFrameAllocatorMark); - mFrameAllocatorMark = 0; - mFrameAllocatorPtr = NULL; } void GFXGLTextureObject::release() diff --git a/Engine/source/gfx/gl/gfxGLUtils.h b/Engine/source/gfx/gl/gfxGLUtils.h index 2218836b0..928cf98e3 100644 --- a/Engine/source/gfx/gl/gfxGLUtils.h +++ b/Engine/source/gfx/gl/gfxGLUtils.h @@ -28,6 +28,32 @@ #include "gfx/gl/gfxGLStateCache.h" #include "gfx/bitmap/imageUtils.h" +inline const char* glGetErrorString(GLenum error) +{ + switch (error) + { + case GL_NO_ERROR: return "No Error"; + case GL_INVALID_ENUM: return "Invalid Enum"; + case GL_INVALID_VALUE: return "Invalid Value"; + case GL_INVALID_OPERATION: return "Invalid Operation"; + case GL_INVALID_FRAMEBUFFER_OPERATION: return "Invalid Framebuffer Operation"; + case GL_OUT_OF_MEMORY: return "Out of Memory"; + case GL_STACK_UNDERFLOW: return "Stack Underflow"; + case GL_STACK_OVERFLOW: return "Stack Overflow"; + case GL_CONTEXT_LOST: return "Context Lost"; + default: return "Unknown Error"; + } +} + +inline void _glCheckErrors(const char *filename, int line) +{ + GLenum err; + while ((err = glGetError()) != GL_NO_ERROR) + Con::printf("OpenGL Error: %s (%d) [%u] %s\n", filename, line, err, glGetErrorString(err)); +} + +#define glCheckErrors() _glCheckErrors(__FILE__, __LINE__) + inline U32 getMaxMipmaps(U32 width, U32 height, U32 depth) { return getMax( getBinLog2(depth), getMax(getBinLog2(width), getBinLog2(height))) + 1; diff --git a/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp b/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp index 1bb34d4f2..a81c0334c 100644 --- a/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp +++ b/Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp @@ -103,9 +103,17 @@ void GFXGLDevice::enumerateAdapters( Vector &adapterList ) } SDL_ClearError(); + U32 debugFlag = 0; +#ifdef TORQUE_DEBUG + debugFlag |= SDL_GL_CONTEXT_DEBUG_FLAG; +#endif SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, debugFlag); SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1); - + SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); +#ifdef TORQUE_GL_SOFTWARE + SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 0); +#endif SDL_GLContext tempContext = SDL_GL_CreateContext( tempWindow ); if( !tempContext ) { diff --git a/Engine/source/gui/buttons/guiButtonBaseCtrl.cpp b/Engine/source/gui/buttons/guiButtonBaseCtrl.cpp index 2a545ffe1..20e42484c 100644 --- a/Engine/source/gui/buttons/guiButtonBaseCtrl.cpp +++ b/Engine/source/gui/buttons/guiButtonBaseCtrl.cpp @@ -303,7 +303,10 @@ void GuiButtonBaseCtrl::onMouseEnter(const GuiEvent& event) SFX->playOnce(mProfile->getSoundButtonOverProfile()); mHighlighted = true; - messageSiblings(mRadioGroup); + + if (mButtonType != ButtonTypeRadio) + messageSiblings(mRadioGroup); + onHighlighted_callback(mHighlighted); } } @@ -320,7 +323,9 @@ void GuiButtonBaseCtrl::onMouseLeave(const GuiEvent&) mDepressed = false; mHighlighted = false; onHighlighted_callback(mHighlighted); - messageSiblings(mRadioGroup); + + if (mButtonType != ButtonTypeRadio) + messageSiblings(mRadioGroup); } //----------------------------------------------------------------------------- diff --git a/Engine/source/gui/buttons/guiButtonBaseCtrl.h b/Engine/source/gui/buttons/guiButtonBaseCtrl.h index cf9566f0c..8ef4331ba 100644 --- a/Engine/source/gui/buttons/guiButtonBaseCtrl.h +++ b/Engine/source/gui/buttons/guiButtonBaseCtrl.h @@ -96,6 +96,7 @@ public: bool getStateOn() const { return mStateOn; } void setDepressed(bool depressed) { mDepressed = depressed; } + bool isDepressed() { return mDepressed; } void resetState() { mDepressed = false; mHighlighted = false; } void setHighlighted(bool highlighted); diff --git a/Engine/source/gui/controls/guiBitmapCtrl.cpp b/Engine/source/gui/controls/guiBitmapCtrl.cpp index fe7aa7862..e572233f0 100644 --- a/Engine/source/gui/controls/guiBitmapCtrl.cpp +++ b/Engine/source/gui/controls/guiBitmapCtrl.cpp @@ -28,6 +28,8 @@ #include "console/engineAPI.h" #include "gfx/gfxDevice.h" #include "gfx/gfxDrawUtil.h" +#include "gfx/gfxAPI.h" +#include "gui/buttons/guiButtonBaseCtrl.h" #include "materials/matTextureTarget.h" @@ -55,11 +57,26 @@ ConsoleDocClass(GuiBitmapCtrl, "@ingroup GuiControls" ); +ImplementEnumType(BitmapDrawMode, + "Draw Mode of the bitmap control.\n\n" + "@ingroup GuiControls") +{ + GuiBitmapCtrl::BitmapMode_Stretch, "Stretch", "Stretches the bitmap to fill the control extents. Aspect ratio is not preserved." +}, +{ GuiBitmapCtrl::BitmapMode_Tile, "Tile", "Repeats the bitmap to fill the control extents without scaling." }, +{ GuiBitmapCtrl::BitmapMode_Fit, "Fit", "Scales the bitmap to fit entirely within the control while preserving aspect ratio. May result in letterboxing." }, +{ GuiBitmapCtrl::BitmapMode_Fill, "Fill", "Scales the bitmap to completely fill the control while preserving aspect ratio. Portions of the bitmap may be cropped." }, +{ GuiBitmapCtrl::BitmapMode_Center, "Center", "Draws the bitmap at its original size centered within the control. No scaling is applied." }, + +EndImplementEnumType; + GuiBitmapCtrl::GuiBitmapCtrl(void) : mStartPoint(0, 0), mColor(ColorI::WHITE), mAngle(0), mWrap(false), + mDrawMode(BitmapMode_Stretch), + mFilterType(GFXTextureFilterLinear), mBitmap(NULL), mBitmapName(StringTable->EmptyString()) { @@ -74,8 +91,10 @@ void GuiBitmapCtrl::initPersistFields() addField("color", TypeColorI, Offset(mColor, GuiBitmapCtrl), "color mul"); addField("wrap", TypeBool, Offset(mWrap, GuiBitmapCtrl), "If true, the bitmap is tiled inside the control rather than stretched to fit."); + addField("drawMode", TYPEID(), Offset(mDrawMode, GuiBitmapCtrl), "Sets the mode to draw this bitmap in this control (wrap forces Tile mode)."); + addField("filterType", TYPEID(), Offset(mFilterType, GuiBitmapCtrl), "Sets the bitmap texture filter mode."); addFieldV("angle", TypeRangedF32, Offset(mAngle, GuiBitmapCtrl), &CommonValidators::DegreeRange, "rotation"); - endGroup( "Bitmap" ); + endGroup("Bitmap"); Parent::initPersistFields(); } @@ -91,6 +110,7 @@ bool GuiBitmapCtrl::onWake() void GuiBitmapCtrl::onSleep() { + mBitmap = NULL; Parent::onSleep(); } @@ -171,36 +191,108 @@ void GuiBitmapCtrl::onRender(Point2I offset, const RectI& updateRect) { GFX->getDrawUtil()->clearBitmapModulation(); GFX->getDrawUtil()->setBitmapModulation(mColor); - if (mWrap) - { - // We manually draw each repeat because non power of two textures will - // not tile correctly when rendered with GFX->drawBitmapTile(). The non POT - // bitmap will be padded by the hardware, and we'll see lots of slack - // in the texture. So... lets do what we must: draw each repeat by itself: - GFXTextureObject* texture = mBitmap; - RectI srcRegion; - RectI dstRegion; - F32 xdone = ((F32)getExtent().x / (F32)texture->mBitmapSize.x) + 1; - F32 ydone = ((F32)getExtent().y / (F32)texture->mBitmapSize.y) + 1; - S32 xshift = mStartPoint.x % texture->mBitmapSize.x; - S32 yshift = mStartPoint.y % texture->mBitmapSize.y; - for (S32 y = 0; y < ydone; ++y) - for (S32 x = 0; x < xdone; ++x) - { - srcRegion.set(0, 0, texture->mBitmapSize.x, texture->mBitmapSize.y); - dstRegion.set(((texture->mBitmapSize.x * x) + offset.x) - xshift, - ((texture->mBitmapSize.y * y) + offset.y) - yshift, - texture->mBitmapSize.x, - texture->mBitmapSize.y); - GFX->getDrawUtil()->drawBitmapStretchSR(texture, dstRegion, srcRegion, GFXBitmapFlip_None, GFXTextureFilterLinear, mAngle); - } + if (dynamic_cast(getParent())) + { + GuiButtonBaseCtrl* parent = static_cast(getParent()); + + GFX->getDrawUtil()->setBitmapModulation(mProfile->mFillColor); + + if (parent->isHighlighted()) + GFX->getDrawUtil()->setBitmapModulation(mProfile->mFillColorHL); + if (parent->isDepressed() || parent->getStateOn()) + GFX->getDrawUtil()->setBitmapModulation(mProfile->mFillColorSEL); + if (!parent->isActive()) + GFX->getDrawUtil()->setBitmapModulation(mProfile->mFillColorNA); } - else + + if (mWrap && mDrawMode != BitmapMode_Tile) + mDrawMode = BitmapMode_Tile; + + RectI ctrlRect(offset, getExtent()); + GFXTextureObject* texture = mBitmap; + + F32 texW = (F32)texture->getWidth(); + F32 texH = (F32)texture->getHeight(); + F32 ctrlW = (F32)getExtent().x; + F32 ctrlH = (F32)getExtent().y; + + switch (mDrawMode) { - RectI rect(offset, getExtent()); - GFX->getDrawUtil()->drawBitmapStretch(mBitmap, rect, GFXBitmapFlip_None, GFXTextureFilterLinear, false, mAngle); + case BitmapMode_Tile: + { + // How many repetitions needed (+1 ensures full coverage) + const S32 xCount = (ctrlW / texW) + 1; + const S32 yCount = (ctrlH / texH) + 1; + + // Scroll offset (wrap-safe) + const S32 xShift = mStartPoint.x % (S32)texW; + const S32 yShift = mStartPoint.y % (S32)texH; + + RectI srcRegion(0, 0, (S32)texW, (S32)texH); + RectI dstRegion; + + for (S32 y = 0; y < yCount; ++y) + { + for (S32 x = 0; x < xCount; ++x) + { + dstRegion.set( + offset.x + (x * texW) - xShift, + offset.y + (y * texH) - yShift, + texW, + texH + ); + + GFX->getDrawUtil()->drawBitmapStretchSR(texture, dstRegion, srcRegion, GFXBitmapFlip_None, mFilterType, true, mAngle); + } + } + + break; + } + case GuiBitmapCtrl::BitmapMode_Fit: + { + F32 scale = getMin(ctrlW / texW, ctrlH / texH); + + S32 drawW = (S32)(texW * scale); + S32 drawH = (S32)(texH * scale); + + S32 x = offset.x + (ctrlW - drawW) * 0.5f; + S32 y = offset.y + (ctrlH - drawH) * 0.5f; + + RectI dst(x, y, drawW, drawH); + GFX->getDrawUtil()->drawBitmapStretch(texture, dst, GFXBitmapFlip_None, mFilterType, false, mAngle); + break; + } + case GuiBitmapCtrl::BitmapMode_Fill: + { + F32 scale = getMax(ctrlW / texW, ctrlH / texH); + + S32 drawW = (S32)(texW * scale); + S32 drawH = (S32)(texH * scale); + + S32 x = offset.x + (ctrlW - drawW) * 0.5f; + S32 y = offset.y + (ctrlH - drawH) * 0.5f; + + RectI dst(x, y, drawW, drawH); + GFX->getDrawUtil()->drawBitmapStretch(texture, dst, GFXBitmapFlip_None, mFilterType, false, mAngle); + break; + } + case GuiBitmapCtrl::BitmapMode_Center: + { + S32 x = offset.x + (ctrlW - texW) * 0.5f; + S32 y = offset.y + (ctrlH - texH) * 0.5f; + + RectI dst(x, y, texW, texH); + + GFX->getDrawUtil()->drawBitmapStretch(texture, dst, GFXBitmapFlip_None, mFilterType, false, mAngle); + break; + } + default: + { + GFX->getDrawUtil()->drawBitmapStretch(texture, ctrlRect, GFXBitmapFlip_None, mFilterType, false, mAngle); + break; + } } } diff --git a/Engine/source/gui/controls/guiBitmapCtrl.h b/Engine/source/gui/controls/guiBitmapCtrl.h index adf6f5322..ab44fdec2 100644 --- a/Engine/source/gui/controls/guiBitmapCtrl.h +++ b/Engine/source/gui/controls/guiBitmapCtrl.h @@ -35,6 +35,15 @@ public: typedef GuiControl Parent; + enum BitmapMode + { + BitmapMode_Stretch, + BitmapMode_Tile, + BitmapMode_Fit, + BitmapMode_Fill, + BitmapMode_Center + }; + protected: /// Name of the bitmap file. If this is 'texhandle' the bitmap is not loaded @@ -47,6 +56,8 @@ protected: /// If true, bitmap tiles inside control. Otherwise stretches. bool mWrap; + BitmapMode mDrawMode; + GFXTextureFilterType mFilterType; public: GFXTexHandle mBitmap; @@ -74,4 +85,7 @@ public: "The bitmap can either be tiled or stretched inside the control."); }; +typedef GuiBitmapCtrl::BitmapMode BitmapDrawMode; +DefineEnumType(BitmapDrawMode); + #endif diff --git a/Engine/source/gui/controls/guiGameListMenuCtrl.cpp b/Engine/source/gui/controls/guiGameListMenuCtrl.cpp index fb69fbc71..6ceb1cbcd 100644 --- a/Engine/source/gui/controls/guiGameListMenuCtrl.cpp +++ b/Engine/source/gui/controls/guiGameListMenuCtrl.cpp @@ -974,7 +974,9 @@ void GuiGameListMenuCtrl::doScriptCommand(StringTableEntry command) if (command && command[0]) { setThisControl(); - Con::evaluate(command, false, __FILE__); + StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); + String context = String::ToString("%s\nObject: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); + Con::evaluate(command, false, context.c_str()); } } diff --git a/Engine/source/gui/controls/guiGameSettingsCtrl.cpp b/Engine/source/gui/controls/guiGameSettingsCtrl.cpp index 0b1e7ebea..a562782a3 100644 --- a/Engine/source/gui/controls/guiGameSettingsCtrl.cpp +++ b/Engine/source/gui/controls/guiGameSettingsCtrl.cpp @@ -494,7 +494,9 @@ void GuiGameSettingsCtrl::doScriptCommand(StringTableEntry command) if (command && command[0]) { setThisControl(); - Con::evaluate(command, false, __FILE__); + StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); + String context = String::ToString("%s\nObject: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); + Con::evaluate(command, false, context.c_str()); } } diff --git a/Engine/source/gui/controls/guiListBoxCtrl.cpp b/Engine/source/gui/controls/guiListBoxCtrl.cpp index 66328b2b3..58441dd46 100644 --- a/Engine/source/gui/controls/guiListBoxCtrl.cpp +++ b/Engine/source/gui/controls/guiListBoxCtrl.cpp @@ -1539,7 +1539,9 @@ StringTableEntry GuiListBoxCtrl::_makeMirrorItemName( SimObject *inObj ) Con::setIntVariable( "$ThisControl", getId() ); Con::setIntVariable( "$ThisObject", inObj->getId() ); - outName = StringTable->insert( Con::evaluate( mMakeNameCallback ).value, true ); + StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); + String context = String::ToString("%s, Object: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); + outName = StringTable->insert( Con::evaluate( mMakeNameCallback, false, context.c_str()).value, true ); } else if ( inObj->getName() ) outName = StringTable->insert( inObj->getName() ); diff --git a/Engine/source/gui/controls/guiMLTextEditCtrl.cpp b/Engine/source/gui/controls/guiMLTextEditCtrl.cpp index 75cebfd41..04a176f9e 100644 --- a/Engine/source/gui/controls/guiMLTextEditCtrl.cpp +++ b/Engine/source/gui/controls/guiMLTextEditCtrl.cpp @@ -211,7 +211,9 @@ bool GuiMLTextEditCtrl::onKeyDown(const GuiEvent& event) case KEY_ESCAPE: if ( mEscapeCommand[0] ) { - Con::evaluate( mEscapeCommand ); + StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); + String context = String::ToString("%s, Object: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); + Con::evaluate( mEscapeCommand, false, context.c_str()); return( true ); } return( Parent::onKeyDown( event ) ); diff --git a/Engine/source/gui/core/guiControl.cpp b/Engine/source/gui/core/guiControl.cpp index bc175e9fb..bf9eec103 100644 --- a/Engine/source/gui/core/guiControl.cpp +++ b/Engine/source/gui/core/guiControl.cpp @@ -2495,7 +2495,16 @@ void GuiControl::getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent const char* GuiControl::evaluate( const char* str ) { smThisControl = this; - const char* result = Con::evaluate(str, false).value; + StringTableEntry objectName = getName(); + if (objectName != NULL) + objectName = getIdString(); + + StringTableEntry groupName = getGroup() ? getGroup()->getName() : NULL; + if (groupName != NULL) + groupName = getGroup()->getIdString(); + + String context = String::ToString("%s\nGroup: %s, Object: %s", getFilename(), groupName, objectName); + const char* result = Con::evaluate(str, false, context.c_str()).value; smThisControl = NULL; return result; diff --git a/Engine/source/platformSDL/sdlPlatformGL.cpp b/Engine/source/platformSDL/sdlPlatformGL.cpp index fd55727b8..22e719f58 100644 --- a/Engine/source/platformSDL/sdlPlatformGL.cpp +++ b/Engine/source/platformSDL/sdlPlatformGL.cpp @@ -19,12 +19,10 @@ namespace PlatformGL #ifdef TORQUE_DEBUG debugFlag |= SDL_GL_CONTEXT_DEBUG_FLAG; #endif - - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, majorOGL); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minorOGL); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, debugFlag); SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1); + SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); #ifdef TORQUE_GL_SOFTWARE SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 0); #endif diff --git a/Engine/source/sim/actionMap.cpp b/Engine/source/sim/actionMap.cpp index 2e9c3b0e7..16d107eb3 100644 --- a/Engine/source/sim/actionMap.cpp +++ b/Engine/source/sim/actionMap.cpp @@ -1482,8 +1482,12 @@ bool ActionMap::processAction(const InputEventInfo* pEvent) if(pNode->flags & Node::BindCmd) { // it's a bind command - if(pNode->makeConsoleCommand) - Con::evaluate(pNode->makeConsoleCommand); + if (pNode->makeConsoleCommand) + { + StringTableEntry objectName = getName() != StringTable->EmptyString() ? getName() : getInternalName(); + String context = String::ToString("%s\nObject: %s", Platform::makeRelativePathName(getFilename(), NULL), objectName); + Con::evaluate(pNode->makeConsoleCommand, false, context.c_str()); + } } else if (pNode->flags & Node::Held) { diff --git a/Engine/source/ts/assimp/assimpAppMaterial.cpp b/Engine/source/ts/assimp/assimpAppMaterial.cpp index fce979dfc..1d560da30 100644 --- a/Engine/source/ts/assimp/assimpAppMaterial.cpp +++ b/Engine/source/ts/assimp/assimpAppMaterial.cpp @@ -206,15 +206,15 @@ void AssimpAppMaterial::initMaterial(const Torque::Path& path, Material* mat) co if (rmName.isNotEmpty()) { mat->_setRoughMap(cleanTextureName(rmName, cleanFile, path, false), 0); // Roughness - mat->mRoughnessChan[0] = 1.0f; - mat->mInvertRoughness[0] = (floatVal == 1.0f); + mat->mRoughnessChan[0] = 1; + mat->mInvertRoughness[0] = false; mat->_setMetalMap(cleanTextureName(rmName, cleanFile, path, false), 0); // Metallic - mat->mMetalChan[0] = 2.0f; + mat->mMetalChan[0] = 2; } if (aoName.isNotEmpty()) { mat->_setAOMap(cleanTextureName(aoName, cleanFile, path, false), 0); // occlusion - mat->mAOChan[0] = 0.0f; + mat->mAOChan[0] = 0; } else { diff --git a/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl b/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl index 0ebcd3794..addc16541 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl +++ b/Templates/BaseGame/game/core/rendering/shaders/gl/lighting.glsl @@ -178,9 +178,9 @@ SurfaceToLight createSurfaceToLight(in Surface surface, in vec3 L) surfaceToLight.Lu = L; surfaceToLight.L = normalize(L); surfaceToLight.H = normalize(surface.V + surfaceToLight.L); - surfaceToLight.NdotL = saturate(dot(surfaceToLight.L, surface.N)); - surfaceToLight.HdotV = saturate(dot(surfaceToLight.H, surface.V)); - surfaceToLight.NdotH = saturate(dot(surfaceToLight.H, surface.N)); + surfaceToLight.NdotL = saturate(dot(surface.N,surfaceToLight.L)); + surfaceToLight.HdotV = saturate(dot(surfaceToLight.H,surface.V)); + surfaceToLight.NdotH = saturate(dot(surface.N,surfaceToLight.H)); return surfaceToLight; } @@ -243,12 +243,12 @@ vec3 evaluateStandardBRDF(Surface surface, SurfaceToLight surfaceToLight) float denominator = 4.0 * max(surface.NdotV, 0.0) * max(surfaceToLight.NdotL, 0.0) + 0.0001; vec3 specularBRDF = numerator / denominator; - vec3 diffuseBRDF = surface.baseColor.rgb * M_1OVER_PI_F * surface.ao; + vec3 diffuseBRDF = surface.baseColor.rgb * surface.ao * M_HALFPI_F; // Final output combining all terms vec3 kS = F; // Specular reflectance vec3 kD = (1.0 - kS) * (1.0 - surface.metalness); // Diffuse reflectance - vec3 returnBRDF = kD * (diffuseBRDF) + specularBRDF; + vec3 returnBRDF = kD * diffuseBRDF + specularBRDF; if(isCapturing == 1) return lerp(returnBRDF ,surface.albedo.rgb,surface.metalness); diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl index a2e8d2f4e..8b544ca9c 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl @@ -177,9 +177,9 @@ inline SurfaceToLight createSurfaceToLight(in Surface surface, in float3 L) surfaceToLight.Lu = L; surfaceToLight.L = normalize(L); surfaceToLight.H = normalize(surface.V + surfaceToLight.L); - surfaceToLight.NdotL = saturate(dot(surfaceToLight.L, surface.N)); + surfaceToLight.NdotL = saturate(dot(surface.N, surfaceToLight.L)); surfaceToLight.HdotV = saturate(dot(surfaceToLight.H, surface.V)); - surfaceToLight.NdotH = saturate(dot(surfaceToLight.H, surface.N)); + surfaceToLight.NdotH = saturate(dot(surface.N, surfaceToLight.H)); return surfaceToLight; } @@ -243,12 +243,12 @@ float3 evaluateStandardBRDF(Surface surface, SurfaceToLight surfaceToLight) float denominator = 4.0 * max(surface.NdotV, 0.0) * max(surfaceToLight.NdotL, 0.0) + 0.0001; float3 specularBRDF = numerator / denominator; - float3 diffuseBRDF = surface.baseColor.rgb * M_1OVER_PI_F * surface.ao; + float3 diffuseBRDF = surface.baseColor.rgb * surface.ao* M_HALFPI_F; // Final output combining all terms float3 kS = F; // Specular reflectance float3 kD = (1.0 - kS) * (1.0 - surface.metalness); // Diffuse reflectance - float3 returnBRDF = kD * (diffuseBRDF) + specularBRDF; + float3 returnBRDF = kD*diffuseBRDF + specularBRDF; if(isCapturing == 1) return lerp(returnBRDF ,surface.albedo.rgb,surface.metalness); @@ -277,8 +277,8 @@ float3 getPunctualLight(Surface surface, SurfaceToLight surfaceToLight, float3 l if(isCapturing != 1) lightfloor = 0.0; - float attenuation = getDistanceAtt(surfaceToLight.Lu, radius); - + float attenuation = getDistanceAtt(surfaceToLight.Lu, radius); + // Calculate both specular and diffuse lighting in one BRDF evaluation float3 directLighting = evaluateStandardBRDF(surface, surfaceToLight); @@ -297,7 +297,7 @@ float3 getSpotlight(Surface surface, SurfaceToLight surfaceToLight, float3 light float attenuation = 1.0f; attenuation *= getDistanceAtt(surfaceToLight.Lu, radius); attenuation *= getSpotAngleAtt(-surfaceToLight.L, lightDir, lightSpotParams.xy); - + // Calculate both specular and diffuse lighting in one BRDF evaluation float3 directLighting = evaluateStandardBRDF(surface, surfaceToLight); diff --git a/Templates/BaseGame/game/tools/convexEditor/convexEditorGui.tscript b/Templates/BaseGame/game/tools/convexEditor/convexEditorGui.tscript index 72b3b13a8..ff10d5dcc 100644 --- a/Templates/BaseGame/game/tools/convexEditor/convexEditorGui.tscript +++ b/Templates/BaseGame/game/tools/convexEditor/convexEditorGui.tscript @@ -60,10 +60,10 @@ function ConvexEditorGui::onWake( %this ) %this.releaseSidePanel(); } - EWorldEditor.UseGridSnap = EditorSettings.value("WorldEditor/Tools/UseGridSnap"); - CESnapOptions-->objectGridSnapBtn.setStateOn( EWorldEditor.UseGridSnap ); - %this.setGridSnap( EWorldEditor.UseGridSnap ); - EWorldEditor.setGridSnap( EWorldEditor.UseGridSnap ); + EWorldEditor.gridSnap = EditorSettings.value("WorldEditor/Tools/gridSnap"); + CESnapOptions-->objectGridSnapBtn.setStateOn( EWorldEditor.gridSnap ); + %this.setGridSnap( EWorldEditor.gridSnap ); + EWorldEditor.setGridSnap( EWorldEditor.gridSnap ); } function ConvexEditorGui::onSleep( %this ) @@ -217,11 +217,11 @@ function ConvexEditorMaterialResetBtn::onClick(%this) function ConvexEditorGui::toggleGridSnap(%this) { - EWorldEditor.UseGridSnap = !EWorldEditor.UseGridSnap; - EditorSettings.setValue("WorldEditor/Tools/UseGridSnap", EWorldEditor.UseGridSnap ); - CESnapOptions-->objectGridSnapBtn.setStateOn( EWorldEditor.UseGridSnap ); - %this.setGridSnap( EWorldEditor.UseGridSnap ); - EWorldEditor.setGridSnap( EWorldEditor.UseGridSnap ); + EWorldEditor.gridSnap = !EWorldEditor.gridSnap; + EditorSettings.setValue("WorldEditor/Tools/gridSnap", EWorldEditor.gridSnap ); + CESnapOptions-->objectGridSnapBtn.setStateOn( EWorldEditor.gridSnap ); + %this.setGridSnap( EWorldEditor.gridSnap ); + EWorldEditor.setGridSnap( EWorldEditor.gridSnap ); } diff --git a/Templates/BaseGame/game/tools/convexEditor/main.tscript b/Templates/BaseGame/game/tools/convexEditor/main.tscript index f81ef26cc..92e4770da 100644 --- a/Templates/BaseGame/game/tools/convexEditor/main.tscript +++ b/Templates/BaseGame/game/tools/convexEditor/main.tscript @@ -130,9 +130,9 @@ function ConvexEditorPlugin::onActivated( %this ) ConvexEditorScaleModeBtn.performClick(); } - EWorldEditor.UseGridSnap = EditorSettings.value("WorldEditor/Tools/UseGridSnap"); - CESnapOptions-->objectGridSnapBtn.setStateOn( EWorldEditor.UseGridSnap ); - %this.setGridSnap( EWorldEditor.UseGridSnap ); + EWorldEditor.gridSnap = EditorSettings.value("WorldEditor/Tools/gridSnap"); + CESnapOptions-->objectGridSnapBtn.setStateOn( EWorldEditor.gridSnap ); + %this.setGridSnap( EWorldEditor.gridSnap ); Parent::onActivated( %this ); EditorGui.SetStandardPalletBar(); diff --git a/Templates/BaseGame/game/tools/guiEditor/gui/guiEditor.ed.gui b/Templates/BaseGame/game/tools/guiEditor/gui/guiEditor.ed.gui index 301d1e689..175cdb29b 100644 --- a/Templates/BaseGame/game/tools/guiEditor/gui/guiEditor.ed.gui +++ b/Templates/BaseGame/game/tools/guiEditor/gui/guiEditor.ed.gui @@ -1411,6 +1411,25 @@ $guiContent = new GuiControl(GuiEditorGui, EditorGuiGroup) { }; }; + new GuiBitmapButtonCtrl() { + bitmapAsset = "ToolsModule:reset_icon_n_image"; + groupNum = "-1"; + buttonType = "PushButton"; + useMouseEvents = "0"; + isContainer = "0"; + Profile = "ToolsGuiDefaultProfile"; + HorizSizing = "left"; + VertSizing = "bottom"; + position = "138 12"; + Extent = "17 17"; + MinExtent = "8 2"; + canSave = "1"; + Visible = "1"; + tooltipprofile = "ToolsGuiToolTipProfile"; + hovertime = "1000"; + internalName = "button0"; + canSaveDynamicFields = "0"; + }; new GuiBitmapButtonCtrl() { bitmapAsset = "ToolsModule:reset_icon_n_image"; groupNum = "-1"; diff --git a/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditor.ed.tscript b/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditor.ed.tscript index b3e89a1c9..d23d61a5f 100644 --- a/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditor.ed.tscript +++ b/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditor.ed.tscript @@ -907,7 +907,7 @@ function GuiEditorTabBook::onTabSelected( %this, %text, %index ) switch$( %name ) { case "guiPage": - + %sidebar-->button0.setVisible( false ); %sidebar-->button1.setVisible( false ); %sidebar-->button2.setVisible( false ); %sidebar-->button3.setVisible( true ); @@ -922,7 +922,7 @@ function GuiEditorTabBook::onTabSelected( %this, %text, %index ) %sidebar-->button3.tooltip = "Hide Selected Control(s)"; case "profilesPage": - + %sidebar-->button0.setVisible( true ); %sidebar-->button1.setVisible( true ); %sidebar-->button2.setVisible( true ); %sidebar-->button3.setVisible( true ); @@ -942,7 +942,11 @@ function GuiEditorTabBook::onTabSelected( %this, %text, %index ) %sidebar-->button1.setBitmap( "ToolsModule:reset_icon_n_image" ); %sidebar-->button1.command = "GuiEditor.revertProfile( GuiEditorProfilesTree.getSelectedProfile() );"; - %sidebar-->button1.tooltip = "Revert Changes to the Selected Profile"; + %sidebar-->button1.tooltip = "Revert Changes to the Selected Profile"; + + %sidebar-->button0.setBitmap( "ToolsModule:iconSave_image" ); + %sidebar-->button0.command = "populateAllFonts();"; + %sidebar-->button0.tooltip = "(Re)Generate font cache"; case "toolboxPage": diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript b/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript index 8b6562f77..9dcd083da 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript @@ -1051,9 +1051,9 @@ function WorldEditorPlugin::onActivated( %this ) ETransformSelection.setVisible(true); } - EWorldEditor.UseGridSnap = EditorSettings.value("WorldEditor/Tools/UseGridSnap"); - ESnapOptions-->GridSnapButton.setStateOn( EWorldEditor.UseGridSnap ); - SnapToBar-->objectGridSnapBtn.setStateOn( EWorldEditor.UseGridSnap ); + EWorldEditor.gridSnap = EditorSettings.value("WorldEditor/Tools/gridSnap"); + ESnapOptions-->GridSnapButton.setStateOn( EWorldEditor.gridSnap ); + SnapToBar-->objectGridSnapBtn.setStateOn( EWorldEditor.gridSnap ); Parent::onActivated(%this); @@ -2615,8 +2615,8 @@ function EWorldEditor::syncGui( %this ) ESnapOptions-->SnapSize.setText( EWorldEditor.getSoftSnapSize() ); ESnapOptions-->GridSize.setText( EWorldEditor.getGridSize() ); - %this.UseGridSnap = EditorSettings.value("WorldEditor/Tools/UseGridSnap"); - ESnapOptions-->GridSnapButton.setStateOn( %this.UseGridSnap ); + %this.gridSnap = EditorSettings.value("WorldEditor/Tools/gridSnap"); + ESnapOptions-->GridSnapButton.setStateOn( %this.gridSnap ); %this.UseGroupCenter = EditorSettings.value("WorldEditor/Tools/UseGroupCenter"); @@ -2961,9 +2961,9 @@ function toggleSnappingOptions( %var ) } else if( %var $= "grid" ) { - EWorldEditor.UseGridSnap = !EWorldEditor.UseGridSnap; - EditorSettings.setValue("WorldEditor/Tools/UseGridSnap", EWorldEditor.UseGridSnap ); - EWorldEditor.setGridSnap( EWorldEditor.UseGridSnap ); + EWorldEditor.gridSnap = !EWorldEditor.gridSnap; + EditorSettings.setValue("WorldEditor/Tools/gridSnap", EWorldEditor.gridSnap ); + EWorldEditor.setGridSnap( EWorldEditor.gridSnap ); } else if( %var $= "byGroup" ) {