Skip to content

Commit

Permalink
Readded HW cursor manager (no image rotation yet)
Browse files Browse the repository at this point in the history
  • Loading branch information
scrawl committed May 13, 2015
1 parent 4825744 commit 9ea416b
Show file tree
Hide file tree
Showing 15 changed files with 270 additions and 276 deletions.
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,6 @@ endif(WIN32)
# Extern
add_subdirectory (extern/osg-ffmpeg-videoplayer)
add_subdirectory (extern/oics)
#add_subdirectory (extern/sdl4ogre)

# Components
add_subdirectory (components)
Expand Down
2 changes: 1 addition & 1 deletion apps/openmw/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ void OMW::Engine::setWindowIcon()
else
{
osg::ref_ptr<osg::Image> image = result.getImage();
SDL_Surface* surface = SDLUtil::imageToSurface(image);
SDL_Surface* surface = SDLUtil::imageToSurface(image, true);
SDL_SetWindowIcon(mWindow, surface);
SDL_FreeSurface(surface);
}
Expand Down
20 changes: 11 additions & 9 deletions apps/openmw/mwgui/windowmanagerimp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@
#include <SDL_keyboard.h>
#include <SDL_clipboard.h>

#include <extern/sdl4ogre/sdlcursormanager.hpp>
#include <components/sdlutil/sdlcursormanager.hpp>

#include <components/fontloader/fontloader.hpp>

#include <components/resource/resourcesystem.hpp>
#include <components/resource/texturemanager.hpp>

#include <components/translation/translation.hpp>

Expand All @@ -35,6 +36,8 @@
#include <components/widgets/widgets.hpp>
#include <components/widgets/tags.hpp>

#include <components/sdlutil/sdlcursormanager.hpp>

#include <components/misc/resourcehelpers.hpp>

#include "../mwbase/inputmanager.hpp"
Expand Down Expand Up @@ -219,15 +222,15 @@ namespace MWGui
mLoadingScreen = new LoadingScreen(mResourceSystem->getVFS(), mViewer);

//set up the hardware cursor manager
//mCursorManager = new SFO::SDLCursorManager();
mCursorManager = new SDLUtil::SDLCursorManager();

MyGUI::PointerManager::getInstance().eventChangeMousePointer += MyGUI::newDelegate(this, &WindowManager::onCursorChange);

MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged);

onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer());

//mCursorManager->setEnabled(true);
mCursorManager->setEnabled(true);

// hide mygui's pointer
MyGUI::PointerManager::getInstance().setVisible(false);
Expand Down Expand Up @@ -417,7 +420,7 @@ namespace MWGui
delete mDebugWindow;
delete mJailScreen;

//delete mCursorManager;
delete mCursorManager;

cleanupGarbage();

Expand Down Expand Up @@ -1152,7 +1155,6 @@ namespace MWGui

void WindowManager::onCursorChange(const std::string &name)
{
/*
if(!mCursorManager->cursorChanged(name))
return; //the cursor manager doesn't want any more info about this cursor
//See if we can get the information we need out of the cursor resource
Expand All @@ -1163,21 +1165,21 @@ namespace MWGui

std::string tex_name = imgSet->getIndexInfo(0,0).texture;

Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().getByName(tex_name);
osg::ref_ptr<osg::Texture2D> tex = mResourceSystem->getTextureManager()->getTexture2D(tex_name, osg::Texture::CLAMP, osg::Texture::CLAMP);
tex->setUnRefImageDataAfterApply(false); // FIXME?

//everything looks good, send it to the cursor manager
if(!tex.isNull())
if(tex.valid())
{
Uint8 size_x = imgSetPtr->getSize().width;
Uint8 size_y = imgSetPtr->getSize().height;
Uint8 hotspot_x = imgSetPtr->getHotSpot().left;
Uint8 hotspot_y = imgSetPtr->getHotSpot().top;
int rotation = imgSetPtr->getRotation();

mCursorManager->receiveCursorInfo(name, rotation, tex, size_x, size_y, hotspot_x, hotspot_y);
mCursorManager->receiveCursorInfo(name, rotation, tex->getImage(), size_x, size_y, hotspot_x, hotspot_y);
}
}
*/
}

void WindowManager::popGuiMode()
Expand Down
6 changes: 3 additions & 3 deletions apps/openmw/mwgui/windowmanagerimp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ namespace Resource
class ResourceSystem;
}

namespace SFO
namespace SDLUtil
{
class CursorManager;
class SDLCursorManager;
}

namespace osgMyGUI
Expand Down Expand Up @@ -454,7 +454,7 @@ namespace MWGui
MyGUI::Gui *mGui; // Gui
std::vector<GuiMode> mGuiModes;

SFO::CursorManager* mCursorManager;
SDLUtil::SDLCursorManager* mCursorManager;

std::vector<Layout*> mGarbageDialogs;
void cleanupGarbage();
Expand Down
2 changes: 1 addition & 1 deletion components/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ add_component_dir (fontloader
)

add_component_dir (sdlutil
sdlgraphicswindow imagetosurface sdlinputwrapper OISCompat events
sdlgraphicswindow imagetosurface sdlinputwrapper OISCompat events sdlcursormanager
)

add_component_dir (version
Expand Down
4 changes: 2 additions & 2 deletions components/sdlutil/imagetosurface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace SDLUtil
{

SDL_Surface* imageToSurface(osg::Image *image)
SDL_Surface* imageToSurface(osg::Image *image, bool flip)
{
int width = image->s();
int height = image->t();
Expand All @@ -15,7 +15,7 @@ SDL_Surface* imageToSurface(osg::Image *image)
for(int x = 0; x < width; ++x)
for(int y = 0; y < height; ++y)
{
osg::Vec4f clr = image->getColor(x, (height-1)-y);
osg::Vec4f clr = image->getColor(x, flip ? ((height-1)-y) : y);
int bpp = surface->format->BytesPerPixel;
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
*(Uint32*)(p) = SDL_MapRGBA(surface->format, static_cast<Uint8>(clr.r() * 255),
Expand Down
2 changes: 1 addition & 1 deletion components/sdlutil/imagetosurface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace SDLUtil

/// Convert an osg::Image to an SDL_Surface.
/// @note The returned surface must be freed using SDL_FreeSurface.
SDL_Surface* imageToSurface(osg::Image* image);
SDL_Surface* imageToSurface(osg::Image* image, bool flip=false);

}

Expand Down
182 changes: 182 additions & 0 deletions components/sdlutil/sdlcursormanager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
#include "sdlcursormanager.hpp"

#include <cassert>

#include <SDL_mouse.h>
#include <SDL_endian.h>

#include <osg/GraphicsContext>
#include <osg/Geometry>
#include <osg/Texture2D>

#include "imagetosurface.hpp"

namespace
{

class MyGraphicsContext {
public:
MyGraphicsContext(int w, int h)
{
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->x = 0;
traits->y = 0;
traits->width = 1;//w;
traits->height = 1;//h;
traits->windowDecoration = false;
traits->doubleBuffer = false;
traits->sharedContext = 0;
traits->pbuffer = true;

_gc = osg::GraphicsContext::createGraphicsContext(traits.get());

if (!_gc)
{
osg::notify(osg::NOTICE)<<"Failed to create pbuffer, failing back to normal graphics window."<<std::endl;

traits->pbuffer = false;
_gc = osg::GraphicsContext::createGraphicsContext(traits.get());
}

if (_gc.valid())
{
_gc->realize();
_gc->makeCurrent();
}
}

osg::ref_ptr<osg::GraphicsContext> getContext()
{
return _gc;
}

bool valid() const { return _gc.valid() && _gc->isRealized(); }

private:
osg::ref_ptr<osg::GraphicsContext> _gc;
};

osg::ref_ptr<osg::Image> decompress (osg::ref_ptr<osg::Image> source)
{
int width = source->s();
int height = source->t();

MyGraphicsContext context(width, height);

osg::ref_ptr<osg::State> state = context.getContext()->getState();

osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
texture->setImage(source);

state->applyTextureAttribute(0, texture);

osg::ref_ptr<osg::Image> resultImage = new osg::Image;
resultImage->allocateImage(width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE);

assert(resultImage->isDataContiguous());

// FIXME: implement for GL ES (PBO & glMapBufferRange?)
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, resultImage->data());

source->releaseGLObjects();
texture->releaseGLObjects();

return resultImage;
}

}

namespace SDLUtil
{

SDLCursorManager::SDLCursorManager() :
mEnabled(false),
mInitialized(false)
{
}

SDLCursorManager::~SDLCursorManager()
{
CursorMap::const_iterator curs_iter = mCursorMap.begin();

while(curs_iter != mCursorMap.end())
{
SDL_FreeCursor(curs_iter->second);
++curs_iter;
}

mCursorMap.clear();
}

void SDLCursorManager::setEnabled(bool enabled)
{
if(mInitialized && enabled == mEnabled)
return;

mInitialized = true;
mEnabled = enabled;

//turn on hardware cursors
if(enabled)
{
_setGUICursor(mCurrentCursor);
}
//turn off hardware cursors
else
{
SDL_ShowCursor(SDL_FALSE);
}
}

bool SDLCursorManager::cursorChanged(const std::string& name)
{
mCurrentCursor = name;

CursorMap::const_iterator curs_iter = mCursorMap.find(name);

//we have this cursor
if(curs_iter != mCursorMap.end())
{
_setGUICursor(name);

return false;
}
else
{
//they should get back to us with more info
return true;
}
}

void SDLCursorManager::_setGUICursor(const std::string &name)
{
SDL_SetCursor(mCursorMap.find(name)->second);
}

void SDLCursorManager::receiveCursorInfo(const std::string& name, int rotDegrees, osg::Image* image, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y)
{
_createCursorFromResource(name, rotDegrees, image, size_x, size_y, hotspot_x, hotspot_y);
}

void SDLCursorManager::_createCursorFromResource(const std::string& name, int rotDegrees, osg::Image* image, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y)
{
if (mCursorMap.find(name) != mCursorMap.end())
return;

osg::ref_ptr<osg::Image> decompressed = decompress(image);

// TODO: rotate

SDL_Surface* surf = SDLUtil::imageToSurface(decompressed, false);

//set the cursor and store it for later
SDL_Cursor* curs = SDL_CreateColorCursor(surf, hotspot_x, hotspot_y);
mCursorMap.insert(CursorMap::value_type(std::string(name), curs));

//clean up
SDL_FreeSurface(surf);

_setGUICursor(name);
}

}
51 changes: 51 additions & 0 deletions components/sdlutil/sdlcursormanager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#ifndef OPENMW_COMPONENTS_SDLUTIL_SDLCURSORMANAGER_H
#define OPENMW_COMPONENTS_SDLUTIL_SDLCURSORMANAGER_H

#include <map>
#include <string>

#include <SDL_types.h>

struct SDL_Cursor;
struct SDL_Surface;

namespace osg
{
class Image;
}

namespace SDLUtil
{
class SDLCursorManager
{
public:
SDLCursorManager();
virtual ~SDLCursorManager();

/// \brief sets whether to actively manage cursors or not
virtual void setEnabled(bool enabled);

/// \brief Tell the manager that the cursor has changed, giving the
/// name of the cursor we changed to ("arrow", "ibeam", etc)
/// \return Whether the manager is interested in more information about the cursor
virtual bool cursorChanged(const std::string &name);

/// \brief Follow up a cursorChanged() call with enough info to create an cursor.
virtual void receiveCursorInfo(const std::string &name, int rotDegrees, osg::Image* image, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y);

private:
void _createCursorFromResource(const std::string &name, int rotDegrees, osg::Image* image, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y);
void _putPixel(SDL_Surface *surface, int x, int y, Uint32 pixel);

void _setGUICursor(const std::string& name);

typedef std::map<std::string, SDL_Cursor*> CursorMap;
CursorMap mCursorMap;

std::string mCurrentCursor;
bool mEnabled;
bool mInitialized;
};
}

#endif
Loading

0 comments on commit 9ea416b

Please sign in to comment.