diff --git a/Aquaria/Avatar.cpp b/Aquaria/Avatar.cpp index a44207b..ddf4b56 100644 --- a/Aquaria/Avatar.cpp +++ b/Aquaria/Avatar.cpp @@ -4470,7 +4470,7 @@ void Avatar::action(int id, int state) if (id == ACTION_PRIMARY && state)// !state { - if (isMiniMapCursorOkay()) + if (dsq->isMiniMapCursorOkay()) { if (this->state.lockedToWall) { @@ -5607,11 +5607,6 @@ Vector Avatar::getHeadPosition() bool lastCursorKeyboard = false; -bool Avatar::isMiniMapCursorOkay() -{ - return ((dsq->inputMode != INPUT_MOUSE) || (!dsq->game->miniMapRender || !dsq->game->miniMapRender->isCursorIn())); -} - void Avatar::onUpdate(float dt) { BBGE_PROF(Avatar_onUpdate); @@ -6427,7 +6422,7 @@ void Avatar::onUpdate(float dt) float len = 0; - if (isMiniMapCursorOkay() && !isActing(ACTION_ROLL) && + if (dsq->isMiniMapCursorOkay() && !isActing(ACTION_ROLL) && _isUnderWater && !riding && !boneLock.on && (movingOn || ((dsq->inputMode == INPUT_JOYSTICK || dsq->inputMode== INPUT_KEYBOARD) || (core->mouse.buttons.left || bursting)))) { diff --git a/Aquaria/Avatar.h b/Aquaria/Avatar.h index 7b3d315..9f51b5c 100644 --- a/Aquaria/Avatar.h +++ b/Aquaria/Avatar.h @@ -158,8 +158,6 @@ public: void onCollide(Entity *e); bool zoomOverriden; void clampPosition(); - - bool isMiniMapCursorOkay(); void splash(bool down); InterpolatedVector myZoom; diff --git a/Aquaria/DSQ.cpp b/Aquaria/DSQ.cpp index 2dc65dc..28d8117 100644 --- a/Aquaria/DSQ.cpp +++ b/Aquaria/DSQ.cpp @@ -5099,3 +5099,9 @@ void DSQ::resetLayerPasses() renderObjectLayers[LR_ENTITIES].startPass = -2; renderObjectLayers[LR_ENTITIES].endPass = 5; } + +bool DSQ::isMiniMapCursorOkay() +{ + return ((inputMode != INPUT_MOUSE) || (!game->miniMapRender || !game->miniMapRender->isCursorIn())); +} + diff --git a/Aquaria/DSQ.h b/Aquaria/DSQ.h index 60d178a..6a17a0c 100644 --- a/Aquaria/DSQ.h +++ b/Aquaria/DSQ.h @@ -1572,6 +1572,7 @@ public: virtual void onBackgroundUpdate(); void resetLayerPasses(); + bool isMiniMapCursorOkay(); protected: diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index c74edd8..2f0d1e7 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -371,6 +371,7 @@ static void compile_time_assertions() compile_assert(oo(Path) == oo(Avatar)); compile_assert(oo(Path) == oo(BaseText)); compile_assert(oo(Path) == oo(PauseQuad)); + compile_assert(oo(Path) == oo(ParticleEffect)); #undef oo } #endif @@ -593,6 +594,16 @@ static SkeletalSprite *getSkeletalSprite(Entity *e) return e ? &e->skeletalSprite : NULL; } +static inline +ParticleEffect *getParticle(lua_State *L, int slot = 1) +{ + ParticleEffect *q = (ParticleEffect*)lua_touserdata(L, slot); + ENSURE_TYPE(q, SCO_PARTICLE_EFFECT); + if (!q) + scriptDebug(L, "Invalid Particle Effect"); + return q; +} + static bool looksLikeGlobal(const char *s) { for( ; *s; ++s) @@ -838,6 +849,8 @@ MakeTypeCheckFunc(isWeb, SCO_WEB) MakeTypeCheckFunc(isIng, SCO_INGREDIENT) MakeTypeCheckFunc(isBeam, SCO_BEAM) MakeTypeCheckFunc(isText, SCO_TEXT) +MakeTypeCheckFunc(isShader, SCO_SHADER) +MakeTypeCheckFunc(isParticleEffect, SCO_PARTICLE_EFFECT) #undef MakeTypeCheckFunc @@ -1794,7 +1807,8 @@ luaFunc(quad_getBorderAlpha) MAKE_QUAD_FUNCS(beam, beam ) \ MAKE_ROBJ_FUNCS(getQuad, quad ) \ MAKE_ROBJ_FUNCS(getWeb, web ) \ - MAKE_ROBJ_FUNCS(getText, text ) + MAKE_ROBJ_FUNCS(getText, text ) \ + MAKE_ROBJ_FUNCS(getParticle, pe ) // first time, create them. (There is a second use of this further down, with different MK_* macros) EXPAND_FUNC_PROTOTYPES @@ -7979,8 +7993,9 @@ luaFunc(setGemPosition) if(mapname.empty()) mapname = dsq->game->sceneName; Vector pos(lua_tonumber(L, 2), lua_tonumber(L, 3)); + bool result = false; - WorldMapTile *tile = dsq->continuity.worldMap.getWorldMapTile(getString(L, 1)); + WorldMapTile *tile = dsq->continuity.worldMap.getWorldMapTile(mapname); if(tile) { pos = dsq->game->worldMapRender->getWorldToTile(tile, pos, true, true); @@ -7991,6 +8006,7 @@ luaFunc(setGemPosition) GemData& gem = *it; gem.pos = pos; gem.mapName = mapname; + result = true; } else { @@ -8001,7 +8017,7 @@ luaFunc(setGemPosition) { debugLog("setGemPosition: Map tile does not exist: " + mapname); } - luaReturnNil(); + luaReturnBool(result); } luaFunc(removeGem) @@ -8336,6 +8352,11 @@ luaFunc(getScreenVirtualSize) luaReturnVec2(core->getVirtualWidth(), core->getVirtualHeight()); } +luaFunc(isMiniMapCursorOkay) +{ + luaReturnBool(dsq->isMiniMapCursorOkay()); +} + luaFunc(inv_isFull) { IngredientData *data = dsq->continuity.getIngredientDataByName(getString(L, 1)); @@ -8557,10 +8578,31 @@ luaFunc(shader_setFloat) luaFunc(shader_delete) { if(core->afterEffectManager) - core->afterEffectManager->unloadShader(lua_tointeger(L, 1)); + core->afterEffectManager->deleteShader(lua_tointeger(L, 1)); luaReturnNil(); } +luaFunc(pe_start) +{ + ParticleEffect *pe = getParticle(L); + if (pe) + pe->start(); + luaReturnNil(); +} + +luaFunc(pe_stop) +{ + ParticleEffect *pe = getParticle(L); + if (pe) + pe->stop(); + luaReturnNil(); +} + +luaFunc(pe_isRunning) +{ + ParticleEffect *pe = getParticle(L); + luaReturnBool(pe && pe->isRunning()); +} //-------------------------------------------------------------------------------------------- @@ -9483,6 +9525,7 @@ static const struct { luaRegister(getScreenVirtualOff), luaRegister(getScreenSize), luaRegister(getScreenVirtualSize), + luaRegister(isMiniMapCursorOkay), luaRegister(inv_isFull), luaRegister(inv_getMaxAmount), @@ -9514,6 +9557,10 @@ static const struct { luaRegister(shader_setInt), luaRegister(shader_delete), + luaRegister(pe_start), + luaRegister(pe_stop), + luaRegister(pe_isRunning), + luaRegister(isQuad), luaRegister(isNode), luaRegister(isObject), @@ -9523,6 +9570,8 @@ static const struct { luaRegister(isIng), luaRegister(isBeam), luaRegister(isText), + luaRegister(isShader), + luaRegister(isParticleEffect), #undef MK_FUNC diff --git a/BBGE/AfterEffect.cpp b/BBGE/AfterEffect.cpp index 938d535..6b6b92c 100644 --- a/BBGE/AfterEffect.cpp +++ b/BBGE/AfterEffect.cpp @@ -113,6 +113,13 @@ void AfterEffectManager::deleteShaders() } } +void AfterEffectManager::unloadShaders() +{ + for(size_t i = 0; i < loadedShaders.size(); ++i) + if(loadedShaders[i]) + loadedShaders[i]->unload(); +} + void AfterEffectManager::clear() { deleteEffects(); @@ -196,7 +203,7 @@ void AfterEffectManager::renderGrid() Shader *activeShader = 0; for (size_t i = 0; i < shaderPipeline.size(); ++i) { - if(shaderPipeline[i]) + if(shaderPipeline[i] && shaderPipeline[i]->isLoaded()) { if(firstShader < 0) { @@ -275,7 +282,7 @@ void AfterEffectManager::renderGrid() for(int i = firstShader + 1; i <= lastShader; ++i) { activeShader = shaderPipeline[i]; - if(!activeShader) + if(!(activeShader && activeShader->isLoaded())) continue; // Swap and exchange framebuffers. The old output buffer serves as texture input for the other one @@ -373,7 +380,7 @@ void AfterEffectManager::renderGridPoints() void AfterEffectManager::unloadDevice() { backupBuffer.unloadDevice(); - deleteShaders(); + unloadShaders(); } void AfterEffectManager::reloadDevice() @@ -399,7 +406,22 @@ void AfterEffectManager::reloadDevice() else backupBuffer.init(-1, -1, true); - loadShaders(); + for (size_t i = 0; i < loadedShaders.size(); ++i) + { + if (Shader *sh = loadedShaders[i]) + { + sh->reload(); + if (!sh->isLoaded()) + { + debugLog("AfterEffect::reloadDevice(): Failed to reload shader"); + delete sh; + loadedShaders[i] = 0; + for(size_t j = 0; j < shaderPipeline.size(); ++j) + if(sh == shaderPipeline[j]) + shaderPipeline[j] = 0; + } + } + } } void AfterEffectManager::addEffect(Effect *e) @@ -612,7 +634,7 @@ int AfterEffectManager::_insertShader(Shader *sh) return loadedShaders.size(); } -void AfterEffectManager::unloadShader(int handle) +void AfterEffectManager::deleteShader(int handle) { Shader *sh = getShaderPtr(handle); if(!sh) diff --git a/BBGE/AfterEffect.h b/BBGE/AfterEffect.h index 90c7d9f..251635f 100644 --- a/BBGE/AfterEffect.h +++ b/BBGE/AfterEffect.h @@ -91,6 +91,7 @@ public: void renderGridPoints(); void loadShaders(); + void unloadShaders(); // unloads shaders but keeps code and data intact, so that they can be reloaded. void deleteShaders(); void unloadDevice(); @@ -116,7 +117,7 @@ public: Shader *getShaderPtr(int handle); void setShaderPipelineSize(size_t size); bool setShaderPipelinePos(int handle, size_t pos); - void unloadShader(int handle); + void deleteShader(int handle); protected: int _insertShader(Shader *sh); diff --git a/BBGE/ParticleEffect.cpp b/BBGE/ParticleEffect.cpp index 821fc3b..72dde64 100644 --- a/BBGE/ParticleEffect.cpp +++ b/BBGE/ParticleEffect.cpp @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ParticleEffect::ParticleEffect() : RenderObject() { + addType(SCO_PARTICLE_EFFECT); running = false; waitForParticles = true; effectLife = -1; diff --git a/BBGE/ScriptObject.cpp b/BBGE/ScriptObject.cpp index 60b5d01..b9a8c21 100644 --- a/BBGE/ScriptObject.cpp +++ b/BBGE/ScriptObject.cpp @@ -39,6 +39,7 @@ static const char *scriptObjTypeNames[] = /* (1 <<11) */ "Text", /* (1 <<12) */ "PauseQuad", /* (1 <<13) */ "Shader", + /* (1 <<14) */ "ParticleEffect", NULL }; diff --git a/BBGE/ScriptObject.h b/BBGE/ScriptObject.h index a6bbb0a..710d067 100644 --- a/BBGE/ScriptObject.h +++ b/BBGE/ScriptObject.h @@ -41,6 +41,7 @@ enum ScriptObjectType SCO_TEXT = 0x0800, SCO_PAUSEQUAD = 0x1000, SCO_SHADER = 0x2000, + SCO_PARTICLE_EFFECT = 0x4000, SCO_FORCE_32BIT = 0xFFFFFFFF }; diff --git a/BBGE/Shader.cpp b/BBGE/Shader.cpp index c6468bc..af5e882 100644 --- a/BBGE/Shader.cpp +++ b/BBGE/Shader.cpp @@ -164,7 +164,10 @@ bool Shader::isLoaded() const void Shader::reload() { - load(vertFile, fragFile); + if (vertFile.size() || fragFile.size()) + load(vertFile, fragFile); + else + loadSrc(vertSrc.c_str(), fragSrc.c_str()); } void Shader::bind() @@ -321,6 +324,9 @@ void Shader::loadSrc(const char *vertCode, const char *fragCode) return; } + vertSrc = vertCode ? vertCode : ""; + fragSrc = fragCode ? fragCode : ""; + _queryUniforms(); #endif @@ -328,15 +334,6 @@ void Shader::loadSrc(const char *vertCode, const char *fragCode) void Shader::_setUniform(Uniform *u) { - /*if(u->location == -1) - { - u->location = glGetUniformLocationARB(g_programObj, u->name); - if(u->location == -1) - { - u->dirty = false; - return; - } - }*/ switch(u->type) { case GL_FLOAT: glUniform1fvARB(u->location, 1, u->data.f); break; @@ -381,9 +378,13 @@ void Shader::_queryUniforms() glGetObjectParameterivARB(g_programObj, GL_OBJECT_ACTIVE_UNIFORMS_ARB , &numUniforms); if (numUniforms <= 0) + { + uniforms.clear(); return; + } uniforms.reserve(numUniforms); + size_t total = 0; for (unsigned int i = 0; i < numUniforms; ++i) { @@ -396,15 +397,27 @@ void Shader::_queryUniforms() u.location = glGetUniformLocationARB(g_programObj, u.name); if(u.location == -1) continue; - u.dirty = false; - u.type = type; - memset(&u.data, 0, sizeof(u.data)); - uniforms.push_back(u); + bool add = total >= uniforms.size(); + if(add || type != u.type) // keep data intact on reload + memset(&u.data, 0, sizeof(u.data)); + u.dirty = true; + u.type = type; + + if(add) + uniforms.push_back(u); + else + uniforms[total] = u; + + ++total; } + uniforms.resize(total); + // sort to be able to do binary search later std::sort(uniforms.begin(), uniforms.end()); + + uniformsDirty = true; } int Shader::_getUniformIndex(const char *name) diff --git a/BBGE/Shader.h b/BBGE/Shader.h index 2b978e7..30b8ba0 100644 --- a/BBGE/Shader.h +++ b/BBGE/Shader.h @@ -44,6 +44,7 @@ public: protected: std::string vertFile, fragFile; + std::string vertSrc, fragSrc; #ifdef BBGE_BUILD_OPENGL GLuint g_programObj; int numUniforms; @@ -72,7 +73,7 @@ private: float f[4]; }; } data; - char name[32]; + char name[64]; bool operator< (const Uniform&) const; };