Quick Links: Download Gideros Studio | Gideros Documentation | Ultimate Guide | Gideros Development Center
iCade plugin - Gideros Forum

iCade plugin

MagnusviriMagnusviri Member
edited March 2012 in Plugins
I have not tested this one bit or even tried to compile it. This is what I came up with by looking at the storekit, gamekit, and uikit plugins.

If anyone has any comments or corrections by just looking (I don't exactly expect anyone to test it for me), I'd appreciate it.

@Caroline, you are hosting the MHUIKit plugin. I've never used GitHub so I was thinking maybe you would like to host this? I also noticed that you seem to be the plugin expert, so you would be a perfect choice to host this! ;)

EDITS:

Fixed a bug

Included usage

This requires the 3 files at the following URL:
https://github.com/scarnie/iCade-iOS/tree/master/iCadeTest/iCade

And this will require some lua code to interpret the events. I'll write some code to do that tomorrow.

/*

This code is MIT licensed, see http://www.opensource.org/licenses/mit-license.php

Events:
iCadeStateChanged
iCadeButtonUp
iCadeButtonDown

Each event has an int that contains the state of the icade: event.state. The values of the state variable are shown in iCadeState.h (see https://github.com/scarnie/iCade-iOS/tree/master/iCadeTest/iCade)

Methods:
BOOL isActive()
setActive(BOOL)
int iCadeState()

*/

#include "gideros.h"
#include "lua.h"
#include "lauxlib.h"

#import "iCadeReaderView.h"

static const char KEY_OBJECTS = ' ';

static const char* STATE_CHANGED = "iCadeStateChanged";
static const char* BUTTON_UP = "iCadeButtonUp";
static const char* BUTTON_DOWN = "iCadeButtonDown";

static void dispatchEvent(lua_State* L, const char* type,
(iCadeState) state)
{
lua_pushlightuserdata(L, (void *)&KEY_OBJECTS);
lua_rawget(L, LUA_REGISTRYINDEX);

lua_rawgeti(L, -1, 1);

if (lua_isnil(L, -1))
{
lua_pop(L, 2);
return;
}

lua_getfield(L, -1, "dispatchEvent");

lua_pushvalue(L, -2);

lua_getglobal(L, "Event");
lua_getfield(L, -1, "new");
lua_remove(L, -2);
lua_pushstring(L, type);
lua_call(L, 1, 1);

lua_pushinteger(L, state);
lua_setfield(L, -2, "state");

if (lua_pcall(L, 2, 0, 0) != 0)
g_error(L, lua_tostring(L, -1));

lua_pop(L, 2);
}

@interface iCadeHelper : NSObject
iCadeReaderView* control;
lua_State* L;
@end

@implementation iCadeHelper
- (id)initWithLuaState:(lua_State *)theL
{
if (self = [super init])
{
L = theL;
control = [[iCadeReaderView alloc] initWithFrame:CGRectZero];
control.active = YES;
control.delegate = self;
UIViewController* controller = g_getRootViewController();
[controller.view addSubview:control];
}
return self;
}
- (void)dealloc {
[control removeFromSuperview];
[control release];
}
- (void)setActive:(BOOL)state {
control.active = state;
}
- (BOOL)isActive {
return control.active;
}
- (iCadeState)iCadeState {
return control.iCadeState;
}
- (void)stateChanged:(iCadeState)state {
dispatchEvent(L, STATE_CHANGED, state);
}
- (void)buttonDown:(iCadeState)button {
dispatchEvent(L, BUTTON_DOWN, button);
}
- (void)buttonUp:(iCadeState)button {
dispatchEvent(L, BUTTON_UP, button);
}

@end

class iCade : public GEventDispatcherProxy
{
public:
iCade(lua_State* L) : L(L)
{
helper = [[iCadeHelper alloc] initWithLuaState:L];
}

~iCade()
{
[helper release];
}

BOOL isActive()
{
return [helper isActive];
}

void setActive(BOOL state)
{
[helper setActive:state];
}

iCadeState iCadeState()
{
return [helper iCadeState];
}

private:
lua_State* L;
iCadeHelper* helper;
};

static int destruct(lua_State* L)
{
void* ptr = *(void**)lua_touserdata(L, 1);
GReferenced* object = static_cast(ptr);
iCade* icade = static_cast(object->proxy());

icade->unref();

return 0;
}

static iCade* getInstance(lua_State* L, int index)
{
GReferenced* object = static_cast(g_getInstance(L, "iCade", index));
iCade* icade = static_cast(object->proxy());

return icade;
}

static int isActive(lua_State* L)
{
iCade* icade = getInstance(L, 1);

lua_pushboolean(L, icade->isActive());

return 1;
}

static int setActive(lua_State* L)
{
iCade* icade = getInstance(L, 1);
bool state = lua_toboolean(L, 2);
icade->setActive(state);

return 0;
}

static int iCadeState(lua_State* L)
{
iCade* icade = getInstance(L, 1);

lua_pushinteger(L, icade->iCadeState());

return 1;
}

static int loader(lua_State* L)
{
const luaL_Reg functionlist[] = {
{"isActive", isActive},
{"setActive", setActive},
{"iCadeState", iCadeState},
{NULL, NULL},
};

g_createClass(L, "iCade", "EventDispatcher", NULL, destruct, functionlist);

lua_getglobal(L, "Event");
lua_pushstring(L, STATE_CHANGED);
lua_setfield(L, -2, "STATE_CHANGED");
lua_pushstring(L, BUTTON_UP);
lua_setfield(L, -2, "BUTTON_UP");
lua_pushstring(L, BUTTON_DOWN);
lua_setfield(L, -2, "BUTTON_DOWN");
lua_pop(L, 1);

// create a weak table in LUA_REGISTRYINDEX that can be accessed with the address of KEY_OBJECTS
lua_pushlightuserdata(L, (void *)&KEY_OBJECTS);
lua_newtable(L); // create a table
lua_pushliteral(L, "v");
lua_setfield(L, -2, "__mode"); // set as weak-value table
lua_pushvalue(L, -1); // duplicate table
lua_setmetatable(L, -2); // set itself as metatable
lua_rawset(L, LUA_REGISTRYINDEX);

iCade* icade = new iCade(L);
g_pushInstance(L, "iCade", icade->object());

lua_pushlightuserdata(L, (void *)&KEY_OBJECTS);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushvalue(L, -2);
lua_rawseti(L, -2, 1);
lua_pop(L, 1);

lua_pushvalue(L, -1);
lua_setglobal(L, "icade");

return 1;
}

static void g_initializePlugin(lua_State* L)
{
lua_getglobal(L, "package");
lua_getfield(L, -1, "preload");

lua_pushcfunction(L, loader);
lua_setfield(L, -2, "icade");

lua_pop(L, 2);
}

static void g_deinitializePlugin(lua_State *L)
{

}

REGISTER_PLUGIN("iCade", "1.0")

Comments

  • 1. I'm just a wannabe plugin expert - I have to have 3 hours of uninterrupted concentration and a lot of stack dumps to do anything with them.

    2. It feels to me that the dispatch function is wrong - it should be in the iCade class - I think that you are looking up "dispatchEvent" in a table where it doesn't exist. The iCade class descends from GEventDispatcherProxy, which allows it to dispatch events. (See gamekit.mm for example)

    3. I would be happy to host when it's more fully tested, although I had not used github before, so am no expert. However, you could work out how to host in under an hour - there's even a github app if you don't like working through Terminal. Then it's easier for you to make changes - if this is something that you're working on, it makes more sense for you to host.

    4. Some things might be wrong (not sure, just put into Xcode, compiled, and picked the obvious things)

    needs - #import "iCadeState.h"

    static void dispatchEvent(lua_State* L, const char* type, (iCadeState) state)
    should be
    static void dispatchEvent(lua_State* L, const char* type, iCadeState state)

    @interface iCadeHelper : NSObject
    should be
    @interface iCadeHelper : NSObject < iCadeEventDelegate >

    and you need { } around the @interface variables.

    You don't need the dealloc if you release the view after addSubview, and if you have dealloc, you need [super dealloc] (unless you are using ARC, in which case you don't have to worry about releases).

    You can't have a function called iCadeState, as it's already defined in iCadeState.h

    Your destruct and getInstance needs to have a <> casting as in:
    GReferenced* object = static_cast< GReferenced* >(ptr);
    iCade* icade = static_cast< iCade* >(object->proxy());

    I haven't gone through the lua stack stuff, so not sure if you've got that right. I tend to that by trial and stack dump.
    +1 -1
  • I forgot to say, that I'm impressed so far, and would love to see this working on your iCade.
    (Wants...)
    +1 -1
  • @Caroline, thanks, those were most of the compile bugs. I can't get the iCadeReaderView to work. It isn't getting text events. Something to do with firstResponder. I'll have to look at it more tomorrow.
    +1 -1
Sign In or Register to comment.