Are there some tips about orx organization?

edited August 2013 in General discussions
As i found it's hard for new orx player have an outline of orx, are there some tips or image show the structure about orx engine?

Comments

  • edited August 2013
    Do you mean the internal organization?
    If so, yes, unfortunately there aren't many docs around beside the source itself.

    From a user point of view however, the wiki is a good source of information. For example, gemberkoekje started a reference page. However it's over a year old so it's missing the most recent features such as the resource module or the interactive console: http://orx-project.org/wiki/en/orx/reference/main#dokuwiki__content

    If you could narrow down your question I'll be happy to answer it.
  • edited August 2013
    Thank you for your reply :) And yes, the internal organization. For a developer view, as i want to changing the module behavior or add some wrap within orx core. I need to know how it work and where to start? are there some structure view or workflow of orx itself? Just the source code?
  • edited August 2013
    I'm afraid there isn't any doc or schema for the internals beside the reference page I mentioned. :(

    I'll try to describe the main components but don't hesitate if you have any more precise questions. :)

    Orx is a collection of modules. There's a module hierarchy that could be seen as a DAG (Direct Acyclic Graph) defines from local dependencies.
    This DAG is used when trying to initialize a module to make sure all its dependencies are initialized before hand and, when exiting from a module M, orx makes sure that all modules depending on M have been closed first.
    Dependencies can be optional.

    The main module's dependencies define which modules will be used when executing orx.
    That's how the tools (orxCrypt, orxFontGen) don't have a graphical window as they only depend on core modules such as memory or config and don't require a renderer nor a screen surface.

    In addition to that system of module, there's another hierarchy used for modules that can spawn instances that will get referenced by other parts of the code. Those are "derive" from the module named orxSTRUCTURE.

    This "structure" can be seen as a base object as it bring a few handy features to anything that inherit from it: reference counting, resource management (including allocation, bookkeeping and de-allocation), GUID (Global Unique ID), ordering (either via a linked list or via a tree).

    If you look at object/orxStructure.h, you'll get the list of all the modules that derive from it (such as orxOBJECT, orxGRAPHIC, orxFRAME, ...).

    All memory allocation go through the orxMemory module, currently using dlmalloc under the hood. Memory is very rarely allocated when running orx, it'll try to re-use memory as much as possible for performance reasons.
    Direct calls to orxMemory are also pretty rare. Mostly for allocation that are not of fixed size (character strings, temp buffer for loading textures, etc...).
    Most of the memory management goes through a module named orxBANK. It can be seen like a dynamic array, however there will never be any re-allocation of the content (ie. keeping pointers on elements is safe as elements won't get moved to a different location), allocations will be aligned to be cache friendly and allocations are grouped in segments (also known as memory chunks).
    Most of the time allocating an element from a bank will simply be a re-use of an expired element and will not trigger any dynamic allocation. Same for deletion. There's a way to reclaim memory if need be but it's very rarely used.

    So orxBANKs serve as containers, and they are the only one defined in orx. orxLINKLIST and orxTREE only do ordering, they are not containers as they are intrusive (akin to the k-list, aka kernel list).

    The orxHASHTABLE is a bit of an hybrid as it'll use an orxBANK for containing the values.

    The game loop isn't hardcoded. Actually the game loop is very simple, it consists in updating the orxClock module.

    Every other module that needs an update can register a callback to orxClock. Callbacks can be called regularly and at a given frequency or only for a given amount of times, via timers (still in orxClock). There isn't any other update mechanic, everything goes through clocks. This centralization has the advantage to allow for easy time stretching and re-organization is need be. Some part of the code can also be downgraded to a lower frequency if they don't need to be updated every frame.
    There's a main "core" clock created by orx but others clocks can be created by users to suit their own needs (there's also a clock called "second" created by the FPS module to do a simple FPS counting).

    All that is OS- or hardware-dependent is abstracted via plugins with the only exception of filesystem/file access as this is needed by the config system (and the config system is very core to the engine). Every other platform-dependent code is handled inside plugins that can either be loaded at runtime or embedded directly at compile time. Those currently are for handling sound, display, mouse, joystick, keyboard, physics and render. User-defined plugin can be created however they can't really be called from outside so they need to register an update callback on a clock.

    The config system is basically a huge key-value dictionary with sections & inheritance. It's also very flexible a single value can be interpreted as different types. It's used everywhere and is very handy, ranging from simple configuration needs to localization, commands handling, etc...

    There's a simple direct event system that is used for communicating between modules without the need of direct dependencies. Users can subscribe to any defined events and even created their own. Events can also be used to give the user the opportunity to modify some data before using them (such as when streaming sound, the packets will be available for inspection/modification via events or with shader parameters).

    All resources are now abstracted via the orxResource module. Right now we mostly load either config files, textures or sound files. However those categories can be extended at will and resource type handlers (such as resource coming from a package, from memory or from network) can be added on the fly (see my small example on how to add support for compressed archive on bitbucket).

    There's a command module which interprets commands (who'd have guessed! ;)). Commands can be added by users and can also be executed from timelines or from within the interactive console.

    There's an intrusive profiler that allows very fine grained analyze of performances with a visual in-game renderer. Users can profile their own code by using the profiler macros (orxPROFILER_PUSH_MARKER/orxPROFILER_POP_MARKER).

    There's an animation graph to automatize animation transition (which is really annoying to setup via textual config atm, but I'm working on it!).

    There's a generic input system that abstract any physical input and let the user add new inputs on the fly (that can be triggered either via a physical peripheral, code or command).
    Inputs can be re-bound at will and can be triggered from code and commands, making it very easy to do tutorials or abstract character interface. If you look at mushroom stew that I wrote for a game jam 4 years ago, all the NPCs have a brain that triggers inputs, meaning that the same character could be played either by a human (mapping the generic input to a physical one) or by an AI (having code triggers the inputs, like pushing virtual buttons).

    There are plenty of other modules (display, physics, sound, frames, viewports, camera, shaders, FXs, ...) and this post is already pretty long so if you have anything precise in mind, don't hesitate! :)
  • edited August 2013
    Thank you very much for such a detail description. Now i have an outline(though not clear enough) :unsure: But i'll read the source code as you mention.
    By the way, Are there UI element for orx?
  • edited August 2013
    There aren't any dedicated UI elements.
    Depending on your needs, there are 2 main approaches.

    If you need complex widgets such as dropdowns, for example, you can integrate any UI library of your choice and hook their rendering into orx. This can easily be done by listening to the object render events and substitute the widget rendering calls to orx default object rendering. In the past users have done this with both CEGUI and libRocket.

    You might be able to find examples in the other projects stored on the same bitbucket account than orx.

    If you only need simple things such as buttons, labels or menus, you can use regular objects in conjunction with camera parenting (to keep them displayed always in the same place on screen) and use a very simple loop in code that will pick the object under the cursor when an input is triggered, look inside it's config section for a property you'd define (such as OnClickTrack), and if found you would then apply the value of that property as a timeline on the picked object.

    If you want an example, you can look at either https://bitbucket.org/iarwain/simple test or https://bitbucket.org/iarwain/resource
    In both cases I use a similar scheme to handle interactions and it allows for a lot of flexibility.
Sign In or Register to comment.