Skip to content

Commit 67926b1

Browse files
committed
Use signals to dispose of the children of Viewports in RGSS1
The weak references method was throwing errors if the object id had already been recycled
1 parent edb3f83 commit 67926b1

File tree

5 files changed

+26
-132
lines changed

5 files changed

+26
-132
lines changed

binding/disposable-binding.h

-102
Original file line numberDiff line numberDiff line change
@@ -26,100 +26,6 @@
2626
#include "binding-util.h"
2727
#include "graphics.h"
2828

29-
/* 'Children' are disposables that are disposed together
30-
* with their parent. Currently this is only used by Viewport
31-
* in RGSS1. */
32-
inline void
33-
disposableAddChild(VALUE disp, VALUE child)
34-
{
35-
GFX_LOCK;
36-
if (NIL_P(disp) || NIL_P(child)) {
37-
return;
38-
}
39-
40-
VALUE objID = rb_obj_id(child);
41-
42-
VALUE children = rb_iv_get(disp, "children");
43-
44-
bool exists = false;
45-
46-
if (NIL_P(children))
47-
{
48-
children = rb_ary_new();
49-
rb_iv_set(disp, "children", children);
50-
}
51-
else {
52-
exists = RTEST(rb_funcall(children, rb_intern("include?"), 1, objID));
53-
}
54-
55-
if (!exists) {
56-
rb_ary_push(children, objID);
57-
VALUE objectspace = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
58-
VALUE method = rb_funcall(disp, rb_intern("method"), 1, rb_id2sym(rb_intern("_sprite_finalizer")));
59-
rb_funcall(objectspace, rb_intern("define_finalizer"), 2, child, method);
60-
}
61-
GFX_UNLOCK;
62-
}
63-
64-
inline void
65-
disposableRemoveChild(VALUE disp, VALUE child)
66-
{
67-
GFX_LOCK;
68-
if (NIL_P(disp) || NIL_P(child)) {
69-
return;
70-
}
71-
72-
VALUE objID = rb_obj_id(child);
73-
74-
VALUE children = rb_iv_get(disp, "children");
75-
if (NIL_P(children))
76-
return;
77-
78-
VALUE index = rb_funcall(children, rb_intern("index"), 1, objID);
79-
if (NIL_P(index))
80-
return;
81-
82-
rb_funcall(children, rb_intern("delete_at"), 1, index);
83-
GFX_UNLOCK;
84-
}
85-
86-
inline void
87-
disposableForgetChild(VALUE disp, VALUE child)
88-
{
89-
VALUE children = rb_iv_get(disp, "children");
90-
91-
if (NIL_P(children)) {
92-
return;
93-
}
94-
95-
VALUE index = rb_funcall(children, rb_intern("index"), 1, child);
96-
if (NIL_P(index)) {
97-
return;
98-
}
99-
100-
rb_funcall(children, rb_intern("delete_at"), 1, index);
101-
}
102-
103-
inline void
104-
disposableDisposeChildren(VALUE disp)
105-
{
106-
VALUE children = rb_iv_get(disp, "children");
107-
108-
if (NIL_P(children))
109-
return;
110-
111-
for (long i = 0; i < RARRAY_LEN(children); ++i) {
112-
int state;
113-
rb_protect([](VALUE args){
114-
VALUE objectspace = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
115-
VALUE ref = rb_funcall(objectspace, rb_intern("_id2ref"), 1, args);
116-
rb_funcall(ref, rb_intern("_mkxp_dispose_alias"), 0);
117-
return Qnil;
118-
}, rb_ary_entry(children, i), &state);
119-
}
120-
//rb_funcall2(rb_ary_entry(children, i), dispFun, 0, 0);
121-
}
122-
12329
template<class C>
12430
RB_METHOD(disposableDispose)
12531
{
@@ -134,9 +40,6 @@ RB_METHOD(disposableDispose)
13440
if (d->isDisposed())
13541
return Qnil;
13642

137-
if (rgssVer == 1)
138-
disposableDisposeChildren(self);
139-
14043
GFX_LOCK;
14144
d->dispose();
14245
GFX_UNLOCK;
@@ -162,11 +65,6 @@ static void disposableBindingInit(VALUE klass)
16265
{
16366
_rb_define_method(klass, "dispose", disposableDispose<C>);
16467
_rb_define_method(klass, "disposed?", disposableIsDisposed<C>);
165-
166-
/* Make sure we always have access to the original method, even
167-
* if it is overridden by user scripts */
168-
if (rgssVer == 1)
169-
rb_define_alias(klass, "_mkxp_dispose_alias", "dispose");
17068
}
17169

17270
template<class C>

binding/viewport-binding.cpp

-20
Original file line numberDiff line numberDiff line change
@@ -68,29 +68,10 @@ RB_METHOD(viewportInitialize) {
6868
wrapProperty(self, &v->getColor(), "color", ColorType);
6969
wrapProperty(self, &v->getTone(), "tone", ToneType);
7070

71-
/* 'elements' holds all SceneElements that become children
72-
* of this viewport, so we can dispose them when the viewport
73-
* is disposed */
74-
rb_iv_set(self, "elements", rb_ary_new());
7571
GFX_UNLOCK;
7672
return self;
7773
}
7874

79-
RB_METHOD(viewportSpriteFinalize)
80-
{
81-
RB_UNUSED_PARAM;
82-
83-
VALUE objectid;
84-
85-
rb_get_args(argc, argv, "o", &objectid RB_ARG_END);
86-
87-
if (rgssVer == 1) {
88-
disposableForgetChild(self, objectid);
89-
}
90-
91-
return Qnil;
92-
}
93-
9475
DEF_GFX_PROP_OBJ_VAL(Viewport, Rect, Rect, "rect")
9576
DEF_GFX_PROP_OBJ_VAL(Viewport, Color, Color, "color")
9677
DEF_GFX_PROP_OBJ_VAL(Viewport, Tone, Tone, "tone")
@@ -111,7 +92,6 @@ void viewportBindingInit() {
11192
sceneElementBindingInit<Viewport>(klass);
11293

11394
_rb_define_method(klass, "initialize", viewportInitialize);
114-
_rb_define_method(klass, "_sprite_finalizer", viewportSpriteFinalize);
11595

11696
INIT_PROP_BIND(Viewport, Rect, "rect");
11797
INIT_PROP_BIND(Viewport, OX, "ox");

binding/viewportelement-binding.h

-9
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,6 @@ RB_METHOD(viewportElementSetViewport)
5555

5656
if (!NIL_P(viewportObj))
5757
viewport = getPrivateDataCheck<Viewport>(viewportObj, ViewportType);
58-
59-
if (rgssVer == 1) {
60-
VALUE vp = viewportElementGetViewport<C>(0, 0, self);
61-
disposableRemoveChild(vp, self);
62-
disposableAddChild(viewportObj, self);
63-
}
6458

6559
GFX_GUARD_EXC( ve->setViewport(viewport); );
6660

@@ -82,9 +76,6 @@ viewportElementInitialize(int argc, VALUE *argv, VALUE self)
8276
if (!NIL_P(viewportObj))
8377
{
8478
viewport = getPrivateDataCheck<Viewport>(viewportObj, ViewportType);
85-
86-
if (rgssVer == 1)
87-
disposableAddChild(viewportObj, self);
8879
}
8980

9081
GFX_LOCK;

src/display/viewport.cpp

+22-1
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,10 @@ void Viewport::releaseResources()
232232
ViewportElement::ViewportElement(Viewport *viewport, int z, int spriteY)
233233
: SceneElement(viewport ? *viewport : *shState->screen(), z, spriteY),
234234
m_viewport(viewport)
235-
{}
235+
{
236+
if (rgssVer == 1 && viewport)
237+
viewportDispCon = viewport->wasDisposed.connect(&ViewportElement::viewportElementDisposal, this);
238+
}
236239

237240
Viewport *ViewportElement::getViewport() const
238241
{
@@ -242,7 +245,25 @@ Viewport *ViewportElement::getViewport() const
242245
void ViewportElement::setViewport(Viewport *viewport)
243246
{
244247
m_viewport = viewport;
248+
249+
viewportDispCon.disconnect();
250+
if (rgssVer == 1 && viewport)
251+
viewportDispCon = viewport->wasDisposed.connect(&ViewportElement::viewportElementDisposal, this);
252+
245253
setScene(viewport ? *viewport : *shState->screen());
246254
onViewportChange();
247255
onGeometryChange(scene->getGeometry());
248256
}
257+
258+
void ViewportElement::viewportElementDisposal()
259+
{
260+
viewportDispCon.disconnect();
261+
Disposable *self = dynamic_cast<Disposable*>(this);
262+
if(self != nullptr)
263+
self->dispose();
264+
}
265+
266+
ViewportElement::~ViewportElement()
267+
{
268+
viewportDispCon.disconnect();
269+
}

src/display/viewport.h

+4
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class ViewportElement : public SceneElement
7171
{
7272
public:
7373
ViewportElement(Viewport *viewport = 0, int z = 0, int spriteY = 0);
74+
~ViewportElement();
7475

7576
DECL_ATTR( Viewport, Viewport* )
7677

@@ -79,6 +80,9 @@ class ViewportElement : public SceneElement
7980

8081
private:
8182
Viewport *m_viewport;
83+
sigslot::connection viewportDispCon;
84+
sigslot::connection viewportElementDispCon;
85+
void viewportElementDisposal();
8286
};
8387

8488
#endif // VIEWPORT_H

0 commit comments

Comments
 (0)