'게임 프로그래밍/ogreEngine'에 해당되는 글 8건

  1. 2010.03.27 기초 튜토리얼8
  2. 2010.03.27 기초 튜토리얼7
  3. 2010.03.27 기초 튜토리얼6
  4. 2010.03.27 기초 튜토리얼5
  5. 2010.03.27 기초 튜토리얼4
  6. 2010.03.27 기초 튜토리얼3
  7. 2010.03.27 기초 튜토리얼2
  8. 2010.03.27 기초 튜토리얼1
2010.03.27 17:28

입문자 튜토리얼 8: 다중 Scene Manager 다루기

튜토리얼 진행중 문제가 발생한다면 Help 포럼 문의하세요.

Contents

*                               1 소개

*                               2 미리 준비해야할

*                               3 프로그램 설정

*                                       3.1 SceneManager 생성

*                                       3.2 Camera 생성

*                                       3.3 Viewport 생성

*                                       3.4 Scene 생성

*                               4 기능 추가하기

*                                       4.1 듀얼 SceneManager

*                                       4.2 SceneManager 서로 바꾸기

*                               5 결론

*                                       5.1 Overlays

*                                       5.2 One Last Note

 

소개

이번 간략한 튜토리얼에서는 어떻게 다수의 scene manager 들을 서로 바꾸는지에 대한 내용을 다루게 됩니다.

튜토리얼에 대한 코드는 여기(http://www.ogre3d.org/wiki/index.php/BasicTutorial8Source) 찾을 있습니다. 코드를 천천히 입력하면서 나오는 결과물을 직접 눈으로 확인하세요

 

미리 준비해야할

cpp파일을생성하고 다음 코드를 추가하세요 :

#include "ExampleApplication.h"

#define CAMERA_NAME "SceneCamera"

 

void setupViewport(RenderWindow *win, SceneManager *curr)

{

}

 

void dualViewport(RenderWindow *win, SceneManager *primary, SceneManager *secondary)

{

}

 

class SMTutorialListener : public ExampleFrameListener, public OIS::KeyListener

{

public:

    SMTutorialListener(RenderWindow* win, SceneManager *primary, SceneManager *secondary)

        : ExampleFrameListener(win, primary->getCamera(CAMERA_NAME), true, false),

          mPrimary(primary), mSecondary(secondary), mDual(false), mContinue(true)

    {

        mKeyboard->setEventCallback(this);

    }

 

    bool frameStarted(const FrameEvent& evt)

    {

        mKeyboard->capture();

        return mContinue;

    }

 

    bool keyPressed(const OIS::KeyEvent &arg)

    {

       switch (arg.key)

       {

       case OIS::KC_ESCAPE:

           mContinue = false;

           break;

 

       default:

           break;

       }

 

       return true;

    }

 

    bool keyReleased(const OIS::KeyEvent &) {return true;}

 

private:

    SceneManager *mPrimary, *mSecondary;

    bool mDual, mContinue;

 

    static void swap(SceneManager *&first, SceneManager *&second)

    {

        SceneManager *tmp = first;

        first = second;

        second = tmp;

    }

};

 

class SMTutorialApplication : public ExampleApplication

{

public:

    SMTutorialApplication()

    {

    }

 

    ~SMTutorialApplication()

    {

    }

protected:

    SceneManager *mPrimary, *mSecondary;

 

    void chooseSceneManager(void)

    {

    }

 

    void createCamera()

    {

    }

 

    void createViewports()

    {

    }

 

    void createScene(void)

    {

    }

 

    void createFrameListener(void)

    {

        mFrameListener = new SMTutorialListener(mWindow, mPrimary, mSecondary);

        mFrameListener->showDebugOverlay(true);

        mRoot->addFrameListener(mFrameListener);

    }

};

 

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32

#define WIN32_LEAN_AND_MEAN

#include "windows.h"

 

INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT)

#else

int main(int argc, char **argv)

#endif

{

    // Create application object

    SMTutorialApplication app;

 

    try {

        app.go();

    } catch(Exception& e) {

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32

        MessageBoxA(NULL, e.getFullDescription().c_str(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL);

#else

        fprintf(stderr, "An exception has occurred: %s\n",

            e.getFullDescription().c_str());

#endif

    }

 

    return 0;

}

컴파일이 제대로 되는지 확인은 하시되 지금시점에서 실행은 되지않으므로 에러가 없다면 넘어갑니다.

 

Trackback 0 : Comment 0

기초 튜토리얼 8-2

Ogre3D 삽질란/Basic Tutorial 8 2008/12/05 10:36

프로그램 설정

SceneManager 생성

SceneManager 선택하는방법에 대해서는 앞서 다룬적이 있습니다. 그러므로 부분에 대해서는 생략합니다. 여기서 다루는 내용과의 차이점은 2개의 SceneManager 생성한다는 입니다. chooseSceneManager함수에 다음 코드를 추가하세요 :

       mPrimary = mRoot->createSceneManager(ST_GENERIC, "primary");

       mSecondary = mRoot->createSceneManager(ST_GENERIC, "secondary");

 

Camera 생성

다음으로 해야 일은 각각의 SceneManager 대한 카메라 객체를 생성하는 입니다. 이전 튜토리얼과의 차이점은 같은 이름으로 2개의 카메라를 생성한다는 뿐입니다. createCamera함수에 다음 코드를 추가하세요 :

       mPrimary->createCamera(CAMERA_NAME);

       mSecondary->createCamera(CAMERA_NAME);

 

Viewport 생성

뷰포트 생성에 있어서 잠시 이전 튜토리얼에서 다룬 내용을 집고 넘어가겠습니다. 뷰포트생성시 2가지 사항을 지켜야 합니다 : 뷰포트 자체에대한 설정을 다음에 실제로 쓰일 카메라의 화면좌우비율을 설정해야 합니다. 다음 코드를 createViewports 함수에 추가하고 계속 진행합니다 :

       setupViewport(mWindow, mPrimary);

뷰포트를 설정하는 코드를 프로그램코드 어디에서나 사용할 있도록 setupViewport함수에 작성합니다. 첫번째로 해야 일은 지금까지 만들어 졌던 모든 뷰포트들을 제거하는 입니다. 비록 지금 아무것도 만들어진게 없다 하더라도 나중에 함수를 호출할때를 대비해서 새로만들 뷰포트 이전에 모든 뷰포트들을 제거하는 작업을 해야합니다. 다음 지금까지 해온 처럼 뷰포트를 설정하게 것입니다. 다음 코드를 파일의 최상위에 있는 setupViewport 함수에 추가하세요 :

   win->removeAllViewports();

 

   Camera *cam = curr->getCamera(CAMERA_NAME);

   Viewport *vp = win->addViewport(cam);

 

   vp->setBackgroundColour(ColourValue(0,0,0));

   cam->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight()));

 

Scene 생성

이제 각각의 SceneManager 표시할 장면을 생성할 차례입니다. 복잡하게 코드를 작성할 필요없이 그냥 2개의 SceneManager 바뀌었다는 것을 알아챌 있을 정도로만 만들겁니다. createScene함수에 다음 코드를 추가하세요 :

       // Setup the TerrainSceneManager

       mPrimary->setSkyBox(true, "Examples/SpaceSkyBox");

 

       // Setup the Generic SceneManager

       mSecondary->setSkyDome(true, "Examples/CloudySky", 5, 8);

이제 컴파일 해보세요. 실행시켜봐도 좋습니다. 다만 ESC키를 누르면 프로그램이 종료된다는 기능밖에는 없습니다.

 

기능 추가하기

듀얼 SceneManager

첫번째로 넣을 기능중 하나는 2개의 SceneManager 나란히 옆으로 위치하면서 화면에 출력하는 기능입니다. V키를 누르면 듀얼 뷰포트모드를 토글할 있습니다. 기본적인 설계는 간단합니다. 듀얼 뷰포트모드를 끄려면 그냥 setupViewport(앞서 작성한 내용)함수에 primary SceneManager 넘겨주며 뷰포트를 싱글모드로 다시 생성합니다. 켜기 위해서는 새로운 함수인 dualViewport함수를 호출하게 됩니다. 뷰포트모드상태를 감시하기위해 mDual 변수가 사용됩니다. 다음 코드를 keyPressed 함수의 switch구문 내부에 추가하세요 :

       case OIS::KC_V:

           mDual = !mDual;

 

           if (mDual)

               dualViewport(mWindow, mPrimary, mSecondary);

           else

               setupViewport(mWindow, mPrimary);

 

           break;

이제 mDual변수내용을 반전시키고 그에 따른 모드에 맞는 적절한 함수를 호출하게 됩니다. 이제 2개의 뷰포트들을 동시에 다루는 dualViewport함수를 정의합니다.

2개의 SceneManager 나란히 출력되기 위해서 해야 일은 setupViewport함수에 작성했던 내용과 기본적으로 동일합니다. 다른점이 하나 있다면 2개의 뷰포트를 생성한다는 입니다. 그리고 생성했던 2개의 SceneManager들에는 각각 하나의 카메라만 존재합니다. 다음 코드를 dualViewport함수에 추가하세요 :

   win->removeAllViewports();

 

   Viewport *vp = 0;

   Camera *cam = primary->getCamera(CAMERA_NAME);

   vp = win->addViewport(cam, 0, 0, 0, 0.5, 1);

   vp->setBackgroundColour(ColourValue(0,0,0));

   cam->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight()));

 

   cam = secondary->getCamera(CAMERA_NAME);

   vp = win->addViewport(cam, 1, 0.5, 0, 0.5, 1);

   vp->setBackgroundColour(ColourValue(0,0,0));

   cam->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight()));

addViewport함수에 새롭게 추가된 매개변수를 제외하고는 익숙한 코드입니다. 첫번째 매개변수는 계속해서 쓰일 카메라입니다. 두번째 매개변수는 뷰포트의 z 위치입니다. z 높이값이 높을수록 위에 위치하게 됩니다. 유의점으로는 같은 z 높이값에 2 이상의 뷰포트가 존재할 없다는 입니다. 겹치지 않더라도 예외는 없습니다. 이어지는 2개의 매개변수들은 뷰포트의 좌측 상단위치 입니다. 값들은 0~1 사이의 값을 가집니다. 마지막으로 남은 2개의 매개변수들은 width height값의 화면상 %비율 입니다( 값들 역시 0~1사이의 값을 가집니다). 그러므로 경우에는 첫번째 뷰포트는 좌표(0, 0)부터 수평으로는 절반크기에 수직으로는 꽉차게 위치하게 됩니다. 두번째 뷰포트는 좌표(0.5, 0)부터 남아있는 절반 수평넓이에 꽉찬 수직크기를 가집니다.

컴파일 실행시켜 보세요. V키를 누르면 2개의 SceneManager 동시에 출력시킬 있게 됩니다.

 

SceneManager 서로 바꾸기

마지막으로 추가할 기능은 C키를 누르면 2개의 SceneManager 언제라도 바꿀 있게끔 하는 기능을 추가하는 것입니다. 구현하는 방법은 setupViewport 또는 dualViewport 호출될때 mPrimary mSecondary 변수값을 바꾸는 입니다. 어떤 SceneManager 어떤 변수에 저장되어 있는지는 걱정하지 마세요. 첫번째 SceneManager 항상 싱글모드에서 출력되고 듀얼모드에서는 항상 좌측에 위치할 입니다. 다음 코드를 keyPressed함수의 switch구문 안에 추가하세요 :

       case OIS::KC_C:

           swap(mPrimary, mSecondary);

변수값이 바뀐 바뀐값을 프로그램에 적용시켜야 합니다. 듀얼모드 또는 싱글모드에 따라서 적절한 뷰포트 셋업함수를 호출하면 됩니다 :

           if (mDual)

               dualViewport(mWindow, mPrimary, mSecondary);

           else

               setupViewport(mWindow, mPrimary);

           break;

완성입니다! 컴파일 실행시켜보세요. C키를 누르면 SceneManager 바꾸고 V키를 누르면 싱글, 듀얼모드로 토글됩니다.

Trackback 0 : Comment 0

기초 튜토리얼 8-3 (마지막)

Ogre3D 삽질란/Basic Tutorial 8 2008/12/05 10:35

결론

Overlays

듀얼 뷰포트모드로 프로그램을 실행하면 오우거 디버그오버레이가 양쪽에 모두 출력되는걸 보게 될겁니다. 뷰포트 1개별로도 오버레이를 그리지 않게끔 해줄 있어야 합니다. 그럴경우 Viewport::setOverlaysEnabled함수로 켜고 끄도록 합니다. 작은 수정을 적용한 코드를 여기(http://www.ogre3d.org/wiki/index.php/BasicTutorial8Source) 작성해 두었습니다. 어떻게 적용해야 모르겠다면 참고하세요.

 

One Last Note

뷰포트클래스자체는 기능이 별로없지만 오우거렌더링에 있어서 아주 중요한 부분입니다. SceneManager 얼마나 많이 생성하는지, 카메라를 SceneManager마다 몇개를 생성하는지는 중요하지 않습니다. 장면을 비추는 카메라에 뷰포트가 설정되지 않는다면 결국 그려지는건 아무것도 없습니다. 그리고 뷰포트를 추가로 생성하기전에 쓰지않는 뷰포트들을 지워줘야 하는것도 잊지 마세요.

출처 : http://begin.pe.kr/category/Ogre3D%20삽질란/Basic%20Tutorial%208

신고
Posted by 우엉 여왕님!! ghostkyow
2010.03.27 17:27

입문자 튜토리얼  7: CEGUI and Ogre

튜토리얼 진행중 문제가 발생한다면 Help 포럼 문의하세요.

Contents

*                               1 미리 알아두어야

*                               2 소개

*                               3 시작하기

*                                       3.1 초기 코드

*                                       3.2 코드 컴파일

*                                       3.3 간략한 소개

*                               4 오우거에 통합시키기

*                                       4.1 CEGUI 초기화

*                                       4.2 이벤트 넣기

*                                       4.3 마우스 이벤트 넣기&변환

*                               5 , 시트, 위젯

*                                       5.1 소개

*                                       5.2 시트 읽어들이기

*                                       5.3 수동으로 객체 생성하기

*                               6 이벤트

*                               7 텍스쳐 렌더링하기

*                               8 결론

*                                       8.1 대안으로 쓸만 것들

*                                       8.2 자세한 정보

 

미리 알아두어야

튜토리얼은 독자가 C++ 프로그래밍이 가능하고 오우거 어플리케이션 설정 컴파일이 가능하다는 가정하에 진행됩니다. 튜토리얼은 이전 튜토리얼을 기초로 작성되었으며 독자는 이전 튜토리얼들을 거쳐왔다고 가정합니다.

소개

이번 튜토리얼에서는 오우거에서 어떻게 CEGUI(내장형 GUI 시스템) 있는지 살펴봅니다. 튜토리얼이 끝날때 여러분은 CEGUI 기초적인 기능을 프로그램에 추가할 있게 것입니다. NOTE: 튜토리얼에서는 CEGUI 모든 기능을 가르쳐 주지 않습니다. 단지 시작할 있게 도와줄 뿐입니다. CEGUI 대한 질문이나 도움요청은 공식 CEGUI홈피(http://www.cegui.org.uk/wiki/index.php/Main_Page) 이용해 주세요.

튜토리얼에 대한 코드는 여기(http://www.ogre3d.org/wiki/index.php/BasicTutorial7Source) 찾을 있습니다. 코드를 천천히 입력하면서 나오는 결과물을 직접 눈으로 확인하세요.

 

시작하기

 

초기 코드

튜토리얼에서는 미리 작성된 코드로 부터 시작 것입니다. 지금까지 튜토리얼을 진행해 처럼 이러한 방식은 익숙하리라 생각합니다. 프로젝트를 생성하고 아래 소스코드를 입력하세요 :

#include "ExampleApplication.h"

#include <CEGUI/CEGUI.h>

#include <OIS/OIS.h>

#include <OgreCEGUIRenderer.h>

 

class TutorialListener : public ExampleFrameListener, public OIS::MouseListener, public OIS::KeyListener

{

public:

    TutorialListener(RenderWindow* win, Camera* cam)

        : ExampleFrameListener(win, cam, true, true)

    {

       mContinue=true;

       mMouse->setEventCallback(this);

       mKeyboard->setEventCallback(this);

    } // CEGUIDemoListener

 

    bool frameStarted(const FrameEvent &evt)

    {

        mKeyboard->capture();

        mMouse->capture();

 

        return mContinue && !mKeyboard->isKeyDown(OIS::KC_ESCAPE);

    }

 

    bool quit(const CEGUI::EventArgs &e)

    {

        mContinue = false;

        return true;

    }

 

    // MouseListener

    bool mouseMoved(const OIS::MouseEvent &arg)

    {

        return true;

    }

 

    bool mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id)

    {

        return true;

    }

 

    bool mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id)

    {

        return true;

    }

 

    // KeyListener

    bool keyPressed(const OIS::KeyEvent &arg)

    {

        return true;

    }

 

    bool keyReleased(const OIS::KeyEvent &arg)

    {

        return true;

    }

 

private:

    bool mContinue;

};

 

 

class CEGUIDemoApplication : public ExampleApplication

{

public:

    CEGUIDemoApplication()

        : mSystem(0), mRenderer(0)

    {

    }

 

    ~CEGUIDemoApplication()

    {

        if (mSystem)

            delete mSystem;

 

        if (mRenderer)

            delete mRenderer;

    }

protected:

   CEGUI::System *mSystem;

   CEGUI::OgreCEGUIRenderer *mRenderer;

 

    void createScene(void)

    {

    }

 

    void createFrameListener(void)

    {

        mFrameListener= new TutorialListener(mWindow, mCamera);

        mFrameListener->showDebugOverlay(true);

        mRoot->addFrameListener(mFrameListener);

    }

 

};

 

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32

#define WIN32_LEAN_AND_MEAN

#include "windows.h"

 

 

INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT)

#else

int main(int argc, char **argv)

#endif

{

    // Create application object

    CEGUIDemoApplication app;

 

    try {

        app.go();

    } catch(Exception& e) {

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32

        MessageBoxA(NULL, e.getFullDescription().c_str(), "An exception has occurred!",

            MB_OK | MB_ICONERROR | MB_TASKMODAL);

#else

        fprintf(stderr, "An exception has occurred: %s\n",

            e.getFullDescription().c_str());

#endif

    }

 

 

    return 0;

}

 

 

코드 컴파일

지금 시점에서 컴파일하고 실행이 되는지 확인하세요. 검은화면밖에 보이지 않을 입니다(ESC키를 누르면 종료합니다). 컴파일시 Linker에러가 발생하면 CEGUIBase_d.lib OgreGUIRenderer_d.lib 파일을 Linker 추가하세요(디버그 모드의 경우임. 릴리즈 모드의 경우에는 _d 부분을 제거).

 

간략한 소개

CEGUI 오우거와 같은 3D 어플리케이션(물론 순수 DirectX OpenGL 완벽하게 지원합니다) 내장될 있는 강력한 GUI 전용 라이브러리 입니다. 오우거가 순수 그래픽 라이브러리인 점에서 많이 닮아 있습니다(사운드나 물리연산같은 다른 기능들을 포함하지 않습니다). CEGUI GUI 라이브러리일 입니다. 무슨 의미냐면 자기 스스로 출력하는 기능도 없을 뿐더러 마우스나 키보드 이벤트를 인지하지도 못합니다. CEGUI 출력되기 위해서는 Renderer 제공되어야 합니다(오우거에서는 OgreGUIRenderer 의미하며 SDK 포함되어 있습니다). 그리고 마우스와 키보드이벤트를 인식시키려면 해당시스템에 임의적으로 삽입시켜야 합니다. 처음부터 무척 힘들게 느껴질지도 모르겠군요. 하지만 실제로는 정말 약간의 코드만 필요로 뿐입니다. 일단 통합되기만 하면 GUI 출력과 입력에 대해서 완벽한 제어를 제공합니다. CEGUI자체만으로는 절대 그렇게 하지 못할 입니다.

CEGUI 다루게 되면 처음보는 희안한 코드들(다른 GUI시스템들을 접해봤다 하더라도) 접할 입니다. 진행하면서 나오는 부분마다 차근차근 설명해 드리겠습니다.

Trackback 0 : Comment 0

기초 튜토리얼 7-2

Ogre3D 삽질란/Basic Tutorial 7 2008/12/04 17:23

오우거에 통합시키기

CEGUI 초기화

지난 튜토리얼에서 CEGUI 구동시키는 법을 간략하게나마 배웠으므로 첫부분에 대한 내용은 넘어가도록 하겠습니다. createScene함수를 찾아서 다음 코드를 추가하세요 :

       mRenderer = new CEGUI::OgreCEGUIRenderer(mWindow, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, mSceneMgr);

       mSystem = new CEGUI::System(mRenderer);

CEGUI 초기화 되었습니다. 이제 사용할 스킨을 선택해야 합니다. GEGUI 높은 수준의 커스터마이징을 지원합니다. 프로그램의 스킨을 바꿔주면서 look and feel 설정할 있도록 지원해 줍니다. 스킨에 대한 내용은 다루지 않을 계획입니다. 많은 사용법을 배우고 싶다면 CEGUI 홈페이지를 방문하세요. 다음 코드는 스킨을 선택합니다 :

CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLookSkin.scheme");

오우거설치시 기본값으로는 아무런 스킨도 설치되지 않습니다. 하지만 CEGUI CEGUI 공식홈페이지를 통해서 설치하면 몇가지 선택가능한 스킨이 포함됩니다(직접 만들 있습니다). 다음작업은 기본 마우스커서와 기본 폰트를 설정 하는 입니다 :

 

mSystem->setDefaultMouseCursor((CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)"MouseArrow");

       mSystem->setDefaultFont((CEGUI::utf8*)"BlueHighway-12");

튜토리얼 시리즈들에서는 GUI 라이브러리를 쓸일이 없더라도 모두 CEGUI 커서를 사용합니다. 다른 GUI 라이브러리를 사용해서 마우스커서를 그리거나 오우거만 이용해서 바로 그릴수 있습니다(후자 경우 복잡한 선택사항이 수도 있습니다). 만약 마우스커서 하나 때문에 CEGUI 써야 하고 메모리 사용량과 개발중인 게임의 용량이 커질까봐 걱정된다면 앞서 설명한 선택사항들을 CEGUI 바꾸는걸 고려해 있습니다.

마지막에서 작성된 코드는 마우스커서를 설정했습니다. 그러나 나중에 있을 튜토리얼들과는 다르게 MouseCursor::setImage함수를 써서 직접적으로 마우스 커서를 설정하지 않았습니다. 튜토리얼에서는 CEGUI 윈도우의 종류(보이진 않습니다) 항상 화면상에 상주할 것이기 때문입니다. 결과적으로 디폴트 커서로 설정한 이미지로 마우스 커서가 만들어 것입니다. 만약 마우스커서를 직접 설정하고 디폴트값은 설정하지 않는다면 CEGUI 윈도우를 시간 통과하면서 보이지 않는 마우스커서가 것입니다( 튜토리얼에서는 절대 보이지 않게 겁니다). 반면에 아무런 CEGUI 윈도우를 출력하지 않는다면 디폴트 마우스 커서는 아무런 효과가 없습니다. 추후 이런 상황을 보게 것입니다. 이런 상황에서는 MouseCursor::setImage 함수를 써서 화면에 어플리케이션용 커서를 출력할 있습니다. 예제 입니다 :

CEGUI::MouseCursor::getSingleton().setImage(CEGUI::System::getSingleton().getDefaultMouseCursor());

 

이벤트 넣기

CEGUI 입력기능이 전혀 없습니다. 마우스의 움직임이나 키보드의 입력을 읽어내지 못합니다. 대신에 사용자로 하여금 입력과 마우스 이벤트를 시스템에 입력시키는 것에 의존합니다. 이제 이벤트를 다룰 차례입니다. CEGUI 쓰려면 버퍼방식 입력을 사용해야 합니다. 그래야만 이벤트가 발생하는 즉시 입력할 있습니다. KeyPressed 함수를 찾아서 다음 코드를 추가하세요 :

       CEGUI::System *sys = CEGUI::System::getSingletonPtr();

       sys->injectKeyDown(arg.key);

       sys->injectChar(arg.text);

시스템 객체를 얻은 이후 2가지 일들이 있습니다. 첫번째는 키가 눌려졌다는 이벤트를 CEGUI 입력하는것이고 두번째는 실제로 눌려진 키를 입력하는 입니다. Non-English 키보드일 경우 key down 이벤트 자체만으로는 항상 올바른 결과값을 가져다 주지 않으므로 눌려진 실제 키값을 입력시키는건 필수적 입니다. injectChar 유니코드를 고려해서 디자인 되었습니다.

이제는 키가 떨어졌을때의 상황처리를 해야 합니다. keyReleased함수를 찾아서 다음 코드를 추가하세요 :

CEGUI::System::getSingleton().injectKeyUp(arg.key);

키가 떨어졌을때는 키값을 입력해 필요가 없습니다. 키가 떨어졌다는 이벤트만 필요할 입니다.

 

마우스 이벤트 넣기&변환

키보드로 입력받는 작업은 모두 끝냈습니다. 이제 마우스 입력차례 입니다. 여기서 작은 문제점이 있습니다. 키가 눌려지고 떨어질때 CEGUI 입력시 변환작업은 없었습니다. OIS CEGUI 키보드에 대해서 같은 코드를 사용합니다. 하지만 마우스의 경우는 경우가 다릅니다. CEGUI 마우스버튼이 눌려졌다는 이벤트를 입력하기 전에 OIS 버튼ID로부터 CEGUI 버튼ID 변환시켜주는 함수를 작성해야 합니다. 다음 코드를 소스코드의 거의 최상단, TutorialListener클래스이전 부분에 추가하세요 :

CEGUI::MouseButton convertButton(OIS::MouseButtonID buttonID)

{

    switch (buttonID)

    {

    case OIS::MB_Left:

        return CEGUI::LeftButton;

 

    case OIS::MB_Right:

        return CEGUI::RightButton;

 

    case OIS::MB_Middle:

        return CEGUI::MiddleButton;

 

    default:

        return CEGUI::LeftButton;

    }

}

이제 마우스 이벤트를 입력시킬 준비가 되었습니다. mousePressed함수에 다음 코드를 추가하세요 :

CEGUI::System::getSingleton().injectMouseButtonDown(convertButton(id));

설명이 필요 없는 코드입니다. 입력받은 버튼ID 변환시켜서 CEGUI 전달합니다. MouseReleased함수에 다음 코드를 추가하세요 :

CEGUI::System::getSingleton().injectMouseButtonUp(convertButton(id));

마지막으로 마우스가 움직였을때 CEGUI 입력하기 입니다. CEGUI::System객체는 injectMouseMove함수를 가지고 있는데 마우스의 상대적 움직임거리를 입력받습니다. OIS::mouseMoved핸들러가 그에 연관된 움직임거리 state.X.rel state.Y.rel변수들을 제공합니다. MouseMoved함수에 다음 코드를 추가하세요 :

CEGUI::System::getSingleton().injectMouseMove(arg.state.X.rel, arg.state.Y.rel);

완성입니다. 이제 CEGUI 마우스와 키보드 입력에대한 모든 설정을 끝마쳤습니다.

Trackback 0 : Comment 0

기초 튜토리얼 7-3 (마지막)

Ogre3D 삽질란/Basic Tutorial 7 2008/12/04 17:22

윈도우, 시트, 위젯

소개

CEGUI 다른 GUI시스템들에 비해서 독특합니다. CEGUI 있어서 출력되는 모든 것들은 CEGUI::Window클래스의 상속된 형태이며 하나의 윈도우는 여러개의 자식 윈도우들을 가질 있습니다. 말은 여러개의 버튼을 포함하는 하나의 프레임을 만든다면 프레임이 윈도우라는 의미입니다. 이런 특징으로 이상한 현상을 유발할 수도 있습니다. 실제로는 절대 쓰이지 않겠지만 버튼 속에 다른 버튼을 배치할 수도 있습니다. 이런 사항들을 언급하냐면 만약에 어떤 위젯을 프로그램에 배치시킨 상황에서 나중에 포인터를 다시 찾고 싶을때가 있을 입니다. 모든 위젯들은 윈도우들에 의해 호출되어 집니다. 그리고 호출했던 윈도우의 함수를 사용함으로써 접근이 가능합니다.

CEGUI 사용하는 대부분의 경우 각각의 객체들을 코드로 생성하지는 않을 입니다. 대신에 CEGUI 레이아웃 에디터같은 툴을 사용해서 프로그램에서 필요로 하는 GUI 레이아웃을 작성합니다. 모든 윈도우, 버튼, 위젯을 화면상에 배치시킨 다음 레이아웃을 텍스트파일로 저장합니다. 나중에 CEGUI GUI시트(이것역시 CEGUI::Window에서 상속받은 형태) 로드시킬 있습니다.

마지막으로 알아두실 것은 CEGUI 정말 많은 위젯들을 포함하고 있씁니다. 모든것들을 튜토리얼안에서 다룰 수는 없으므로 CEGUI 사용하기로 마음먹었으면 꾸미기위해 CEGUI공식 홈페이지를 방문하셔서 많은 정보를 얻으시길 바랍니다.

 

시트 읽어들이기

CEGUI에서 시트를 읽는 작업은 무척 쉽습니다. WindowManager클래스가 제공하는 “loadWindowLayout” 함수로 시트를 읽어들이고 CEGUI::Window객체에 넣을 있습니다. 그런 다음 CEGUI::System::setGUISheet함수로 출력할 있습니다만 튜토리얼에서는 사용하지 않을 입니다. 하지만 적어도 어떻게 쓰는지 예제라도 보여드려야 죄책감이 들지 않을것 같군요. 튜토리얼용 코드에 추가하지 마세요(만약에 추가했다면 결과를 확인하고 해당 코드를 삭제해 주세요) :

       // Do not add this to the program

       CEGUI::Window* sheet = CEGUI::WindowManager::getSingleton().loadWindowLayout((CEGUI::utf8*)"ogregui.layout");

       mSystem->setGUISheet(sheet);

코드는 지금 보여질 시트를 선택합니다. 나중에 시트의 포인터는 System::getGUISheet함수를 통해서 다시 구할 있습니다. 그리고 GUI시트를 다른 어떤 시트와도 setGUISheet함수를 통해서 매끄럽게 교체할 수도 있습니다(나중에 현재의 시트를 다시 복구하고 싶다면 포인터를 저장해 두세요).

 

수동으로 객체 생성하기

앞서 얘기한 대로 CEGUI 쓰면서 GUI시트는 에디터를 써서 만들게 될겁니다. 하지만 가끔씩은 수동으로 위젯을 화면상에 올릴 필요도 있습니다. 예를 들어서 나중에 기능을 추가시킬 Quit 버튼을 추가할 겁니다. 튜토리얼을 진행하면서 Quit버튼 밖에도 많은 것들을 추가할 계획이고 최초로 생성될 디폴트 CEGUI::Window 앞으로 만들어질 모든 위젯들을 포함할 입니다. 다음 코드를 createScene함수에 추가하세요 :

       CEGUI::WindowManager *win = CEGUI::WindowManager::getSingletonPtr();

       CEGUI::Window *sheet = win->createWindow("DefaultGUISheet", "CEGUIDemo/Sheet");

코드는 WindowManager 사용해서 "CEGUIDemo/Sheet"라는 이름을 가진 "DefaultGUISheet" 생성합니다. 시트이름은 마음대로 지을 있습니다. 게다가 이렇게 "SomeApp/MainMenu/Submenu3/CancelButton"처럼 계층적방식으로 위젯 이름을 짓는것은 매우 흔한(그리고 추천되는) 방식입니다. 다음으로 해야 일은 Quit버튼을 생성하고 크기를 설정하는 입니다 :

       CEGUI::Window *quit = win->createWindow("TaharezLook/Button", "CEGUIDemo/QuitButton");

       quit->setText("Quit");

       quit->setSize(CEGUI::UVector2(CEGUI::UDim(0.15, 0), CEGUI::UDim(0.05, 0)));

무슨 암호문을 놓은것 처럼 보이는군요. CEGUI 크기와 위치에 대해서 "unified dimension" 시스템을 사용합니다. 크기를 설정할때는 반드시 UDim객체를 만들어서 원하는 크기를 설정한다음 생성될 객체에게 알려줘야 합니다. 첫번째 매개변수는