Structure
PrefaceI put a lot of thought and effort in to ensuring that RMPY would have an organized, stable, and easy to use structure. but this doesn't mean that it is perfect or suitable for ARC.
This first post will explain the overall structure of the current code base and will hence forth serve as a discussion topic where people can ask questions for clarification, post suggestions for modification and improvement, and in general discuss the structure.
Basic ComponentsThe editor is divided up into three major components or groups of classes.
- Launcher: This part is the main application class derived from wx.App. It launches the application loads the Kernel, displays the splash screen ect.
- Kernel: This is the CORE of the program. it consists of a group of classes that load components from plugins, organizes packages and (while this part hasn't been written yet) is intended to manage dependencies of components. It also provides and interface to access those components in an implamentation independent manner
- Components: These are a large collections of classes and functions that operate in a modular fashion and implement a single piece of functionality, like loading game data or drawing the map so it can be edited. they can rely on other components to implement sub functionality and expose a uniform interface. the premises is that each components can be replaced individually so the extending or replacing functionality is easy.
each part is explained below.
LauncherThe launcher is fairly simple. it creates the Application loads the Kernel and all the components (core or plugin) loads the configurations (for components and other settings) and then loads the main frame components which in turns loads the rest of the program
KernelThe kernel provides the base functionality of the entire system. it serves as an interface to load and dispatch components and a place to store objects and other values that more than one component needs access to. The kernel can register functions for callback to be run when certain events are raised, register components types, their implementations, and the packages they were loaded from. and dispatch those components with a simple call to "get_component("TYPE")"
When a component is registered in the Kernel the structure looks like this
- static class Manager
- property: types {}
- key: "Type_Name" => value: object class Type
- property: components {}
- key: "PACKAGE_NAME_AUTHOR_VERSION" => value: object class Component
- property: object class or function object of component
a call to
Manager.get_component("Type_Name")
returns a Component object. either the one assigned to the types 'default' property or the first registered component. the class or function can be accessed through the components object's 'object' property
Componentsthere are several general types of components that shape the program
they are as follows
- Frame Components: classes inheriting from wx.Frame. they include the main editor frame
- Layout Components: Generic classes that server to load other components. A Frame will load one and it will load a bunch of other components to populate the Frame with controls.
- Controls: a control is a GUI elements that the user sees and possibly interacts with. things like a scroll bar, a panel, a button, ect. a costume control would be the map display.
- Dialogs: small frames with a single purpose. Ie. create a new project, save the current one, or import data.
- Data Handlers: these classes serve to handle the data. they perform operations like saving data, loading data, or editing the data that is the Map ect.. the Undo/Redo action framework would be under this.
The Loading of Pluginsin the Kernel there is a class called package. the intended use of this class is to subclass it and then use the build in methods to first register any components types that the package introduces and then add the components in the package as implementations of those types. this is all done in the __init__ method of the Package subclass using the Package class functions
and s
and at the end
is called to register all the types and components in the Kernel. in this sense a Plugin is really a set of components grouped into a package. the loading of the package is simply the creation of an instance of the Package subclass. Taking a look at the core_
init.py file in the Core folder should give a good demonstration of how this is done as this file creates a Package "CORE" to load all the default components
I also have a config option in the Kernel that is used to set the default components. an ini file that uses sections for each component type and properties like author, name, package, and version to set the default. the User_defaults.ini shows this.
you can read the source for further clarification of the details of the implementation. I've documented it fairly well but if you have any questions please ask away.