Finally bring cursors into the resource manager framework

- Hotspots are still hardcoded, unfortunately
- Obscuring the cursor when using the keyboard now works properly
This commit is contained in:
2014-04-21 04:05:55 -04:00
parent 321cd7c2e5
commit 84192cd52f
10 changed files with 71 additions and 136 deletions

View File

@@ -513,9 +513,9 @@
91C1FCAA0FCB6F7200EBAA65 /* message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBAB90FB91ADB001E34EA /* message.cpp */; };
91C1FCAB0FCB6F7300EBAA65 /* pict.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBAA90FB8F733001E34EA /* pict.cpp */; };
91C6864A0FD5EEFD000F6D01 /* pc.graphics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91B3EF0A0F969BD300BF5B67 /* pc.graphics.cpp */; };
91C688E80FD702B9000F6D01 /* cursors.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C688E70FD702B9000F6D01 /* cursors.m */; };
91C688E90FD702B9000F6D01 /* cursors.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C688E70FD702B9000F6D01 /* cursors.m */; };
91C688EA0FD702B9000F6D01 /* cursors.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C688E70FD702B9000F6D01 /* cursors.m */; };
91C688E80FD702B9000F6D01 /* cursors.mm in Sources */ = {isa = PBXBuildFile; fileRef = 91C688E70FD702B9000F6D01 /* cursors.mm */; };
91C688E90FD702B9000F6D01 /* cursors.mm in Sources */ = {isa = PBXBuildFile; fileRef = 91C688E70FD702B9000F6D01 /* cursors.mm */; };
91C688EA0FD702B9000F6D01 /* cursors.mm in Sources */ = {isa = PBXBuildFile; fileRef = 91C688E70FD702B9000F6D01 /* cursors.mm */; };
91D634560F8FD77800674AB3 /* BoE.icns in Resources */ = {isa = PBXBuildFile; fileRef = 2B8F435C0C0973680012E4A8 /* BoE.icns */; };
91E5C1F30F9E489B00C21460 /* graphtool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91B3F10A0F9779C300BF5B67 /* graphtool.cpp */; };
91E5C1F40F9E489B00C21460 /* soundtool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91B3F10F0F9779D000BF5B67 /* soundtool.cpp */; };
@@ -1618,7 +1618,7 @@
91BFA3DE19033E01001686E4 /* gzstream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gzstream.cpp; sourceTree = "<group>"; };
91BFA3DF19033E01001686E4 /* gzstream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gzstream.h; sourceTree = "<group>"; };
91C688E60FD702B9000F6D01 /* cursors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cursors.h; sourceTree = "<group>"; };
91C688E70FD702B9000F6D01 /* cursors.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = cursors.m; sourceTree = "<group>"; };
91C688E70FD702B9000F6D01 /* cursors.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cursors.mm; sourceTree = "<group>"; };
91D62F330F8EB84800674AB3 /* bladesofexile.rsrc */ = {isa = PBXFileReference; lastKnownFileType = archive.rsrc; path = bladesofexile.rsrc; sourceTree = "<group>"; };
91D635AA0F90E7B500674AB3 /* stealth.exs */ = {isa = PBXFileReference; lastKnownFileType = file; path = stealth.exs; sourceTree = "<group>"; };
91D635AB0F90E7B500674AB3 /* stealth.meg */ = {isa = PBXFileReference; lastKnownFileType = file; path = stealth.meg; sourceTree = "<group>"; };
@@ -2102,7 +2102,7 @@
913D03340FA0FFFF00184C18 /* src */ = {
isa = PBXGroup;
children = (
91C688E70FD702B9000F6D01 /* cursors.m */,
91C688E70FD702B9000F6D01 /* cursors.mm */,
91E5C7A60F9F615400C21460 /* fileio.cpp */,
91B3F10A0F9779C300BF5B67 /* graphtool.cpp */,
91B3F11E0F97801F00BF5B67 /* mathutil.cpp */,
@@ -2821,7 +2821,7 @@
912287040FD330F300B21642 /* field.cpp in Sources */,
912287050FD330F300B21642 /* message.cpp in Sources */,
912287060FD330F300B21642 /* pict.cpp in Sources */,
91C688E80FD702B9000F6D01 /* cursors.m in Sources */,
91C688E80FD702B9000F6D01 /* cursors.mm in Sources */,
91A32D160FDE049900C4E957 /* ticpp.cpp in Sources */,
91A32D170FDE049900C4E957 /* tinystr.cpp in Sources */,
91A32D180FDE049900C4E957 /* tinyxml.cpp in Sources */,
@@ -2876,7 +2876,7 @@
912286FE0FD330EC00B21642 /* message.cpp in Sources */,
912286FF0FD330ED00B21642 /* pict.cpp in Sources */,
91C6864A0FD5EEFD000F6D01 /* pc.graphics.cpp in Sources */,
91C688E90FD702B9000F6D01 /* cursors.m in Sources */,
91C688E90FD702B9000F6D01 /* cursors.mm in Sources */,
91A32D1B0FDE049F00C4E957 /* ticpp.cpp in Sources */,
91A32D1C0FDE049F00C4E957 /* tinystr.cpp in Sources */,
91A32D1D0FDE04A000C4E957 /* tinyxml.cpp in Sources */,
@@ -2934,7 +2934,7 @@
91C1FCAB0FCB6F7300EBAA65 /* pict.cpp in Sources */,
912283C90FD0E16C00B21642 /* undo.cpp in Sources */,
912286F80FD330E500B21642 /* dlogutil.cpp in Sources */,
91C688EA0FD702B9000F6D01 /* cursors.m in Sources */,
91C688EA0FD702B9000F6D01 /* cursors.mm in Sources */,
91A32D200FDE04A500C4E957 /* ticpp.cpp in Sources */,
91A32D210FDE04A500C4E957 /* tinystr.cpp in Sources */,
91A32D220FDE04A600C4E957 /* tinyxml.cpp in Sources */,

View File

@@ -33,6 +33,7 @@
#include "scrollbar.h"
#include "boe.menus.h"
#include "winutil.h"
#include "cursors.h"
RECT bottom_buttons[7];
RECT town_buttons[10];
@@ -1545,11 +1546,8 @@ bool handle_keystroke(sf::Event& event){
if(overall_mode == MODE_STARTUP)
return false;
// Only hide the cursor if it's in the window.
// This is because we want to show it as soon as the mouse moves, but we don't receive mouse move events if it's outside the window.
if(sf::IntRect(mainPtr.getPosition(), sf::Vector2i(mainPtr.getSize())).contains(sf::Mouse::getPosition()))
mainPtr.setMouseCursorVisible(false);
obscureCursor();
// DEBUG
// sprintf((char *) debug, "%d ",(short) chr2);

View File

@@ -27,7 +27,6 @@
#include "message.h"
#include <array>
#include <boost/lexical_cast.hpp>
#include "cursors.h"
#include "winutil.h"
extern short stat_window,which_combat_type,current_pc;
@@ -1189,7 +1188,7 @@ void init_mini_map() {
void make_cursor_watch()
{
// TODO: If this doesn't work, which I suspect it won't, add a "custom" watch cursor and use that. Or conclude this isn't even needed.
SetNSCursorWatch();
setCursorWatch();
}
////

View File

@@ -337,10 +337,6 @@ void Handle_One_Event()
break;
case sf::Event::MouseMoved:
// The original game called ObscureCursor in the handle_keystroke function,
// which hides the mouse cursor until it's moved.
// SFML's hide cursor function is always permanent, so this is here to balance that out.
mainPtr.setMouseCursorVisible(true);
if(!gInBackground) {
location where(event.mouseMove.x, event.mouseMove.y);
change_cursor(where);
@@ -459,7 +455,6 @@ void close_program()
// TODO: Ultimately we would like to have cleanup happen automatically, negating the need for this function
//end_music();
if(univ.town.loaded()) univ.town.unload();
clean_up_graphtool();
}
void handle_apple_menu(int item_hit)
@@ -802,7 +797,7 @@ void change_cursor(location where_curs)
if ((overall_mode == MODE_OUTDOORS || overall_mode == MODE_TOWN || overall_mode == MODE_COMBAT) && world_screen.contains(where_curs)){
cursor_direction = get_cur_direction(where_curs);
cursor_needed = arrow_curs[cursor_direction.x + 1][cursor_direction.y + 1];// 100 + (cursor_direction.x) + 10 * ( cursor_direction.y);
cursor_needed = arrow_curs[cursor_direction.y + 1][cursor_direction.x + 1];
}
if (cursor_needed != current_cursor)

View File

@@ -123,7 +123,6 @@ int main(int argc, char* argv[]) {
while(!All_Done)
Handle_One_Event();
clean_up_graphtool();
return 0;
}

View File

@@ -6,23 +6,19 @@
// Wrappers for NSCursor, based on an Apple example
//
#ifdef __cplusplus
#define C_DECL extern "C"
#else
#define C_DECL
#endif
#ifndef BOE_CURSORS_H
#define BOE_CURSORS_H
struct CocoaCursor {
class Cursor {
void* ptr;
public:
Cursor(const char* imgPath, float hotSpotX, float hotSpotY);
~Cursor();
void apply();
};
typedef struct CocoaCursor CocoaCursor, *CursorRef; // including the struct keyword for Objective-C's sake
C_DECL CursorRef CreateCursorFromFile(const char* imgPath, float hotSpotX, float hotSpotY);
C_DECL void DisposeNSCursor(CursorRef cursor);
C_DECL void SetNSCursor(CursorRef cursor);
C_DECL void SetNSCursorWatch();
C_DECL void HideNSCursor();
C_DECL void ShowNSCursor();
C_DECL void CleanUp();
void setCursorWatch();
// This hides the cursor until it moves
void obscureCursor();
#undef C_DECL
#endif

View File

@@ -6,9 +6,8 @@
// Wrappers for NSCursor, based on an Apple example
//
#import <Cocoa/Cocoa.h>
#import "cursors.h"
NSAutoreleasePool *pool;
#include "cursors.h"
#include <Cocoa/Cocoa.h>
static NSImage* ImageFromURL(CFURLRef url){
CGImageSourceRef imageSource = CGImageSourceCreateWithURL(url, NULL);
@@ -39,42 +38,29 @@ static NSImage* ImageFromURL(CFURLRef url){
return newImage;
}
CursorRef CreateCursorFromFile(const char* path, float hotSpotX, float hotSpotY){
Cursor::Cursor(const char* path, float hotSpotX, float hotSpotY){
FSRef ref;
FSPathMakeRef((UInt8*)path, &ref, NULL);
CFURLRef imgPath = CFURLCreateFromFSRef(NULL, &ref);
#if 0
static BOOL inited = NO;
if(!inited){
// TODO: Why is this here? Should I move it somewhere else?
NSApplicationLoad();
pool = [[NSAutoreleasePool alloc] init];
[[[NSWindow alloc] init] release];
inited = YES;
}
#endif
NSImage *img = ImageFromURL(imgPath);
NSCursor *cursor = [[NSCursor alloc] initWithImage:img hotSpot:NSMakePoint(hotSpotX, hotSpotY)];
[img release];
CursorRef theCursor = malloc(sizeof(CocoaCursor));
theCursor->ptr = cursor;
return theCursor;
ptr = cursor;
}
void DisposeNSCursor(CursorRef cursor){
[(NSCursor*)cursor->ptr release];
free(cursor);
Cursor::~Cursor(){
[(NSCursor*)ptr release];
}
void SetNSCursor(CursorRef cursor){
[(NSCursor*)cursor->ptr set];
void Cursor::apply(){
[(NSCursor*)ptr set];
}
void SetNSCursorWatch() {
void setCursorWatch() {
}
void CleanUp(){
// [pool release];
void obscureCursor() {
[NSCursor setHiddenUntilMouseMoves: YES];
}

View File

@@ -19,7 +19,6 @@
#include <boost/filesystem.hpp>
#include <boost/math/constants/constants.hpp>
#include "cursors.h"
#include "restypes.hpp"
using boost::math::constants::pi;
@@ -30,28 +29,25 @@ cursor_type arrow_curs[3][3] = {
{SW_curs, S_curs, SE_curs},
};
cursor_type current_cursor = sword_curs;
CursorRef cursors[24] = {
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
const std::string cursors[24] = {
"wand", "eyedropper", "brush", "spraycan",
"eraser", "topleft", "bottomright", "hand",
"NW", "N", "NE",
"W", "wait", "E",
"SW", "S", "SE",
"sword", "boot", "drop", "target",
"talk", "key", "look",
};
RECT bg[21];
RECT map_pat[30];
RECT bw_pats[6];
sf::Texture bg_gworld;
bool use_win_graphics = false;
CursorRef GetCursorFromPath(std::string filename, location hotspot);
sf::Shader maskShader;
extern fs::path progDir;
// TODO: Shouldn't need this
extern sf::RenderWindow mainPtr;
void clean_up_graphtool(){
for(int i = 0; i < 24; i++)
DisposeNSCursor(cursors[i]);
CleanUp();
}
void init_graph_tool(){
fs::path shaderPath = progDir/"data"/"shaders";
fs::path fragPath = shaderPath/"mask.frag", vertPath = shaderPath/"mask.vert";
@@ -83,14 +79,6 @@ void init_graph_tool(){
delete[] vbuf;
int i,j;
// TODO: The duplication of location here shouldn't be necessary
// TODO: Store the hotspots on disk instead of hardcoded here
static const location cursor_hs[24] = {
location{ 1, 4}, location{14, 1}, location{13, 5}, location{8,8}, location{8,8}, location{8,8}, location{8,8}, location{0,14},
location{ 3,12}, location{ 7,13}, location{ 3,12},
location{ 3, 9}, location{ 8, 8}, location{ 8, 3},
location{ 3,12}, location{ 7,13}, location{ 3,12},
location{ 1, 1}, location{ 7, 3}, location{ 0,14}, location{8,8}, location{6,7}, location{3,2}, location{7,6}
};
static const location pat_offs[17] = {
location{0,3}, location{1,1}, location{2,1}, location{2,0},
location{3,0}, location{3,1}, location{1,3}, location{0,0},
@@ -107,28 +95,6 @@ void init_graph_tool(){
18,19,20,21,22,24,25,27,
28,29
};
static const char*const edit_cursor_files[8] = {
"wand.gif","eyedropper.gif","brush.gif","spraycan.gif",
"eraser.gif","topleft.gif","bottomright.gif","hand.gif"
};
static const char*const arrow_files[3][3] = {
{"NW.gif","W.gif","SW.gif"},
{"N.gif","wait.gif","S.gif"},
{"NE.gif","E.gif","SE.gif"}
};
static const char*const game_cursor_files[7] = {
"sword.gif","boot.gif","drop.gif","target.gif",
"talk.gif","key.gif","look.gif"
};
if (cursors[0] == NULL) {
for (i = 0; i < 8; i++)
cursors[i] = GetCursorFromPath(edit_cursor_files[i],cursor_hs[i]);
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
cursors[arrow_curs[i][j]] = GetCursorFromPath(arrow_files[i][j],cursor_hs[arrow_curs[i][j]]);
for (i = 17; i < 24; i++)
cursors[i] = GetCursorFromPath(game_cursor_files[i - 17],cursor_hs[i]);
}
// for (i = 0; i < 21; i++)
// bg[i] = GetPixPat(128 + i);
for(i = 0; i < 17; i++){
@@ -176,7 +142,8 @@ void init_graph_tool(){
void set_cursor(cursor_type which_c) {
current_cursor = which_c;
SetNSCursor(cursors[current_cursor]);
Cursor& curs = *ResMgr::get<CursorRsrc>(cursors[current_cursor]);
curs.apply();
}
void restore_cursor(){
@@ -653,17 +620,6 @@ std::string get_str(std::string list, short j){
return strings[j - 1];
}
extern fs::path progDir;
CursorRef GetCursorFromPath(std::string filename, location hotspot){
fs::path fullpath = progDir/"Scenario Editor"/"graphics.exd";
if(use_win_graphics) fullpath /= "win";
else fullpath /= "mac";
fullpath /= "cursors";
fullpath /= filename;
printf("Loading cursor from: %s\n\n",fullpath.c_str());
return CreateCursorFromFile(fullpath.c_str(), hotspot.x, hotspot.y);
}
m_pic_index_t m_pic_index[] = {
{1, 1, 1},
{2, 1, 1},

View File

@@ -102,7 +102,6 @@ struct cCustomGraphics {
};
void init_graph_tool();
void clean_up_graphtool();
void set_cursor(cursor_type which_curs);
void restore_cursor();
void rect_draw_some_item(sf::RenderTarget& targ_gworld,RECT targ_rect);

View File

@@ -16,25 +16,19 @@
#include <vector>
#include <string>
#include <fstream>
#include <map>
#include <boost/filesystem/path.hpp>
struct cCursor {
sf::Image img;
int xHot, yHot;
};
#include "cursors.h"
#include "location.h"
using ImageRsrc = sf::Image;
using CursorRsrc = cCursor;
using CursorRsrc = Cursor;
using FontRsrc = sf::Font;
using StringRsrc = std::vector<std::string>;
using SoundRsrc = sf::SoundBuffer;
namespace ResMgr {
template<> inline ImageRsrc* resLoader<ImageRsrc>::operator() (std::string fname) {
// static bool inited = false;
// if(!inited) {
// wxImage::AddHandler(new wxPNGHandler());
// }
fs::path fpath = resPool<ImageRsrc>::rel2abs(fname + ".png");
ImageRsrc* img = new ImageRsrc();
if(img->loadFromFile(fpath.string())) return img;
@@ -43,10 +37,16 @@ namespace ResMgr {
}
template<> inline CursorRsrc* resLoader<CursorRsrc>::operator() (std::string fname) {
// static bool inited = false;
// if(!inited) {
// wxImage::AddHandler(new wxGIFHandler());
// }
// TODO: Store the hotspots on disk instead of hardcoded here
static const std::map<std::string,location> cursor_hs = {
{"wand", {1, 4}}, {"eyedropper", {14, 1}}, {"brush", {13, 5}}, {"spraycan", {8, 8}},
{"eraser", {8, 8}}, {"topleft", {8, 8}}, {"bottomright", {8, 8}}, {"hand", {0, 14}},
{"NW", {3, 12}}, {"N", {7, 13}}, {"NE", {3, 12}},
{"W", {3, 9}}, {"wait", {8, 8}}, {"E", {8, 3}},
{"SW", {3, 12}}, {"S", {7, 13}}, {"SE", {3, 12}},
{"sword", {1, 1}}, {"boot", {7, 3}}, {"drop", {0, 14}}, {"target", {8, 8}},
{"talk", {6, 7}}, {"key", {3, 2}}, {"look", {7, 6}}
};
fs::path fpath = resPool<CursorRsrc>::rel2abs(fname + ".gif");
fs::path hotpath = resPool<CursorRsrc>::rel2abs(fname + ".hot");
int x = 0, y = 0;
@@ -54,12 +54,19 @@ namespace ResMgr {
std::ifstream fin(hotpath.c_str());
fin >> x >> y;
fin.close();
} else fprintf(stderr,"Cursor hotspot missing: %s",fname.c_str());
sf::Image img;
if(img.loadFromFile(fpath.string())) {
CursorRsrc* cur = new CursorRsrc{img,x,y};
return cur;
} else {
auto entry = cursor_hs.find(fname);
if(entry == cursor_hs.end())
fprintf(stderr,"Cursor hotspot missing: %s",fname.c_str());
else {
fprintf(stderr,"Cursor hotspot missing (using fallback value): %s",fname.c_str());
location hs = entry->second;
x = hs.x; y = hs.y;
}
}
// TODO: Handle errors?
CursorRsrc* cur = new Cursor(fpath.c_str(),x,y);
return cur;
throw xResMgrErr("Failed to load GIF cursor: " + fname);
}