Merge pull request #149 from WaywardHeart/viewportDisposablesRGSS1

Use signals to dispose of the children of Viewports in RGSS1
This commit is contained in:
Splendide Imaginarius 2024-04-29 20:51:10 +00:00 committed by GitHub
commit 89801da619
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 26 additions and 132 deletions

View file

@ -26,100 +26,6 @@
#include "binding-util.h"
#include "graphics.h"
/* 'Children' are disposables that are disposed together
* with their parent. Currently this is only used by Viewport
* in RGSS1. */
inline void
disposableAddChild(VALUE disp, VALUE child)
{
GFX_LOCK;
if (NIL_P(disp) || NIL_P(child)) {
return;
}
VALUE objID = rb_obj_id(child);
VALUE children = rb_iv_get(disp, "children");
bool exists = false;
if (NIL_P(children))
{
children = rb_ary_new();
rb_iv_set(disp, "children", children);
}
else {
exists = RTEST(rb_funcall(children, rb_intern("include?"), 1, objID));
}
if (!exists) {
rb_ary_push(children, objID);
VALUE objectspace = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
VALUE method = rb_funcall(disp, rb_intern("method"), 1, rb_id2sym(rb_intern("_sprite_finalizer")));
rb_funcall(objectspace, rb_intern("define_finalizer"), 2, child, method);
}
GFX_UNLOCK;
}
inline void
disposableRemoveChild(VALUE disp, VALUE child)
{
GFX_LOCK;
if (NIL_P(disp) || NIL_P(child)) {
return;
}
VALUE objID = rb_obj_id(child);
VALUE children = rb_iv_get(disp, "children");
if (NIL_P(children))
return;
VALUE index = rb_funcall(children, rb_intern("index"), 1, objID);
if (NIL_P(index))
return;
rb_funcall(children, rb_intern("delete_at"), 1, index);
GFX_UNLOCK;
}
inline void
disposableForgetChild(VALUE disp, VALUE child)
{
VALUE children = rb_iv_get(disp, "children");
if (NIL_P(children)) {
return;
}
VALUE index = rb_funcall(children, rb_intern("index"), 1, child);
if (NIL_P(index)) {
return;
}
rb_funcall(children, rb_intern("delete_at"), 1, index);
}
inline void
disposableDisposeChildren(VALUE disp)
{
VALUE children = rb_iv_get(disp, "children");
if (NIL_P(children))
return;
for (long i = 0; i < RARRAY_LEN(children); ++i) {
int state;
rb_protect([](VALUE args){
VALUE objectspace = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
VALUE ref = rb_funcall(objectspace, rb_intern("_id2ref"), 1, args);
rb_funcall(ref, rb_intern("_mkxp_dispose_alias"), 0);
return Qnil;
}, rb_ary_entry(children, i), &state);
}
//rb_funcall2(rb_ary_entry(children, i), dispFun, 0, 0);
}
template<class C>
RB_METHOD(disposableDispose)
{
@ -134,9 +40,6 @@ RB_METHOD(disposableDispose)
if (d->isDisposed())
return Qnil;
if (rgssVer == 1)
disposableDisposeChildren(self);
GFX_LOCK;
d->dispose();
GFX_UNLOCK;
@ -162,11 +65,6 @@ static void disposableBindingInit(VALUE klass)
{
_rb_define_method(klass, "dispose", disposableDispose<C>);
_rb_define_method(klass, "disposed?", disposableIsDisposed<C>);
/* Make sure we always have access to the original method, even
* if it is overridden by user scripts */
if (rgssVer == 1)
rb_define_alias(klass, "_mkxp_dispose_alias", "dispose");
}
template<class C>

View file

@ -68,29 +68,10 @@ RB_METHOD(viewportInitialize) {
wrapProperty(self, &v->getColor(), "color", ColorType);
wrapProperty(self, &v->getTone(), "tone", ToneType);
/* 'elements' holds all SceneElements that become children
* of this viewport, so we can dispose them when the viewport
* is disposed */
rb_iv_set(self, "elements", rb_ary_new());
GFX_UNLOCK;
return self;
}
RB_METHOD(viewportSpriteFinalize)
{
RB_UNUSED_PARAM;
VALUE objectid;
rb_get_args(argc, argv, "o", &objectid RB_ARG_END);
if (rgssVer == 1) {
disposableForgetChild(self, objectid);
}
return Qnil;
}
DEF_GFX_PROP_OBJ_VAL(Viewport, Rect, Rect, "rect")
DEF_GFX_PROP_OBJ_VAL(Viewport, Color, Color, "color")
DEF_GFX_PROP_OBJ_VAL(Viewport, Tone, Tone, "tone")
@ -111,7 +92,6 @@ void viewportBindingInit() {
sceneElementBindingInit<Viewport>(klass);
_rb_define_method(klass, "initialize", viewportInitialize);
_rb_define_method(klass, "_sprite_finalizer", viewportSpriteFinalize);
INIT_PROP_BIND(Viewport, Rect, "rect");
INIT_PROP_BIND(Viewport, OX, "ox");

View file

@ -55,12 +55,6 @@ RB_METHOD(viewportElementSetViewport)
if (!NIL_P(viewportObj))
viewport = getPrivateDataCheck<Viewport>(viewportObj, ViewportType);
if (rgssVer == 1) {
VALUE vp = viewportElementGetViewport<C>(0, 0, self);
disposableRemoveChild(vp, self);
disposableAddChild(viewportObj, self);
}
GFX_GUARD_EXC( ve->setViewport(viewport); );
@ -82,9 +76,6 @@ viewportElementInitialize(int argc, VALUE *argv, VALUE self)
if (!NIL_P(viewportObj))
{
viewport = getPrivateDataCheck<Viewport>(viewportObj, ViewportType);
if (rgssVer == 1)
disposableAddChild(viewportObj, self);
}
GFX_LOCK;

View file

@ -232,7 +232,10 @@ void Viewport::releaseResources()
ViewportElement::ViewportElement(Viewport *viewport, int z, int spriteY)
: SceneElement(viewport ? *viewport : *shState->screen(), z, spriteY),
m_viewport(viewport)
{}
{
if (rgssVer == 1 && viewport)
viewportDispCon = viewport->wasDisposed.connect(&ViewportElement::viewportElementDisposal, this);
}
Viewport *ViewportElement::getViewport() const
{
@ -242,7 +245,25 @@ Viewport *ViewportElement::getViewport() const
void ViewportElement::setViewport(Viewport *viewport)
{
m_viewport = viewport;
viewportDispCon.disconnect();
if (rgssVer == 1 && viewport)
viewportDispCon = viewport->wasDisposed.connect(&ViewportElement::viewportElementDisposal, this);
setScene(viewport ? *viewport : *shState->screen());
onViewportChange();
onGeometryChange(scene->getGeometry());
}
void ViewportElement::viewportElementDisposal()
{
viewportDispCon.disconnect();
Disposable *self = dynamic_cast<Disposable*>(this);
if(self != nullptr)
self->dispose();
}
ViewportElement::~ViewportElement()
{
viewportDispCon.disconnect();
}

View file

@ -71,6 +71,7 @@ class ViewportElement : public SceneElement
{
public:
ViewportElement(Viewport *viewport = 0, int z = 0, int spriteY = 0);
~ViewportElement();
DECL_ATTR( Viewport, Viewport* )
@ -79,6 +80,9 @@ protected:
private:
Viewport *m_viewport;
sigslot::connection viewportDispCon;
sigslot::connection viewportElementDispCon;
void viewportElementDisposal();
};
#endif // VIEWPORT_H