New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

flixel' plugin system improvement #121

Closed
WingEraser opened this Issue Nov 13, 2012 · 13 comments

Comments

Projects
None yet
4 participants
@WingEraser

WingEraser commented Nov 13, 2012

I’ve been looking at the way how flixel manages the plugin system. There are two things I don’t feel right about it.

  1. TimerManager and DebugPathDisplay plugins are added during FlxG::init(). Shouldn’t plugins be added by the user itself? It’s just a waste to call update for plugins if you don’t even use it.
  2. FlxGame::switchState(), clears the TimerManager. It should be done generally by calling FlxG::removeAllPlugins or resetAllPlugins or something like that. Before you know a lot of custom plugins will be added to the flixel core.
@Dovyski

This comment has been minimized.

Show comment
Hide comment
@Dovyski

Dovyski Jan 15, 2013

Member

I think lots of improvements in the future can be implemented as plugins. A new plugin system will keep Flixel core simple, new (and more complex) plugins could be created, attracting more developers to help improve Flixel without touching (or deeply understanding) its core.

I really like how Wordpress plugins work. They are build on top of a hook/filter system, so they are really plugins (just drop the code and start using, no changes). Flixel plugins could be implemented like that: the core would call hooks at special points and any plugin "listening" to that hook could react accordingly.

How about that?

Member

Dovyski commented Jan 15, 2013

I think lots of improvements in the future can be implemented as plugins. A new plugin system will keep Flixel core simple, new (and more complex) plugins could be created, attracting more developers to help improve Flixel without touching (or deeply understanding) its core.

I really like how Wordpress plugins work. They are build on top of a hook/filter system, so they are really plugins (just drop the code and start using, no changes). Flixel plugins could be implemented like that: the core would call hooks at special points and any plugin "listening" to that hook could react accordingly.

How about that?

@WingEraser

This comment has been minimized.

Show comment
Hide comment
@WingEraser

WingEraser Feb 17, 2013

You want something like this:

FlxSprite::aMethod()
{
    preMethod, called before the actual code.

    the actual code + hookMethod, called inside the actual code.

    postMethod, called after the actual code.
}

Store all methods in an Array and also needs to check whether the mehod belongs to the Class::method().
(how does the bbcode in github works? Hehe Thanks @IQAndreas)

WingEraser commented Feb 17, 2013

You want something like this:

FlxSprite::aMethod()
{
    preMethod, called before the actual code.

    the actual code + hookMethod, called inside the actual code.

    postMethod, called after the actual code.
}

Store all methods in an Array and also needs to check whether the mehod belongs to the Class::method().
(how does the bbcode in github works? Hehe Thanks @IQAndreas)

@IQAndreas

This comment has been minimized.

Show comment
Hide comment
@IQAndreas

IQAndreas Feb 17, 2013

Member

Unrelated to the issue, but I edited your code, @WingEraser, to show how to get code blocks working (edit the comment to see how I did it. I'm not entirely sure how to insert the special characters without them being parsed)

GitHub uses Markdown and then adds a few of its own features.

Member

IQAndreas commented Feb 17, 2013

Unrelated to the issue, but I edited your code, @WingEraser, to show how to get code blocks working (edit the comment to see how I did it. I'm not entirely sure how to insert the special characters without them being parsed)

GitHub uses Markdown and then adds a few of its own features.

@Dovyski

This comment has been minimized.

Show comment
Hide comment
@Dovyski

Dovyski Feb 27, 2013

Member

Something like that, @WingEraser . The pre/post methods are not part of my plugin idea. The hooks would be placed at special points within the method being hooked.

If we place the hooks carefully and at significant places, then it won't cause a huge performance impact.

Member

Dovyski commented Feb 27, 2013

Something like that, @WingEraser . The pre/post methods are not part of my plugin idea. The hooks would be placed at special points within the method being hooked.

If we place the hooks carefully and at significant places, then it won't cause a huge performance impact.

@WingEraser

This comment has been minimized.

Show comment
Hide comment
@WingEraser

WingEraser Feb 27, 2013

FlxClass

public function callback
public Array args;

public void method()
{
    // Do the actual code
    // Somewhere inside the code fire the hook.
    callback(args...);
}

public void setCallback(callback, args)
{
    this.callback = callback
    this.args = args;
}

So, this is how a hook could look like. Where do you want to place those hooks actually? We got plenty of time to think about the places.
But back to topic, can we remove TimeManager and DebugPathDisplay from the core? It's used by FlxGame.
Hmm...FlxTimer, is not in the plugin folder? The timer update happens in the TimeManager.

(I'm programming Java at the moment, I'm not used to switch to other syntax immediately.)

WingEraser commented Feb 27, 2013

FlxClass

public function callback
public Array args;

public void method()
{
    // Do the actual code
    // Somewhere inside the code fire the hook.
    callback(args...);
}

public void setCallback(callback, args)
{
    this.callback = callback
    this.args = args;
}

So, this is how a hook could look like. Where do you want to place those hooks actually? We got plenty of time to think about the places.
But back to topic, can we remove TimeManager and DebugPathDisplay from the core? It's used by FlxGame.
Hmm...FlxTimer, is not in the plugin folder? The timer update happens in the TimeManager.

(I'm programming Java at the moment, I'm not used to switch to other syntax immediately.)

@Dovyski

This comment has been minimized.

Show comment
Hide comment
@Dovyski

Dovyski Apr 4, 2013

Member

That's what I had in mind, @WingEraser ! However the args are not provided by the developer, but by Flixel itself according to the "active" method. Something like this:

public void method()
{
    var importantMethodVar :Type = (...);
    // Do the actual code
    // Somewhere inside the code fire the hook.
    callback(importantMethodVar);
}

Using that approach, one could create a plugin that injects physics into any sprite added to the state.

Member

Dovyski commented Apr 4, 2013

That's what I had in mind, @WingEraser ! However the args are not provided by the developer, but by Flixel itself according to the "active" method. Something like this:

public void method()
{
    var importantMethodVar :Type = (...);
    // Do the actual code
    // Somewhere inside the code fire the hook.
    callback(importantMethodVar);
}

Using that approach, one could create a plugin that injects physics into any sprite added to the state.

This was referenced Nov 27, 2013

@Dovyski

This comment has been minimized.

Show comment
Hide comment
@Dovyski

Dovyski May 4, 2014

Member

I'm planning to start working on this soon. Before I get my hands dirty, I would like some feedback on the API I have in mind. Here's the idea.

Flixel will have several "hooks", special portions of the code that will trigger an action. Developers can use hooks to change or enhance Flixel behavior. Hooks will be available as signals (pretty much as As3Signals), accessible through FlxG.hooks.

Below is a snippet of how developers will use hooks:

FlxG.hooks.stateSwitched.add(myHookHandler);

function myHookHandler(newState :FlxState) :void {
   trace("new state active " + newState);
}

// later, when the hook is not needed anymore
FlxG.hooks.stateSwitched.remove(myHookHandler);

Flixel code will use hooks as follows (fragment from FlxG.switchState()):

static public function switchState(State:FlxState):void
{
    _game._requestedState = State;
    FlxG.hooks.stateSwitched.distpach(State);
}

HaxeFlixel already has an implemented FlxSignal, which I will borrow. If the API is OK for everyone, we can start discussing hooks.

Member

Dovyski commented May 4, 2014

I'm planning to start working on this soon. Before I get my hands dirty, I would like some feedback on the API I have in mind. Here's the idea.

Flixel will have several "hooks", special portions of the code that will trigger an action. Developers can use hooks to change or enhance Flixel behavior. Hooks will be available as signals (pretty much as As3Signals), accessible through FlxG.hooks.

Below is a snippet of how developers will use hooks:

FlxG.hooks.stateSwitched.add(myHookHandler);

function myHookHandler(newState :FlxState) :void {
   trace("new state active " + newState);
}

// later, when the hook is not needed anymore
FlxG.hooks.stateSwitched.remove(myHookHandler);

Flixel code will use hooks as follows (fragment from FlxG.switchState()):

static public function switchState(State:FlxState):void
{
    _game._requestedState = State;
    FlxG.hooks.stateSwitched.distpach(State);
}

HaxeFlixel already has an implemented FlxSignal, which I will borrow. If the API is OK for everyone, we can start discussing hooks.

@IQAndreas

This comment has been minimized.

Show comment
Hide comment
@IQAndreas

IQAndreas May 5, 2014

Member

I think signals are an excellent approach in this case.

One thought though, instead of FlxG.hooks, will we want hooks to be a property on each FlxPlugin instance?

Also, do we want to send the FlxState instance as a parameter, or make it more "event like", where you have an Event object containing the relevant data?

Member

IQAndreas commented May 5, 2014

I think signals are an excellent approach in this case.

One thought though, instead of FlxG.hooks, will we want hooks to be a property on each FlxPlugin instance?

Also, do we want to send the FlxState instance as a parameter, or make it more "event like", where you have an Event object containing the relevant data?

@Dovyski

This comment has been minimized.

Show comment
Hide comment
@Dovyski

Dovyski May 5, 2014

Member

One thought though, instead of FlxG.hooks, will we want hooks to be a property on each FlxPlugin instance?

We can place the hooks property on each plugin, but only if they will actually dispatch events. I don't believe we will need plugins dispatching hooks (they can, of course, but the most important and juicy hooks will be from Flixel itself).

Also, do we want to send the FlxState instance as a parameter, or make it more "event like", where you have an Event object containing the relevant data?

I thought about that, but we should avoid at all cost the creation of a new event instance every time a hook is dispatched. I would like it to be something simpler than events, otherwise we will need an Event subclasss for each hook, since they all have different needs.

We can solve the problem of creating new objects every dispatch by using a pool though.

Member

Dovyski commented May 5, 2014

One thought though, instead of FlxG.hooks, will we want hooks to be a property on each FlxPlugin instance?

We can place the hooks property on each plugin, but only if they will actually dispatch events. I don't believe we will need plugins dispatching hooks (they can, of course, but the most important and juicy hooks will be from Flixel itself).

Also, do we want to send the FlxState instance as a parameter, or make it more "event like", where you have an Event object containing the relevant data?

I thought about that, but we should avoid at all cost the creation of a new event instance every time a hook is dispatched. I would like it to be something simpler than events, otherwise we will need an Event subclasss for each hook, since they all have different needs.

We can solve the problem of creating new objects every dispatch by using a pool though.

@Gama11

This comment has been minimized.

Show comment
Hide comment
@Gama11

Gama11 May 5, 2014

Why FlxG.hooks, and not FlxG.signals? The latter seems to be the more obvious naming, and we also use that in HaxeFlixel.

Btw, I'm not sure if you'll be able to copy the FlxSignal implementation too closely, a lot of it depends on advanced haxe features.

Gama11 commented May 5, 2014

Why FlxG.hooks, and not FlxG.signals? The latter seems to be the more obvious naming, and we also use that in HaxeFlixel.

Btw, I'm not sure if you'll be able to copy the FlxSignal implementation too closely, a lot of it depends on advanced haxe features.

@Dovyski

This comment has been minimized.

Show comment
Hide comment
@Dovyski

Dovyski May 5, 2014

Member

FlxG.signals is way better indeed! About the implementation, I noticed the Haxe features, but I can deal with them.

Member

Dovyski commented May 5, 2014

FlxG.signals is way better indeed! About the implementation, I noticed the Haxe features, but I can deal with them.

@Dovyski

This comment has been minimized.

Show comment
Hide comment
@Dovyski

Dovyski May 17, 2014

Member

I've started working on this issue. It's possible to track my progress in the fix-issue-121 branch.

Member

Dovyski commented May 17, 2014

I've started working on this issue. It's possible to track my progress in the fix-issue-121 branch.

@Dovyski

This comment has been minimized.

Show comment
Hide comment
@Dovyski

Dovyski Jun 5, 2014

Member

First iteration has landed in 79450d8

Member

Dovyski commented Jun 5, 2014

First iteration has landed in 79450d8

@Dovyski Dovyski closed this Jan 11, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment