Aplicación Práctica - Algo con un Poco más de Carne


En este artículo vamos a integrar CEGUI dentro de una Aplicación Práctica.

CEGUI


Esta versión del código también dirá adios a los proyectos con VC71 y hola a los proyectos con VC8 (Visual C++ 2005). Esta versión del código también tiene como objetivo Ogre 1.4.x (Eihort) - otra vez, si estan ejecutando Dagon (1.2.x) probablemente tendrás que hacer cambios menores para que funcione, seran principalmente en la cola de mensajes, así como en OIS (ya que los ejemplos de OIS usan el último OIS, que viene con el SDK). Siempre, este código era compilado y probado contra Ogre SDK (1.4.1 en este caso).

CEGUI es una librería de renderizado de UI 2D que es independiente del motor de renderizado - tiene soporte directo para OpenGL e Irrlick y también en Ogre. Es una librería altamente basada en XML. Puedes definir toda tu interfaz gráfica en ficheros XML que CEGUI cargará y comprobará en tiempo de ejecución. CEGUI viene con varios ejemplos, incluidos los media necesarios para ejecutar estos ejemplos y los archivos de script XML necesarios para definir el aspecto de los elementos de la interfaz gráfica usadas en los ejemplos. Estos proporcionan esquemas, aspecto, y archivos de fondos que son buenos para poder empezar, pero puedes cambiarlos cuando lo desees para dar otro aspecto a tu Interfaz Gráfica. Sin embargo, hacer esto está fuera del objetivo de este artículo, mirar el sitio CEGUI para obtener más información.

Renderizado de Interfaces Gráficas


CEGUI renderiza sus elementos gráficos como quads de mallas que son dibujadas a una dispositivo "el espacio de pantalla". Esto significa que los objetos de malla hechos que contienen tus controles que se mostraran en pantalla no tienen transformaciones de vista o proyección. Este es el modo estándar en el que el sistema de interfaz gráficas 2D funciona. CEGUI interactua con Ogre mediante el "OgreGUIRenderer", una clase que se proporciona en los "Samples" de Ogre peru que existe en el espacio de nombres "CEGUI". El OgreGUIRenderer simplemente toma comandos de dibujado de CEGUI y los traslada a Mallas de Ogre y datos de textura que Ogre puede mostrar, normalmente en la cola de renderizado "Superposición" (RENDER_QUEUE_OVERLAY). Esto asegura que la Interfaz gráfica se ha dibujado sobre todas las cosas de tu escena. En el código, no necesitas tratar con la clase OgreGUIRenderer nada más que para hacer una instancia de una y pasársela a CEGUI, entonces se apropia de ella.

Entrada y CEGUI


Has proporcionado CEGUI con todos los eventos de entrada - este no tiene un proceso de entrada inherente propio, depende en su lugar de los datos de entrada proporcionados por tu aplicación. Esto tiene unos interesantes beneficios. No tienes que preocuparte sobre tener que lidiar con la librería gráfica con tu aplicación para acceder a los datos de entrada. Además, puedes recortar CEGUI como quieras en el "bucle de entrada" no proporcionando ningún dato de entrada. Tampoco estas atado a una librería de entrada o API en concreto; puedes usar lo que necesites: OIS, SDL, DirectInput, Win32 o XWindows. Tu eliges. En este artículo usamos OIS para manejar los eventos de entrada.

Los archivos de datos de CEGUI


Como he mencionado, eres perfectamente capaz de definir tus fontos de la interfaz gráfica por código, pero el método más habitual es mediante varias archivos XML que CEGUI consume como datos de entrada. Estos archivos definen los "esquemas", "la apariencia", "el fondo", "los conjuntos de imagen" y las fuentes de pantalla que CEGUI mostrará.

  • Esquema (Scheme) : Definición de elementos de interfaz gráfica que son válidos en un "scheme" particular, por ejemplo botones, cajas de texto, y demás. Se guardan en archivos .scheme.
  • Apariencia (look-and-feel) : Definición del modo en que cada elemento de la interfaz gráfica se presenta en la pantalla, incluidos sus fondos, texturas usandas en su renderizado. Son los archivos .looknfeel.
  • Fondo (Layout) : Define la posición, tamaño , relación en la jerarquía y otras propiedades usadas para mostrar los elementos actuales de la interfaz gráfica en una única unidad: la "sheet" UI (hoja). Se guarda en archivos .layout.
  • Conjuntos de Imagen (Imageset) : Definen las texturas usadas en un esquema, y las coordenadas UV que son mapeadas para los elementos quads de la interfaz gráfica en la pantalla. Se guardan en archivos .imageset.
  • Fuentes Tipográficas (Font) : Debería ser obvio; CEGUI necesita saber donde encontrar las fuentes que intentas usar para tu texto, incluidas las definiciones de glyphs y las texturas de fuente a usar. Son los archivos .font.


en el archivo de datos de recursos gui.zip que acompaña al código de este artículo, encontrarás muchos ejemplos de todos estos tipos de archivos. Mira a través de cada tipo de archivo y verás que contiene - Son sólo archivos XML. Su formato y contenido deberían ser evidentes una vez que los has examinado un poco - sino, mira el sitio de CEGUI donde tienes documentación. Este artículo usa el esquema "TaharezLookSkin". (El nombre "Taharez" viene por el nombre de la persona que creó el esquema, la apariencia, la textura y el conjunto de imagen para el esquema).

El Sistema de Skinning de Falagard


Hay otra parte de CEGUI que funciona por detrás de las scenas, pero que comenzó con CEGUI 0.5.x (la versión usada en este artículo), es el núcleo de sus operaciones). El sistema de skinning de "Falagard" fue pensado como una forma de eliminar la necesidad de crear un módulo de código separado (DLL) que fue usado para ensamblar y renderizar cada esquema diferente y la apariencia. Como verás en los foros de Ogre la persona responsable de su creación fue Falagard. Este método de skinning de interfaz gráfica es una generalización, un modo conducido por datos de renderizar los elementos gráficos sin tener un autor especial de código.

El Código


Vayamos al código. Si has seguido esta serie de tutoriales, estaras familiarizado con el código que produce una ventana de renderizado en blanco y espera que pulses la tecla ESC para salir. En esta versión del código, la ventana en blanco es reemplazada por un fondo que hemos usado en nuestra fase de prueba de concepto como una página de menú principal minimalista. Contiene tres botones, sólo uno de los cuales hace algo. Ese botón (el botón de "Quit" (Salir)) te permite, además de con la tecla ESC, salir.

Los Datos


Miremos los archivos de datos vitales para CEGUI usados en este artículo: el archivo layout. Hay más de una herramienta de edición de fondos visuales de CEGUI, y cada una es diferente, así que encontrarás más simple editar los archivos XML .layout a mano.

En el archivo gui.zip en el directorio de resource/ bajo Debug en la distribución de fuentes, encontrarás un archivo llamado "katana.layout". Aquí estan los contenidos de ese archivo por completo:

<?xml version="1.0" ?>
 
<GUILayout>
 
    <Window Type="TaharezLook/FrameWindow" Name="Main">
 
            <Property Name="UnifiedAreaRect" Value="{{0.0,0},{0.0,0},{1.0,0},{1.0,0}}" />
 
            <Property Name="FrameEnabled" Value="false" />
 
            <Property Name="TitlebarEnabled" Value="false" />
 
            <Property Name="CloseButtonEnabled" Value="False" />
 
        <Window Type="TaharezLook/Button" Name="cmdQuit">
 
            <Property Name="Text" Value="Quit" />
 
               <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.7,0},{0.6,0},{0.77,0}}" />
 
        </Window>
 
        <Window Type="TaharezLook/Button" Name="cmdOptions">
 
               <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.6,0},{0.6,0},{0.67,0}}" />
 
            <Property Name="Text" Value="Options" />
 
        </Window>
 
        <Window Type="TaharezLook/Button" Name="cmdInstantAction">
 
               <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.5,0},{0.6,0},{0.57,0}}" />
 
            <Property Name="Text" Value="Instant Action" />
 
        </Window>
 
    </Window>
 
</GUILayout>
La primera cosa que te darás cuenta (probablemente). como con CEGUI 0.5.x, el único modo de definir elementos UI es con el sistema de Dimensión Unificada, en este archivo de fondo, estamos usando UnifiedAreaRect, el cual es una serie de parejas de números que definen el left, top, right y boton de tu elemento de UI. Las parejas de números son establecidas para permitirte definir tu dimensión en términos de absolutas o relativas, en el espacio del elemento contenedor. Por ejemplo, la definición del rectángulo:
{{0.4,0},{0.5,0},{0.6,0},{0.57,0}}
le dice a CEGUI que, en el "espacio" del elemento padre (en este caso, la FrameWindow que hace de contenedor de primer nivel de la hoja entera de la GUI), queremos colocar nuestro elemento (en el caso de este conjunto de números que he robado del fondo, el botón "Instant Action") 40% (0.4) desde la izquierda (left) del FrameWindow, y 50% (0.5) desde la parte superior (top) (usando la esquina superior izquierdadel botón como su origen). El ancho del botón será 20% (0.2, o "0.6 - 0.4") del ancho de su contenedor, con su altura del 7% de la altura de su padre (0.07). Si quiero definir el tamaño de los botones en términos absolutos, podíamos haber usado estos números en su lugar (e insertar el valor en píxeles en vez de sus coordenadas relativas).
También puedes combinar valores relativos y absolutos en el modo que más te guste; no importa el orden de precedencia si especificas ambos para una dimensión particular.

Las primeras líneas en el fondo le dicen a CEGUi que queremos llamar a nuestra ventana de alto nivel ("Main"), y que queremos la pantalla completa - (0,0) a (1,1) en términos relativos. No queremos ver su barra de título (que está activa por defecto), su botón de cierre "X" (por defecto) o su frame (por defecto). Colocamos tres botones en la pantalla, en el centro, organizados de arriba a abajo (pero no en el orden en el que aparecen en el archivo - cuando ejecutes la aplicación se mostrará "Instant Action", luego "Options", y más tare "Quit" de arriba a abajo). El botón "Name" de parámetro es importante - es donde engancharemos las acciones del botón (una pulsación de ratón por ejemplo) en el código, como veremos brevemente.

Y entonces, ahora el Código


Resaltaré los cambios hechos al código para integrar CEGUI en la aplicación. Primero, en la main.cpp, algunas cabeceras adicionales:
// necesitado para ser capaz de crear una interfaz de renderizado de CEGUI
 
#include "OgreCEGUIRenderer.h"
 
// includes de CEGUI
 
#include "CEGUISystem.h"
 
#include "CEGUIInputEvent.h"
 
#include "CEGUIWindow.h"
 
#include "CEGUIWindowManager.h"
 
#include "CEGUISchemeManager.h"
 
#include "CEGUIFontManager.h"
 
#include "elements/CEGUIFrameWindow.h"
CEGUI 0.7.1 (realmente 0.7.0) introdujo varios cambios que, en mi opinión, limpian la apariencia del código un poco. Incluso si no estas de acuerdo, hay todavía algunos cambios que hay que tener en cuenta si estas usando 0.7.0+. Debajo está la sección include que debe ser usada si estas usando CEGUI 0.7.1:
#include "RendererModules/Ogre/CEGUIOgreRenderer.h"
 
// include de CEGUI
 
#include "CEGUISystem.h"
 
#include "CEGUIInputEvent.h"
 
#include "CEGUIWindow.h"
 
#include "CEGUIWindowManager.h"
 
#include "CEGUISchemeManager.h"
 
#include "CEGUIFontManager.h"
 
#include "elements/CEGUIFrameWindow.h"
En este caso, el primer include ha sido cambiado porque el OgreRenderer no será más una parte automática de la versión de Ogre, pero ha sido dejado en el código de CEGUI con un nombre cambiado para que coincida con el patrón de otros renderizadores incluidos en ese paquete. Resalto los cambios que deben ser hechos usando 0.7.1.

Crearemos una instancia del renderizador GUI, así que necesitamos referenciar su cabecera. Encontrarás la cabecera en el SDK o en el fuente de ogre bajo Samples/include (que fue añadido a las rutas de directorios include adionales del proyecto). las cabeceras CEGUI pueden ser encontradas en el SDK bajo include/CEGUI (que ha sido añadido a las rutas include). Usa para verlos "CEGUI/CEGUISystem.h", aunque fue abandonado en CEGUI- Todos estos archivos CEGUI ahora tienen el prefijo del directorio eliminado. Si estas teniendo problemas ara compilar siéntete libre de incluir ambos "include/CEGUI" e "include" (donde "include" contiene el subdirectorio "CEGUI"). Probablemente no necesito incluir el archivo "elements/CEGUIFrameWindow.h".

Inicializando CEGUI


main.cpp

// con un manejador de escena y una ventana, podemos crear un renderizador GUI
 
    CEGUI::OgreCEGUIRenderer* pGUIRenderer = new CEGUI::OgreCEGUIRenderer(
 
        window,                    // la ventana de renderizador creada anteriormente
 
        Ogre::RENDER_QUEUE_OVERLAY,        // CEGUI deberia renderizar en esta cola de renderizado
 
        false,                    // ponlo todo en la anterior cola de renderizado
 
        3000,                    // esto es innecesario en CEGUI actualmente -- numero max. quads
 
        sceneMgr                // usa este scenemanager para es UI
 
    );
 
    // crea la clase root CEGUI
 
    CEGUI::System* pSystem = new CEGUI::System(pGUIRenderer);
 
 
    // le decimos donde esta (mira CEGUI.log en el directorio de trabajo)
 
    CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative);
 
    // usa este esquema de definicion CEGUI (mira los docs de CEGUI)
 
    CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLookSkin.scheme", (CEGUI::utf8*)"GUI");
 
    // muestra el cursor de raton de CEGUI (definido en el look-n-feel)
 
    pSystem->setDefaultMouseCursor((CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)"MouseArrow");
 
    // usa esta fuente para el texto en la UI
 
    CEGUI::FontManager::getSingleton().createFont("Tahoma-8.font", (CEGUI::utf8*)"GUI");
 
    pSystem->setDefaultFont((CEGUI::utf8*)"Tahoma-8");
 
    // carga un fondo desde el archivo de fondo XML (lo encontrarás en resources/gui.zip), y
 
    // ponlo en el grupo de recursos de GUI
 
    CEGUI::Window* pLayout = CEGUI::WindowManager::getSingleton().loadWindowLayout("katana.layout", "", "GUI");
 
    // necesitaras decirle a CEGUI que layout mostra. Puedes llamar a este a la hora de cambiar el fondo a otro
 
    // fondo que quieras (ej: moviendo la pantalla a otra pantalla o cargando tu fondo HUD). Nota que esto toma
 
        // una instancia CEGUI::Window -- podrás usar todo (cualquier widget) que sirva como una ventana raiz.
 
    pSystem->setGUISheet(pLayout);
Aquí, también hay varios cambios si estas usando CEGUI 0.7.0+. el modo en que CEGUI es inicializado fue cambiado y es mucho más simple de leer. Debajo está el código de CEGUI para esta sección.
// con un manejador de escena y una ventana, podemos crear un renderizador de GUI.
    // un nuevo modo de instanciar un CEGUIOgreRenderer (Ogre 1.7)
 
    Ogre::RenderTarget *mRenderTarget = window;
 
    CEGUI::OgreRenderer* pGUIRenderer = &CEGUI::OgreRenderer::bootstrapSystem(*mRenderTarget);
 
    // crea la clase root de CEGUI
 
    CEGUI::System* pSystem = CEGUI::System::getSingletonPtr();
 
 
    // le decimos donde esta (mira CEGUI.log en el directorio de trabajo)
 
    CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative);
 
    // usa este esquema de definicion CEGUI (mira los docs de CEGUI)
 
    CEGUI::SchemeManager::getSingleton().create((CEGUI::utf8*)"TaharezLookSkin.scheme", (CEGUI::utf8*)"GUI");
 
    // muestra el cursor de raton de CEGUI (definido en el look-n-feel)
 
    pSystem->setDefaultMouseCursor((CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)"MouseArrow");
 
 
    // usa esta fuente para el texto en la UI
 
    CEGUI::FontManager::getSingleton().create("Tahoma-8.font", (CEGUI::utf8*)"GUI");
 
    pSystem->setDefaultFont((CEGUI::utf8*)"Tahoma-8");
 
 
    // carga un fondo desde un archivo layout XML (lo encontraras en resources/gui.zip), y
 
    // lo pondras en el grupo de recurso de GUI
 
    CEGUI::Window* pLayout = CEGUI::WindowManager::getSingleton().loadWindowLayout("katana.layout", "", "GUI");
 
 
    // necesitas decir a CEGUI que fondo mostrar. Puedes decirselo a la hora de cambiar el fondo a
 
    // otro fondo cargado (ej: moviendo la pantalla a otra pantalla o cargando tu fondo HUD). Date cuenta de que esto
 
    // coge una instancia de CEGUI::Window -- puedes usar cualquier cosa (como control) que sirve como ventana root.
 
    pSystem->setGUISheet(pLayout);
Los cambios importantes aquí son el nuevo modo de instanciar el OgreRenderer CEGUI. Date cuenta de que el nombre de la clase ha cambiado de CEGUI::OgreCEGUIRenderer a CEGUI::OgreRenderer. Además la gran llamada a la función de inicialización ha sido reducida a una bonita función con un único parámetro, además de manejar un número de características de inicialización basadas en lo que le pases. la sección de inicialización:
Ogre::RenderTarget *mRenderTarget = window;
 
    CEGUI::OgreRenderer* pGUIRenderer = &CEGUI::OgreRenderer::bootstrapSystem(*mRenderTarget);
 
 
    // crea la clase del root de CEGUI
 
    CEGUI::System* pSystem = CEGUI::System::getSingletonPtr();
Necesitamos un puntero a objetivo de renderizado de Ogre (RendererTarget) en vez de una ventana de Ogre. La función bootstrapSystem extrapolará toda esta información que has usado al viejo método de instanciación.

Todavía queremos un puntero al Sistema CEGUI.

Este código está comentado así que no hay mucho que decir. Date cuenta de que la ventana de renderizado de Ogre que fue creada en main.cpp ("window") así como el manejador de escena ("scenemagr") podrás encontrar ete código en main.cpp siguiendo la creación e instalación de estos objetos.

Soporte de entrada para CEGUI


Hemos necesitado cambiar la firma de la clase InputHandler para tomar un parámetro adicional: un puntero a la instancia de CEGUI::System que hemos creado en main.cpp. Esto es así porque ahora el manejador de entrada es responsable de empujar los eventos de entrada en CEGUI:

input.cpp

// MouseListener
 
bool InputHandler::mouseMoved(const OIS::MouseEvent &evt) {
 
    m_pSystem->injectMouseWheelChange(evt.state.Z.rel);
 
    return m_pSystem->injectMouseMove(evt.state.X.rel, evt.state.Y.rel);
 
}
 
bool InputHandler::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID btn) {
 
    CEGUI::MouseButton button = CEGUI::NoButton;
 
 
    if (btn == OIS::MB_Left)
 
        button = CEGUI::LeftButton;
 
    if (btn == OIS::MB_Middle)
 
        button = CEGUI::MiddleButton;
 
    if (btn == OIS::MB_Right)
 
        button = CEGUI::RightButton;
 
    return m_pSystem->injectMouseButtonDown(button);
 
}
 
bool InputHandler::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID btn) {
 
    CEGUI::MouseButton button = CEGUI::NoButton;
 
 
    if (btn == OIS::MB_Left)
 
        button = CEGUI::LeftButton;
 
 
    if (btn == OIS::MB_Middle)
 
        button = CEGUI::MiddleButton;
 
 
    if (btn == OIS::MB_Right)
 
        button = CEGUI::RightButton;
 
 
    return m_pSystem->injectMouseButtonUp(button);
 
}
 
// KeyListener
 
bool InputHandler::keyPressed(const OIS::KeyEvent &evt) {
 
    unsigned int ch = evt.text;
 
 
    m_pSystem->injectKeyDown(evt.key);
 
    return m_pSystem->injectChar(ch);
 
}
 
bool InputHandler::keyReleased(const OIS::KeyEvent &evt) {
 
    if (evt.key == OIS::KC_ESCAPE)
 
        m_simulation->requestStateChange(SHUTDOWN);
 
 
    return m_pSystem->injectKeyUp(evt.key);
 
}
Date cuenta: Devolviendo los resultados de injectChar y injectKeyUp puede resultar en pulsaciones de tecla siendo perdidas cuando se teclea rápidamente. Deberías querer devolver true en su lugar, así que todas las teclas del búfer seran procesadas.

Resulta evidente como los eventos de entrada para a CEGUI desde su código - las llamas "inject***" en el código anterior (que son métodos de CEGUI::System). Puedes hacer estas llamadas desde donde quieras que se acceda a los eventos de entrada; He hecho la clase de manejo de la entrada porque es conveniente y el resto de la aplicación realmente no tiene que preocuparse sobre el resto - Esto será notificado a través de acciones de UI a través de una ruta diferente.

main.cpp

    // ya que el manejador de entrada trata con la entrada a CEGUI, necesitamos darle un puntero
 
    // a la instancia en uso del sistema CEGUI
 
    InputHandler *handler = new InputHandler(pSystem, sim, hWnd);
 
    // ponemos nuestro estado "main menu" (menu principal)
 
    sim->requestStateChange(GUI);
También cambiamos al estado "GUI" en lugar de "SIMULATION" como hicimos en el artículo previo - en una aplicación normal deberías ir primero al estado "main menu" en lugar de ir directamente al juego, así este estado cambia siguiendo ese patrón. Deberías también tratar con la creación de una clase para tratar con las acciones de UI en tu manejador de estado; sólo tenemos que hacer esto en el main.cpp:
// hace una instancia de nuestra clase de manejo de hoja de GUI
 
    MainMenuDlg* pDlg = new MainMenuDlg(pSystem, pLayout, sim);
Esta clase de manejo de acción es nueva en este artículo; encontrarás su declaración y definición en MainMenuDlg.h y .cpp:

MainMenuDlg.h


#pragma once
 
#include "CEGUIWindow.h"
 
namespace CEGUI
 
{
    class System;
    class Window;
}
 
class Simulation;
 
 
class MainMenuDlg
 
{
 
public:
 
    MainMenuDlg(CEGUI::System* pSystem, CEGUI::Window* pSheet, Simulation* pSimulation);
 
    ~MainMenuDlg();
 
    // los manejadores de eventos de CEGUI. Puedes nombrar a estos como te guste
 
    // firma: bool <nombre metodo>(const CEGUI::EventArgs &args)
 
    bool Quit_OnClick(const CEGUI::EventArgs &args);
 
    bool Options_OnClick(const CEGUI::EventArgs &args);
 
    bool Launch_OnClick(const CEGUI::EventArgs &args);
 
private:
 
    CEGUI::System* m_pSystem;    // puntero a la instancia del sistema CEGUI
 
    CEGUI::Window* m_pWindow;    // puntero a la hoja de fondo de la ventana
 
    Simulation* m_pSimulation;    // puntero al controlador de Simulacion
 
};

MainMenuDlg.cpp

#include "MainMenuDlg.h"
 
#include "Simulation.h"
 
#include "CEGUISystem.h"
 
#include "CEGUIWindow.h"
 
#include "CEGUIWindowManager.h"
 
#include "elements/CEGUIPushButton.h"
 
 
MainMenuDlg::MainMenuDlg(CEGUI::System *pSystem, CEGUI::Window *pSheet, Simulation *pSimulation)
 
{
 
    m_pSystem = pSystem;
 
    m_pWindow = pSheet;
 
    m_pSimulation = pSimulation;
 
    // enlace de los manejadores de evento a los elementos de ventana
 
    CEGUI::PushButton* pQuitButton = (CEGUI::PushButton *)CEGUI::WindowManager::getSingleton().getWindow("cmdQuit");
 
    pQuitButton->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&MainMenuDlg::Quit_OnClick, this));
 
    CEGUI::PushButton* pOptionsButton = (CEGUI::PushButton *)CEGUI::WindowManager::getSingleton().getWindow("cmdOptions");
 
    pOptionsButton->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&MainMenuDlg::Options_OnClick, this));
 
    CEGUI::PushButton* pLaunchButton = (CEGUI::PushButton *)CEGUI::WindowManager::getSingleton().getWindow("cmdInstantAction");
 
    pLaunchButton->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&MainMenuDlg::Launch_OnClick, this));
 
}
 
MainMenuDlg::~MainMenuDlg()
 
{
 
}
 
bool MainMenuDlg::Quit_OnClick(const CEGUI::EventArgs &args)
 
{
 
    m_pSimulation->requestStateChange(SHUTDOWN);
 
    return true;
 
}
 
bool MainMenuDlg::Launch_OnClick(const CEGUI::EventArgs &args)
 
{
 
    return true;
 
}
 
bool MainMenuDlg::Options_OnClick(const CEGUI::EventArgs &args)
 
{
 
    return true;
 
}
Las dos cosas principales a observar son (a) como los métodos del manejador de acción son enlazados a los eventos de CEGUI, y (b) que manejamos el click del botón "Quit" (Salir) diciendo a la aplicación que apague (al igual que hicimos con el manejador de tecla presionada de ESC). Si te sientes encorsetado, puedes hacer tus propios fondos y añadir código a otros manejadores (Launch_OnClick y Options_OnClick) a las diferentes hojas de estilo de GUI que se muestran (usando llamadas a "loadWindowLayout" como en el anterior main.cpp).

Conclusión


No hay mucho más que eso realmente - como instales tus manejadores de acción UI, y como trates la entrada en CEGUI, es cosa tuya. Puedes usar el código aquí, o crear el tuyo.

Descarga del Código


Como he mencionado, he migrado el código a proyectos a Ogre 1.4.x (Eihort) y también al formato VC8. Puedes descargar el código y debería compilarse bien si tienes el Ogre 1.4.x SDK instalado (y si estas usando VC8, claro). Deberías necesitar cambiar el directorio de trabajo en Visual Studio, y necesitarás una copia del archivo gui.zip desde la carpteta Debug en el árbol del código fuente PracticalApp a la carpeta "resource" en $(OGRE_HOME)/bin/Debug (necesitarás crear esta carpeta). también puedes ejecutarlo desde la carpeta Debug en PracticalApp si tu PATH contiene $(OGRE_HOME)/bin/Debug.

CEGUI 0.7.1 nota


El anterior código enlazado en la sección de descargas no es para 0.7.1. .Aquí está el nuevo gui.zip que puedes usar con este tutorial y CEGUI 0.7.1.