From 81ac0780f8e1c9414cb16c56415861b0f2c13224 Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Tue, 23 Sep 2014 21:12:58 +0200 Subject: [PATCH] Revert Disposable concept back into core Pretty much a revert of e858bbdcf5cc8120dd169d7efb8ae8d13ab0b5c5. We need this in core to properly implement F12 reset. --- binding-mri/binding-util.h | 18 ++---- binding-mri/bitmap-binding.cpp | 4 +- binding-mri/disposable-binding.h | 28 ++++++-- binding-mri/font-binding.cpp | 3 + binding-mri/tilemap-binding.cpp | 4 +- binding-mri/tilemapvx-binding.cpp | 2 + binding-mri/viewportelement-binding.h | 2 +- binding-mruby/binding-util.h | 17 ++--- binding-mruby/bitmap-binding.cpp | 6 +- binding-mruby/disposable-binding.h | 30 ++++++--- binding-mruby/font-binding.cpp | 3 + binding-mruby/tilemap-binding.cpp | 4 +- binding-mruby/viewportelement-binding.h | 2 +- src/bitmap.cpp | 86 ++++++++++++++++++------- src/bitmap.h | 7 +- src/disposable.h | 86 ++++++++++++------------- src/font.cpp | 3 +- src/graphics.cpp | 6 +- src/plane.cpp | 30 ++++++--- src/plane.h | 5 ++ src/scene.cpp | 8 +++ src/scene.h | 8 +++ src/sprite.cpp | 43 ++++++++++--- src/sprite.h | 5 ++ src/tileatlasvx.cpp | 2 +- src/tilemap.cpp | 51 +++++++++------ src/tilemap.h | 3 + src/tilemapvx.cpp | 47 ++++++++++---- src/tilemapvx.h | 3 + src/util.h | 4 ++ src/viewport.cpp | 20 +++++- src/viewport.h | 7 ++ src/window.cpp | 57 +++++++++++----- src/window.h | 5 ++ src/windowvx.cpp | 72 ++++++++++++++++----- src/windowvx.h | 5 ++ 36 files changed, 476 insertions(+), 210 deletions(-) diff --git a/binding-mri/binding-util.h b/binding-mri/binding-util.h index f8718b2..b84a50b 100644 --- a/binding-mri/binding-util.h +++ b/binding-mri/binding-util.h @@ -101,22 +101,12 @@ static void freeInstance(void *inst) void raiseDisposedAccess(VALUE self); -inline void -checkDisposed(VALUE self) -{ - if (!RTYPEDDATA_DATA(self)) - raiseDisposedAccess(self); -} - template inline C * getPrivateData(VALUE self) { C *c = static_cast(RTYPEDDATA_DATA(self)); - if (!c) - raiseDisposedAccess(self); - return c; } @@ -124,8 +114,6 @@ template static inline C * getPrivateDataCheck(VALUE self, const rb_data_type_t &type) { - /* We don't check for disposed here because any disposable - * property is always also nullable */ void *obj = Check_TypedStruct(self, &type); return static_cast(obj); } @@ -341,7 +329,7 @@ rb_check_argc(int actual, int expected) RB_METHOD(Klass##Get##PropName) \ { \ RB_UNUSED_PARAM; \ - checkDisposed(self); \ + checkDisposed(self); \ return rb_iv_get(self, prop_iv); \ } \ RB_METHOD(Klass##Set##PropName) \ @@ -360,7 +348,9 @@ rb_check_argc(int actual, int expected) { \ RB_UNUSED_PARAM; \ Klass *k = getPrivateData(self); \ - return value_fun(k->get##PropName()); \ + type value; \ + GUARD_EXC( value = k->get##PropName(); ) \ + return value_fun(value); \ } \ RB_METHOD(Klass##Set##PropName) \ { \ diff --git a/binding-mri/bitmap-binding.cpp b/binding-mri/bitmap-binding.cpp index 5f805e8..8781d05 100644 --- a/binding-mri/bitmap-binding.cpp +++ b/binding-mri/bitmap-binding.cpp @@ -128,7 +128,7 @@ RB_METHOD(bitmapBlt) src = getPrivateDataCheck(srcObj, BitmapType); srcRect = getPrivateDataCheck(srcRectObj, RectType); - GUARD_EXC( b->blt(x, y, src, srcRect->toIntRect(), opacity); ); + GUARD_EXC( b->blt(x, y, *src, srcRect->toIntRect(), opacity); ); return self; } @@ -151,7 +151,7 @@ RB_METHOD(bitmapStretchBlt) destRect = getPrivateDataCheck(destRectObj, RectType); srcRect = getPrivateDataCheck(srcRectObj, RectType); - GUARD_EXC( b->stretchBlt(destRect->toIntRect(), src, srcRect->toIntRect(), opacity); ); + GUARD_EXC( b->stretchBlt(destRect->toIntRect(), *src, srcRect->toIntRect(), opacity); ); return self; } diff --git a/binding-mri/disposable-binding.h b/binding-mri/disposable-binding.h index 0df8b48..7dfe928 100644 --- a/binding-mri/disposable-binding.h +++ b/binding-mri/disposable-binding.h @@ -64,32 +64,48 @@ RB_METHOD(disposableDispose) { RB_UNUSED_PARAM; - C *c = static_cast(RTYPEDDATA_DATA(self)); + C *d = getPrivateData(self); + + if (!d) + return Qnil; /* Nothing to do if already disposed */ - if (!c) + if (d->isDisposed()) return Qnil; disposableDisposeChildren(self); - delete c; - setPrivateData(self, 0); + d->dispose(); return Qnil; } +template RB_METHOD(disposableIsDisposed) { RB_UNUSED_PARAM; - return rb_bool_new(RTYPEDDATA_DATA(self) == 0); + C *d = getPrivateData(self); + + if (!d) + return Qtrue; + + return rb_bool_new(d->isDisposed()); } template static void disposableBindingInit(VALUE klass) { _rb_define_method(klass, "dispose", disposableDispose); - _rb_define_method(klass, "disposed?", disposableIsDisposed); + _rb_define_method(klass, "disposed?", disposableIsDisposed); +} + +template +inline void +checkDisposed(VALUE self) +{ + if (disposableIsDisposed(0, 0, self) == Qtrue) + raiseDisposedAccess(self); } #endif // DISPOSABLEBINDING_H diff --git a/binding-mri/font-binding.cpp b/binding-mri/font-binding.cpp index 99d6fa5..809f0da 100644 --- a/binding-mri/font-binding.cpp +++ b/binding-mri/font-binding.cpp @@ -160,6 +160,9 @@ RB_METHOD(FontSetName) return argv[0]; } +template +static void checkDisposed(VALUE) {} + DEF_PROP_OBJ_VAL(Font, Color, Color, "color") DEF_PROP_OBJ_VAL(Font, Color, OutColor, "out_color") diff --git a/binding-mri/tilemap-binding.cpp b/binding-mri/tilemap-binding.cpp index 54cbd05..bdb429f 100644 --- a/binding-mri/tilemap-binding.cpp +++ b/binding-mri/tilemap-binding.cpp @@ -101,6 +101,8 @@ RB_METHOD(tilemapGetAutotiles) { RB_UNUSED_PARAM; + checkDisposed(self); + return rb_iv_get(self, "autotiles"); } @@ -119,7 +121,7 @@ RB_METHOD(tilemapGetViewport) { RB_UNUSED_PARAM; - checkDisposed(self); + checkDisposed(self); return rb_iv_get(self, "viewport"); } diff --git a/binding-mri/tilemapvx-binding.cpp b/binding-mri/tilemapvx-binding.cpp index 88e56ed..58a586d 100644 --- a/binding-mri/tilemapvx-binding.cpp +++ b/binding-mri/tilemapvx-binding.cpp @@ -71,6 +71,8 @@ RB_METHOD(tilemapVXGetBitmapArray) { RB_UNUSED_PARAM; + checkDisposed(self); + return rb_iv_get(self, "bitmap_array"); } diff --git a/binding-mri/viewportelement-binding.h b/binding-mri/viewportelement-binding.h index 21e3fef..f3c5928 100644 --- a/binding-mri/viewportelement-binding.h +++ b/binding-mri/viewportelement-binding.h @@ -35,7 +35,7 @@ RB_METHOD(viewportElementGetViewport) { RB_UNUSED_PARAM; - checkDisposed(self); + checkDisposed(self); return rb_iv_get(self, "viewport"); } diff --git a/binding-mruby/binding-util.h b/binding-mruby/binding-util.h index 19f359b..28e1211 100644 --- a/binding-mruby/binding-util.h +++ b/binding-mruby/binding-util.h @@ -155,7 +155,7 @@ defineClass(mrb_state *mrb, const char *name) #define DEF_PROP_OBJ_VAL(Klass, PropKlass, PropName, prop_iv) \ MRB_METHOD(Klass##Get##PropName) \ { \ - checkDisposed(mrb, self); \ + checkDisposed(mrb, self); \ return getProperty(mrb, self, prop_iv); \ } \ MRB_METHOD(Klass##Set##PropName) \ @@ -194,7 +194,9 @@ defineClass(mrb_state *mrb, const char *name) MRB_METHOD(Klass##Get##PropName) \ { \ Klass *k = getPrivateData(mrb, self); \ - return mrb_##conv_t##_value(k->get##PropName()); \ + mrb_type value; \ + GUARD_EXC( value = k->get##PropName(); ) \ + return mrb_##conv_t##_value(value); \ } \ MRB_METHOD(Klass##Set##PropName) \ { \ @@ -256,21 +258,12 @@ getSym(mrb_state *mrb, CommonSymbol sym) void raiseDisposedAccess(mrb_state *mrb, mrb_value self); -inline void checkDisposed(mrb_state *mrb, mrb_value self) -{ - if (!DATA_PTR(self)) - raiseDisposedAccess(mrb, self); -} - template inline C * -getPrivateData(mrb_state *mrb, mrb_value self) +getPrivateData(mrb_state *, mrb_value self) { C *c = static_cast(DATA_PTR(self)); - if (!c) - raiseDisposedAccess(mrb, self); - return c; } diff --git a/binding-mruby/bitmap-binding.cpp b/binding-mruby/bitmap-binding.cpp index f4cd260..d200a83 100644 --- a/binding-mruby/bitmap-binding.cpp +++ b/binding-mruby/bitmap-binding.cpp @@ -114,7 +114,7 @@ MRB_METHOD(bitmapBlt) src = getPrivateDataCheck(mrb, srcObj, BitmapType); srcRect = getPrivateDataCheck(mrb, srcRectObj, RectType); - GUARD_EXC( b->blt(x, y, src, srcRect->toIntRect(), opacity); ) + GUARD_EXC( b->blt(x, y, *src, srcRect->toIntRect(), opacity); ) return mrb_nil_value(); } @@ -137,7 +137,7 @@ MRB_METHOD(bitmapStretchBlt) destRect = getPrivateDataCheck(mrb, destRectObj, RectType); srcRect = getPrivateDataCheck(mrb, srcRectObj, RectType); - GUARD_EXC( b->stretchBlt(destRect->toIntRect(), src, srcRect->toIntRect(), opacity); ) + GUARD_EXC( b->stretchBlt(destRect->toIntRect(), *src, srcRect->toIntRect(), opacity); ) return mrb_nil_value(); } @@ -280,7 +280,7 @@ MRB_METHOD(bitmapTextSize) MRB_METHOD(bitmapGetFont) { - checkDisposed(mrb, self); + checkDisposed(mrb, self); return getProperty(mrb, self, CSfont); } diff --git a/binding-mruby/disposable-binding.h b/binding-mruby/disposable-binding.h index eda37de..9b1895c 100644 --- a/binding-mruby/disposable-binding.h +++ b/binding-mruby/disposable-binding.h @@ -66,33 +66,47 @@ disposableDisposeChildren(mrb_state *mrb, mrb_value disp) template MRB_METHOD(disposableDispose) { - C *c = static_cast(DATA_PTR(self)); + C *d = static_cast(DATA_PTR(self)); - /* Nothing to do if already disposed */ - if (!c) + if (!d) + return mrb_nil_value(); + + if (d->isDisposed()) return mrb_nil_value(); disposableDisposeChildren(mrb, self); - delete c; - DATA_PTR(self) = 0; + d->dispose(); return mrb_nil_value(); } template -MRB_METHOD(disposableDisposed) +MRB_METHOD(disposableIsDisposed) { MRB_UNUSED_PARAM; - return mrb_bool_value(DATA_PTR(self) == 0); + C *d = static_cast(DATA_PTR(self)); + + if (!d) + return mrb_true_value(); + + return mrb_bool_value(d->isDisposed()); } template static void disposableBindingInit(mrb_state *mrb, RClass *klass) { mrb_define_method(mrb, klass, "dispose", disposableDispose, MRB_ARGS_NONE()); - mrb_define_method(mrb, klass, "disposed?", disposableDisposed, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "disposed?", disposableIsDisposed, MRB_ARGS_NONE()); +} + +template +inline void +checkDisposed(mrb_state *mrb, mrb_value self) +{ + if (mrb_test(disposableIsDisposed(0, self))) + raiseDisposedAccess(mrb, self); } #endif // DISPOSABLEBINDING_H diff --git a/binding-mruby/font-binding.cpp b/binding-mruby/font-binding.cpp index d811869..22e34cd 100644 --- a/binding-mruby/font-binding.cpp +++ b/binding-mruby/font-binding.cpp @@ -103,6 +103,9 @@ MRB_METHOD(FontSetName) return name; } +template +static void checkDisposed(mrb_state *, mrb_value) {} + DEF_PROP_I(Font, Size) DEF_PROP_B(Font, Bold) DEF_PROP_B(Font, Italic) diff --git a/binding-mruby/tilemap-binding.cpp b/binding-mruby/tilemap-binding.cpp index 2ec1eb0..1d4efcf 100644 --- a/binding-mruby/tilemap-binding.cpp +++ b/binding-mruby/tilemap-binding.cpp @@ -106,6 +106,8 @@ MRB_METHOD(tilemapInitialize) MRB_METHOD(tilemapGetAutotiles) { + checkDisposed(mrb, self); + return getProperty(mrb, self, CSautotiles); } @@ -120,7 +122,7 @@ MRB_METHOD(tilemapUpdate) MRB_METHOD(tilemapGetViewport) { - checkDisposed(mrb, self); + checkDisposed(mrb, self); return getProperty(mrb, self, CSviewport); } diff --git a/binding-mruby/viewportelement-binding.h b/binding-mruby/viewportelement-binding.h index a4ea09c..38cd3d1 100644 --- a/binding-mruby/viewportelement-binding.h +++ b/binding-mruby/viewportelement-binding.h @@ -32,7 +32,7 @@ template MRB_METHOD(viewportElementGetViewport) { - checkDisposed(mrb, self); + checkDisposed(mrb, self); return getProperty(mrb, self, CSviewport); } diff --git a/src/bitmap.cpp b/src/bitmap.cpp index c95afaa..119dc24 100644 --- a/src/bitmap.cpp +++ b/src/bitmap.cpp @@ -297,21 +297,18 @@ Bitmap::Bitmap(const Bitmap &other) p->gl = shState->texPool().request(other.width(), other.height()); - blt(0, 0, &other, rect()); + blt(0, 0, other, rect()); } Bitmap::~Bitmap() { - if (p->megaSurface) - SDL_FreeSurface(p->megaSurface); - else - shState->texPool().release(p->gl); - - delete p; + dispose(); } int Bitmap::width() const { + guardDisposed(); + if (p->megaSurface) return p->megaSurface->w; @@ -320,6 +317,8 @@ int Bitmap::width() const int Bitmap::height() const { + guardDisposed(); + if (p->megaSurface) return p->megaSurface->h; @@ -328,14 +327,16 @@ int Bitmap::height() const IntRect Bitmap::rect() const { + guardDisposed(); + return IntRect(0, 0, width(), height()); } void Bitmap::blt(int x, int y, - const Bitmap *source, IntRect rect, + const Bitmap &source, IntRect rect, int opacity) { - if (!source) + if (source.isDisposed()) return; // FIXME: RGSS allows the source rect to both lie outside @@ -344,23 +345,25 @@ void Bitmap::blt(int x, int y, // doesn't fix anything for a direct stretch_blt call). /* Clamp rect to source bitmap size */ - if (rect.x + rect.w > source->width()) - rect.w = source->width() - rect.x; + if (rect.x + rect.w > source.width()) + rect.w = source.width() - rect.x; - if (rect.y + rect.h > source->height()) - rect.h = source->height() - rect.y; + if (rect.y + rect.h > source.height()) + rect.h = source.height() - rect.y; stretchBlt(IntRect(x, y, rect.w, rect.h), source, rect, opacity); } void Bitmap::stretchBlt(const IntRect &destRect, - const Bitmap *source, const IntRect &sourceRect, + const Bitmap &source, const IntRect &sourceRect, int opacity) { + guardDisposed(); + GUARD_MEGA; - if (!source) + if (source.isDisposed()) return; opacity = clamp(opacity, 0, 255); @@ -368,13 +371,13 @@ void Bitmap::stretchBlt(const IntRect &destRect, if (opacity == 0) return; - if (source->megaSurface()) + if (source.megaSurface()) { /* Don't do transparent blits for now */ if (opacity < 255) - source->ensureNonMega(); + source.ensureNonMega(); - SDL_Surface *srcSurf = source->megaSurface(); + SDL_Surface *srcSurf = source.megaSurface(); SDL_Rect srcRect = sourceRect; SDL_Rect dstRect = destRect; @@ -421,7 +424,7 @@ void Bitmap::stretchBlt(const IntRect &destRect, { /* Fast blit */ GLMeta::blitBegin(p->gl); - GLMeta::blitSource(source->p->gl); + GLMeta::blitSource(source.p->gl); GLMeta::blitRectangle(sourceRect, destRect); GLMeta::blitEnd(); } @@ -437,10 +440,10 @@ void Bitmap::stretchBlt(const IntRect &destRect, GLMeta::blitRectangle(destRect, Vec2i()); GLMeta::blitEnd(); - FloatRect bltSubRect((float) sourceRect.x / source->width(), - (float) sourceRect.y / source->height(), - ((float) source->width() / sourceRect.w) * ((float) destRect.w / gpTex.width), - ((float) source->height() / sourceRect.h) * ((float) destRect.h / gpTex.height)); + FloatRect bltSubRect((float) sourceRect.x / source.width(), + (float) sourceRect.y / source.height(), + ((float) source.width() / sourceRect.w) * ((float) destRect.w / gpTex.width), + ((float) source.height() / sourceRect.h) * ((float) destRect.h / gpTex.height)); BltShader &shader = shState->shaders().blt; shader.bind(); @@ -452,7 +455,7 @@ void Bitmap::stretchBlt(const IntRect &destRect, quad.setTexPosRect(sourceRect, destRect); quad.setColor(Vec4(1, 1, 1, normOpacity)); - source->p->bindTexture(shader); + source.p->bindTexture(shader); p->bindFBO(); p->pushSetViewport(shader); @@ -475,6 +478,8 @@ void Bitmap::fillRect(int x, int y, void Bitmap::fillRect(const IntRect &rect, const Vec4 &color) { + guardDisposed(); + GUARD_MEGA; p->fillRect(rect, color); @@ -501,6 +506,8 @@ void Bitmap::gradientFillRect(const IntRect &rect, const Vec4 &color1, const Vec4 &color2, bool vertical) { + guardDisposed(); + GUARD_MEGA; SimpleColorShader &shader = shState->shaders().simpleColor; @@ -545,6 +552,8 @@ void Bitmap::clearRect(int x, int y, int width, int height) void Bitmap::clearRect(const IntRect &rect) { + guardDisposed(); + GUARD_MEGA; p->fillRect(rect, Vec4()); @@ -554,6 +563,8 @@ void Bitmap::clearRect(const IntRect &rect) void Bitmap::blur() { + guardDisposed(); + GUARD_MEGA; Quad &quad = shState->gpQuad(); @@ -597,6 +608,8 @@ void Bitmap::blur() void Bitmap::radialBlur(int angle, int divisions) { + guardDisposed(); + GUARD_MEGA; angle = clamp(angle, 0, 359); @@ -690,6 +703,8 @@ void Bitmap::radialBlur(int angle, int divisions) void Bitmap::clear() { + guardDisposed(); + GUARD_MEGA; p->bindFBO(); @@ -707,6 +722,8 @@ void Bitmap::clear() Color Bitmap::getPixel(int x, int y) const { + guardDisposed(); + GUARD_MEGA; if (x < 0 || y < 0 || x >= width() || y >= height()) @@ -737,6 +754,8 @@ Color Bitmap::getPixel(int x, int y) const void Bitmap::setPixel(int x, int y, const Color &color) { + guardDisposed(); + GUARD_MEGA; uint8_t pixel[] = @@ -757,6 +776,8 @@ void Bitmap::setPixel(int x, int y, const Color &color) void Bitmap::hueChange(int hue) { + guardDisposed(); + GUARD_MEGA; if ((hue % 360) == 0) @@ -818,6 +839,8 @@ static std::string fixupString(const char *str) void Bitmap::drawText(const IntRect &rect, const char *str, int align) { + guardDisposed(); + GUARD_MEGA; std::string fixed = fixupString(str); @@ -1046,6 +1069,8 @@ static uint16_t utf8_to_ucs2(const char *_input, IntRect Bitmap::textSize(const char *str) { + guardDisposed(); + GUARD_MEGA; TTF_Font *font = p->font->getSdlFont(); @@ -1092,6 +1117,9 @@ SDL_Surface *Bitmap::megaSurface() const void Bitmap::ensureNonMega() const { + if (isDisposed()) + return; + GUARD_MEGA; } @@ -1104,3 +1132,13 @@ void Bitmap::taintArea(const IntRect &rect) { p->addTaintedArea(rect); } + +void Bitmap::releaseResources() +{ + if (p->megaSurface) + SDL_FreeSurface(p->megaSurface); + else + shState->texPool().release(p->gl); + + delete p; +} diff --git a/src/bitmap.h b/src/bitmap.h index 89216d0..6217da1 100644 --- a/src/bitmap.h +++ b/src/bitmap.h @@ -49,11 +49,11 @@ public: IntRect rect() const; void blt(int x, int y, - const Bitmap *source, IntRect rect, + const Bitmap &source, IntRect rect, int opacity = 255); void stretchBlt(const IntRect &destRect, - const Bitmap *source, const IntRect &sourceRect, + const Bitmap &source, const IntRect &sourceRect, int opacity = 255); void fillRect(int x, int y, @@ -120,6 +120,9 @@ public: sigc::signal modified; private: + void releaseResources(); + const char *klassName() const { return "bitmap"; } + BitmapPrivate *p; }; diff --git a/src/disposable.h b/src/disposable.h index a83f36f..412b058 100644 --- a/src/disposable.h +++ b/src/disposable.h @@ -24,69 +24,65 @@ #include "exception.h" +#include #include #include class Disposable { public: - ~Disposable() + Disposable() + : disposed(false) + {} + + virtual ~Disposable() { + assert(disposed); + } + + void dispose() + { + if (disposed) + return; + + releaseResources(); + disposed = true; wasDisposed(); } - sigc::signal wasDisposed; -}; - -/* A helper struct which monitors the dispose signal of - * properties, and automatically sets the prop pointer to - * null. Can call an optional notify method when prop is - * nulled */ -template -struct DisposeWatch -{ - typedef void (C::*NotifyFun)(); - - DisposeWatch(C &owner, P *&propLocation, NotifyFun notify = 0) - : owner(owner), - notify(notify), - propLocation(propLocation) - {} - - ~DisposeWatch() + bool isDisposed() const { - dispCon.disconnect(); + return disposed; } - /* Call this when a new object was set for the prop */ - void update(Disposable *prop) + sigc::signal wasDisposed; + +protected: + void guardDisposed() const { - dispCon.disconnect(); - - if (!prop) - return; - - dispCon = prop->wasDisposed.connect - (sigc::mem_fun(this, &DisposeWatch::onDisposed)); + if (isDisposed()) + throw Exception(Exception::RGSSError, + "disposed %s", klassName()); } private: - /* The object owning the prop (and this helper) */ - C &owner; - /* Optional notify method */ - const NotifyFun notify; - /* Location of the prop pointer inside the owner */ - P * &propLocation; - sigc::connection dispCon; + virtual void releaseResources() = 0; + virtual const char *klassName() const = 0; - void onDisposed() - { - dispCon.disconnect(); - propLocation = 0; - - if (notify) - (owner.*notify)(); - } + bool disposed; }; +template +inline bool +nullOrDisposed(const C *d) +{ + if (!d) + return true; + + if (d->isDisposed()) + return true; + + return false; +} + #endif // DISPOSABLE_H diff --git a/src/font.cpp b/src/font.cpp index 09b5ec8..e4ddcd9 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -341,8 +341,7 @@ void Font::setSize(int value) p->sdlFont = 0; } -#undef CHK_DISP -#define CHK_DISP +static void guardDisposed() {} DEF_ATTR_RD_SIMPLE(Font, Size, int, p->size) DEF_ATTR_SIMPLE (Font, Bold, bool, p->bold) diff --git a/src/graphics.cpp b/src/graphics.cpp index 9f69076..ebcc456 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -674,11 +674,7 @@ void Graphics::frameReset() p->fpsLimiter.resetFrameAdjust(); } -#undef RET_IF_DISP -#define RET_IF_DISP(x) - -#undef CHK_DISP -#define CHK_DISP +static void guardDisposed() {} DEF_ATTR_RD_SIMPLE(Graphics, FrameRate, int, p->frameRate) diff --git a/src/plane.cpp b/src/plane.cpp index 1982bce..f050489 100644 --- a/src/plane.cpp +++ b/src/plane.cpp @@ -45,7 +45,6 @@ static float fwrap(float value, float range) struct PlanePrivate { Bitmap *bitmap; - DisposeWatch bitmapWatch; NormValue opacity; BlendType blendType; @@ -67,7 +66,6 @@ struct PlanePrivate PlanePrivate() : bitmap(0), - bitmapWatch(*this, bitmap), opacity(255), blendType(BlendNormal), color(&tmp.color), @@ -103,7 +101,7 @@ struct PlanePrivate return; } - if (!bitmap) + if (nullOrDisposed(bitmap)) return; /* Scaled (zoomed) bitmap dimensions */ @@ -169,15 +167,14 @@ DEF_ATTR_OBJ_VALUE(Plane, Tone, Tone*, p->tone) Plane::~Plane() { - unlink(); - - delete p; + dispose(); } void Plane::setBitmap(Bitmap *value) { + guardDisposed(); + p->bitmap = value; - p->bitmapWatch.update(value); if (!value) return; @@ -187,6 +184,8 @@ void Plane::setBitmap(Bitmap *value) void Plane::setOX(int value) { + guardDisposed(); + if (p->ox == value) return; @@ -196,6 +195,8 @@ void Plane::setOX(int value) void Plane::setOY(int value) { + guardDisposed(); + if (p->oy == value) return; @@ -205,6 +206,8 @@ void Plane::setOY(int value) void Plane::setZoomX(float value) { + guardDisposed(); + if (p->zoomX == value) return; @@ -214,6 +217,8 @@ void Plane::setZoomX(float value) void Plane::setZoomY(float value) { + guardDisposed(); + if (p->zoomY == value) return; @@ -223,6 +228,8 @@ void Plane::setZoomY(float value) void Plane::setBlendType(int value) { + guardDisposed(); + switch (value) { default : @@ -246,7 +253,7 @@ void Plane::initDynAttribs() void Plane::draw() { - if (!p->bitmap) + if (nullOrDisposed(p->bitmap)) return; if (!p->opacity) @@ -301,3 +308,10 @@ void Plane::onGeometryChange(const Scene::Geometry &geo) p->sceneGeo = geo; p->quadSourceDirty = true; } + +void Plane::releaseResources() +{ + unlink(); + + delete p; +} diff --git a/src/plane.h b/src/plane.h index 1b55278..91a9e03 100644 --- a/src/plane.h +++ b/src/plane.h @@ -54,6 +54,11 @@ private: void draw(); void onGeometryChange(const Scene::Geometry &); + + void releaseResources(); + const char *klassName() const { return "plane"; } + + ABOUT_TO_ACCESS_DISP }; #endif // PLANE_H diff --git a/src/scene.cpp b/src/scene.cpp index 9f660f7..a642288 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -134,11 +134,15 @@ void SceneElement::setScene(Scene &scene) int SceneElement::getZ() const { + aboutToAccess(); + return z; } void SceneElement::setZ(int value) { + aboutToAccess(); + if (z == value) return; @@ -148,11 +152,15 @@ void SceneElement::setZ(int value) bool SceneElement::getVisible() const { + aboutToAccess(); + return visible; } void SceneElement::setVisible(bool value) { + aboutToAccess(); + visible = value; } diff --git a/src/scene.h b/src/scene.h index d32dc8b..4dd46b3 100644 --- a/src/scene.h +++ b/src/scene.h @@ -79,6 +79,8 @@ public: DECL_ATTR_VIRT( Z, int ) DECL_ATTR_VIRT( Visible, bool ) + virtual void aboutToAccess() const = 0; + protected: /* A bit about OpenGL state: * @@ -134,4 +136,10 @@ private: int spriteY; }; +#define ABOUT_TO_ACCESS_NOOP \ + void aboutToAccess() const {} + +#define ABOUT_TO_ACCESS_DISP \ + void aboutToAccess() const { guardDisposed(); } + #endif // SCENE_H diff --git a/src/sprite.cpp b/src/sprite.cpp index b436db2..681e219 100644 --- a/src/sprite.cpp +++ b/src/sprite.cpp @@ -43,7 +43,6 @@ struct SpritePrivate { Bitmap *bitmap; - DisposeWatch bitmapWatch; Quad quad; Transform trans; @@ -87,7 +86,6 @@ struct SpritePrivate SpritePrivate() : bitmap(0), - bitmapWatch(*this, bitmap), srcRect(&tmp.rect), mirrored(false), bushDepth(0), @@ -159,7 +157,7 @@ struct SpritePrivate { isVisible = false; - if (!bitmap) + if (nullOrDisposed(bitmap)) return; if (!opacity) @@ -209,7 +207,7 @@ struct SpritePrivate void updateWave() { - if (!bitmap) + if (nullOrDisposed(bitmap)) return; if (wave.amp == 0) @@ -298,9 +296,7 @@ Sprite::Sprite(Viewport *viewport) Sprite::~Sprite() { - unlink(); - - delete p; + dispose(); } DEF_ATTR_RD_SIMPLE(Sprite, Bitmap, Bitmap*, p->bitmap) @@ -330,11 +326,12 @@ DEF_ATTR_OBJ_VALUE(Sprite, Tone, Tone*, p->tone) void Sprite::setBitmap(Bitmap *bitmap) { + guardDisposed(); + if (p->bitmap == bitmap) return; p->bitmap = bitmap; - p->bitmapWatch.update(bitmap); if (!bitmap) return; @@ -350,6 +347,8 @@ void Sprite::setBitmap(Bitmap *bitmap) void Sprite::setX(int value) { + guardDisposed(); + if (p->trans.getPosition().x == value) return; @@ -358,6 +357,8 @@ void Sprite::setX(int value) void Sprite::setY(int value) { + guardDisposed(); + if (p->trans.getPosition().y == value) return; @@ -372,6 +373,8 @@ void Sprite::setY(int value) void Sprite::setOX(int value) { + guardDisposed(); + if (p->trans.getOrigin().x == value) return; @@ -380,6 +383,8 @@ void Sprite::setOX(int value) void Sprite::setOY(int value) { + guardDisposed(); + if (p->trans.getOrigin().y == value) return; @@ -388,6 +393,8 @@ void Sprite::setOY(int value) void Sprite::setZoomX(float value) { + guardDisposed(); + if (p->trans.getScale().x == value) return; @@ -396,6 +403,8 @@ void Sprite::setZoomX(float value) void Sprite::setZoomY(float value) { + guardDisposed(); + if (p->trans.getScale().y == value) return; @@ -408,6 +417,8 @@ void Sprite::setZoomY(float value) void Sprite::setAngle(float value) { + guardDisposed(); + if (p->trans.getRotation() == value) return; @@ -416,6 +427,8 @@ void Sprite::setAngle(float value) void Sprite::setMirror(bool mirrored) { + guardDisposed(); + if (p->mirrored == mirrored) return; @@ -425,6 +438,8 @@ void Sprite::setMirror(bool mirrored) void Sprite::setBushDepth(int value) { + guardDisposed(); + if (p->bushDepth == value) return; @@ -434,6 +449,8 @@ void Sprite::setBushDepth(int value) void Sprite::setBlendType(int type) { + guardDisposed(); + switch (type) { default : @@ -452,6 +469,7 @@ void Sprite::setBlendType(int type) #define DEF_WAVE_SETTER(Name, name, type) \ void Sprite::setWave##Name(type value) \ { \ + guardDisposed(); \ if (p->wave.name == value) \ return; \ p->wave.name = value; \ @@ -477,6 +495,8 @@ void Sprite::initDynAttribs() /* Flashable */ void Sprite::update() { + guardDisposed(); + Flashable::update(); p->wave.phase += p->wave.speed / 180; @@ -556,3 +576,10 @@ void Sprite::onGeometryChange(const Scene::Geometry &geo) p->sceneRect.w = geo.rect.w; p->sceneRect.h = geo.rect.h; } + +void Sprite::releaseResources() +{ + unlink(); + + delete p; +} diff --git a/src/sprite.h b/src/sprite.h index b1645bb..8a9ba09 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -74,6 +74,11 @@ private: void draw(); void onGeometryChange(const Scene::Geometry &); + + void releaseResources(); + const char *klassName() const { return "sprite"; } + + ABOUT_TO_ACCESS_DISP }; #endif // SPRITE_H diff --git a/src/tileatlasvx.cpp b/src/tileatlasvx.cpp index a2062ad..711675c 100644 --- a/src/tileatlasvx.cpp +++ b/src/tileatlasvx.cpp @@ -291,7 +291,7 @@ void build(TEXFBO &tf, Bitmap *bitmaps[BM_COUNT]) Bitmap *bm; #define EXEC_BLITS(part) \ - if ((bm = bitmaps[BM_##part])) \ + if (!nullOrDisposed(bm = bitmaps[BM_##part])) \ { \ GLMeta::blitSource(bm->getGLTypes()); \ for (size_t i = 0; i < blits##part##N; ++i) \ diff --git a/src/tilemap.cpp b/src/tilemap.cpp index d0601e2..b92cc34 100644 --- a/src/tilemap.cpp +++ b/src/tilemap.cpp @@ -38,7 +38,6 @@ #include "tileatlas.h" #include -#include #include #include @@ -204,6 +203,8 @@ struct GroundLayer : public ViewportElement void drawFlashInt(); void onGeometryChange(const Scene::Geometry &geo); + + ABOUT_TO_ACCESS_NOOP }; struct ZLayer : public ViewportElement @@ -232,6 +233,8 @@ struct ZLayer : public ViewportElement void initUpdateZ(); void finiUpdateZ(ZLayer *prev); + + ABOUT_TO_ACCESS_NOOP }; struct TilemapPrivate @@ -242,7 +245,6 @@ struct TilemapPrivate Bitmap *autotiles[autotileCount]; Bitmap *tileset; - DisposeWatch tilesetWatch; Table *mapData; Table *flashData; @@ -347,7 +349,6 @@ struct TilemapPrivate TilemapPrivate(Viewport *viewport) : viewport(viewport), tileset(0), - tilesetWatch(*this, tileset), mapData(0), flashData(0), priorities(0), @@ -432,7 +433,7 @@ struct TilemapPrivate void updateAtlasInfo() { - if (!tileset) + if (nullOrDisposed(tileset)) { atlas.size = Vec2i(); return; @@ -458,7 +459,7 @@ struct TilemapPrivate for (int i = 0; i < autotileCount; ++i) { - if (!autotiles[i]) + if (nullOrDisposed(autotiles[i])) continue; if (autotiles[i]->megaSurface()) @@ -506,20 +507,10 @@ struct TilemapPrivate flashDirty = true; } - void onAutotileDisposed(int i) - { - /* RMXP actually crashes if an active autotile bitmap is disposed.. - * let's not crash ourselves, for consistency's sake */ - autotiles[i] = 0; - autotilesCon[i].disconnect(); - autotilesDispCon[i].disconnect(); - atlasDirty = true; - } - /* Checks for the minimum amount of data needed to display */ bool verifyResources() { - if (!tileset) + if (nullOrDisposed(tileset)) return false; if (!mapData) @@ -1208,7 +1199,7 @@ void Tilemap::Autotiles::set(int i, Bitmap *bitmap) p->autotilesDispCon[i].disconnect(); p->autotilesDispCon[i] = bitmap->wasDisposed.connect - (sigc::bind(sigc::mem_fun(p, &TilemapPrivate::onAutotileDisposed), i)); + (sigc::mem_fun(p, &TilemapPrivate::invalidateAtlasContents)); p->updateAutotileInfo(); } @@ -1229,11 +1220,13 @@ Tilemap::Tilemap(Viewport *viewport) Tilemap::~Tilemap() { - delete p; + dispose(); } void Tilemap::update() { + guardDisposed(); + if (!p->tilemapReady) return; @@ -1253,6 +1246,8 @@ void Tilemap::update() Tilemap::Autotiles &Tilemap::getAutotiles() const { + guardDisposed(); + return p->autotilesProxy; } @@ -1267,11 +1262,12 @@ DEF_ATTR_RD_SIMPLE(Tilemap, OY, int, p->offset.y) void Tilemap::setTileset(Bitmap *value) { + guardDisposed(); + if (p->tileset == value) return; p->tileset = value; - p->tilesetWatch.update(value); if (!value) return; @@ -1286,6 +1282,8 @@ void Tilemap::setTileset(Bitmap *value) void Tilemap::setMapData(Table *value) { + guardDisposed(); + if (p->mapData == value) return; @@ -1302,6 +1300,8 @@ void Tilemap::setMapData(Table *value) void Tilemap::setFlashData(Table *value) { + guardDisposed(); + if (p->flashData == value) return; @@ -1318,6 +1318,8 @@ void Tilemap::setFlashData(Table *value) void Tilemap::setPriorities(Table *value) { + guardDisposed(); + if (p->priorities == value) return; @@ -1334,6 +1336,8 @@ void Tilemap::setPriorities(Table *value) void Tilemap::setVisible(bool value) { + guardDisposed(); + if (p->visible == value) return; @@ -1349,6 +1353,8 @@ void Tilemap::setVisible(bool value) void Tilemap::setOX(int value) { + guardDisposed(); + if (p->offset.x == value) return; @@ -1359,6 +1365,8 @@ void Tilemap::setOX(int value) void Tilemap::setOY(int value) { + guardDisposed(); + if (p->offset.y == value) return; @@ -1367,3 +1375,8 @@ void Tilemap::setOY(int value) p->zOrderDirty = true; p->mapViewportDirty = true; } + +void Tilemap::releaseResources() +{ + delete p; +} diff --git a/src/tilemap.h b/src/tilemap.h index 89775c1..6e68d92 100644 --- a/src/tilemap.h +++ b/src/tilemap.h @@ -68,6 +68,9 @@ public: private: TilemapPrivate *p; + + void releaseResources(); + const char *klassName() const { return "tilemap"; } }; #endif // TILEMAP_H diff --git a/src/tilemapvx.cpp b/src/tilemapvx.cpp index f9f09d3..fb5aae5 100644 --- a/src/tilemapvx.cpp +++ b/src/tilemapvx.cpp @@ -36,7 +36,6 @@ #include #include -#include // FIXME: Implement flash @@ -95,6 +94,8 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader { p->drawAbove(); } + + ABOUT_TO_ACCESS_NOOP }; AboveLayer above; @@ -154,15 +155,6 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader atlasDirty = true; } - void onBitmapDisposed(int i) - { - bitmaps[i] = 0; - bmChangedCons[i].disconnect(); - bmDisposedCons[i].disconnect(); - - atlasDirty = true; - } - void invalidateBuffers() { buffersDirty = true; @@ -290,7 +282,7 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader { ShaderBase *shader; - if (bitmaps[BM_A1] != 0) + if (!nullOrDisposed(bitmaps[BM_A1])) { /* Animated tileset */ TilemapVXShader &tmShader = shState->shaders().tilemapVX; @@ -351,6 +343,8 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader mapViewportDirty = true; } + ABOUT_TO_ACCESS_NOOP + /* TileAtlasVX::Reader */ void onQuads(const FloatRect *t, const FloatRect *p, size_t n, bool overPlayer) @@ -379,7 +373,7 @@ void TilemapVX::BitmapArray::set(int i, Bitmap *bitmap) p->bmDisposedCons[i].disconnect(); p->bmDisposedCons[i] = bitmap->wasDisposed.connect - (sigc::bind(sigc::mem_fun(p, &TilemapVXPrivate::onBitmapDisposed), i)); + (sigc::mem_fun(p, &TilemapVXPrivate::invalidateAtlas)); } Bitmap *TilemapVX::BitmapArray::get(int i) const @@ -398,11 +392,13 @@ TilemapVX::TilemapVX(Viewport *viewport) TilemapVX::~TilemapVX() { - delete p; + dispose(); } void TilemapVX::update() { + guardDisposed(); + if (++p->frameIdx >= 30*3*4) p->frameIdx = 0; @@ -419,6 +415,8 @@ void TilemapVX::update() TilemapVX::BitmapArray &TilemapVX::getBitmapArray() const { + guardDisposed(); + return p->bitmapsProxy; } @@ -430,22 +428,30 @@ DEF_ATTR_RD_SIMPLE(TilemapVX, OY, int, p->offset.y) Viewport *TilemapVX::getViewport() const { + guardDisposed(); + return p->getViewport(); } bool TilemapVX::getVisible() const { + guardDisposed(); + return p->getVisible(); } void TilemapVX::setViewport(Viewport *value) { + guardDisposed(); + p->setViewport(value); p->above.setViewport(value); } void TilemapVX::setMapData(Table *value) { + guardDisposed(); + if (p->mapData == value) return; @@ -459,6 +465,8 @@ void TilemapVX::setMapData(Table *value) void TilemapVX::setFlashData(Table *value) { + guardDisposed(); + if (p->flashData == value) return; @@ -467,6 +475,8 @@ void TilemapVX::setFlashData(Table *value) void TilemapVX::setFlags(Table *value) { + guardDisposed(); + if (p->flags == value) return; @@ -480,12 +490,16 @@ void TilemapVX::setFlags(Table *value) void TilemapVX::setVisible(bool value) { + guardDisposed(); + p->setVisible(value); p->above.setVisible(value); } void TilemapVX::setOX(int value) { + guardDisposed(); + if (p->offset.x == value) return; @@ -495,9 +509,16 @@ void TilemapVX::setOX(int value) void TilemapVX::setOY(int value) { + guardDisposed(); + if (p->offset.y == value) return; p->offset.y = value; p->mapViewportDirty = true; } + +void TilemapVX::releaseResources() +{ + delete p; +} diff --git a/src/tilemapvx.h b/src/tilemapvx.h index 1a0f313..0e2b4be 100644 --- a/src/tilemapvx.h +++ b/src/tilemapvx.h @@ -66,6 +66,9 @@ public: private: TilemapVXPrivate *p; + + void releaseResources(); + const char *klassName() const { return "tilemap"; } }; #endif // TILEMAPVX_H diff --git a/src/util.h b/src/util.h index b8b42f4..8009a26 100644 --- a/src/util.h +++ b/src/util.h @@ -119,6 +119,7 @@ inline bool contains(const C &c, const V &v) #define DEF_ATTR_RD_SIMPLE_DETAILED(klass, name, type, location, keyword1) \ type klass :: get##name() keyword1 \ { \ + guardDisposed(); \ return location; \ } @@ -126,6 +127,7 @@ inline bool contains(const C &c, const V &v) DEF_ATTR_RD_SIMPLE_DETAILED(klass, name, type, location, keyword1) \ void klass :: set##name(type value) \ { \ + guardDisposed(); \ location = value; \ } @@ -141,6 +143,7 @@ inline bool contains(const C &c, const V &v) DEF_ATTR_RD_SIMPLE_DETAILED(klass, name, type, location, const) \ void klass :: set##name(type value) \ { \ + guardDisposed(); \ *location = *value; \ } @@ -148,6 +151,7 @@ inline bool contains(const C &c, const V &v) DEF_ATTR_RD_SIMPLE_DETAILED(klass, name, type, location, ) \ void klass :: set##name(type value) \ { \ + guardDisposed(); \ *location = *value; \ } diff --git a/src/viewport.cpp b/src/viewport.cpp index 49c3798..fed9f18 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -134,9 +134,14 @@ void Viewport::initViewport(int x, int y, int width, int height) Viewport::~Viewport() { - unlink(); + dispose(); +} - delete p; +void Viewport::update() +{ + guardDisposed(); + + Flashable::update(); } DEF_ATTR_RD_SIMPLE(Viewport, OX, int, geometry.xOrigin) @@ -148,6 +153,8 @@ DEF_ATTR_OBJ_VALUE(Viewport, Tone, Tone*, p->tone) void Viewport::setOX(int value) { + guardDisposed(); + if (geometry.xOrigin == value) return; @@ -157,6 +164,8 @@ void Viewport::setOX(int value) void Viewport::setOY(int value) { + guardDisposed(); + if (geometry.yOrigin == value) return; @@ -212,6 +221,13 @@ void Viewport::onGeometryChange(const Geometry &geo) p->recomputeOnScreen(); } +void Viewport::releaseResources() +{ + unlink(); + + delete p; +} + ViewportElement::ViewportElement(Viewport *viewport, int z, int spriteY) : SceneElement(viewport ? *viewport : *shState->screen(), z, spriteY), diff --git a/src/viewport.h b/src/viewport.h index 325da41..416d4da 100644 --- a/src/viewport.h +++ b/src/viewport.h @@ -37,6 +37,8 @@ public: Viewport(); ~Viewport(); + void update(); + DECL_ATTR( Rect, Rect* ) DECL_ATTR( OX, int ) DECL_ATTR( OY, int ) @@ -54,6 +56,11 @@ private: void onGeometryChange(const Geometry &); bool isEffectiveViewport(Rect *&, Color *&, Tone *&) const; + void releaseResources(); + const char *klassName() const { return "viewport"; } + + ABOUT_TO_ACCESS_DISP + ViewportPrivate *p; friend struct ViewportPrivate; diff --git a/src/window.cpp b/src/window.cpp index 1d43d95..9ba18c7 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -169,10 +169,8 @@ struct QuadChunk struct WindowPrivate { Bitmap *windowskin; - DisposeWatch windowskinWatch; Bitmap *contents; - DisposeWatch contentsWatch; bool bgStretch; Rect *cursorRect; @@ -226,6 +224,8 @@ struct WindowPrivate { unlink(); } + + ABOUT_TO_ACCESS_NOOP }; WindowControls controlsElement; @@ -250,9 +250,7 @@ struct WindowPrivate WindowPrivate(Viewport *viewport = 0) : windowskin(0), - windowskinWatch(*this, windowskin), contents(0), - contentsWatch(*this, contents, &WindowPrivate::markControlVertDirty), bgStretch(true), cursorRect(&tmp.rect), active(true), @@ -550,7 +548,7 @@ struct WindowPrivate void drawBase() { - if (!windowskin) + if (nullOrDisposed(windowskin)) return; if (size == Vec2i(0, 0)) @@ -584,7 +582,7 @@ struct WindowPrivate void drawControls() { - if (!windowskin && !contents) + if (nullOrDisposed(windowskin) && nullOrDisposed(contents)) return; if (size == Vec2i(0, 0)) @@ -612,7 +610,7 @@ struct WindowPrivate shader.bind(); shader.applyViewportProj(); - if (windowskin) + if (!nullOrDisposed(windowskin)) { shader.setTranslation(Vec2i(effectX, effectY)); @@ -625,7 +623,7 @@ struct WindowPrivate TEX::setSmooth(false); } - if (contents) + if (!nullOrDisposed(contents)) { /* Draw contents bitmap */ glState.scissorBox.setIntersect(contentsRect); @@ -692,15 +690,13 @@ Window::Window(Viewport *viewport) Window::~Window() { - p->controlsElement.release(); - - unlink(); - - delete p; + dispose(); } void Window::update() { + guardDisposed(); + p->updateControls(); p->stepAnimations(); } @@ -725,8 +721,9 @@ DEF_ATTR_OBJ_VALUE(Window, CursorRect, Rect*, p->cursorRect) void Window::setWindowskin(Bitmap *value) { + guardDisposed(); + p->windowskin = value; - p->windowskinWatch.update(value); if (!value) return; @@ -736,11 +733,12 @@ void Window::setWindowskin(Bitmap *value) void Window::setContents(Bitmap *value) { + guardDisposed(); + if (p->contents == value) return; p->contents = value; - p->contentsWatch.update(value); p->controlsVertDirty = true; if (!value) @@ -752,6 +750,8 @@ void Window::setContents(Bitmap *value) void Window::setStretch(bool value) { + guardDisposed(); + if (value == p->bgStretch) return; @@ -761,6 +761,8 @@ void Window::setStretch(bool value) void Window::setActive(bool value) { + guardDisposed(); + if (p->active == value) return; @@ -770,6 +772,8 @@ void Window::setActive(bool value) void Window::setPause(bool value) { + guardDisposed(); + if (p->pause == value) return; @@ -781,6 +785,8 @@ void Window::setPause(bool value) void Window::setWidth(int value) { + guardDisposed(); + if (p->size.x == value) return; @@ -790,6 +796,8 @@ void Window::setWidth(int value) void Window::setHeight(int value) { + guardDisposed(); + if (p->size.y == value) return; @@ -799,6 +807,8 @@ void Window::setHeight(int value) void Window::setOX(int value) { + guardDisposed(); + if (p->contentsOffset.x == value) return; @@ -808,6 +818,8 @@ void Window::setOX(int value) void Window::setOY(int value) { + guardDisposed(); + if (p->contentsOffset.y == value) return; @@ -817,6 +829,8 @@ void Window::setOY(int value) void Window::setOpacity(int value) { + guardDisposed(); + if (p->opacity == value) return; @@ -826,6 +840,8 @@ void Window::setOpacity(int value) void Window::setBackOpacity(int value) { + guardDisposed(); + if (p->backOpacity == value) return; @@ -835,6 +851,8 @@ void Window::setBackOpacity(int value) void Window::setContentsOpacity(int value) { + guardDisposed(); + if (p->contentsOpacity == value) return; @@ -878,3 +896,12 @@ void Window::onViewportChange() { p->controlsElement.setScene(*this->scene); } + +void Window::releaseResources() +{ + p->controlsElement.release(); + + unlink(); + + delete p; +} diff --git a/src/window.h b/src/window.h index a3fb315..f7cfc04 100644 --- a/src/window.h +++ b/src/window.h @@ -67,6 +67,11 @@ private: void setVisible(bool value); void onViewportChange(); + + void releaseResources(); + const char *klassName() const { return "window"; } + + ABOUT_TO_ACCESS_DISP }; #endif // WINDOW_H diff --git a/src/windowvx.cpp b/src/windowvx.cpp index 399e7b0..9b7fd13 100644 --- a/src/windowvx.cpp +++ b/src/windowvx.cpp @@ -148,15 +148,11 @@ static const uint8_t pauseQuad[] = static elementsN(pauseQuad); -typedef DisposeWatch BitmapWatch; - struct WindowVXPrivate { Bitmap *windowskin; - BitmapWatch windowskinWatch; Bitmap *contents; - BitmapWatch contentsWatch; Rect *cursorRect; bool active; @@ -227,9 +223,7 @@ struct WindowVXPrivate WindowVXPrivate(int x, int y, int w, int h) : windowskin(0), - windowskinWatch(*this, windowskin), contents(0), - contentsWatch(*this, contents), cursorRect(&tmp.rect), active(true), arrowsVisible(true), @@ -401,7 +395,7 @@ struct WindowVXPrivate void redrawBaseTex() { - if (!windowskin) + if (nullOrDisposed(windowskin)) return; if (base.tex.tex == TEX::ID(0)) @@ -514,7 +508,7 @@ struct WindowVXPrivate size_t i = 0; Vertex *vert = &ctrlVert.vertices[0]; - if (contents && arrowsVisible) + if (!nullOrDisposed(contents) && arrowsVisible) { if (contentsOff.x > 0) i += Quad::setTexPosRect(&vert[i*4], scrollArrowSrc.l, arrowPos.l); @@ -721,6 +715,9 @@ struct WindowVXPrivate if (base.tex.tex == TEX::ID(0)) return; + bool windowskinValid = !nullOrDisposed(windowskin); + bool contentsValid = !nullOrDisposed(contents); + Vec2i trans(geo.x + sceneOffset.x, geo.y + sceneOffset.y); @@ -728,7 +725,7 @@ struct WindowVXPrivate shader.bind(); shader.applyViewportProj(); - if (windowskin) + if (windowskinValid) { shader.setTranslation(trans); shader.setTexSize(Vec2i(base.tex.width, base.tex.height)); @@ -749,9 +746,9 @@ struct WindowVXPrivate if (openness < 255) return; - bool drawCursor = cursorVert.count() > 0 && windowskin; + bool drawCursor = cursorVert.count() > 0 && windowskinValid; - if (drawCursor || contents) + if (drawCursor || contentsValid) { /* Translate cliprect from local into screen space */ IntRect clip = clipRect; @@ -789,7 +786,7 @@ struct WindowVXPrivate TEX::setSmooth(false); } - if (contents) + if (contentsValid) { if (rgssVer <= 2) glState.scissorBox.setIntersect(clip); @@ -828,13 +825,13 @@ WindowVX::WindowVX(int x, int y, int width, int height) WindowVX::~WindowVX() { - unlink(); - - delete p; + dispose(); } void WindowVX::update() { + guardDisposed(); + p->stepAnimations(); p->updatePauseQuad(); @@ -843,6 +840,8 @@ void WindowVX::update() void WindowVX::move(int x, int y, int width, int height) { + guardDisposed(); + p->width = width; p->height = height; @@ -857,11 +856,15 @@ void WindowVX::move(int x, int y, int width, int height) bool WindowVX::isOpen() const { + guardDisposed(); + return p->openness == 255; } bool WindowVX::isClosed() const { + guardDisposed(); + return p->openness == 0; } @@ -889,21 +892,23 @@ DEF_ATTR_OBJ_VALUE(WindowVX, Tone, Tone*, p->tone) void WindowVX::setWindowskin(Bitmap *value) { + guardDisposed(); + if (p->windowskin == value) return; p->windowskin = value; - p->windowskinWatch.update(value); p->base.texDirty = true; } void WindowVX::setContents(Bitmap *value) { + guardDisposed(); + if (p->contents == value) return; p->contents = value; - p->contentsWatch.update(value); FloatRect rect = p->contents->rect(); p->contentsQuad.setTexPosRect(rect, rect); @@ -912,6 +917,8 @@ void WindowVX::setContents(Bitmap *value) void WindowVX::setActive(bool value) { + guardDisposed(); + if (p->active == value) return; @@ -922,6 +929,8 @@ void WindowVX::setActive(bool value) void WindowVX::setArrowsVisible(bool value) { + guardDisposed(); + if (p->arrowsVisible == value) return; @@ -931,6 +940,8 @@ void WindowVX::setArrowsVisible(bool value) void WindowVX::setPause(bool value) { + guardDisposed(); + if (p->pause == value) return; @@ -942,6 +953,8 @@ void WindowVX::setPause(bool value) void WindowVX::setWidth(int value) { + guardDisposed(); + if (p->width == value) return; @@ -956,6 +969,8 @@ void WindowVX::setWidth(int value) void WindowVX::setHeight(int value) { + guardDisposed(); + if (p->height == value) return; @@ -970,6 +985,8 @@ void WindowVX::setHeight(int value) void WindowVX::setOX(int value) { + guardDisposed(); + if (p->contentsOff.x == value) return; @@ -979,6 +996,8 @@ void WindowVX::setOX(int value) void WindowVX::setOY(int value) { + guardDisposed(); + if (p->contentsOff.y == value) return; @@ -988,6 +1007,8 @@ void WindowVX::setOY(int value) void WindowVX::setPadding(int value) { + guardDisposed(); + if (p->padding == value) return; @@ -998,6 +1019,8 @@ void WindowVX::setPadding(int value) void WindowVX::setPaddingBottom(int value) { + guardDisposed(); + if (p->paddingBottom == value) return; @@ -1007,6 +1030,8 @@ void WindowVX::setPaddingBottom(int value) void WindowVX::setOpacity(int value) { + guardDisposed(); + if (p->opacity == value) return; @@ -1016,6 +1041,8 @@ void WindowVX::setOpacity(int value) void WindowVX::setBackOpacity(int value) { + guardDisposed(); + if (p->backOpacity == value) return; @@ -1025,6 +1052,8 @@ void WindowVX::setBackOpacity(int value) void WindowVX::setContentsOpacity(int value) { + guardDisposed(); + if (p->contentsOpacity == value) return; @@ -1034,6 +1063,8 @@ void WindowVX::setContentsOpacity(int value) void WindowVX::setOpenness(int value) { + guardDisposed(); + if (p->openness == value) return; @@ -1063,3 +1094,10 @@ void WindowVX::onGeometryChange(const Scene::Geometry &geo) p->sceneOffset.x = geo.rect.x - geo.xOrigin; p->sceneOffset.y = geo.rect.y - geo.yOrigin; } + +void WindowVX::releaseResources() +{ + unlink(); + + delete p; +} diff --git a/src/windowvx.h b/src/windowvx.h index d90840f..d0e1eca 100644 --- a/src/windowvx.h +++ b/src/windowvx.h @@ -73,6 +73,11 @@ private: void draw(); void onGeometryChange(const Scene::Geometry &); + + void releaseResources(); + const char *klassName() const { return "window"; } + + ABOUT_TO_ACCESS_DISP }; #endif // WINDOWVX_H