Skip to content

Tour of the code base

Robert Bragg edited this page Jul 13, 2013 · 1 revision

We have a separation in the codebase between "rut" and "rig". Rut is for "Rig Utilities". There is no current intention to use the library for anything other than Rig but it seemed like a good practice to differentiate code that provides general purpose utilities from code that is very strictly only relevant to the Rig editor. In the future the Rig project could conceivably provide multiple interactive tools.

Looking inside Rut...

Inside Rut we have "RutShell" (rut-shell.c) which is where we handle platform abstraction details, like input handling and the mainloop.

rut/rut-type.h: This is our low-fi type system that lets you mix and match interfaces to build up a type. Note: It's not a hierachical inheritance system, you can just declare a set of interfaces that your type implements. For a good, simple example of declaring a new type look at rut/rut-graph.c. You might see some older examples that follow a different style, but the style in rut-graph is the one to follow.

rut/rut-property.h: This is our introspectable property system that lets us create properties that the editor can discover and automatically create widgets for inspecting and manipulating. This also gives a way to bind properties together.

rut/rut-closure.h: We don't have a very high-level signalling mechanism in Rig, but instead we use this api to track lists of callbacks for notifying orthogonal components of interesting events.

rut-graph and rut-transform are used for managing graphs of stuff. rut-graph is used both for the graph of widgets used for the Rig editor ui and also the graph of entities that form the UI description being edited.

Some other general utilities in rut include: rut-arcball to help with rotating objects in 3D. rut-bitmask to manage arbitrarily long bit masks (i.e. may not simply fit in a 32bit int). rut-color for manipulating colours (rgb+hsl) including [un]serializing them. rut-mesh gives us a way to manage complex triangle meshes on the cpu and iterate through the triangles. rut-planes for dealing with mathematical planes. rut-timeline for driving property changes over time. rut-util.h also has a few misc utils so you might want to skim through the header.

We have a load of simple traditional widgets for implementing the Rig editor UI, and these are things like: rut-button, rut-drop-down,rut-text,rut-label,rut-fold,rut-image,rut-icon,rut-icon-button,rut-nine-slice,rut-rectangle,rut-number-slider,rut-toggle,rut-vec3-slider,rut-color-button,rut-color-picker

We have a load of 2d containers too like: rut-bin,rut-box-layout,rut-fixed,rut-flow-layout,rut-stack,rut-ui-viewport

rut-entity.h: provides the entity system that we use for building up UI scenes. Entities have a position, scale and rotation, but then mostly everything else about an entity is defined by attaching components to an entity.

under rut/components we have several components which can be attached to entities including: rut-camera,rut-diamond,rut-light,rut-material,rut-model,rut-pointalism and rut-shape

components can also be categorised according to types including RUT_COMPONENT_TYPE_CAMERA,LIGHT,GEOMETRY,MATERIAL

Looking inside Rig...

rig-engine.c is the hub of Rig where everything ends up integrated. You'll see some #ifdefs for RIG_EDITOR_ENABLED to mark code that's not required in device mode and also runtime checks for _rig_in_device_mode and new code should be mindful of these checks too.

The center area of the editor is managed in rig-camera-view.c and this deals with things like input for selecting and moving entities and drives painting of the UI being designed (not of the editor).

rig-renderer.c is the monolithic code that handles the low level rendering of a UI scenegraph using Cogl.

Something to understand, is that we want to maintain a separation between describing the semantic meaning of entities (done by attaching components and changing the properties of those components) from the exact way that entities get rendered on the GPU.

In the future we envisage having alternative, special purpose renderers that might handle very specific styles (e.g. cartoon style or sketch style rendering) but for that to be possible we need to avoid tightly coupling the components and rig-engine with the details of how we render.

We use protocol buffers as a way to serialize data both for saving to disc and also talking to slave devices over the network.

rig.proto contains a json like description of the protocol buffer messages we use for serializing our UI descriptions. E.g. adding a new component will involve describing how to serialize it as message here.

rig-pb.c contains the code for actually serializing and unserializing our data structures. We use libprotobuf-c to help with this.

Anything that manipulates the UI description needs to go through the undo journal in rig-undo-journal.c. This is how we handle ctrl-z/y undo/redo and the intention is to also support fine grained communication with slave devices at this level by being able to serialize the same undo/redo structures to send over the network. (currently we just trigger a full UI sync whenever the journal changes)

When building rig we create three binaries for running in three modes, rig-editor.c has the main() function for the editor, rig-device.c is for running in device mode without the editor chrome and rig-slave.c is for running in device mode but also with the ability to connect over the network to the editor.

Clone this wiki locally