This will give an introduction to what one should be aware of when developing plugins for the MegaZine 3 Engine. If anything is unclear, have a look at the code of the existing plugins.
Plugins should have a unique name, because there cannot be two plugins with the same name loaded into the engine.
The name should be the same as the classname, just in all lowercase. A plugin must be compiled into a swf file bearing the plugin's name.
Example: Plugin Dummy
- Class name: Dummy
- Plugin name: dummy
- File name: dummy.swf
A plugin should be located in a package bearing the plugin's name inside the plugins package. All plugin specific classes such as interfaces, events and supplementary classes should be placed into this package.
Example: Plugin Dummy
- Package name: de.mightypirates.megazine.plugins.dummy
The use of interfaces can not be enforced, naturally, but is very strongly recommended to keep file sizes of the separate components to a minimum. This means that one should provide an interface for a plugin if it offers some functionality which might be used in other plugins (e.g. the gotoAnchor function in the Anchors plugin).
An interface should be named IPluginName, i.e. the name of the plugin's class with a prefixed capital "i".
Plugins may depend upon the availability of other plugins, i.e. they use functionality offered by other plugins.
There are two basic types of dependency: strong and weak dependencies. A strong dependency requires the other plugin to be available for the plugin depending on it to work at all.
A weak dependency triggers the engine to try to load the plugin it depends on, but if the load fails it can work on its own. So basically weak dependencies may be used when a plugin gains additional functionality from other plugins, and wishes to automatically load those.
Whenever another plugin is used, it should at least be declared in a weak dependency, otherwise the loading order cannot be guaranteed. On the topic of loading order: plugins will always be loaded in such a way that plugins that are being used by others (as declared via dependencies) will be loaded first. This also implies that there cannot be any circular dependencies, as it would be impossible which plugin to load first. Thus, whenever a circular strong dependency is found, the affected plugins will not be loaded. Whenever a circular weak dependency is found, the order cannot be guaranteed and might differ between multiple application runs.
Registering / Initializing
There are two setup phases for plugins, the registration and the initialization step.
- In the initialization step the settings will be loaded and the book will be fully available (in the ready state). It is recommended to setup GUI elements in this step. When subclassing the AbstractPlugin class, plugins will also be initialized in such an order, that plugins a plugin depends on are initialized first.
One main plugin interface is the attribute handling. Each plugin may register itself as a handler for certain attributes. Those can be attributes of chapters, page sides or elements.
They will be called whenever a chapter, page side or element finishes
loading. For chapters and page sides this will happen once, triggered during
the initial setup, and whenever more chapters or pages are added
dynamically to the book. As for elements, it will always fire when an
AbstractElement finishes loading, i.e. when the element's page comes
into the range of pages that are kept in memory. Thus, one should keep
proper memory handling in mind, because this happens whenever the user
flips forwards and backwards in a book.
The exact timing is as follows:
Chapters, the attribute handling is invoked after the chapter and all its pages have been added to the book. This happens once in the lifetime of the
PageSides, the attribute handling is invoked after all its
ElementProxynodes have been created. This happens once in the lifetime of the
ElementProxys, the attribute handling is invoked after the element has been initialized (last action in the constructor). This happens once in the lifetime of the
AbstractElements, the attribute handling is invoked after the element is complete, but it might not yet be fully initialized. This happens whenever the
PageSidecontaining the element leaves and reenters the range of pages to be kept in memory.
The AbstractPlugin class offers a few convenience functions for plugins, which makes it recommendable to extend this class whenever building a plugin. In general it is sufficient to implement the IPlugin interface correctly.
What the AbstractPlugin provides can be seen in the API, but here are the main two points:
- initialize: the initialize function is automatically called when the book is ready, i.e. fully initialized. This can be used for plugin setup where settings are required. For AbstractPlugin subclasses it is also guaranteed that a plugin's dependencies are initialized before it itself is (unless there is a circular dependency, of course).
- setElementProperty/getElementProperty: this can be used to bind properties to elements. This uses a Dictionary with weak keys for mapping, so one does not have to worry about memory / garbage collection.
Plugins may also add new DisplayObjects to the scene graph / stage.
There are three possibilities for that, once on a global level, to a layer specifically meant for that, on top of the rest of the engine (MegaZine.pluginLayer), once on page level (PageSide.pluginLayer), and once on an element level (same here, again a special layer named pluginLayer).
These layers are accessible through the interfaces of the respective objects, and can be used by the plugins to display graphics.
It is recommended to use the ASUL framework for loading and working with graphics inside the engine. The AbstractPlugin provides some functionality to make this as easy as possible.
|MegaZine3 Plugin-related articles|
|Plugin Articles||Writing a plugin · Writing a plugin II · Plugin development|