-
Notifications
You must be signed in to change notification settings - Fork 561
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
Add a new global method: Crafty.system() #878
Conversation
I like the idea very much. Conceptually it's like a singleton entity and component in one, which can be further composed of smaller systems. My thoughts:
Now onto implementation concerns:
|
I should explain something about the intended usage. The object that you pass in to Crafty.system isn't the system itself, but a kind of template for it. (Much like how a component and an entity are different things.) For instance, when canvasLayer is switched to this system:
This isn't quite what I'm going for -- each thing labelled a systems should be complete in and of itself, so once you've defined a system you probably don't want to inherit from it. There is the extend method, which will make it easy to share common functionality between systems through mixin objects. Since one of the main goals of this whole setup is to abstract out how we handle render layers, that'll be a good test of how well it works. You'll be able to create canvas/webgl/dom layers, but each will share a bunch of methods. Obviously once I have some experience actually working with this code, I might change my tune on what it should do! :)
Initially I had that called destroy, rather than remove, which means it had to be called on the template. I changed the name for consistency with how component methods are named, but didn't change the logic otherwise. I'll look at that again and probably change it to make more sense!
See above for why I don't think it makes sense specifically supporting this. |
Ok, now I understand your use case a bit better. So given your use-case: // creating a system
var canvasLayer = { ... };
Crafty.system("Canvas", canvasLayer);
Crafty.system("CanvasUI", canvasLayer);
// retrieving a system
Crafty.system("Canvas"); what is the difference, advantages/disadvantages over // creating a system
var canvasLayer = { ... };
Crafty.c("CanvasLayer", canvasLayer);
Crafty.e("Canvas", "CanvasLayer");
Crafty.e("CanvasUI", "CanvasLayer");
// retrieving a system
Crafty("Canvas").get(0); It seems like Crafty already has the tools to achieve something like this (no need to reinvent the wheel), or am I missing something here? Perhaps you want to avoid looping over all entities in the selector? |
There are a few reasons for adding a new type of object, rather than reusing components/entities.
It also just didn't feel right to me to make the viewport or graphical layers into entities. It's probably technically possible, but I think it makes sense to make the distinction clear in the code. They're different concepts, and they're going to be used in different ways. |
// Check the template itself | ||
if (typeof this._systemTemplate.remove === "function") { | ||
this._systemTemplate.remove(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is what I meant: why not call the remove
method with this
as the context, rather than this._systemTemplate
? (the remove
method should get copied over from the template)
if (typeof this.remove === "function") {
this.remove();
}
Ok, my main concern is to avoid code duplication. Now we will have e.g. |
I actually tried to do this, but the functions really do require different logic in different contexts:
What I ended up doing was having the underlying logic abstracted out -- that's what the |
Thanks for the review, because these are definitely choices that should be well justified! There are a couple of small changes I'll push (using |
I pushed theses changes: renamed to |
dc0de61
to
b50e475
Compare
Great, I suggest adding |
Can we merge this? |
While working on a (failed, I got really sick last week) 7drl, I didn't see any huge issues with this, but there are a couple things that should be addressed.
Once I fix that bug we can merge this. |
- Switch from using a global to a method on the global Crafty object. - Add a method for unbinding all callbacks - Assign a context for each callbacks handler, so we don't need to search for it - Fix a bug in the callback logic when unbinding a callback in the middle of a trigger depth > 1; add a related test
It's very natural to want an arbitrary, non-entity object that can participate in the event system. Currently when objects like the viewport or the graphical layers want to listen to an event, they have to refer to themselves via hardcoded references, since the events happen in the global context. This introduces the idea of systems which have a set of methods for participating in events. These methods parallel those that Crafty and each entity implement. When a system is created, a new object is created with these methods, and then it is extended with the methods/properties of a provided template object. An `init` method and an `events` property can be provided that fill the same role as for components. By default the system will be lazily created -- that is, it will only be created when referred to for the first time. (This is what we do now with Crafty.canvasLayer and the like.) In the future, we'll probably want to extend the capability of systems. In particular, I envision that components and systems with the same name would have some connection -- perhaps the system could have methods for operating on all such entities at once. I tested moving canvasLayer, domLayer, and webgl to this new paradigm and it seemed to work ok, but the actual switchover will happen in a new PR.
Fixed the bug (and added a test for it), and added the doc note. I'll go ahead and merge this once Travis reports back (the tests all passed locally, though). |
Add a new global method: Crafty.system()
I'm sorry that you fell sick and didn't finish your project. It's a very exhilarating experience to finish such a project successfully in a few days :) I just played with event binding in my code, and had a programming error when binding to an event on the global Crafty instance. Crafty.c("MyComponent", {
init: function() {
Crafty.bind("MyEvent", function() {
this.myData = "example"; // this refers to Crafty here, not the entity that will have "MyComponent"
});
}
}); Was this always the case that |
I'm pretty sure -- we always triggered the callback with something like |
It's very natural to want a non-entity object that can participate in the event system. Currently when objects like the viewport or the graphical layers want to listen to an event, they have to refer to themselves via hardcoded references, since those event handlers get run with
Crafty
as the context.This introduces the idea of systems which have a set of methods for participating in events. These methods parallel those that Crafty and each entity implement.
When a system is created, a new object is created with these methods, and then it is extended with the methods/properties of a provided template object. An
init
method and anevents
property can be provided that fill the same role as for components. By default the system will be lazily created -- that is, it will only be created when referred to for the first time. (This is what we do now with Crafty.canvasLayer and the like.)In the future, we'll probably want to extend the capability of systems. In particular, I envision that components and systems with the same name would have some connection -- perhaps the system could have methods for operating on all such entities at once.
I tested moving canvasLayer, domLayer, and webgl to this new paradigm and it seemed to work ok, but the actual switchover will happen in a new PR.
There were some small updates to the callbackMethods mixin required to implement this properly.