mirror of https://github.com/OpenMW/openmw.git
Readded HW cursor manager (no image rotation yet)
parent
4825744a03
commit
9ea416b852
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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
|
@ -1,27 +0,0 @@
|
||||
set(SDL4OGRE_LIBRARY "sdl4ogre")
|
||||
|
||||
# Sources
|
||||
|
||||
set(SDL4OGRE_SOURCE_FILES
|
||||
sdlinputwrapper.cpp
|
||||
sdlcursormanager.cpp
|
||||
sdlwindowhelper.cpp
|
||||
imagerotate.cpp
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
set(SDL4OGRE_SOURCE_FILES ${SDL4OGRE_SOURCE_FILES} osx_utils.mm)
|
||||
endif ()
|
||||
|
||||
set(SDL4OGRE_HEADER_FILES
|
||||
OISCompat.h
|
||||
cursormanager.hpp
|
||||
events.h
|
||||
)
|
||||
|
||||
add_library(${SDL4OGRE_LIBRARY} STATIC ${SDL4OGRE_SOURCE_FILES} ${SDL4OGRE_HEADER_FILES})
|
||||
|
||||
link_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
|
||||
target_link_libraries(${SDL4OGRE_LIBRARY} ${SDL2_LIBRARY})
|
@ -1,30 +0,0 @@
|
||||
#ifndef SDL4OGRE_CURSOR_MANAGER_H
|
||||
#define SDL4OGRE_CURSOR_MANAGER_H
|
||||
|
||||
#include <SDL_types.h>
|
||||
#include <string>
|
||||
|
||||
#include <OgreTexture.h>
|
||||
#include <OgrePrerequisites.h>
|
||||
|
||||
namespace SFO
|
||||
{
|
||||
class CursorManager
|
||||
{
|
||||
public:
|
||||
virtual ~CursorManager(){}
|
||||
|
||||
/// \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) = 0;
|
||||
|
||||
/// \brief Follow up a cursorChanged() call with enough info to create an cursor.
|
||||
virtual void receiveCursorInfo(const std::string &name, int rotDegrees, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y) = 0;
|
||||
|
||||
/// \brief sets whether to actively manage cursors or not
|
||||
virtual void setEnabled(bool enabled) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,161 +0,0 @@
|
||||
#include "sdlcursormanager.hpp"
|
||||
|
||||
#include <OgreHardwarePixelBuffer.h>
|
||||
#include <OgreTextureManager.h>
|
||||
#include <OgreRoot.h>
|
||||
|
||||
#include <SDL_mouse.h>
|
||||
#include <SDL_endian.h>
|
||||
|
||||
#include "imagerotate.hpp"
|
||||
|
||||
namespace SFO
|
||||
{
|
||||
|
||||
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, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y)
|
||||
{
|
||||
_createCursorFromResource(name, rotDegrees, tex, size_x, size_y, hotspot_x, hotspot_y);
|
||||
}
|
||||
|
||||
/// \brief creates an SDL cursor from an Ogre texture
|
||||
void SDLCursorManager::_createCursorFromResource(const std::string& name, int rotDegrees, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y)
|
||||
{
|
||||
if (mCursorMap.find(name) != mCursorMap.end())
|
||||
return;
|
||||
|
||||
std::string tempName = tex->getName() + "_rotated";
|
||||
|
||||
// we use a render target to uncompress the DDS texture
|
||||
// just blitting doesn't seem to work on D3D9
|
||||
ImageRotate::rotate(tex->getName(), tempName, static_cast<float>(-rotDegrees));
|
||||
|
||||
Ogre::TexturePtr resultTexture = Ogre::TextureManager::getSingleton().getByName(tempName);
|
||||
|
||||
// now blit to memory
|
||||
Ogre::Image destImage;
|
||||
resultTexture->convertToImage(destImage);
|
||||
|
||||
SDL_Surface* surf = SDL_CreateRGBSurface(0,size_x,size_y,32,0xFF000000,0x00FF0000,0x0000FF00,0x000000FF);
|
||||
|
||||
|
||||
//copy the Ogre texture to an SDL surface
|
||||
for(size_t x = 0; x < size_x; ++x)
|
||||
{
|
||||
for(size_t y = 0; y < size_y; ++y)
|
||||
{
|
||||
Ogre::ColourValue clr = destImage.getColourAt(x, y, 0);
|
||||
|
||||
//set the pixel on the SDL surface to the same value as the Ogre texture's
|
||||
_putPixel(surf, x, y, SDL_MapRGBA(surf->format, static_cast<Uint8>(clr.r * 255),
|
||||
static_cast<Uint8>(clr.g * 255), static_cast<Uint8>(clr.b * 255), static_cast<Uint8>(clr.a * 255)));
|
||||
}
|
||||
}
|
||||
|
||||
//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);
|
||||
Ogre::TextureManager::getSingleton().remove(tempName);
|
||||
|
||||
_setGUICursor(name);
|
||||
}
|
||||
|
||||
void SDLCursorManager::_putPixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
|
||||
{
|
||||
int bpp = surface->format->BytesPerPixel;
|
||||
/* Here p is the address to the pixel we want to set */
|
||||
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
|
||||
|
||||
switch(bpp) {
|
||||
case 1:
|
||||
*p = pixel;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
*(Uint16 *)p = pixel;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
|
||||
p[0] = (pixel >> 16) & 0xff;
|
||||
p[1] = (pixel >> 8) & 0xff;
|
||||
p[2] = pixel & 0xff;
|
||||
} else {
|
||||
p[0] = pixel & 0xff;
|
||||
p[1] = (pixel >> 8) & 0xff;
|
||||
p[2] = (pixel >> 16) & 0xff;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
*(Uint32 *)p = pixel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
#ifndef SDL4OGRE_CURSORMANAGER_H
|
||||
#define SDL4OGRE_CURSORMANAGER_H
|
||||
|
||||
#include "cursormanager.hpp"
|
||||
#include <map>
|
||||
|
||||
struct SDL_Cursor;
|
||||
struct SDL_Surface;
|
||||
|
||||
namespace SFO
|
||||
{
|
||||
class SDLCursorManager :
|
||||
public CursorManager
|
||||
{
|
||||
public:
|
||||
SDLCursorManager();
|
||||
virtual ~SDLCursorManager();
|
||||
|
||||
virtual void setEnabled(bool enabled);
|
||||
|
||||
virtual bool cursorChanged(const std::string &name);
|
||||
virtual void receiveCursorInfo(const std::string &name, int rotDegrees, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y);
|
||||
|
||||
private:
|
||||
void _createCursorFromResource(const std::string &name, int rotDegrees, Ogre::TexturePtr tex, 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…
Reference in New Issue