diff --git a/Engine/source/T3D/assets/MaterialAsset.cpp b/Engine/source/T3D/assets/MaterialAsset.cpp index eaafca03d..8fd2b6ecf 100644 --- a/Engine/source/T3D/assets/MaterialAsset.cpp +++ b/Engine/source/T3D/assets/MaterialAsset.cpp @@ -169,7 +169,13 @@ void MaterialAsset::initializeAsset() mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath; if (Torque::FS::IsScriptFile(mScriptPath)) - Con::executeFile(mScriptPath, false, false); + { + if (!Sim::findObject(mMatDefinitionName)) + if (Con::executeFile(mScriptPath, false, false)) + mLoadedState = ScriptLoaded; + else + mLoadedState = Failed; + } loadMaterial(); } @@ -179,7 +185,22 @@ void MaterialAsset::onAssetRefresh() mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath; if (Torque::FS::IsScriptFile(mScriptPath)) - Con::executeFile(mScriptPath, false, false); + { + //Since we're refreshing, we can assume that the file we're executing WILL have an existing definition. + //But that definition, whatever it is, is the 'correct' one, so we enable the Replace Existing behavior + //when the engine encounters a named object conflict. + String redefineBehaviorPrev = Con::getVariable("$Con::redefineBehavior"); + Con::setVariable("$Con::redefineBehavior", "replaceExisting"); + + if (Con::executeFile(mScriptPath, false, false)) + mLoadedState = ScriptLoaded; + else + mLoadedState = Failed; + + //And now that we've executed, switch back to the prior behavior + Con::setVariable("$Con::redefineBehavior", redefineBehaviorPrev.c_str()); + + } loadMaterial(); } @@ -206,7 +227,7 @@ void MaterialAsset::loadMaterial() if (mMaterialDefinition) SAFE_DELETE(mMaterialDefinition); - if (mMatDefinitionName != StringTable->EmptyString()) + if (mLoadedState == ScriptLoaded && mMatDefinitionName != StringTable->EmptyString()) { Material* matDef; if (!Sim::findObject(mMatDefinitionName, matDef)) diff --git a/Engine/source/T3D/assets/MaterialAsset.h b/Engine/source/T3D/assets/MaterialAsset.h index 018e2a989..07ec0227a 100644 --- a/Engine/source/T3D/assets/MaterialAsset.h +++ b/Engine/source/T3D/assets/MaterialAsset.h @@ -70,6 +70,12 @@ class MaterialAsset : public AssetBase public: static StringTableEntry smNoMaterialAssetFallback; + enum MaterialAssetErrCode + { + ScriptLoaded = AssetErrCode::Extended, + Extended + }; + public: MaterialAsset(); virtual ~MaterialAsset(); diff --git a/Engine/source/T3D/fx/particleEmitter.cpp b/Engine/source/T3D/fx/particleEmitter.cpp index 5f7b0829d..45acd1ecb 100644 --- a/Engine/source/T3D/fx/particleEmitter.cpp +++ b/Engine/source/T3D/fx/particleEmitter.cpp @@ -1551,13 +1551,10 @@ void ParticleEmitter::updateBBox() for (Particle* part = part_list_head.next; part != NULL; part = part->next) { - for (Particle* part = part_list_head.next; part != NULL; part = part->next) - { - Point3F particleSize(part->size * 0.5f); - F32 motion = getMax((part->vel.len() * part->totalLifetime / 1000.0f), 1.0f); - minPt.setMin(part->pos - particleSize - Point3F(motion)); - maxPt.setMax(part->pos + particleSize + Point3F(motion)); - } + Point3F particleSize(part->size * 0.5f); + F32 motion = getMax((part->vel.len() * part->totalLifetime / 1000.0f), 1.0f); + minPt.setMin(part->pos - particleSize - Point3F(motion)); + maxPt.setMax(part->pos + particleSize + Point3F(motion)); } mObjBox = Box3F(minPt, maxPt); @@ -1675,8 +1672,8 @@ void ParticleEmitter::addParticle(const Point3F& pos, const Point3F& axis, const } else { - U32 dBlockIndex = gRandGen.randI() % mDataBlock->particleDataBlocks.size(); - mDataBlock->particleDataBlocks[dBlockIndex]->initializeParticle(pNew, vel); + dBlockIndex = gRandGen.randI() % mDataBlock->particleDataBlocks.size(); + mDataBlock->particleDataBlocks[dBlockIndex]->initializeParticle(pNew, vel); } updateKeyData( pNew ); @@ -2220,7 +2217,7 @@ void ParticleEmitter::setupOriented( Particle *part, LinearColorF partCol = mLerp( part->color, ( part->color * ambientColor ), ambientLerp ); const ColorI color = partCol.toColorI(); // Here we deal with UVs for animated particle (oriented) - if (part->dataBlock->animateTexture) + if (part->dataBlock->animateTexture && !part->dataBlock->animTexFrames.empty()) { // Let particle compute the UV indices for current frame S32 fm = (S32)(part->currentAge*(1.0f/1000.0f)*part->dataBlock->framesPerSec); @@ -2331,7 +2328,7 @@ void ParticleEmitter::setupAligned( const Particle *part, LinearColorF partCol = mLerp( part->color, ( part->color * ambientColor ), ambientLerp ); const ColorI color = partCol.toColorI(); // Here we deal with UVs for animated particle - if (part->dataBlock->animateTexture) + if (part->dataBlock->animateTexture && !part->dataBlock->animTexFrames.empty()) { // Let particle compute the UV indices for current frame S32 fm = (S32)(part->currentAge*(1.0f/1000.0f)*part->dataBlock->framesPerSec); @@ -2520,7 +2517,7 @@ void ParticleEmitter::setupRibbon(Particle *part, ColorI pCol = partCol.toColorI(); // Here we deal with UVs for animated particle (oriented) - if (part->dataBlock->animateTexture) + if (part->dataBlock->animateTexture && !part->dataBlock->animTexFrames.empty()) { // Let particle compute the UV indices for current frame S32 fm = (S32)(part->currentAge*(1.0f / 1000.0f)*part->dataBlock->framesPerSec); diff --git a/Engine/source/T3D/fx/precipitation.cpp b/Engine/source/T3D/fx/precipitation.cpp index caebe48cd..4356cd45f 100644 --- a/Engine/source/T3D/fx/precipitation.cpp +++ b/Engine/source/T3D/fx/precipitation.cpp @@ -127,7 +127,7 @@ ConsoleDocClass( PrecipitationData, //---------------------------------------------------------- PrecipitationData::PrecipitationData() { - soundProfile = NULL; + INIT_SOUNDASSET(Sound); INIT_IMAGEASSET(Drop); @@ -143,8 +143,7 @@ PrecipitationData::PrecipitationData() void PrecipitationData::initPersistFields() { - addField( "soundProfile", TYPEID< SFXTrack >(), Offset(soundProfile, PrecipitationData), - "Looping SFXProfile effect to play while Precipitation is active." ); + INITPERSISTFIELD_SOUNDASSET(Sound, PrecipitationData, "Looping SFXProfile effect to play while Precipitation is active."); addProtectedField( "dropTexture", TypeFilename, Offset(mDropName, PrecipitationData), &_setDropData, &defaultProtectedGetFn, "@brief Texture filename for drop particles.\n\n" @@ -190,7 +189,7 @@ bool PrecipitationData::preload( bool server, String &errorStr ) if( Parent::preload( server, errorStr) == false) return false; - if( !server && !sfxResolve( &soundProfile, errorStr ) ) + if (!server && !getSFXProfile()) return false; return true; @@ -200,7 +199,7 @@ void PrecipitationData::packData(BitStream* stream) { Parent::packData(stream); - sfxWrite( stream, soundProfile ); + PACKDATA_SOUNDASSET(Sound); PACKDATA_IMAGEASSET(Drop); @@ -217,7 +216,7 @@ void PrecipitationData::unpackData(BitStream* stream) { Parent::unpackData(stream); - sfxRead( stream, &soundProfile ); + UNPACKDATA_SOUNDASSET(Sound); UNPACKDATA_IMAGEASSET(Drop); @@ -598,9 +597,9 @@ bool Precipitation::onNewDataBlock( GameBaseData *dptr, bool reload ) { SFX_DELETE( mAmbientSound ); - if ( mDataBlock->soundProfile ) + if ( mDataBlock->getSFXProfile()) { - mAmbientSound = SFX->createSource( mDataBlock->soundProfile, &getTransform() ); + mAmbientSound = SFX->createSource(mDataBlock->getSFXProfile(), &getTransform() ); if ( mAmbientSound ) mAmbientSound->play(); } diff --git a/Engine/source/T3D/fx/precipitation.h b/Engine/source/T3D/fx/precipitation.h index 58c8c44dd..cdef0c2a8 100644 --- a/Engine/source/T3D/fx/precipitation.h +++ b/Engine/source/T3D/fx/precipitation.h @@ -34,8 +34,9 @@ #endif #include "T3D/assets/ImageAsset.h" +#include "T3D/assets/SoundAsset.h" -class SFXTrack; +//class SFXTrack; class SFXSource; //-------------------------------------------------------------------------- @@ -45,30 +46,39 @@ class PrecipitationData : public GameBaseData typedef GameBaseData Parent; public: - SFXTrack* soundProfile; + //SFXTrack* soundProfile; + DECLARE_SOUNDASSET(PrecipitationData, Sound); + DECLARE_SOUNDASSET_SETGET(PrecipitationData, Sound); - DECLARE_IMAGEASSET(PrecipitationData, Drop, onDropChanged, GFXStaticTextureSRGBProfile); ///< Texture for drop particles - DECLARE_IMAGEASSET_SETGET(PrecipitationData, Drop); + DECLARE_IMAGEASSET(PrecipitationData, Drop, onDropChanged, GFXStaticTextureSRGBProfile); ///< Texture for drop particles + DECLARE_IMAGEASSET_SETGET(PrecipitationData, Drop); - StringTableEntry mDropShaderName; ///< The name of the shader used for raindrops + StringTableEntry mDropShaderName; ///< The name of the shader used for raindrops - DECLARE_IMAGEASSET(PrecipitationData, Splash, onSplashChanged, GFXStaticTextureSRGBProfile); ///< Texture for splash particles - DECLARE_IMAGEASSET_SETGET(PrecipitationData, Splash); + DECLARE_IMAGEASSET(PrecipitationData, Splash, onSplashChanged, GFXStaticTextureSRGBProfile); ///< Texture for splash particles + DECLARE_IMAGEASSET_SETGET(PrecipitationData, Splash); - StringTableEntry mSplashShaderName; ///< The name of the shader used for raindrops + StringTableEntry mSplashShaderName; ///< The name of the shader used for raindrops - S32 mDropsPerSide; ///< How many drops are on a side of the raindrop texture. - S32 mSplashesPerSide; ///< How many splash are on a side of the splash texture. + S32 mDropsPerSide; ///< How many drops are on a side of the raindrop texture. + S32 mSplashesPerSide; ///< How many splash are on a side of the splash texture. - PrecipitationData(); - DECLARE_CONOBJECT(PrecipitationData); - bool preload( bool server, String& errorStr ); - static void initPersistFields(); - virtual void packData(BitStream* stream); - virtual void unpackData(BitStream* stream); + PrecipitationData(); + DECLARE_CONOBJECT(PrecipitationData); + bool preload( bool server, String& errorStr ); + static void initPersistFields(); + virtual void packData(BitStream* stream); + virtual void unpackData(BitStream* stream); - void onDropChanged() {} - void onSplashChanged() {} + void onDropChanged() {} + void onSplashChanged() {} + + SFXProfile* getSFXProfile() { + if (mSoundAsset.notNull()) + return mSoundAsset->getSfxProfile(); + else + return NULL; + } }; struct Raindrop diff --git a/Engine/source/T3D/prefab.cpp b/Engine/source/T3D/prefab.cpp index 38934062f..0bebb443f 100644 --- a/Engine/source/T3D/prefab.cpp +++ b/Engine/source/T3D/prefab.cpp @@ -242,7 +242,7 @@ bool Prefab::protectedSetFile( void *object, const char *index, const char *data return false; } -void Prefab::setFile( String file ) +void Prefab::setFile( StringTableEntry file ) { AssertFatal( isServerObject(), "Prefab-bad" ); @@ -257,7 +257,7 @@ void Prefab::setFile( String file ) // be called for the client-side prefab but maybe the user did so accidentally. if ( isClientObject() ) { - Con::errorf( "Prefab::setFile( %s ) - Should not be called on a client-side Prefab.", file.c_str() ); + Con::errorf( "Prefab::setFile( %s ) - Should not be called on a client-side Prefab.", file ); return; } diff --git a/Engine/source/T3D/prefab.h b/Engine/source/T3D/prefab.h index 6ebe88b0a..def70857e 100644 --- a/Engine/source/T3D/prefab.h +++ b/Engine/source/T3D/prefab.h @@ -90,7 +90,7 @@ public: void render( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ); /// - void setFile( String file ); + void setFile(StringTableEntry file ); /// Removes all children from this Prefab and puts them into a SimGroup /// which is added to the Scene and returned to the caller. diff --git a/Engine/source/T3D/tsStatic.cpp b/Engine/source/T3D/tsStatic.cpp index 9b093f476..9028653b8 100644 --- a/Engine/source/T3D/tsStatic.cpp +++ b/Engine/source/T3D/tsStatic.cpp @@ -1675,10 +1675,6 @@ void TSStatic::onInspect(GuiInspector* inspector) { dSprintf(matFieldName, 128, "MaterialSlot%d", i); - //addComponentField(matFieldName, "A material used in the shape file", "Material", matAsset->getAssetId(), ""); - //Con::executef(this, "onConstructComponentField", mTargetComponent, field->mFieldName); - Con::printf("Added material field for MaterialSlot %d", i); - GuiInspectorField* fieldGui = materialGroup->constructField(TypeMaterialAssetPtr); fieldGui->init(inspector, materialGroup); diff --git a/Engine/source/console/astNodes.cpp b/Engine/source/console/astNodes.cpp index 091f6cf1c..aaca1ea06 100644 --- a/Engine/source/console/astNodes.cpp +++ b/Engine/source/console/astNodes.cpp @@ -56,57 +56,7 @@ namespace Compiler using namespace Compiler; -class FuncVars -{ - struct Var - { - S32 reg; - TypeReq currentType; - StringTableEntry name; - bool isConstant; - }; - -public: - S32 assign(StringTableEntry var, TypeReq currentType, S32 lineNumber, bool isConstant = false) - { - std::unordered_map::iterator found = vars.find(var); - if (found != vars.end()) - { - AssertISV(!found->second.isConstant, avar("Reassigning variable %s when it is a constant. File: %s Line : %d", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber)); - return found->second.reg; - } - - S32 id = counter++; - vars[var] = { id, currentType, var, isConstant }; - variableNameMap[id] = var; - - return id; - } - - S32 lookup(StringTableEntry var, S32 lineNumber) - { - std::unordered_map::iterator found = vars.find(var); - AssertISV(found != vars.end(), avar("Variable %s referenced before used when compiling script. File: %s Line: %d", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber)); - return found->second.reg; - } - - TypeReq lookupType(StringTableEntry var, S32 lineNumber) - { - std::unordered_map::iterator found = vars.find(var); - - AssertISV(found != vars.end(), avar("Variable %s referenced before used when compiling script. File: %s Line: %d", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber)); - return found->second.currentType; - } - - inline S32 count() { return counter; } - - std::unordered_map variableNameMap; - -private: - std::unordered_map vars; - S32 counter = 0; -}; - +FuncVars gEvalFuncVars; FuncVars* gFuncVars = NULL; inline FuncVars* getFuncVars(S32 lineNumber) @@ -1602,7 +1552,8 @@ U32 FunctionDeclStmtNode::compileStmt(CodeStream& codeStream, U32 ip) tbl->add(fnName, nameSpace, varName); } - gFuncVars = NULL; + // In eval mode, global func vars are allowed. + gFuncVars = gIsEvalCompile ? &gEvalFuncVars : NULL; return ip; } diff --git a/Engine/source/console/codeBlock.cpp b/Engine/source/console/codeBlock.cpp index 1d1ad7593..f03ec25f6 100644 --- a/Engine/source/console/codeBlock.cpp +++ b/Engine/source/console/codeBlock.cpp @@ -37,6 +37,9 @@ CodeBlock * CodeBlock::smCodeBlockList = NULL; CodeBlock * CodeBlock::smCurrentCodeBlock = NULL; ConsoleParser *CodeBlock::smCurrentParser = NULL; +extern FuncVars gEvalFuncVars; +extern FuncVars* gFuncVars; + //------------------------------------------------------------------------- CodeBlock::CodeBlock() @@ -491,6 +494,8 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con chompUTF8BOM(inScript, &script); gSyntaxError = false; + gIsEvalCompile = false; + gFuncVars = NULL; consoleAllocReset(); @@ -629,6 +634,11 @@ ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inStr addToCodeList(); gStatementList = NULL; + + // we are an eval compile if we don't have a file name associated (no exec) + gIsEvalCompile = fileName == NULL; + // In eval mode, global func vars are allowed. + gFuncVars = gIsEvalCompile ? &gEvalFuncVars : NULL; // Set up the parser. smCurrentParser = getParserForFile(fileName); @@ -667,6 +677,8 @@ ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inStr codeStream.emit(OP_RETURN_VOID); codeStream.emitCodeStream(&codeSize, &code, &lineBreakPairs); + + S32 localRegisterCount = gIsEvalCompile ? gEvalFuncVars.count() : 0; consoleAllocReset(); @@ -683,7 +695,8 @@ ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inStr if (lastIp + 1 != codeSize) Con::warnf(ConsoleLogEntry::General, "precompile size mismatch, precompile: %d compile: %d", codeSize, lastIp); - return std::move(exec(0, fileName, NULL, 0, 0, noCalls, NULL, setFrame)); + // repurpose argc as local register counter for global state + return std::move(exec(0, fileName, NULL, localRegisterCount, 0, noCalls, NULL, setFrame)); } //------------------------------------------------------------------------- diff --git a/Engine/source/console/compiledEval.cpp b/Engine/source/console/compiledEval.cpp index f4c48ef68..360c13c90 100644 --- a/Engine/source/console/compiledEval.cpp +++ b/Engine/source/console/compiledEval.cpp @@ -693,7 +693,8 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa // Do we want this code to execute using a new stack frame? if (setFrame < 0) { - gEvalState.pushFrame(NULL, NULL, 0); + // argc is the local count for eval + gEvalState.pushFrame(NULL, NULL, argc); gCallStack.pushFrame(0); popFrame = true; } @@ -734,7 +735,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa SimObject* curObject = NULL; SimObject* saveObject = NULL; Namespace::Entry* nsEntry; - Namespace* ns; + Namespace* ns = NULL; const char* curFNDocBlock = NULL; const char* curNSDocBlock = NULL; const S32 nsDocLength = 128; diff --git a/Engine/source/console/compiler.cpp b/Engine/source/console/compiler.cpp index 1ab6e7b22..13839feda 100644 --- a/Engine/source/console/compiler.cpp +++ b/Engine/source/console/compiler.cpp @@ -34,6 +34,8 @@ #include "console/simBase.h" +extern FuncVars gEvalFuncVars; + namespace Compiler { @@ -86,6 +88,7 @@ namespace Compiler //------------------------------------------------------------ bool gSyntaxError = false; + bool gIsEvalCompile = false; //------------------------------------------------------------ @@ -121,6 +124,7 @@ namespace Compiler getFunctionStringTable().reset(); getIdentTable().reset(); getFunctionVariableMappingTable().reset(); + gEvalFuncVars.clear(); } void *consoleAlloc(U32 size) { return gConsoleAllocator.alloc(size); } @@ -132,6 +136,44 @@ namespace Compiler using namespace Compiler; +S32 FuncVars::assign(StringTableEntry var, TypeReq currentType, S32 lineNumber, bool isConstant) +{ + std::unordered_map::iterator found = vars.find(var); + if (found != vars.end()) + { + AssertISV(!found->second.isConstant, avar("Reassigning variable %s when it is a constant. File: %s Line : %d", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber)); + return found->second.reg; + } + + S32 id = counter++; + vars[var] = { id, currentType, var, isConstant }; + variableNameMap[id] = var; + + return id; +} + +S32 FuncVars::lookup(StringTableEntry var, S32 lineNumber) +{ + std::unordered_map::iterator found = vars.find(var); + AssertISV(found != vars.end(), avar("Variable %s referenced before used when compiling script. File: %s Line: %d", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber)); + return found->second.reg; +} + +TypeReq FuncVars::lookupType(StringTableEntry var, S32 lineNumber) +{ + std::unordered_map::iterator found = vars.find(var); + + AssertISV(found != vars.end(), avar("Variable %s referenced before used when compiling script. File: %s Line: %d", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber)); + return found->second.currentType; +} + +void FuncVars::clear() +{ + vars.clear(); + variableNameMap.clear(); + counter = 0; +} + //------------------------------------------------------------------------- diff --git a/Engine/source/console/compiler.h b/Engine/source/console/compiler.h index 117576a61..24067257f 100644 --- a/Engine/source/console/compiler.h +++ b/Engine/source/console/compiler.h @@ -276,6 +276,35 @@ namespace Compiler void consoleAllocReset(); extern bool gSyntaxError; + extern bool gIsEvalCompile; +}; + +class FuncVars +{ + struct Var + { + S32 reg; + TypeReq currentType; + StringTableEntry name; + bool isConstant; + }; + +public: + S32 assign(StringTableEntry var, TypeReq currentType, S32 lineNumber, bool isConstant = false); + + S32 lookup(StringTableEntry var, S32 lineNumber); + + TypeReq lookupType(StringTableEntry var, S32 lineNumber); + + inline S32 count() { return counter; } + + std::unordered_map variableNameMap; + + void clear(); + +private: + std::unordered_map vars; + S32 counter = 0; }; /// Utility class to emit and patch bytecode diff --git a/Engine/source/gfx/gfxInit.cpp b/Engine/source/gfx/gfxInit.cpp index b5d67206d..0a5c66466 100644 --- a/Engine/source/gfx/gfxInit.cpp +++ b/Engine/source/gfx/gfxInit.cpp @@ -290,7 +290,7 @@ GFXAdapter *GFXInit::getBestAdapterChoice() { S32 adapterIdx = dAtoi(adapterDevice.c_str()); if (adapterIdx == -1) - adapter = chooseAdapter(adapterType, outputDevice.c_str()); + adapter = chooseAdapter(NullDevice, outputDevice.c_str()); else adapter = chooseAdapter(adapterType, adapterIdx); } diff --git a/Engine/source/gfx/gl/gfxGLDevice.cpp b/Engine/source/gfx/gl/gfxGLDevice.cpp index 6179bd618..1c82b4e74 100644 --- a/Engine/source/gfx/gl/gfxGLDevice.cpp +++ b/Engine/source/gfx/gl/gfxGLDevice.cpp @@ -933,7 +933,7 @@ void GFXGLDevice::setupGenericShaders( GenericShaderType type ) } GFXShader* GFXGLDevice::createShader() { - GFXGLShader* shader = new GFXGLShader(); + GFXGLShader* shader = new GFXGLShader(this); shader->registerResourceWithDevice( this ); return shader; } diff --git a/Engine/source/gfx/gl/gfxGLShader.cpp b/Engine/source/gfx/gl/gfxGLShader.cpp index eed45b3e1..8595a96d4 100644 --- a/Engine/source/gfx/gl/gfxGLShader.cpp +++ b/Engine/source/gfx/gl/gfxGLShader.cpp @@ -382,10 +382,11 @@ void GFXGLShaderConstBuffer::onShaderReload( GFXGLShader *shader ) mWasLost = true; } -GFXGLShader::GFXGLShader() : +GFXGLShader::GFXGLShader(GFXGLDevice* device) : mVertexShader(0), mPixelShader(0), mProgram(0), + mDevice(device), mConstBufferSize(0), mConstBuffer(NULL) { @@ -707,7 +708,8 @@ void GFXGLShader::initHandles() dMemset(mConstBuffer, 0, mConstBufferSize); // Set our program so uniforms are assigned properly. - glUseProgram(mProgram); + mDevice->setShader(this, false); + // Iterate through uniforms to set sampler numbers. for (HandleMap::Iterator iter = mHandles.begin(); iter != mHandles.end(); ++iter) { @@ -724,7 +726,6 @@ void GFXGLShader::initHandles() dMemcpy(mConstBuffer + handle->mOffset, &handle->mSamplerNum, handle->getSize()); } } - glUseProgram(0); //instancing if (!mInstancingFormat) @@ -831,6 +832,7 @@ void GFXGLShader::setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer) // Copy new value into our const buffer and set in GL. dMemcpy(mConstBuffer + handle->mOffset, buffer->mBuffer + handle->mOffset, handle->getSize()); + switch(handle->mDesc.constType) { case GFXSCT_Float: diff --git a/Engine/source/gfx/gl/gfxGLShader.h b/Engine/source/gfx/gl/gfxGLShader.h index 80fa4d9d9..e3d3bb69c 100644 --- a/Engine/source/gfx/gl/gfxGLShader.h +++ b/Engine/source/gfx/gl/gfxGLShader.h @@ -32,14 +32,15 @@ class GFXGLShaderConstHandle; class FileStream; class GFXGLShaderConstBuffer; +class GFXGLDevice; class GFXGLShader : public GFXShader { typedef Map HandleMap; public: - GFXGLShader(); + GFXGLShader(GFXGLDevice* device); virtual ~GFXGLShader(); - + /// @name GFXShader interface /// @{ virtual GFXShaderConstHandle* getShaderConstHandle(const String& name); @@ -99,6 +100,7 @@ protected: U32 mConstBufferSize; U8* mConstBuffer; HandleMap mHandles; + GFXGLDevice* mDevice; Vector mValidHandles; }; diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index 7cbea6d64..967c3e7d7 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -258,17 +258,19 @@ bool GuiCanvas::onAdd() // Make sure we're able to render. newDevice->setAllowRender( true ); - if(mDisplayWindow) + // NULL device returns a nullptr for getPlatformWindow + PlatformWindow* window = getPlatformWindow(); + if (mDisplayWindow && window) { - getPlatformWindow()->show(); + window->show(); WindowManager->setDisplayWindow(true); - getPlatformWindow()->setDisplayWindow(true); + window->setDisplayWindow(true); } - else + else if (window) { - getPlatformWindow()->hide(); + window->hide(); WindowManager->setDisplayWindow(false); - getPlatformWindow()->setDisplayWindow(false); + window->setDisplayWindow(false); } // Propagate add to parents. diff --git a/Engine/source/terrain/terrData.cpp b/Engine/source/terrain/terrData.cpp index a80e350f0..be43d6638 100644 --- a/Engine/source/terrain/terrData.cpp +++ b/Engine/source/terrain/terrData.cpp @@ -1613,3 +1613,15 @@ void TerrainBlock::deleteZodiacPrimitiveBuffer() } } +DefineEngineMethod(TerrainBlock, getTerrain, String, (), , "Returns the terrain file used for this terrain block, either via the asset or the filename assigned, which ever is valid") +{ + return object->getTerrain(); +} +DefineEngineMethod(TerrainBlock, getTerrainAsset, String, (), , "Returns the assetId used for this terrain block") +{ + return object->getTerrainAssetId(); +} +DefineEngineMethod(TerrainBlock, setTerrain, bool, (const char* terrain), , "Terrain assignment.first tries asset then flat file.") +{ + return object->_setTerrain(StringTable->insert(terrain)); +} diff --git a/Engine/source/terrain/terrData.h b/Engine/source/terrain/terrData.h index 5550ea30e..cc1479004 100644 --- a/Engine/source/terrain/terrData.h +++ b/Engine/source/terrain/terrData.h @@ -488,6 +488,39 @@ public: void inspectPostApply(); virtual void getUtilizedAssets(Vector* usedAssetsList); + + const StringTableEntry getTerrain() const + { + if (mTerrainAsset && (mTerrainAsset->getTerrainFilePath() != StringTable->EmptyString())) + return mTerrainAsset->getTerrainFilePath(); + else if (mTerrainAssetId != StringTable->EmptyString()) + return mTerrainAssetId; + else if (mTerrFileName != StringTable->EmptyString()) + return mTerrFileName; + else + return StringTable->EmptyString(); + } + + const StringTableEntry getTerrainAssetId() const + { + if (mTerrainAssetId != StringTable->EmptyString()) + return mTerrainAssetId; + else + return StringTable->EmptyString(); + } + + bool _setTerrain(StringTableEntry terrain) + { + if (terrain == StringTable->EmptyString()) + return false; + + if (AssetDatabase.isDeclaredAsset(terrain)) + setTerrainAsset(terrain); + else + mTerrFileName = terrain; + + return true; + } protected: bool mUpdateBasetex; diff --git a/Templates/BaseGame/game/data/UI/guis/mainMenu.gui b/Templates/BaseGame/game/data/UI/guis/mainMenu.gui index 4cc06b26e..f33c06b1d 100644 --- a/Templates/BaseGame/game/data/UI/guis/mainMenu.gui +++ b/Templates/BaseGame/game/data/UI/guis/mainMenu.gui @@ -1,5 +1,3 @@ -exec( "tools/gui/profiles.ed.tscript" ); - //--- OBJECT WRITE BEGIN --- $guiContent = new GuiChunkedBitmapCtrl(MainMenuGui) { bitmapAsset = "UI:background_dark_image"; diff --git a/Templates/BaseGame/game/main.tscript.in b/Templates/BaseGame/game/main.tscript.in index 5d5569e7d..4e83ff2b2 100644 --- a/Templates/BaseGame/game/main.tscript.in +++ b/Templates/BaseGame/game/main.tscript.in @@ -1,10 +1,6 @@ $Core::windowIcon = "data/icon.png"; $Core::splashWindowImage = "data/splash.png"; -// Display a splash window immediately to improve app responsiveness before -// engine is initialized and main window created. -displaySplashWindow($Core::splashWindowImage); - // Console does something. setLogMode(6); @@ -20,6 +16,13 @@ ModuleDatabase.setModuleExtension("module"); ModuleDatabase.scanModules( "core", false ); ModuleDatabase.LoadExplicit( "CoreModule" ); +// Display a splash window immediately to improve app responsiveness before +// engine is initialized and main window created. +if ($Server::Dedicated == false) + displaySplashWindow($Core::splashWindowImage); +else + $Video::forceDisplayAdapter = -1; + //----------------------------------------------------------------------------- // Load any gameplay modules ModuleDatabase.scanModules( "data", false ); @@ -42,6 +45,7 @@ else } } -closeSplashWindow(); +if ($Server::Dedicated == false) + closeSplashWindow(); echo("Engine initialized..."); \ No newline at end of file diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript index ec2d0db4d..747d3e86d 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetBrowser.tscript @@ -618,7 +618,9 @@ function AssetBrowser::loadDirectories( %this ) %dataItem = AssetBrowser-->filterTree.insertItem(AssetBrowser-->filterTree.modulesIdx, "data"); AssetBrowser-->filterTree.tagsIdx = AssetBrowser-->filterTree.insertItem(1, "Tags"); - AssetBrowser-->filterTree.creatorIdx = AssetBrowser-->filterTree.insertItem(1, "Creator"); + + if(!%this.selectMode) + AssetBrowser-->filterTree.creatorIdx = AssetBrowser-->filterTree.insertItem(1, "Creator"); %this.dirHandler.loadFolders("data", %dataItem); diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/terrain.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/terrain.tscript index 9081729d0..c7e8fe92e 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/terrain.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/assetTypes/terrain.tscript @@ -79,7 +79,7 @@ function AssetBrowser::createTerrainAsset(%this) } else { - toolsMessageBox( "Import Terrain", + MessageBox( "Import Terrain", "Terrain import failed! Check console for error messages.", "Ok", "Error" ); } diff --git a/Templates/BaseGame/game/tools/assetBrowser/scripts/creator.tscript b/Templates/BaseGame/game/tools/assetBrowser/scripts/creator.tscript index 15dc88d0a..48366f453 100644 --- a/Templates/BaseGame/game/tools/assetBrowser/scripts/creator.tscript +++ b/Templates/BaseGame/game/tools/assetBrowser/scripts/creator.tscript @@ -47,7 +47,7 @@ function AssetBrowser::loadCreatorClasses(%this) %this.addCreatorClass("LevelInfo", "Level Info" ); %this.addCreatorClass("Marker", "Path Node" ); %this.addCreatorClass("MissionArea", "Mission Area" ); - %this.addCreatorClass("Note", "Note" ); + %this.addCreatorClass("NotesObject", "Note" ); %this.addCreatorClass("Path" ); %this.addCreatorClass("SpawnSphere", "General Spawn Sphere" ); %this.addCreatorClass("SpawnSphere", "Player Spawn Sphere"/*, "PlayerDropPoint"*/ ); diff --git a/Templates/BaseGame/game/tools/convexEditor/main.tscript b/Templates/BaseGame/game/tools/convexEditor/main.tscript index 260c955ae..3930f5b11 100644 --- a/Templates/BaseGame/game/tools/convexEditor/main.tscript +++ b/Templates/BaseGame/game/tools/convexEditor/main.tscript @@ -145,7 +145,6 @@ function ConvexEditorPlugin::onDeactivated( %this ) ConvexEditorTreeWindow.setVisible( false ); ConvexEditorOptionsWindow.setVisible( false ); - ConvexEditorToolbar.setVisible( false ); %this.map.pop(); // Remove our menu. diff --git a/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditor.ed.tscript b/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditor.ed.tscript index e9eabea7e..823fa39b3 100644 --- a/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditor.ed.tscript +++ b/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditor.ed.tscript @@ -910,7 +910,7 @@ function GuiEditorTabBook::onWake( %this ) item[ 1 ] = "Categorized View" TAB "" TAB "GuiEditorToolbox.setViewType( \"Categorized\" );"; }; - GlobalActionMap.bindCmd( keyboard, space, "", "AssetBrowser.toggleDialog();" ); + GlobalActionMap.bindCmd( keyboard, "shift space", "", "AssetBrowser.toggleDialog();" ); } //--------------------------------------------------------------------------------------------- diff --git a/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditorCanvas.ed.tscript b/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditorCanvas.ed.tscript index 1fbe50c12..f62fe12ea 100644 --- a/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditorCanvas.ed.tscript +++ b/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditorCanvas.ed.tscript @@ -283,7 +283,7 @@ function GuiEditCanvas::load( %this, %filename ) // group. And, it should be the only thing in the group. if( !isObject( $guiContent ) ) { - toolsMessageBox( getEngineName(), + MessageBox( getEngineName(), "You have loaded a Gui file that was created before this version. It has been loaded but you must open it manually from the content list dropdown", "Ok", "Information" ); return 0; @@ -333,7 +333,7 @@ function GuiEditCanvas::save( %this, %selectedOnly, %noPrompt ) return; else if( %selected.getCount() > 1 ) { - toolsMessageBox( "Invalid selection", "Only a single control hierarchy can be saved to a file. Make sure you have selected only one control in the tree view." ); + MessageBox( "Invalid selection", "Only a single control hierarchy can be saved to a file. Make sure you have selected only one control in the tree view." ); return; } @@ -464,7 +464,7 @@ function GuiEditCanvas::save( %this, %selectedOnly, %noPrompt ) GuiEditorStatusBar.print( "Saved file '" @ %currentObject.getFileName() @ "'" ); } else - toolsMessageBox( "Error writing to file", "There was an error writing to file '" @ %currentFile @ "'. The file may be read-only.", "Ok", "Error" ); + MessageBox( "Error writing to file", "There was an error writing to file '" @ %currentFile @ "'. The file may be read-only.", "Ok", "Error" ); } //--------------------------------------------------------------------------------------------- @@ -490,7 +490,7 @@ function GuiEditCanvas::append( %this ) if( !isObject( $guiContent ) ) { - toolsMessageBox( "Error loading GUI file", "The GUI content controls could not be found. This function can only be used with files saved by the GUI editor.", "Ok", "Error" ); + MessageBox( "Error loading GUI file", "The GUI content controls could not be found. This function can only be used with files saved by the GUI editor.", "Ok", "Error" ); return; } @@ -519,7 +519,7 @@ function GuiEditCanvas::revert( %this ) if( %filename $= "" ) return; - if( toolsMessageBox( "Revert Gui", "Really revert the current Gui? This cannot be undone.", "OkCancel", "Question" ) == $MROk ) + if( MessageBox( "Revert Gui", "Really revert the current Gui? This cannot be undone.", "OkCancel", "Question" ) == $MROk ) %this.load( %filename ); } diff --git a/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditorNewGuiDialog.ed.tscript b/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditorNewGuiDialog.ed.tscript index 85fa7263e..248c0e97d 100644 --- a/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditorNewGuiDialog.ed.tscript +++ b/Templates/BaseGame/game/tools/guiEditor/scripts/guiEditorNewGuiDialog.ed.tscript @@ -81,7 +81,7 @@ function GuiEditorNewGuiDialog::onOK( %this ) if( isObject( %name ) && %name.isMemberOfClass( "GuiControl" ) ) { - if( toolsMessageBox( "Warning", "Replace the existing control '" @ %name @ "'?", "OkCancel", "Question" ) == $MROk ) + if( MessageBox( "Warning", "Replace the existing control '" @ %name @ "'?", "OkCancel", "Question" ) == $MROk ) %name.delete(); else return; diff --git a/Templates/BaseGame/game/tools/projectImporter/scripts/pre40/T3Dpre4ProjectImporter.tscript b/Templates/BaseGame/game/tools/projectImporter/scripts/pre40/T3Dpre4ProjectImporter.tscript index d996182dd..645bd38ca 100644 --- a/Templates/BaseGame/game/tools/projectImporter/scripts/pre40/T3Dpre4ProjectImporter.tscript +++ b/Templates/BaseGame/game/tools/projectImporter/scripts/pre40/T3Dpre4ProjectImporter.tscript @@ -919,7 +919,7 @@ T3Dpre4ProjectImporter::genProcessor("DebrisData", "shape shapeAsset shapeFile s T3Dpre4ProjectImporter::genProcessor("DecalData", "material materialAsset"); T3Dpre4ProjectImporter::genProcessor("ExplosionData", "explosionShape explosionShapeAsset"); T3Dpre4ProjectImporter::genProcessor("ParticleData", "texture textureAsset textureName textureAsset textureExt textureExtAsset textureExtName textureExtAsset"); -T3Dpre4ProjectImporter::genProcessor("PrecipitationData", "drop dropAsset dropTexture dropAsset splash splashAsset splashTexture splashAsset"); +T3Dpre4ProjectImporter::genProcessor("PrecipitationData", "drop dropAsset dropTexture dropAsset splash splashAsset splashTexture splashAsset soundProfile soundAsset"); T3Dpre4ProjectImporter::genProcessor("SplashData", "texture textureAsset"); T3Dpre4ProjectImporter::genProcessor("LightFlareData", "flareTexture flareTextureAsset"); T3Dpre4ProjectImporter::genProcessor("PhysicsDebrisData", "shape shapeAsset shapeFile shapeAsset"); diff --git a/Templates/BaseGame/game/tools/projectImporter/scripts/projectImporter.tscript b/Templates/BaseGame/game/tools/projectImporter/scripts/projectImporter.tscript index ab62befb8..039a71238 100644 --- a/Templates/BaseGame/game/tools/projectImporter/scripts/projectImporter.tscript +++ b/Templates/BaseGame/game/tools/projectImporter/scripts/projectImporter.tscript @@ -556,23 +556,49 @@ function processLegacyField(%line, %originalFieldName, %newFieldName) %targetFilename = sanitizeFilename(%value); if(isObject(%targetFilename)) + { + if(%originalFieldName $= "soundProfile") { - //likely a material name, so handle it that way - %assetId = MaterialAsset::getAssetIdByMaterialName(%targetFilename); + $ProjectImporter::assetQuery.clear(); + %foundAssets = AssetDatabase.findAssetName($ProjectImporter::assetQuery, %targetFilename); + if(%foundAssets != 0) + { + %assetId = $ProjectImporter::assetQuery.getAsset(0); + } + } + else + { + //likely a material name, so handle it that way + %assetId = MaterialAsset::getAssetIdByMaterialName(%targetFilename); + } } else { if(!isFile(%targetFilename)) - { - error("Legacy Project Importer - file described in line could not be found/is not valid"); - return %line; - } - - $ProjectImporter::assetQuery.clear(); - %foundAssets = AssetDatabase.findAssetLooseFile($ProjectImporter::assetQuery, %targetFilename); - if(%foundAssets != 0) - { - %assetId = $ProjectImporter::assetQuery.getAsset(0); + { + if(%originalFieldName $= "soundProfile") + { + $ProjectImporter::assetQuery.clear(); + %foundAssets = AssetDatabase.findAssetName($ProjectImporter::assetQuery, %targetFilename); + if(%foundAssets != 0) + { + %assetId = $ProjectImporter::assetQuery.getAsset(0); + } + } + else + { + error("Legacy Project Importer - file described in line could not be found/is not valid"); + return %line; + } + } + else + { + $ProjectImporter::assetQuery.clear(); + %foundAssets = AssetDatabase.findAssetLooseFile($ProjectImporter::assetQuery, %targetFilename); + if(%foundAssets != 0) + { + %assetId = $ProjectImporter::assetQuery.getAsset(0); + } } } diff --git a/Templates/BaseGame/game/tools/riverEditor/riverEditorGui.tscript b/Templates/BaseGame/game/tools/riverEditor/riverEditorGui.tscript index 814782cb2..bb0f40037 100644 --- a/Templates/BaseGame/game/tools/riverEditor/riverEditorGui.tscript +++ b/Templates/BaseGame/game/tools/riverEditor/riverEditorGui.tscript @@ -76,9 +76,9 @@ function RiverEditorGui::createRiver( %this ) baseColor = "45 108 171 255"; - rippleTex = "core/rendering/images/ripple.dds"; - foamTex = "core/rendering/images/foam"; - depthGradientTex = "core/rendering/images/depthcolor_ramp"; + rippleTex = "Core_Rendering:ripple_image"; + foamTex = "Core_Rendering:foam_image"; + depthGradientTex = "Core_Rendering:depthcolor_ramp_image"; }; return %river; diff --git a/Templates/BaseGame/game/tools/worldEditor/gui/objectBuilderGui.ed.gui b/Templates/BaseGame/game/tools/worldEditor/gui/objectBuilderGui.ed.gui index dc757dc54..8dafe0357 100644 --- a/Templates/BaseGame/game/tools/worldEditor/gui/objectBuilderGui.ed.gui +++ b/Templates/BaseGame/game/tools/worldEditor/gui/objectBuilderGui.ed.gui @@ -313,30 +313,6 @@ function ObjectBuilderGui::createImageAssetType(%this, %index) else %name = %this.field[%index, text]; - // - /*%this.textControls[%this.numControls] = new GuiTextCtrl() { - profile = "ToolsGuiTextRightProfile"; - internalName = "assetText"; - text = %name; - extent = %this.fieldNameExtent; - position = %this.curXPos @ " " @ %this.curYPos; - modal = "1"; - }; - - // - %this.controls[%this.numControls] = new GuiButtonCtrl() { - HorizSizing = "width"; - profile = "ToolsGuiButtonProfile"; - internalName = "assetButton"; - extent = %this.fileButtonExtent; - position = %this.curXPos + %this.columnOffset @ " " @ %this.curYPos; - modal = "1"; - command = %this @ ".getImageAsset(" @ %index @ ");"; - }; - - %val = %this.field[%index, value]; - %this.controls[%this.numControls].setText(fileBase(%val) @ fileExt(%val));*/ - %this.textControls[%this.numControls] = new GuiTextCtrl() { profile = "ToolsGuiTextRightProfile"; text = %name; @@ -375,7 +351,7 @@ function ObjectBuilderGui::createImageAssetType(%this, %index) modal = "1"; command = %this @ ".getImageAsset(" @ %index @ ");"; }; - %button.setBitmap("ToolsModule:change_material_btn_n_image"); + %button.setBitmap("ToolsModule:GameTSCtrl_image"); %this.controls[%this.numControls].addGuiControl(%button); %this.numControls++; @@ -412,6 +388,279 @@ function ObjectBuilderGui::gotImageAsset(%this, %name) // This doesn't work for button controls as getValue returns their state! //%this.controls[%this.currentControl].setValue(%name); } + +//------------------------------------------------------------------------------ +function ObjectBuilderGui::createMaterialAssetType(%this, %index) +{ + if(%index >= %this.numFields || %this.field[%index, name] $= "") + { + error("ObjectBuilderGui::createMaterialAssetType: invalid field"); + return; + } + + // + if(%this.field[%index, text] $= "") + %name = %this.field[%index, name]; + else + %name = %this.field[%index, text]; + + %this.textControls[%this.numControls] = new GuiTextCtrl() { + profile = "ToolsGuiTextRightProfile"; + text = %name; + extent = %this.fieldNameExtent; + position = %this.curXPos @ " " @ %this.curYPos; + modal = "1"; + }; + + // + %this.controls[%this.numControls] = new GuiControl() { + HorizSizing = "width"; + profile = "ToolsGuiDefaultProfile"; + extent = %this.textEditExtent; + position = %this.curXPos + %this.columnOffset @ " " @ %this.curYPos; + modal = "1"; + }; + + %text = new GuiTextEditCtrl() { + class = ObjectBuilderGuiTextEditCtrl; + internalName = "assetText"; + HorizSizing = "width"; + profile = "ToolsGuiTextEditProfile"; + extent = getWord(%this.textEditExtent,0) - getWord(%this.matButtonExtent,0) - 2 @ " " @ getWord(%this.textEditExtent,1); + text = %this.field[%index, value]; + position = "0 0"; + modal = "1"; + }; + %this.controls[%this.numControls].addGuiControl(%text); + + %button = new GuiBitmapButtonCtrl() { + internalName = "assetButton"; + HorizSizing = "left"; + profile = "ToolsGuiButtonProfile"; + extent = %this.matButtonExtent; + position = getWord(%this.textEditExtent,0) - getWord(%this.matButtonExtent,0) @ " 0"; + modal = "1"; + command = %this @ ".getMaterialAsset(" @ %index @ ");"; + }; + %button.setBitmap("ToolsModule:change_material_btn_n_image"); + %this.controls[%this.numControls].addGuiControl(%button); + + %this.numControls++; + %this.curYPos += %this.defaultFieldStep; +} + +function ObjectBuilderGui::getMaterialAsset(%this, %index) +{ + if(%index >= %this.numFields || %this.field[%index, name] $= "") + { + error("ObjectBuilderGui::getMaterialAsset: invalid field"); + return; + } + + %val = %this.field[%index, ext]; + + //%path = filePath(%val); + //%ext = fileExt(%val); + + %this.currentControl = %index; + AssetBrowser.showDialog("MaterialAsset", %this @ ".gotMaterialAsset", "", "", ""); + //getLoadFilename( %val @ "|" @ %val, %this @ ".gotFileName", %this.lastPath ); +} + +function ObjectBuilderGui::gotMaterialAsset(%this, %name) +{ + %index = %this.currentControl; + + %this.field[%index, value] = %name; + %this.controls[%this.currentControl]-->assetText.setText(%name); + + %this.lastPath = %name; + + // This doesn't work for button controls as getValue returns their state! + //%this.controls[%this.currentControl].setValue(%name); +} + +//------------------------------------------------------------------------------ +function ObjectBuilderGui::createShapeAssetType(%this, %index) +{ + if(%index >= %this.numFields || %this.field[%index, name] $= "") + { + error("ObjectBuilderGui::createShapeAssetType: invalid field"); + return; + } + + // + if(%this.field[%index, text] $= "") + %name = %this.field[%index, name]; + else + %name = %this.field[%index, text]; + + %this.textControls[%this.numControls] = new GuiTextCtrl() { + profile = "ToolsGuiTextRightProfile"; + text = %name; + extent = %this.fieldNameExtent; + position = %this.curXPos @ " " @ %this.curYPos; + modal = "1"; + }; + + // + %this.controls[%this.numControls] = new GuiControl() { + HorizSizing = "width"; + profile = "ToolsGuiDefaultProfile"; + extent = %this.textEditExtent; + position = %this.curXPos + %this.columnOffset @ " " @ %this.curYPos; + modal = "1"; + }; + + %text = new GuiTextEditCtrl() { + class = ObjectBuilderGuiTextEditCtrl; + internalName = "assetText"; + HorizSizing = "width"; + profile = "ToolsGuiTextEditProfile"; + extent = getWord(%this.textEditExtent,0) - getWord(%this.matButtonExtent,0) - 2 @ " " @ getWord(%this.textEditExtent,1); + text = %this.field[%index, value]; + position = "0 0"; + modal = "1"; + }; + %this.controls[%this.numControls].addGuiControl(%text); + + %button = new GuiBitmapButtonCtrl() { + internalName = "assetButton"; + HorizSizing = "left"; + profile = "ToolsGuiButtonProfile"; + extent = %this.matButtonExtent; + position = getWord(%this.textEditExtent,0) - getWord(%this.matButtonExtent,0) @ " 0"; + modal = "1"; + command = %this @ ".getShapeAsset(" @ %index @ ");"; + }; + %button.setBitmap("ToolsModule:shape_editor_n_image"); + %this.controls[%this.numControls].addGuiControl(%button); + + %this.numControls++; + %this.curYPos += %this.defaultFieldStep; +} + +function ObjectBuilderGui::getShapeAsset(%this, %index) +{ + if(%index >= %this.numFields || %this.field[%index, name] $= "") + { + error("ObjectBuilderGui::getShapeAsset: invalid field"); + return; + } + + %val = %this.field[%index, ext]; + + //%path = filePath(%val); + //%ext = fileExt(%val); + + %this.currentControl = %index; + AssetBrowser.showDialog("ShapeAsset", %this @ ".gotShapeAsset", "", "", ""); + //getLoadFilename( %val @ "|" @ %val, %this @ ".gotFileName", %this.lastPath ); +} + +function ObjectBuilderGui::gotShapeAsset(%this, %name) +{ + %index = %this.currentControl; + + %this.field[%index, value] = %name; + %this.controls[%this.currentControl]-->assetText.setText(%name); + + %this.lastPath = %name; + + // This doesn't work for button controls as getValue returns their state! + //%this.controls[%this.currentControl].setValue(%name); +} + +//------------------------------------------------------------------------------ +function ObjectBuilderGui::createSoundAssetType(%this, %index) +{ + if(%index >= %this.numFields || %this.field[%index, name] $= "") + { + error("ObjectBuilderGui::createSoundAssetType: invalid field"); + return; + } + + // + if(%this.field[%index, text] $= "") + %name = %this.field[%index, name]; + else + %name = %this.field[%index, text]; + + %this.textControls[%this.numControls] = new GuiTextCtrl() { + profile = "ToolsGuiTextRightProfile"; + text = %name; + extent = %this.fieldNameExtent; + position = %this.curXPos @ " " @ %this.curYPos; + modal = "1"; + }; + + // + %this.controls[%this.numControls] = new GuiControl() { + HorizSizing = "width"; + profile = "ToolsGuiDefaultProfile"; + extent = %this.textEditExtent; + position = %this.curXPos + %this.columnOffset @ " " @ %this.curYPos; + modal = "1"; + }; + + %text = new GuiTextEditCtrl() { + class = ObjectBuilderGuiTextEditCtrl; + internalName = "assetText"; + HorizSizing = "width"; + profile = "ToolsGuiTextEditProfile"; + extent = getWord(%this.textEditExtent,0) - getWord(%this.matButtonExtent,0) - 2 @ " " @ getWord(%this.textEditExtent,1); + text = %this.field[%index, value]; + position = "0 0"; + modal = "1"; + }; + %this.controls[%this.numControls].addGuiControl(%text); + + %button = new GuiBitmapButtonCtrl() { + internalName = "assetButton"; + HorizSizing = "left"; + profile = "ToolsGuiButtonProfile"; + extent = %this.matButtonExtent; + position = getWord(%this.textEditExtent,0) - getWord(%this.matButtonExtent,0) @ " 0"; + modal = "1"; + command = %this @ ".getSoundAsset(" @ %index @ ");"; + }; + %button.setBitmap("ToolsModule:SFXEmitter_image"); + %this.controls[%this.numControls].addGuiControl(%button); + + %this.numControls++; + %this.curYPos += %this.defaultFieldStep; +} + +function ObjectBuilderGui::getSoundAsset(%this, %index) +{ + if(%index >= %this.numFields || %this.field[%index, name] $= "") + { + error("ObjectBuilderGui::getSoundAsset: invalid field"); + return; + } + + %val = %this.field[%index, ext]; + + //%path = filePath(%val); + //%ext = fileExt(%val); + + %this.currentControl = %index; + AssetBrowser.showDialog("SoundAsset", %this @ ".gotSoundAsset", "", "", ""); + //getLoadFilename( %val @ "|" @ %val, %this @ ".gotFileName", %this.lastPath ); +} + +function ObjectBuilderGui::gotSoundAsset(%this, %name) +{ + %index = %this.currentControl; + + %this.field[%index, value] = %name; + %this.controls[%this.currentControl]-->assetText.setText(%name); + + %this.lastPath = %name; + + // This doesn't work for button controls as getValue returns their state! + //%this.controls[%this.currentControl].setValue(%name); +} //------------------------------------------------------------------------------ function ObjectBuilderGui::createMaterialNameType(%this, %index) { @@ -680,6 +929,15 @@ function ObjectBuilderGui::process(%this) case "TypeImageAsset": %this.createImageAssetType(%i); + case "TypeMaterialAsset": + %this.createMaterialAssetType(%i); + + case "TypeShapeAsset": + %this.createShapeAssetType(%i); + + case "TypeSoundAsset": + %this.createSoundAssetType(%i); + case "TypeMaterialName": %this.createMaterialNameType(%i); @@ -753,7 +1011,10 @@ function ObjectBuilderGui::onOK(%this) continue; } if (%this.field[%i, type] $= "TypeImageAsset" || - %this.field[%i, type] $= "TypeTerrainAsset") + %this.field[%i, type] $= "TypeTerrainAsset" || + %this.field[%i, type] $= "TypeMaterialAsset" || + %this.field[%i, type] $= "TypeShapeAsset" + ) { %this.field[%i, value] = %this.controls[%i]-->assetText.getText(); continue; @@ -861,7 +1122,6 @@ function ObjectBuilderGui::buildScatterSky( %this, %dontWarnAboutSun ) %this.addField( "moonMatAsset", "TypeMaterialAsset", "Moon Material", "Core_Rendering:moon_wglow" ); %this.addField( "nightCubemap", "TypeCubemapName", "Night Cubemap", "NightCubemap" ); %this.addField( "useNightCubemap", "TypeBool", "Use Night Cubemap", "true" ); - } function ObjectBuilderGui::buildCloudLayer(%this) @@ -954,7 +1214,7 @@ function ObjectBuilderGui::buildSun( %this, %dontWarnAboutScatterSky ) // This is a trick... any fields added after process won't show // up as controls, but will be applied to the created object. - %this.addField( "coronaMaterial", "TypeMaterialName", "Corona Material", "Corona_Mat" ); + %this.addField( "coronaMaterial", "TypeMaterialAsset", "Corona Material", "Core_Rendering:Corona_Mat" ); %this.addField( "flareType", "TypeLightFlareDataPtr", "Flare", "SunFlareExample" ); } @@ -994,9 +1254,9 @@ function ObjectBuilderGui::addWaterObjectFields(%this) %this.addField("waveSpeed[2]", "TypeFloat", "Wave Speed", "1"); %this.addField("overallWaveMagnitude", "TypeFloat", "Overall Wave Magnitude", "1.0"); - %this.addField("rippleTexAsset", "TypeImageAssetId", "Ripple Texture", "Core_Rendering:ripple_image" ); - %this.addField("depthGradientTexAsset", "TypeImageAssetId", "Depth Gradient Texture", "Core_Rendering:depthcolor_ramp_imag" ); - %this.addField("foamTexAsset", "TypeImageAssetId", "Foam Texture", "Core_Rendering:foam_image" ); + %this.addField("rippleTex", "TypeImageAsset", "Ripple Texture", "Core_Rendering:ripple_image" ); + %this.addField("depthGradientTex", "TypeImageAsset", "Depth Gradient Texture", "Core_Rendering:depthcolor_ramp_image" ); + %this.addField("foamTex", "TypeImageAsset", "Foam Texture", "Core_Rendering:foam_image" ); } function ObjectBuilderGui::buildWaterBlock(%this) @@ -1038,8 +1298,8 @@ function ObjectBuilderGui::buildTerrainBlock(%this) function ObjectBuilderGui::buildGroundCover( %this ) { %this.objectClassName = "GroundCover"; - %this.addField( "material", "TypeMaterialName", "Material Name", "" ); - %this.addField( "shapeFilename[0]", "TypeFile", "Shape File [Optional]", "", "*.*"); + %this.addField( "materialAsset", "TypeMaterialAsset", "Material Asset", "" ); + %this.addField( "shapeAsset[0]", "TypeShapeAsset", "Shape Asset [Optional]", "", ""); %this.process(); // This is a trick... any fields added after process won't show @@ -1212,6 +1472,9 @@ function ObjectBuilderGui::buildGeneralDropPoint(%this) function ObjectBuilderGui::buildNotesObject(%this) { %this.objectClassName = "NotesObject"; + %this.addField("note", "TypeString", "Note Text", ""); + %this.addField("showArrow", "TypeBool", "Show Arrow", ""); + %this.addField("arrowColor", "TypeColorI", "Arrow Color", "255 0 0 255"); %this.process(); } //------------------------------------------------------------------------------ @@ -1221,11 +1484,11 @@ function ObjectBuilderGui::buildVolumetricFog(%this) { // Change this if you want to default to another Folder // Otherwise every time you want to add a Fog you will go this. - %defShape = "core/rendering/shapes/Fog_Cube.DAE"; + %defShape = "Core_Rendering:Fog_Cube"; %this.lastPath=getMainDotCsDir() @ %defShape; OBObjectName.setValue( "" ); %this.objectClassName = "VolumetricFog"; - %this.addField( "shapeName", "TypeFile", "Shape (Fog volume)", "", "*.dts;*.dae"); + %this.addField( "shapeAsset", "TypeShapeAsset", "Shape (Fog volume)", "", ""); %this.addField("Scale", "TypePoint3", "Scale", "1 1 1"); %this.addField("FogColor", "TypeColorI", "FogColor", "200 200 200 255"); %this.process(); diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript b/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript index e7972a4c8..dca4d1f30 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript @@ -1826,7 +1826,10 @@ function EditorTree::update( %this ) // Tooltip for TSStatic function EditorTree::GetTooltipTSStatic( %this, %obj ) { - return "Shape: " @ %obj.shapeName; + %shapeName = %obj.shapeAsset; + if(%shapeName $= "") + %shapeName = %obj.getShape(); + return "Shape: " @ %shapeName; } // Tooltip for ShapeBase @@ -1862,7 +1865,10 @@ function EditorTree::GetTooltipPrefab( %this, %obj ) // Tooltip for GroundCover function EditorTree::GetTooltipGroundCover( %this, %obj ) { - %text = "Material: " @ %obj.material; + %matName = %obj.materialAsset; + if(%matName $= "") + %matName = %obj.getMaterial(); + %text = "Material: " @ %matName; for(%i=0; %i<8; %i++) { if(%obj.probability[%i] > 0 && %obj.shapeFilename[%i] !$= "") diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/editor.keybinds.tscript b/Templates/BaseGame/game/tools/worldEditor/scripts/editor.keybinds.tscript index a077b8611..74c681bd5 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/editor.keybinds.tscript +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/editor.keybinds.tscript @@ -79,4 +79,4 @@ GlobalActionMap.bind(keyboard, "tilde", toggleConsole); EditorMap.bind( mouse, "alt zaxis", editorWheelFadeScroll ); -EditorMap.bindCmd( keyboard, space, "", "AssetBrowser.toggleDialog();" ); +EditorMap.bindCmd( keyboard, "shift space", "", "AssetBrowser.toggleDialog();" ); diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/menuHandlers.ed.tscript b/Templates/BaseGame/game/tools/worldEditor/scripts/menuHandlers.ed.tscript index a1771cdcf..a2ea3b015 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/menuHandlers.ed.tscript +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/menuHandlers.ed.tscript @@ -204,8 +204,7 @@ function EditorNewLevel( %level ) %saveFirst = false; if ( EditorIsDirty() ) { - error(knob); - %saveFirst = toolsMessageBox("Mission Modified", "Would you like to save changes to the current mission \"" @ + %saveFirst = MessageBox("Mission Modified", "Would you like to save changes to the current mission \"" @ $Server::MissionFile @ "\" before creating a new mission?", "SaveDontSave", "Question") == $MROk; } @@ -300,7 +299,7 @@ function EditorSaveMission() // first check for dirty and read-only files: if((EWorldEditor.isDirty || ETerrainEditor.isMissionDirty) && !isWriteableFileName($Server::MissionFile)) { - toolsMessageBox("Error", "Mission file \""@ $Server::MissionFile @ "\" is read-only. Continue?", "Ok", "Stop"); + MessageBox("Error", "Mission file \""@ $Server::MissionFile @ "\" is read-only. Continue?", "Ok", "Stop"); return false; } if(ETerrainEditor.isDirty) @@ -310,9 +309,18 @@ function EditorSaveMission() while ((%terrainObject = containerSearchNext()) != 0) { - if (!isWriteableFileName(%terrainObject.terrainFile)) + %terrFile = %terrainObject.getTerrain(); + if(AssetDatabase.isDeclaredAsset(%terrFile)) { - if (toolsMessageBox("Error", "Terrain file \""@ %terrainObject.terrainFile @ "\" is read-only. Continue?", "Ok", "Stop") == $MROk) + %assetDef = AssetDatabase.acquireAsset(%terrFile); + %file = %assetDef.getTerrainFilePath(); + AssetDatabase.releaseAsset(%terrFile); + %terrFile = %file; + } + + if (!isWriteableFileName(%terrFile)) + { + if (MessageBox("Error", "Terrain file \""@ %terrainObject.terrainFile @ "\" is read-only. Continue?", "Ok", "Stop") == $MROk) continue; else return false; @@ -497,12 +505,12 @@ function EditorOpenMission(%levelAsset) if( EditorIsDirty()) { // "EditorSaveBeforeLoad();", "getLoadFilename(\"*.mis\", \"EditorDoLoadMission\");" - if(toolsMessageBox("Mission Modified", "Would you like to save changes to the current mission \"" @ + if(MessageBox("Mission Modified", "Would you like to save changes to the current mission \"" @ $Server::MissionFile @ "\" before opening a new mission?", SaveDontSave, Question) == $MROk) { - if(! EditorSaveMission()) - return; - } + if(!EditorSaveMission()) + return; + } } if(%levelAsset $= "") @@ -779,8 +787,20 @@ function makeSelectedAMesh(%assetId) function EditorTakeControlOfEntity() { %object = EWorldEditor.getSelectedObject(0); - switchCamera(localClientConnection, %object); - switchControlObject(localClientConnection, %object); + if(isObject(%object) && %object.getClassName() !$= "Camera") + { + $Editor::previousControlObject = localClientConnection.getControlObject(); + localClientConnection.setControlObject(%object); + + } +} + +function EditorReleaseControlOfEntity() +{ + if(isObject($Editor::previousControlObject)) + { + localClientConnection.setControlObject($Editor::previousControlObject); + } } function EditorMount() diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/menus.ed.tscript b/Templates/BaseGame/game/tools/worldEditor/scripts/menus.ed.tscript index 21eaea05a..bf69e6bdb 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/menus.ed.tscript +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/menus.ed.tscript @@ -459,9 +459,11 @@ function EditorGui::buildMenus(%this) Item[18] = "Explode Selected Prefab" TAB "" TAB "EditorExplodePrefab();"; Item[19] = "-"; Item[20] = "Take control of entity" TAB "" TAB "EditorTakeControlOfEntity();"; - Item[21] = "-"; - Item[22] = "Mount Selection A to B" TAB "" TAB "EditorMount();"; - Item[23] = "Unmount Selected Object" TAB "" TAB "EditorUnmount();"; + Item[21] = "Release control of entity" TAB "" TAB "EditorReleaseControlOfEntity();"; + + Item[22] = "-"; + Item[23] = "Mount Selection A to B" TAB "" TAB "EditorMount();"; + Item[24] = "Unmount Selected Object" TAB "" TAB "EditorUnmount();"; }; } }