Skip to content

Commit

Permalink
yes, I'm still working on #ShinyCocos
Browse files Browse the repository at this point in the history
  • Loading branch information
Rolando Abarca committed Apr 13, 2010
1 parent 7a80739 commit 9ebda7f
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 46 deletions.
90 changes: 65 additions & 25 deletions Integration/SC_CocosNode.m
Expand Up @@ -28,6 +28,19 @@
#import "rb_chipmunk.h"

VALUE rb_cCocosNode;
ccHashSet *scheduledMethods;

typedef struct hashMethod_ {
VALUE object;
VALUE methods;
} hashMethod;

static int scheduledMethodsEql(void *ptr, void *elt)
{
hashMethod *first = (hashMethod *)ptr;
hashMethod *second = (hashMethod *)elt;
return (first->object == second->object);
}

#pragma mark CocosNode extension

Expand Down Expand Up @@ -70,6 +83,7 @@ @interface CocosNode (SC_Extension)
- (void)rb_on_enter;
- (void)rb_on_enter_transition_did_finish;
- (void)rb_on_exit;
- (void)rb_dealloc;
- (void)rb_draw;

// chipmunk support
Expand Down Expand Up @@ -123,6 +137,20 @@ - (void)rb_on_exit {
}
}

- (void)rb_dealloc {
[self rb_dealloc];
if (userData) {
// get rid of scheduledMethods if any
hashMethod tmpMethod;
tmpMethod.object = (VALUE)userData;
hashMethod *methods = ccHashSetFind(scheduledMethods, CC_HASH_INT(userData), &tmpMethod);
if (methods) {
VALUE rb_methods = methods->methods;
rb_gc_unregister_address(&rb_methods);
}
}
}

- (void)rb_draw {
[self rb_draw];
if (userData) {
Expand Down Expand Up @@ -150,25 +178,19 @@ - (void)chipmunk_step:(ccTime)delta {
- (void)rbScheduler:(ccTime)delta {
if (!userData)
return;
VALUE methods = rb_ivar_get((VALUE)userData, id_sc_ivar_scheduled_methods);
if (methods != Qnil) {
hashMethod tmpMethod;
tmpMethod.object = (VALUE)userData;
hashMethod *methods = ccHashSetFind(scheduledMethods, CC_HASH_INT(userData), &tmpMethod);
if (methods) {
int i;
VALUE rb_delta = rb_float_new(delta);
tSCProtectWrapper *w = (tSCProtectWrapper *)malloc(sizeof(tSCProtectWrapper));
for (i=0; i < RARRAY_LEN(methods); i++) {
ID m_id = rb_to_id(RARRAY_PTR(methods)[i]);
// simulating thread_exclusive
/*
VALUE critical = rb_thread_critical;
rb_thread_critical = 1;
w->obj = (VALUE)userData;
w->method = m_id;
w->delta = rb_delta;
rb_ensure(sc_protect_wrapper, (VALUE)w, sc_set_critical, (VALUE)critical);
*/
VALUE rb_methods = methods->methods;
for (i=0; i < RARRAY_LEN(rb_methods); i++) {
ID m_id = rb_to_id(RARRAY_PTR(rb_methods)[i]);
sc_protect_funcall((VALUE)userData, m_id, 1, rb_delta);
}
free(w);
} else {
CCLOG(@"running scheduled method for %d, but no ary set?", userData);
}
}

Expand Down Expand Up @@ -745,13 +767,20 @@ VALUE rb_cCocosNode_attach_chipmunk_shape(VALUE object, VALUE rb_shape) {
*/
VALUE rb_cCocosNode_schedule(VALUE object, VALUE method) {
Check_Type(method, T_SYMBOL);
VALUE methods = rb_ivar_get(object, id_sc_ivar_scheduled_methods);
if (methods == Qnil) {
methods = rb_ary_new3(1, method);
rb_ivar_set(object, id_sc_ivar_scheduled_methods, methods);
hashMethod tmpMethod;
tmpMethod.object = (VALUE)object;
hashMethod *methods = (hashMethod *)ccHashSetFind(scheduledMethods, CC_HASH_INT(object), &tmpMethod);
if (!methods) {
CCLOG(@"**** inserting new scheduled method for object %d", object);
methods = (hashMethod *)malloc(sizeof(hashMethod));
methods->object = object;
VALUE rb_methods = rb_ary_new3(1, method);
methods->methods = rb_methods;
rb_gc_register_address(&rb_methods);
ccHashSetInsert(scheduledMethods, CC_HASH_INT(object), methods, nil);
[CC_NODE(object) schedule:@selector(rbScheduler:)];
} else {
rb_ary_push(methods, method);
rb_ary_push(methods->methods, method);
}

return object;
Expand All @@ -762,15 +791,23 @@ VALUE rb_cCocosNode_schedule(VALUE object, VALUE method) {
*/
VALUE rb_cCocosNode_unschedule(VALUE object, VALUE method) {
Check_Type(method, T_SYMBOL);
VALUE methods = rb_ivar_get(object, id_sc_ivar_scheduled_methods);
if (methods != Qnil) {
sc_protect_funcall(methods, id_sc_delete, 1, method);
hashMethod tmpMethod;
tmpMethod.object = (VALUE)object;
hashMethod *methods = (hashMethod *)ccHashSetFind(scheduledMethods, CC_HASH_INT(object), &tmpMethod);
if (methods) {
sc_protect_funcall(methods->methods, id_sc_delete, 1, method);
if (RARRAY_LEN(methods) == 0) {
// empty array, unschedule the ruby scheduler
[CC_NODE(object) unschedule:@selector(rbScheduler)];
// and remove the object from the hash
VALUE rb_methods = methods->methods;
rb_gc_unregister_address(&rb_methods);
ccHashSetRemove(scheduledMethods, CC_HASH_INT(object), methods);
free(methods);
}
return methods->methods;
}
return methods;
return Qnil;
}

/*
Expand Down Expand Up @@ -969,5 +1006,8 @@ void init_rb_cCocosNode() {
sc_method_swap([CocosNode class], @selector(onEnter), @selector(rb_on_enter));
sc_method_swap([CocosNode class], @selector(onEnterTransitionDidFinish), @selector(rb_on_enter_transition_did_finish));
sc_method_swap([CocosNode class], @selector(onExit), @selector(rb_on_exit));
// sc_method_swap([CocosNode class], @selector(draw), @selector(rb_draw)); // BUG
sc_method_swap([CocosNode class], @selector(dealloc), @selector(rb_dealloc));

// hash for scheduled methods
scheduledMethods = ccHashSetNew(20, scheduledMethodsEql);
}
10 changes: 1 addition & 9 deletions Integration/SC_init.m
Expand Up @@ -293,16 +293,8 @@ void Init_ShinyCocos() {
rb_define_const(rb_mCocos2D, "REACHABLE_VIA_WIFI_NETWORK", INT2FIX(ReachableViaWiFiNetwork));
}

void Init_encdb();
void Init_stringio();
void Init_syck();
void Init_zlib();
void Init_thread();
extern void Init_zlib();

void Init_SC_Ruby_Extensions() {
// Init_encdb();
// Init_stringio();
// Init_syck();
Init_zlib();
Init_thread();
}
20 changes: 10 additions & 10 deletions Integration/ShinyCocos.m
Expand Up @@ -37,17 +37,17 @@ void ShinyCocosSetup(NSString *devLibs) {
NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
NSString *rubyLib = [NSString stringWithFormat:@"%@/lib", resourcePath];
NSString *rubyVendor = [NSString stringWithFormat:@"%@/vendor", resourcePath];
NSString *entryPoint = [NSString stringWithFormat:@"%@/main.rb", resourcePath];
NSString *entryPoint = [NSString stringWithFormat:@"%@/main.rb", rubyVendor];

sc_argc = 2;
sc_argv = (char **)malloc(sizeof(char *) * 2);
sc_argv = (char **)malloc(sizeof(char *) * (sc_argc));
sc_argv[0] = "ShinyCocos";
sc_argv[1] = (char *)[entryPoint cStringUsingEncoding:NSUTF8StringEncoding];
sc_argv[1] = (char *)[entryPoint UTF8String];

// ruby_sysinit(&sc_argc, &sc_argv);
{
RUBY_INIT_STACK;
ruby_init();
ruby_options(sc_argc, sc_argv);
}

/* add the bundle resource path to the search path */
Expand All @@ -67,7 +67,7 @@ void ShinyCocosSetup(NSString *devLibs) {
extern void sc_require(char *fname);

void ShinyCocosStart(UIWindow *window, id appDelegate) {
int state;
int state_;
_appDelegate = appDelegate;
/* hide the top bar */
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];
Expand All @@ -77,15 +77,15 @@ void ShinyCocosStart(UIWindow *window, id appDelegate) {
[[Director sharedDirector] attachInWindow:window];
[window makeKeyAndVisible];

ruby_script("main.rb");
ruby_script("ShinyCocos"); // set the name script
// test for secure_require
if (rb_obj_respond_to(rb_mKernel, rb_intern("secure_require"), 0)) {
rb_protect(RUBY_METHOD_FUNC(sc_require), (VALUE)"main", &state);
rb_protect(RUBY_METHOD_FUNC(sc_require), (VALUE)"main", &state_);
} else {
rb_protect(RUBY_METHOD_FUNC(rb_require), (VALUE)"main", &state);
rb_protect(RUBY_METHOD_FUNC(rb_require), (VALUE)"main", &state_);
}
if (state != 0)
sc_error(state);
if (state_ != 0)
sc_error(state_);
}

void ShinyCocosInitChipmunk() {
Expand Down
8 changes: 6 additions & 2 deletions Template/vendor/main.rb
Expand Up @@ -18,5 +18,9 @@ def touches_ended(touches)
end
end

Cocos2D::Director.set_orientation Cocos2D::Director::ORIENTATION_LANDSCAPE_RIGHT
Cocos2D::Director.run_scene DemoScene.new
if $0 == "ShinyCocos"
Cocos2D::Director.set_orientation Cocos2D::Director::ORIENTATION_LANDSCAPE_RIGHT
Cocos2D::Director.run_scene DemoScene.new
else
$stderr.puts "This script should be run only from a ShinyCocos environment"
end

0 comments on commit 9ebda7f

Please sign in to comment.