IntermediateTutorial3Source

From Ogre Wiki

Jump to: navigation, search

This is the source for Intermediate Tutorial 3

#include <CEGUI/CEGUISystem.h>
#include <CEGUI/CEGUISchemeManager.h>
#include <OgreCEGUIRenderer.h>

#include "ExampleApplication.h"

class MouseQueryListener : public ExampleFrameListener, public OIS::MouseListener
{
public:
    enum QueryFlags
    {
        NINJA_MASK = 1<<0,
        ROBOT_MASK = 1<<1
    };

    MouseQueryListener(RenderWindow* win, Camera* cam, SceneManager *sceneManager, CEGUI::Renderer *renderer)
        : ExampleFrameListener(win, cam, false, true), mGUIRenderer(renderer)
    {
        // Setup default variables
        mCount = 0;
        mCurrentObject = NULL;
        mLMouseDown = false;
        mRMouseDown = false;
        mSceneMgr = sceneManager;

        // Reduce move speed
        mMoveSpeed = 50;
        mRotateSpeed /= 500;

        // Register this so that we get mouse events.
        mMouse->setEventCallback(this);

        // Create RaySceneQuery
        mRaySceneQuery = mSceneMgr->createRayQuery(Ray());

        // Set result text, and default state
        mRobotMode = true;
        mDebugText = "Robot Mode Enabled - Press Space to Toggle";
    } // MouseQueryListener

    ~MouseQueryListener()
    {
        mSceneMgr->destroyQuery(mRaySceneQuery);
    }

    bool frameStarted(const FrameEvent &evt)
    {
        // Process the base frame listener code.  Since we are going to be
        // manipulating the translate vector, we need this to happen first.
        if (!ExampleFrameListener::frameStarted(evt))
            return false;

        // Swap modes
        if(mKeyboard->isKeyDown(OIS::KC_SPACE) && mTimeUntilNextToggle <= 0)
        {
            mRobotMode = !mRobotMode;
            mTimeUntilNextToggle = 1;
            mDebugText = (mRobotMode ? String("Robot") : String("Ninja")) + " Mode Enabled - Press Space to Toggle";
        }

        // Setup the scene query
        Vector3 camPos = mCamera->getPosition();
        Ray cameraRay(Vector3(camPos.x, 5000.0f, camPos.z), Vector3::NEGATIVE_UNIT_Y);
        mRaySceneQuery->setRay(cameraRay);

        // Perform the scene query
        mRaySceneQuery->setSortByDistance(false);
        RaySceneQueryResult &result = mRaySceneQuery->execute();
        RaySceneQueryResult::iterator itr;

        // Get the results, set the camera height
        for (itr = result.begin(); itr != result.end(); itr++)
        {
            if (itr->worldFragment)
            {
                Real terrainHeight = itr->worldFragment->singleIntersection.y;
                if ((terrainHeight + 10.0f) > camPos.y)
                    mCamera->setPosition(camPos.x, terrainHeight + 10.0f, camPos.z);
                break;
            } // if
        } // for

        return true;
    }

    /* MouseListener callbacks. */
    bool mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id)
    {
        // Left mouse button up
        if (id == OIS::MB_Left)
        {
            onLeftReleased(arg);
            mLMouseDown = false;
        } // if

        // Right mouse button up
        else if (id == OIS::MB_Right)
        {
            onRightReleased(arg);
            mRMouseDown = false;
        } // else if

        return true;
    }

    bool mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id)
    {
        // Left mouse button down
        if (id == OIS::MB_Left)
        {
            onLeftPressed(arg);
            mLMouseDown = true;
        } // if

        // Right mouse button down
        else if (id == OIS::MB_Right)
        {
            onRightPressed(arg);
            mRMouseDown = true;
        } // else if

        return true;
    }

    bool mouseMoved(const OIS::MouseEvent &arg)
    {
        // Update CEGUI with the mouse motion
        CEGUI::System::getSingleton().injectMouseMove(arg.state.X.rel, arg.state.Y.rel);

        // If we are dragging the left mouse button.
        if (mLMouseDown)
        {
            CEGUI::Point mousePos = CEGUI::MouseCursor::getSingleton().getPosition();
            Ray mouseRay = mCamera->getCameraToViewportRay(mousePos.d_x/float(arg.state.width),mousePos.d_y/float(arg.state.height));
            mRaySceneQuery->setRay(mouseRay);
            mRaySceneQuery->setSortByDistance(false);

            RaySceneQueryResult &result = mRaySceneQuery->execute();
            RaySceneQueryResult::iterator itr;

            for (itr = result.begin(); itr != result.end(); itr++)
                if (itr->worldFragment)
                {
                    mCurrentObject->setPosition(itr->worldFragment->singleIntersection);
                    break;
                } // if 
        } // if

        // If we are dragging the right mouse button.
        else if (mRMouseDown)
        {
            mCamera->yaw(Degree(-arg.state.X.rel * mRotateSpeed));
            mCamera->pitch(Degree(-arg.state.Y.rel * mRotateSpeed));
        } // else if

        return true;
    }

    // Specific handlers
    void onLeftPressed(const OIS::MouseEvent &arg)
    {
        // Turn off bounding box.
        if (mCurrentObject)
            mCurrentObject->showBoundingBox(false);

        // Setup the ray scene query
        CEGUI::Point mousePos = CEGUI::MouseCursor::getSingleton().getPosition();
        Ray mouseRay = mCamera->getCameraToViewportRay(mousePos.d_x/float(arg.state.width), mousePos.d_y/float(arg.state.height));
        mRaySceneQuery->setRay(mouseRay);
        mRaySceneQuery->setSortByDistance(true);
        mRaySceneQuery->setQueryMask(mRobotMode ? ROBOT_MASK : NINJA_MASK);

        // Execute query
        RaySceneQueryResult &result = mRaySceneQuery->execute();
        RaySceneQueryResult::iterator itr;

        // Get results, create a node/entity on the position
        for (itr = result.begin(); itr != result.end(); itr++)
        {
            if (itr->movable && itr->movable->getName().substr(0, 5) != "tile[")
            {
                mCurrentObject = itr->movable->getParentSceneNode();
                break;
            } // if

            else if (itr->worldFragment)
            {
                Entity *ent;
                char name[16];

                if (mRobotMode)
                {
                    sprintf(name, "Robot%d", mCount++);
                    ent = mSceneMgr->createEntity(name, "robot.mesh");
                    ent->setQueryFlags(ROBOT_MASK);
                } // if
                else
                {
                    sprintf(name, "Ninja%d", mCount++);
                    ent = mSceneMgr->createEntity(name, "ninja.mesh");
                    ent->setQueryFlags(NINJA_MASK);
                } // else

                mCurrentObject = mSceneMgr->getRootSceneNode()->createChildSceneNode(String(name) + "Node", itr->worldFragment->singleIntersection);
                mCurrentObject->attachObject(ent);
                mCurrentObject->setScale(0.1f, 0.1f, 0.1f);
                break;
            } // else if
        } // for

        // Show the bounding box to highlight the selected object
        if (mCurrentObject)
            mCurrentObject->showBoundingBox(true);
    }

    void onLeftReleased(const OIS::MouseEvent &arg)
    {
    }

    void onRightPressed(const OIS::MouseEvent &arg)
    {
        CEGUI::MouseCursor::getSingleton().hide();
    }

    virtual void onRightReleased(const OIS::MouseEvent &arg)
    {
        CEGUI::MouseCursor::getSingleton().show();
    }

protected:
    RaySceneQuery *mRaySceneQuery;     // The ray scene query pointer
    bool mLMouseDown, mRMouseDown;     // True if the mouse buttons are down
    int mCount;                        // The number of robots on the screen
    SceneManager *mSceneMgr;           // A pointer to the scene manager
    SceneNode *mCurrentObject;         // The newly created object
    CEGUI::Renderer *mGUIRenderer;     // CEGUI renderer
    bool mRobotMode;                   // The current state
};

class MouseQueryApplication : public ExampleApplication
{
protected:
    CEGUI::OgreCEGUIRenderer *mGUIRenderer;
    CEGUI::System *mGUISystem;         // CEGUI system
public:
    MouseQueryApplication()
    {
    }

    ~MouseQueryApplication() 
    {
    }
protected:
    void chooseSceneManager(void)
    {
        // Use the terrain scene manager.
        mSceneMgr = mRoot->createSceneManager(ST_EXTERIOR_CLOSE);
    }

    void createScene(void)
    {
        // Set ambient light
        mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
        mSceneMgr->setSkyDome(true, "Examples/CloudySky", 5, 8);

        // World geometry
        mSceneMgr->setWorldGeometry("terrain.cfg");

        // Set camera look point
        mCamera->setPosition(40, 100, 580);
        mCamera->pitch(Degree(-30));
        mCamera->yaw(Degree(-45));

        // CEGUI setup
        mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, mSceneMgr);
        mGUISystem = new CEGUI::System(mGUIRenderer);

        // Mouse
        CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLookSkin.scheme");
        CEGUI::MouseCursor::getSingleton().setImage("TaharezLook", "MouseArrow");
    }

    void createFrameListener(void)
    {
        mFrameListener = new MouseQueryListener(mWindow, mCamera, mSceneMgr, mGUIRenderer);
        mFrameListener->showDebugOverlay(true);
        mRoot->addFrameListener(mFrameListener);
    }
};


#if OGRE_PLATFORM == PLATFORM_WIN32 || 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
    MouseQueryApplication 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;
}
Ogre Tutorials

Ogre Beginner Tutorials: 1. Basic Introduction - 2. Cameras, Lights and Shadows - 3. Terrain, Sky and Fog - 4. Frame Listeners and Unbuffered Input - 5. Buffered Input - 6. The Ogre Startup Sequence - 7. CEGUI and OGRE - 8. Multiple and Dual SceneManagers

Intermediate Tutorials: 1. Animation, Interpolation and Quaternions - 2. RaySceneQueries and Basic Mouse Usage (1/2) - 3. Mouse Picking and SceneQuery Masks (2/2) - 4. Volume Selection and Manual Objects - 5. Static Geometry - 6. Projective Decals - 7. Render to Texture

Advanced Tutorials: 1. Resources and ResourceManagers

See also: Artist Tutorials - Ogre Articles - Cookbook

Personal tools
administration