diff --git a/Aquaria/DSQ.cpp b/Aquaria/DSQ.cpp index ae23154..4c1774a 100644 --- a/Aquaria/DSQ.cpp +++ b/Aquaria/DSQ.cpp @@ -771,12 +771,15 @@ static bool sdlVideoModeOK(int disp, const int w, const int h, const int bpp) void DSQ::init() { #define PSIZEOF(x) { std::ostringstream os_; os_ << ("sizeof(" #x ") = ") << sizeof(x); debugLog(os_.str()); } + PSIZEOF(ScriptObject); PSIZEOF(RenderObject); PSIZEOF(Quad); + PSIZEOF(CollideQuad); PSIZEOF(Element); PSIZEOF(Shot); PSIZEOF(Bone); PSIZEOF(PauseQuad); + PSIZEOF(SkeletalSprite); PSIZEOF(Entity); PSIZEOF(CollideEntity); PSIZEOF(ScriptedEntity); diff --git a/Aquaria/Entity.h b/Aquaria/Entity.h index 832740b..083cf49 100644 --- a/Aquaria/Entity.h +++ b/Aquaria/Entity.h @@ -49,7 +49,7 @@ struct BoneLock int collisionMaskIndex; }; -class Entity : public Quad, public StateMachine, public SoundHolder +class Entity : public CollideQuad, public StateMachine, public SoundHolder { public: Entity(); diff --git a/Aquaria/Game.cpp b/Aquaria/Game.cpp index f779c04..17125bb 100644 --- a/Aquaria/Game.cpp +++ b/Aquaria/Game.cpp @@ -3853,7 +3853,7 @@ bool Game::collideHairVsCircle(Entity *a, int num, const Vector &pos2, float rad } // NOTE THIS FUNCTION ASSUMES THAT IF A BONE ISN'T AT FULL ALPHA (1.0) IT IS DISABLED -Bone *Game::collideSkeletalVsCircle(Entity *skeletal, RenderObject *circle) +Bone *Game::collideSkeletalVsCircle(Entity *skeletal, CollideQuad *circle) { return collideSkeletalVsCircle(skeletal, circle->position, circle->collideRadius); } @@ -3885,7 +3885,7 @@ Bone *Game::collideSkeletalVsLine(Entity *skeletal, Vector start, Vector end, fl return closest; } -bool Game::collideCircleVsLine(RenderObject *r, Vector start, Vector end, float radius) +bool Game::collideCircleVsLine(CollideQuad *r, Vector start, Vector end, float radius) { bool collision = false; if (isTouchingLine(start, end, r->position, radius+r->collideRadius, &lastCollidePosition)) @@ -3895,7 +3895,7 @@ bool Game::collideCircleVsLine(RenderObject *r, Vector start, Vector end, float return collision; } -bool Game::collideCircleVsLineAngle(RenderObject *r, float angle, float startLen, float endLen, float radius, Vector basePos) +bool Game::collideCircleVsLineAngle(CollideQuad *r, float angle, float startLen, float endLen, float radius, Vector basePos) { bool collision = false; float rads = MathFunctions::toRadians(angle); diff --git a/Aquaria/Game.h b/Aquaria/Game.h index 8c6be4b..05e7d3b 100644 --- a/Aquaria/Game.h +++ b/Aquaria/Game.h @@ -186,10 +186,10 @@ public: bool collideHairVsCircle(Entity *a, int num, const Vector &pos2, float radius, float perc=0, int *colSegment=0); bool collideCircleVsCircle(Entity *a, Entity *b); - Bone *collideSkeletalVsCircle(Entity *skeletal, RenderObject *circle); + Bone *collideSkeletalVsCircle(Entity *skeletal, CollideQuad *circle); Bone *collideSkeletalVsLine(Entity *skeletal, Vector start, Vector end, float radius); - bool collideCircleVsLine(RenderObject *r, Vector start, Vector end, float radius); - bool collideCircleVsLineAngle(RenderObject *r, float angle, float startLen, float endLen, float radius, Vector basePos); + bool collideCircleVsLine(CollideQuad *r, Vector start, Vector end, float radius); + bool collideCircleVsLineAngle(CollideQuad *r, float angle, float startLen, float endLen, float radius, Vector basePos); Bone *collideSkeletalVsCircle(Entity *skeletal, Vector pos, float radius); void handleShotCollisions(Entity *e, bool hasShield=false); void handleShotCollisionsSkeletal(Entity *e); diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index 6eedece..2340800 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -630,6 +630,16 @@ Quad *getQuad(lua_State *L, int slot = 1) return q; } +static inline +CollideQuad *getCollideQuad(lua_State *L, int slot = 1) +{ + CollideQuad *q = (CollideQuad*)lua_touserdata(L, slot); + ENSURE_TYPE(q, SCO_COLLIDE_QUAD); + if (!q) + scriptDebug(L, "Invalid CollideQuad"); + return q; +} + static inline BaseText *getText(lua_State *L, int slot = 1) { @@ -1013,6 +1023,7 @@ MakeTypeCheckFunc(isText, SCO_TEXT) MakeTypeCheckFunc(isShader, SCO_SHADER) MakeTypeCheckFunc(isParticleEffect, SCO_PARTICLE_EFFECT) MakeTypeCheckFunc(isQuadGrid, SCO_QUAD_GRID) +MakeTypeCheckFunc(isCollideQuad, SCO_COLLIDE_QUAD) #undef MakeTypeCheckFunc @@ -1467,13 +1478,13 @@ luaFunc(obj_getGravity) luaFunc(obj_getCollideRadius) { - RenderObject *r = robj(L); + CollideQuad *r = getCollideQuad(L); luaReturnNum(r ? r->collideRadius : 0); } luaFunc(obj_setCollideRadius) { - RenderObject *r = robj(L); + CollideQuad *r = getCollideQuad(L); if (r) r->collideRadius = lua_tonumber(L, 2); luaReturnNil(); @@ -1751,7 +1762,7 @@ luaFunc(obj_disableMotionBlur) luaFunc(obj_collideCircleVsLine) { - RenderObject *r = robj(L); + CollideQuad *r = getCollideQuad(L); float x1, y1, x2, y2, sz; x1 = lua_tonumber(L, 2); y1 = lua_tonumber(L, 3); @@ -1766,7 +1777,7 @@ luaFunc(obj_collideCircleVsLine) luaFunc(obj_collideCircleVsLineAngle) { - RenderObject *r = robj(L); + CollideQuad *r = getCollideQuad(L); float angle = lua_tonumber(L, 2); float start=lua_tonumber(L, 3), end=lua_tonumber(L, 4), radius=lua_tonumber(L, 5); float x=lua_tonumber(L, 6); @@ -1937,6 +1948,7 @@ luaFunc(quad_getBorderAlpha) luaReturnNum(b ? b->borderAlpha : 0.0f); } + // --- standard set/get functions for each type, wrapping RenderObject functions --- #define MK_FUNC(base, getter, prefix, suffix) \ @@ -5530,7 +5542,7 @@ luaFunc(entity_handleShotCollisionsHair) luaFunc(entity_collideSkeletalVsCircle) { Entity *e = entity(L); - RenderObject *e2 = robj(L,2); + CollideQuad *e2 = getCollideQuad(L,2); Bone *b = 0; if (e && e2) { diff --git a/Aquaria/Shot.cpp b/Aquaria/Shot.cpp index 844194f..ba23315 100644 --- a/Aquaria/Shot.cpp +++ b/Aquaria/Shot.cpp @@ -281,7 +281,7 @@ void Shot::fire(bool playSfx) } -Shot::Shot() : Quad(), Segmented(0,0) +Shot::Shot() : CollideQuad(), Segmented(0,0) { addType(SCO_SHOT); extraDamage= 0; @@ -466,7 +466,7 @@ void Shot::suicide() velocity = 0; fadeAlphaWithLife = true; dead = true; - + destroySegments(0.2f); if (emitter) { diff --git a/Aquaria/Shot.h b/Aquaria/Shot.h index bb7f2e1..90a0cc4 100644 --- a/Aquaria/Shot.h +++ b/Aquaria/Shot.h @@ -74,7 +74,7 @@ struct ShotData }; -class Shot : public Quad, public Segmented, public Scriptable +class Shot : public CollideQuad, public Segmented, public Scriptable { public: diff --git a/BBGE/Base.h b/BBGE/Base.h index 4bff87e..fa8bf3a 100644 --- a/BBGE/Base.h +++ b/BBGE/Base.h @@ -31,6 +31,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define compile_assert(pred) switch(0){case 0:case (pred):;} +// C++11's override specifier is too useful not to use it if we have it +#if (__cplusplus >= 201103L) || (defined(_MSC_VER) && (_MSC_VER+0 >= 1900)) +#define OVERRIDE override +#endif + +#ifndef OVERRIDE +#define OVERRIDE +#endif + + #ifdef _MSC_VER //#pragma warning(disable:4786) //#pragma warning(disable:4005) diff --git a/BBGE/Quad.cpp b/BBGE/Quad.cpp index 59f798c..d686cac 100644 --- a/BBGE/Quad.cpp +++ b/BBGE/Quad.cpp @@ -627,6 +627,10 @@ PauseQuad::PauseQuad() : Quad(), pauseLevel(0), positionSnapTo(0) addType(SCO_PAUSEQUAD); } +PauseQuad::~PauseQuad() +{ +} + void PauseQuad::onUpdate(float dt) { if (positionSnapTo) @@ -642,3 +646,36 @@ void PauseQuad::setPositionSnapTo(InterpolatedVector *positionSnapTo) { this->positionSnapTo = positionSnapTo; } + +CollideQuad::CollideQuad() + : collideRadius(0) +{ + addType(SCO_COLLIDE_QUAD); +} + +CollideQuad::~CollideQuad() +{ +} + +void CollideQuad::renderCollision() +{ + if (collideRadius > 0) + { + glPushMatrix(); + glLoadIdentity(); + core->setupRenderPositionAndScale(); + glBindTexture(GL_TEXTURE_2D, 0); + glTranslatef(position.x+offset.x, position.y+offset.y, 0); + + glTranslatef(internalOffset.x, internalOffset.y, 0); + glEnable(GL_BLEND); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4f(1,0,0,0.5); + drawCircle(collideRadius, 8); + glDisable(GL_BLEND); + glTranslatef(offset.x, offset.y,0); + glPopMatrix(); + } +} + diff --git a/BBGE/Quad.h b/BBGE/Quad.h index f05c53a..17c8c15 100644 --- a/BBGE/Quad.h +++ b/BBGE/Quad.h @@ -127,6 +127,7 @@ class PauseQuad : public Quad { public: PauseQuad(); + virtual ~PauseQuad(); int pauseLevel; void setPositionSnapTo(InterpolatedVector *positionSnapTo); @@ -136,6 +137,16 @@ protected: void onUpdate(float dt); }; +class CollideQuad : public Quad +{ +public: + CollideQuad(); + virtual ~CollideQuad(); + virtual void renderCollision() OVERRIDE; + + float collideRadius; +}; + #define QUAD(x) Quad *x = new Quad; addRenderObject(x); #endif diff --git a/BBGE/RenderObject.cpp b/BBGE/RenderObject.cpp index 3a9862f..3deb30d 100644 --- a/BBGE/RenderObject.cpp +++ b/BBGE/RenderObject.cpp @@ -133,11 +133,7 @@ RenderObject::RenderObject() overrideCullRadiusSqr = 0; repeatTexture = false; alphaMod = 1; - collideRadius = 0; - motionBlurTransition = false; - motionBlurFrameOffsetCounter = 0; - motionBlurFrameOffset = 0; - motionBlur = false; + motionBlur = 0; idx = -1; _fv = false; _fh = false; @@ -173,11 +169,11 @@ RenderObject::RenderObject() colorIsSaved = false; shareAlphaWithChildren = false; shareColorWithChildren = false; - motionBlurTransitionTimer = 0; } RenderObject::~RenderObject() { + freeMotionBlur(); } Vector RenderObject::getWorldPosition() @@ -454,22 +450,25 @@ void RenderObject::moveToBack() void RenderObject::enableMotionBlur(int sz, int off) { - motionBlur = true; - motionBlurPositions.resize(sz); - motionBlurFrameOffsetCounter = 0; - motionBlurFrameOffset = off; - for (size_t i = 0; i < motionBlurPositions.size(); i++) + MotionBlurData *mb = ensureMotionBlur(); + mb->transition = false; + mb->positions.resize(sz); + mb->frameOffsetCounter = 0; + mb->frameOffset = off; + for (size_t i = 0; i < mb->positions.size(); i++) { - motionBlurPositions[i].position = position; - motionBlurPositions[i].rotz = rotation.z; + mb->positions[i].position = position; + mb->positions[i].rotz = rotation.z; } } void RenderObject::disableMotionBlur() { - motionBlurTransition = true; - motionBlurTransitionTimer = 1.0; - motionBlur = false; + if(MotionBlurData *mb = this->motionBlur) + { + mb->transition = true; + mb->transitionTimer = 1.0; + } } bool RenderObject::isfhr() @@ -540,31 +539,27 @@ void RenderObject::render() } } - if (motionBlur || motionBlurTransition) + if (MotionBlurData *mb = this->motionBlur) { - Vector oldPos = position; - float oldAlpha = alpha.x; - float oldRotZ = rotation.z; - for (size_t i = 0; i < motionBlurPositions.size(); i++) + const Vector oldPos = position; + const float oldAlpha = alpha.x; + const float oldRotZ = rotation.z; + const size_t sz = mb->positions.size(); + const float m = 1.0f / float(sz); + const float m2 = 0.5f * (mb->transition ? mb->transitionTimer : 1.0f); + for (size_t i = 0; i < sz; i++) { - position = motionBlurPositions[i].position; - rotation.z = motionBlurPositions[i].rotz; - alpha = 1.0f-(float(i)/float(motionBlurPositions.size())); - alpha *= 0.5f; - if (motionBlurTransition) - { - alpha *= motionBlurTransitionTimer; - } + position = mb->positions[i].position; + rotation.z = mb->positions[i].rotz; + alpha = (1.0f-(float(i) * m)) * m2; renderCall(); } position = oldPos; alpha.x = oldAlpha; rotation.z = oldRotZ; - - renderCall(); } - else - renderCall(); + + renderCall(); } void RenderObject::renderCall() @@ -729,24 +724,6 @@ void RenderObject::renderCall() void RenderObject::renderCollision() { - if (collideRadius > 0) - { - glPushMatrix(); - glLoadIdentity(); - core->setupRenderPositionAndScale(); - glBindTexture(GL_TEXTURE_2D, 0); - glTranslatef(position.x+offset.x, position.y+offset.y, 0); - - glTranslatef(internalOffset.x, internalOffset.y, 0); - glEnable(GL_BLEND); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4f(1,0,0,0.5); - drawCircle(collideRadius, 8); - glDisable(GL_BLEND); - glTranslatef(offset.x, offset.y,0); - glPopMatrix(); - } } void RenderObject::addDeathNotify(RenderObject *r) @@ -967,32 +944,47 @@ void RenderObject::onUpdate(float dt) childGarbage.clear(); } - if (motionBlur) + if (MotionBlurData *mb = this->motionBlur) { - if (motionBlurFrameOffsetCounter >= motionBlurFrameOffset) + if(!mb->transition) { - motionBlurFrameOffsetCounter = 0; - motionBlurPositions[0].position = position; - motionBlurPositions[0].rotz = rotation.z; - for (int i = motionBlurPositions.size()-1; i > 0; i--) + if (mb->frameOffsetCounter >= mb->frameOffset) { - motionBlurPositions[i] = motionBlurPositions[i-1]; + mb->frameOffsetCounter = 0; + mb->positions[0].position = position; + mb->positions[0].rotz = rotation.z; + for (int i = mb->positions.size()-1; i > 0; i--) + { + mb->positions[i] = mb->positions[i-1]; + } } + else + mb->frameOffsetCounter ++; } else - motionBlurFrameOffsetCounter ++; - } - if (motionBlurTransition) - { - motionBlurTransitionTimer -= dt*2; - if (motionBlurTransitionTimer <= 0) { - motionBlur = motionBlurTransition = false; - motionBlurTransitionTimer = 0; + mb->transitionTimer -= dt*2; + if (mb->transitionTimer <= 0) + freeMotionBlur(); } } +} +void RenderObject::updateLife(float dt) +{ + if (decayRate > 0) + { + life -= decayRate*dt; + if (life<=0) + { + safeKill(); + } + } + if (fadeAlphaWithLife && !alpha.isInterpolating()) + { + alpha = life/maxLife; + } } void RenderObject::unloadDevice() @@ -1011,6 +1003,26 @@ void RenderObject::reloadDevice() } } +MotionBlurData* RenderObject::ensureMotionBlur() +{ + MotionBlurData *mb = this->motionBlur; + if(!mb) + { + mb = new MotionBlurData; + this->motionBlur = mb; + } + return mb; +} + +void RenderObject::freeMotionBlur() +{ + if(motionBlur) + { + delete motionBlur; + motionBlur = NULL; + } +} + bool RenderObject::setTexture(const std::string &n) { std::string name = n; @@ -1074,3 +1086,8 @@ bool RenderObject::isCoordinateInRadius(const Vector &pos, float r) return (d.getSquaredLength2D() < r*r); } + +MotionBlurData::MotionBlurData() + : transition(false), frameOffsetCounter(0), frameOffset(0), transitionTimer(0) +{ +} diff --git a/BBGE/RenderObject.h b/BBGE/RenderObject.h index 3f7bce7..89951ea 100644 --- a/BBGE/RenderObject.h +++ b/BBGE/RenderObject.h @@ -70,6 +70,15 @@ struct MotionBlurFrame float rotz; }; +struct MotionBlurData +{ + MotionBlurData(); + bool transition; + unsigned frameOffsetCounter, frameOffset; + float transitionTimer; + std::vector positions; +}; + class RenderObjectLayer; class RenderObject : public ScriptObject @@ -80,8 +89,6 @@ public: virtual ~RenderObject(); virtual void render(); - static RenderObjectLayer *rlayer; - void setTexturePointer(CountedPtr t) { this->texture = t; @@ -172,8 +179,6 @@ public: void safeKill(); - void enqueueChildDeletion(RenderObject *r); - Vector getWorldPosition(); Vector getWorldCollidePosition(const Vector &vec=Vector(0,0,0)); Vector getInvRotPosition(const Vector &vec); @@ -206,64 +211,80 @@ public: virtual void unloadDevice(); virtual void reloadDevice(); + MotionBlurData *ensureMotionBlur(); + void freeMotionBlur(); + //-------------------------------- Methods above, fields below + static RenderObjectLayer *rlayer; static bool renderCollisionShape; static bool renderPaths; static size_t lastTextureApplied; static bool lastTextureRepeat; - float width, height; // Only used by Quads, but stored here for getCullRadius() + //-------------------------- + + // fields ordered by hotness + + // TODO: this should be a bitmask + bool fadeAlphaWithLife; + bool blendEnabled; + bool renderBeforeParent; + bool updateAfterParent; + bool shareAlphaWithChildren; + bool shareColorWithChildren; + bool cull; + bool ignoreUpdate; + bool useOldDT; + bool repeatTexture; + bool _dead; + bool _hidden; + bool _fv, _fh; + + unsigned char pm; // unsigned char to save space + + InterpolatedVector position, scale, color, alpha, rotation; InterpolatedVector offset, rotationOffset, internalOffset, beforeScaleOffset; InterpolatedVector velocity, gravity; CountedPtr texture; - //int mode; - bool fadeAlphaWithLife; - - bool blendEnabled; enum BlendTypes { BLEND_DEFAULT = 0, BLEND_ADD, BLEND_SUB, BLEND_MULT }; unsigned char blendType; + float life; - float followCamera; + float alphaMod; + float updateCull; + int layer; + + float decayRate; + float maxLife; - bool renderBeforeParent; - bool updateAfterParent; - - + int overrideRenderPass; + int renderPass; + float overrideCullRadiusSqr; + // --- This is hack and should not exist --- bool colorIsSaved; // Used for both color and alpha Vector savedColor; // Saved values from setColorMult() float savedAlpha; - bool shareAlphaWithChildren; - bool shareColorWithChildren; - bool cull; - float updateCull; - int layer; + float width, height; // Only used by Quads, but stored here for getCullRadius() + // ---------------------- typedef std::vector Children; Children children, childGarbage; - - - float collideRadius; - - - float alphaMod; - - bool ignoreUpdate; - bool useOldDT; - protected: + RenderObject *parent; + virtual void onFH(){} virtual void onFV(){} virtual void onSetTexture(){} @@ -272,22 +293,7 @@ protected: virtual void deathNotify(RenderObject *r); virtual void onEndOfLife() {} - inline void updateLife(float dt) - { - if (decayRate > 0) - { - life -= decayRate*dt; - if (life<=0) - { - safeKill(); - } - } - if (fadeAlphaWithLife && !alpha.isInterpolating()) - { - - alpha = life/maxLife; - } - } + void updateLife(float dt); // Is this object or any of its children rendered in pass "pass"? bool hasRenderPass(const int pass); @@ -295,27 +301,15 @@ protected: inline void renderCall(); virtual void renderCollision(); - bool repeatTexture; - unsigned char pm; // unsigned char to save space typedef std::list RenderObjectList; RenderObjectList deathNotifications; - int overrideRenderPass; - int renderPass; - float overrideCullRadiusSqr; - float motionBlurTransitionTimer; - int motionBlurFrameOffsetCounter, motionBlurFrameOffset; - std::vectormotionBlurPositions; - bool motionBlur, motionBlurTransition; - bool _dead; - bool _hidden; - bool _fv, _fh; - - size_t idx; - RenderObject *parent; + size_t idx; // index in layer StateData *stateData; - float decayRate; - float maxLife; + MotionBlurData *motionBlur; + +private: + void enqueueChildDeletion(RenderObject *r); }; #endif diff --git a/BBGE/ScriptObject.h b/BBGE/ScriptObject.h index 00c3c84..70f9eef 100644 --- a/BBGE/ScriptObject.h +++ b/BBGE/ScriptObject.h @@ -43,6 +43,7 @@ enum ScriptObjectType SCO_SHADER = 0x2000, SCO_PARTICLE_EFFECT = 0x4000, SCO_QUAD_GRID = 0x8000, + SCO_COLLIDE_QUAD = 0x10000, SCO_FORCE_32BIT = 0xFFFFFFFF }; diff --git a/BBGE/SkeletalSprite.cpp b/BBGE/SkeletalSprite.cpp index bc5c93f..89328bd 100644 --- a/BBGE/SkeletalSprite.cpp +++ b/BBGE/SkeletalSprite.cpp @@ -66,7 +66,7 @@ void SkeletalKeyframe::copyAllButTime(SkeletalKeyframe *copy) this->t = t; } -Bone::Bone() : Quad() +Bone::Bone() : CollideQuad() { addType(SCO_BONE); fileRenderQuad = true; @@ -332,7 +332,7 @@ void Bone::renderCollision() glPopAttrib(); } else - Quad::renderCollision(); + CollideQuad::renderCollision(); } Vector Bone::getCollisionMaskNormal(size_t index) diff --git a/BBGE/SkeletalSprite.h b/BBGE/SkeletalSprite.h index d09d46d..567cea6 100644 --- a/BBGE/SkeletalSprite.h +++ b/BBGE/SkeletalSprite.h @@ -42,7 +42,7 @@ enum AnimationCommand class ParticleEffect; class SkeletalSprite; -class Bone : public Quad +class Bone : public CollideQuad { friend class SkeletalSprite; public: @@ -94,7 +94,7 @@ public: void spawnParticlesFromCollisionMask(const char *p, unsigned intv, int layer, float rotz = 0); Vector getCollisionMaskNormal(size_t index); - virtual void renderCollision(); + virtual void renderCollision() OVERRIDE; protected: std::vector emitters;