Man Linux: Main Page and Category List

NAME

       libgiigic-usage - LibGIIGIC Overview

PURPOSE

       LibGIIGIC  is intended to help the game developer with a flexible input
       mapping system which enables the user to  easily  adjust  the  bindings
       between game actions and the input device movements.

NO FEAR

       Please  do  not  get  confused  by the tons of API calls. Most are only
       useful if you are developing new configmanagers  or  applications  that
       have  very  special  needs,  like reconfiguring their controlset on the
       fly.

       A "normal" game will usually only  use  a  very  small  subset  of  the
       LibGIIGIC  API,  depending  if  it  wants  to  just  use  a  given  GIC
       configuration, or  if  it  also  wants  to  implement  a  configuration
       manager.

       Actually  it  is a good idea, to at least allow the user to run his own
       config manager if he wants to.

TERMINOLOGY

       LibGIIGIC has its own terminology that describes how an application and
       the  actions  that  can  be  triggered  within  it  relate. This can be
       confusing at first, so please make sure you read this section carefully
       and refer to it, if unsure.

       From  LibGIIGIC’s  point  of  view,  an application is represented as a
       "Head".  This term stems from the fact, that an application might serve
       multiple  displays  (heads)  with different configurations. LibGGI will
       usually have its own inputs for each head, then.

       Within each head, applications will usually have  different  needs  for
       input  mapping,  depending  on the current state of the application. In
       LibGIIGIC this is called a "Context".

       Each context (like "in game",  "main  menu",  ...)  will  usually  have
       several  aspects  that  can be controlled, for example movement, weapon
       choice, etc.  This is what LibGIIGIC calls a "Control".

       Most Controls have several subunits. For example movement  may  contain
       "forward",  "backward",  "left"  and  "right".  LibGIIGIC  calls  these
       "Features".

       Most of the time, one feature can be controlled by a single  keystroke,
       mouse-click,  joystick  movement, etc. However sometimes it makes sense
       to have multiple bindings for the same feature.

       Any such user input that  is  associated  to  a  feature  is  called  a
       "Recognizer".

       This hierarchy of types that builds the skeleton of LibGIIGIC.

       It     can     be     represented     as     a     file.     Look    at
       programs/demos/configmanager.gic for an  example.  Such  a  ".gic-file"
       contains all the configuration info for a given head.

       Of  course  it is not enough to just recognize, that a feature has been
       activated by some input. One usually wants to act on that.

       LibGIIGIC allows to bind callback functions to features that get called
       when a Recognizer triggers. These are called "Actions".

SIMPLE EXAMPLE

       Now let’s have a look at a very simple sample program - demo.c

       When  working with LibGIIGIC, you first need to initialize the library.
       Do this using gicInit(). When you don’t need LibGIIGIC  anymore,  close
       it  down  using  gicExit(). Don’t be afraid to use that in higher level
       libraries.  LibGIIGIC is aware of being initialized and exited multiple
       times,  and  will  handle it correctly, as long as the calls are nested
       properly.

       These calls only initialize the lib. To interact with it, you  need  to
       allocate  a gic_handle_t using gicOpen(NULL). The parameter is reserved
       for future expansion. When you are done with  it,  free  the  allocated
       handle using gicClose(handle).

       If you have an existing configuration file, you just read it:

       config = fopen("demo.gic", "r");
       head = gicHeadRead(handle, config);
       fclose(config);

       Simple - right?

       You  can  of course stuff your other data there, too. gicHeadRead(3) is
       aware of where to stop, so you can store your data before and after the
       LibGIIGIC data to your liking.

       If  you  are  interested  in rehearsing the terminoloy chapter, you may
       want to look at the demo.gic file yourself. It is  human  readable  and
       you will find the hierarchy of objects in there.

       Now what you got back is an object "head" which is of type gic_head(3).

       However, you will usually work with contexts, as the  application  will
       normally enter different states associated with gic_context(3)’s.

       You can extract the contexts from the head like this:

       menu = gicHeadLookupContext(handle, head, "Menu context");

       Now we have one point that needs to be cleaned up: the file also stores
       actions, which are basically callbacks.  However  how  does  one  store
       function  pointers  in  a config file in a way that does not break when
       moving the config file between platforms etc. ?

       You don’t. The next step is to reestablish the  "action  mapping"  -  a
       connection  between  a  symbolic  name  of  the  action, and the actual
       callback function. This  mapping  is  stored  in  a  variable  of  type
       gic_actionlist.

       A sample list would be:

       gic_actionlist actionmapping[]= {
             {NULL,"mynextaction",   my_action,      NULL},
             {NULL,"myprevaction",   my_action2,     (void *)0x12345678},
             {NULL,NULL,NULL,NULL}
       };

       The  first  element of each gic_actionlist-entry here is reserved for a
       chaining pointer and always NULL.

       The second element is the name of the action as it appears in the .gic-
       file.   The  third  is  the  callback  function,  and the fourth a void
       pointer to some private data which will be given to the callback.

       The fourth entry  allows  to  reuse  the  same  callback  function  for
       multiple  purposes,  which  makes  a  lot  of  sense,  as many callback
       functions are usually very similar.

       You can now re-map the actions using this call:

       gicHeadMapActions(handle,head,actionmapping);

       This will cause LibGIIGIC to iterate through the  head  and  its  child
       objects and find any actions attached. If the action names match a name
       in the actionmapping list, the respective callbacks are set up.

       From then on, LibGIIGIC is ready to receive events. You just receive  a
       gii_event from LibGII (or LibGGI which uses LibGII for input), or build
       one yourself, if you insist not to use LibGII.

       You can then feed the event to LibGIIGIC using:

       gicContextHandleEvent(handle,menu, &event);

       Note, that it does not make sense to send an event to a  head,  as  the
       event  might  have different meanings depending on context. So you just
       feed it to the right context.

       Now if an event matches the description in the .gic file, the requested
       action  callbacks  will fire. We will discuss them in greater detail in
       the next section.

       When we are done with LibGIIGIC, we should close down  all  handles  we
       opened using gicClose(handle) and finally call gicExit().

CALLBACK FUNCTIONS (ACTIONS)

       If  a  recognizer triggers, it will activate the feature it is attached
       to, which will in turn call the actions bound to it.

       Action functions have the following prototype:

       void my_action(gic_handle_t hand, gic_actionlist *action,
             gic_feature *feature, gic_state newstate,gic_flag flag,
             int recnum);

       When it gets called, it is given a lot of data that  allows  to  derive
       why it was called.

       First  of  all it gets the gic_handle_t that triggered the action. This
       is useful, if you want to call LibGIIGIC functions within the callback.

       Then  you get the gic_actionlist of the action that caused the callback
       to be actived. This  datatype  was  already  covered  in  the  previous
       section.   It’s  most common uses are differentiating calls to a common
       callback that serves multiple  purposes.  To  achieve  this,  the  most
       interesting  entries  are action->name and action->privdata, which will
       commonly be used to find out which action triggered  and  to  point  to
       some common data structure that will be modified by the actions.

       The  gic_feature(3)  points to the feature that this action is bound to
       and can as well be used to differentiate when binding a  single  action
       function to multiple features.

       When  a  feature  gets activated, it can have an "extent to which it is
       activated". This is used  by  features  that  don’t  only  have  on/off
       characteristics,  but  rather a linear notion of "how active they are".
       An example for this is e.g. a control for turning. Simple input devices
       like  keyboards  can  only say turn left/don’t turn left, while mice or
       joysticks can say how fast or far to turn.

       gic_state  carries  this   information.   The   macros   GIC_STATE_MIN,
       GIC_STATE_MAX,  GIC_STATE_MIDDLE  and  GIC_NOACTION can be used to find
       out how strong the respective measure of activation was.

       gic_flag can carry additional information about the  action.  If  flags
       are  set,  that  are  within GIC_FLAG_MUSTKNOWMASK, you are expected to
       handle them.  Set flags outside that bitmask are optional  and  can  be
       ignored for application development.

       Up  to  now, only one such flag is defined: GIC_FLAG_PULSE.  If set, it
       indicates, that the events triggering the action is of a "pulsed" type,
       i.e.  it  is expected to be released immediately after it was received,
       so you should handle it similar to the case of an event  like  the  one
       you  received,  immediately  followed  by  one  of  the  same kind with
       gic_state containing GIC_STATE_MIN.

       The integer recnum gives the number of the recognizer that caused  this
       event to trigger. This can be used when implementing "adding policies",
       like if turning with joystick and mouse at the same time will  add  up,
       or will just use the highest value, or whatever.

USING THE LAZY ACTION HELPERS

       Many simple programs will prefer not to use their own action callbacks,
       but rather just use this predefined callback system.

       For this to work, you have to bind all relevant actions you do not want
       to handle yourself to gicActionLazyAction(3).

       The privdata field must point to a gicActionLazyData(3) variable.

       When using the Lazy action helpers, you usually do something like this:

       ggiEventRead(vis,&event,emAll);               /* get an event. */
       /* Let LibGIC evaluate it for the menu context */
       gicContextHandleEvent(hand, menucon, &event);

       Now the gicActionLazyAction(3) callbacks are run, and you can check how
       much the individual gicActionLazyData(3) elements are active.

       For  this, you do: gicActionLazyGetstate(&lazydata) which will return a
       gic_state  you  can  evaluate.  (The  gicActionLazyAction(3)   callback
       implement  a  "max  activation  is  returned"  policy  with  respect to
       multiple active recognizers).

       This will also handle the case of pulsed inputs, which will be returned
       and then deleted.

       If  you are unsure about the state of the variables (e.g. at startup or
       after retraining the mappings),  you  can  reset  the  variables  using
       gicActionLazyReset(3).

TRAINING

       TODO

CONFLICTS

       TODO

SEE ALSO

       libgiigic(7)