FIFE 2008.0
|
00001 /*************************************************************************** 00002 * Copyright (C) 2005-2008 by the FIFE team * 00003 * http://www.fifengine.de * 00004 * This file is part of FIFE. * 00005 * * 00006 * FIFE is free software; you can redistribute it and/or * 00007 * modify it under the terms of the GNU Lesser General Public * 00008 * License as published by the Free Software Foundation; either * 00009 * version 2.1 of the License, or (at your option) any later version. * 00010 * * 00011 * This library is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00014 * Lesser General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU Lesser General Public * 00017 * License along with this library; if not, write to the * 00018 * Free Software Foundation, Inc., * 00019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 00020 ***************************************************************************/ 00021 00022 // Standard C++ library includes 00023 #if defined( WIN32 ) 00024 #include <windows.h> 00025 #include <sdl.h> 00026 #endif 00027 00028 #if defined( __unix__ ) 00029 #include <X11/Xcursor/Xcursor.h> 00030 #endif 00031 00032 // 3rd party library includes 00033 00034 // FIFE includes 00035 // These includes are split up in two parts, separated by one empty line 00036 // First block: files included from the FIFE root src directory 00037 // Second block: files included from the same folder 00038 #include "util/structures/rect.h" 00039 #include "util/time/timemanager.h" 00040 #include "util/log/logger.h" 00041 00042 #include "imagepool.h" 00043 #include "animationpool.h" 00044 #include "animation.h" 00045 #include "image.h" 00046 #include "renderbackend.h" 00047 #include "cursor.h" 00048 00049 #if defined( WIN32 ) 00050 00051 // From SDL_sysmouse.c 00052 struct WMcursor { 00053 HCURSOR curs; 00054 #ifndef _WIN32_WCE 00055 Uint8 *ands; 00056 Uint8 *xors; 00057 #endif 00058 }; 00059 00060 #endif 00061 00062 #if defined( __unix__ ) 00063 00064 // Stops the compiler from confusing it with FIFE:Cursor 00065 typedef Cursor XCursor; 00066 00067 // From SDL_x11mouse.c 00068 struct WMcursor { 00069 Cursor x_cursor; 00070 }; 00071 00072 #endif 00073 00074 namespace FIFE { 00075 static Logger _log(LM_GUI); // We should have a log module for cursor 00076 00077 Cursor::Cursor(ImagePool* imgpool, AnimationPool* animpool, RenderBackend* renderbackend): 00078 m_cursor_id(NC_ARROW), 00079 m_drag_id(0), 00080 m_cursor_type(CURSOR_NATIVE), 00081 m_drag_type(CURSOR_NONE), 00082 m_native_cursor(NULL), 00083 m_renderbackend(renderbackend), 00084 m_imgpool(imgpool), 00085 m_animpool(animpool), 00086 m_animtime(0), 00087 m_drag_animtime(0), 00088 m_drag_offset_x(0), 00089 m_drag_offset_y(0), 00090 m_mx(0), 00091 m_my(0), 00092 m_timemanager(TimeManager::instance()), 00093 m_invalidated(false) { 00094 assert(m_timemanager); 00095 set(m_cursor_type, m_cursor_id); 00096 } 00097 00098 void Cursor::set(MouseCursorType ctype, unsigned int cursor_id) { 00099 m_cursor_id = cursor_id; 00100 m_cursor_type = ctype; 00101 int mx, my; 00102 SDL_GetMouseState(&mx, &my); 00103 00104 if (ctype == CURSOR_NATIVE) { 00105 if (!SDL_ShowCursor(1)) { 00106 SDL_PumpEvents(); 00107 SDL_WarpMouse(mx, my); 00108 } 00109 setNativeCursor(cursor_id); 00110 } else { 00111 if (SDL_ShowCursor(0)) { 00112 SDL_PumpEvents(); 00113 SDL_WarpMouse(mx, my); 00114 } 00115 if (ctype == CURSOR_ANIMATION) { 00116 m_animtime = m_timemanager->getTime(); 00117 } 00118 } 00119 m_invalidated = false; 00120 } 00121 00122 void Cursor::setDrag(MouseCursorType ctype, unsigned int drag_id, int drag_offset_x, int drag_offset_y) { 00123 m_drag_type = ctype; 00124 m_drag_id = drag_id; 00125 m_drag_offset_x = drag_offset_x; 00126 m_drag_offset_y = drag_offset_y; 00127 if (ctype != CURSOR_NONE) { 00128 if (ctype == CURSOR_ANIMATION) { 00129 m_drag_animtime = m_timemanager->getTime(); 00130 } 00131 } 00132 } 00133 00134 void Cursor::invalidate() { 00135 if (m_native_cursor != NULL) { 00136 SDL_free(m_native_cursor->wm_cursor); 00137 m_native_cursor->wm_cursor = NULL; 00138 SDL_FreeCursor(m_native_cursor); 00139 m_native_cursor = NULL; 00140 00141 m_invalidated = true; 00142 } 00143 } 00144 00145 void Cursor::draw() { 00146 if (m_invalidated) { 00147 set(m_cursor_type, m_cursor_id); 00148 } 00149 00150 SDL_GetMouseState(&m_mx, &m_my); 00151 if ((m_cursor_type == CURSOR_NATIVE) && (m_drag_type == CURSOR_NONE)) { 00152 return; 00153 } 00154 00155 // render possible drag image 00156 Image* img = NULL; 00157 if (m_drag_type == CURSOR_IMAGE) { 00158 img = &m_imgpool->getImage(m_drag_id); 00159 } else if (m_drag_type == CURSOR_ANIMATION) { 00160 Animation& anim = m_animpool->getAnimation(m_drag_id); 00161 int animtime = (m_timemanager->getTime() - m_drag_animtime) % anim.getDuration(); 00162 img = anim.getFrameByTimestamp(animtime); 00163 } 00164 if (img) { 00165 Rect area(m_mx + m_drag_offset_x + img->getXShift(), m_my + m_drag_offset_y + img->getYShift(), img->getWidth(), img->getHeight()); 00166 m_renderbackend->pushClipArea(area, false); 00167 img->render(area); 00168 m_renderbackend->popClipArea(); 00169 } 00170 00171 // render possible cursor image 00172 img = NULL; 00173 if (m_cursor_type == CURSOR_IMAGE) { 00174 img = &m_imgpool->getImage(m_cursor_id); 00175 } else if (m_cursor_type == CURSOR_ANIMATION) { 00176 Animation& anim = m_animpool->getAnimation(m_cursor_id); 00177 int animtime = (m_timemanager->getTime() - m_animtime) % anim.getDuration(); 00178 img = anim.getFrameByTimestamp(animtime); 00179 } 00180 if (img) { 00181 Rect area(m_mx + img->getXShift(), m_my + img->getYShift(), img->getWidth(), img->getHeight()); 00182 m_renderbackend->pushClipArea(area, false); 00183 img->render(area); 00184 m_renderbackend->popClipArea(); 00185 } 00186 } 00187 00188 unsigned int Cursor::getNativeId(unsigned int cursor_id) { 00189 #if defined( WIN32 ) 00190 switch (cursor_id) { 00191 case NC_ARROW: 00192 return 32512; // IDC_ARROW; 00193 case NC_IBEAM: 00194 return 32513; // IDC_IBEAM; 00195 case NC_WAIT: 00196 return 32514; // IDC_WAIT; 00197 case NC_CROSS: 00198 return 32515; // IDC_CROSS; 00199 case NC_UPARROW: 00200 return 32516; // IDC_UPARROW; 00201 case NC_RESIZESE: 00202 return 32642; // IDC_SIZENWSE; 00203 case NC_RESIZESW: 00204 return 32643; // IDC_SIZENESW; 00205 case NC_RESIZEE: 00206 return 32644; // IDC_SIZEWE; 00207 case NC_RESIZES: 00208 return 32645; // IDC_SIZENS; 00209 case NC_RESIZENW: 00210 return 32642; // IDC_SIZENWSE; 00211 case NC_RESIZENE: 00212 return 32643; // IDC_SIZENESW; 00213 case NC_RESIZEW: 00214 return 32644; // IDC_SIZEWE; 00215 case NC_RESIZEN: 00216 return 32645; // IDC_SIZENS; 00217 case NC_RESIZEALL: 00218 return 32646; // IDC_SIZEALL; 00219 case NC_NO: 00220 return 32648; // IDC_NO; 00221 case NC_HAND: 00222 return 32649; // IDC_HAND; 00223 case NC_APPSTARTING: 00224 return 32650; // IDC_APPSTARTING; 00225 case NC_HELP: 00226 return 32651; // IDC_HELP; 00227 default: 00228 break; 00229 } 00230 00231 #elif defined( __unix__ ) 00232 switch (cursor_id) { 00233 case NC_ARROW: 00234 return 68; 00235 case NC_IBEAM: 00236 return 152; 00237 case NC_WAIT: 00238 return 150; 00239 case NC_CROSS: 00240 return 130; 00241 case NC_UPARROW: 00242 return 22; 00243 case NC_RESIZESE: 00244 return 14; 00245 case NC_RESIZESW: 00246 return 12; 00247 case NC_RESIZEE: 00248 return 96; 00249 case NC_RESIZES: 00250 return 16; 00251 case NC_RESIZENW: 00252 return 134; 00253 case NC_RESIZENE: 00254 return 136; 00255 case NC_RESIZEW: 00256 return 70; 00257 case NC_RESIZEN: 00258 return 138; 00259 case NC_RESIZEALL: 00260 return 52; 00261 case NC_NO: 00262 return 0; 00263 case NC_HAND: 00264 return 60; 00265 case NC_APPSTARTING: 00266 return 150; 00267 case NC_HELP: 00268 return 92; 00269 default: 00270 break; 00271 } 00272 #endif 00273 return cursor_id; 00274 } 00275 00276 void Cursor::setNativeCursor(unsigned int cursor_id) { 00277 #if defined( WIN32 ) || defined(__unix__) 00278 // Check if a value in NativeCursors is requested 00279 cursor_id = getNativeId(cursor_id); 00280 00281 // Load cursor 00282 #if defined( __unix__ ) 00283 static Display* dsp = XOpenDisplay(NULL); 00284 XCursor xCursor = XcursorShapeLoadCursor(dsp, cursor_id); 00285 if (xCursor == 0) { 00286 if (m_native_cursor != NULL) { 00287 SDL_FreeCursor(m_native_cursor); 00288 m_native_cursor = NULL; 00289 } 00290 FL_WARN(_log, "Cursor: No cursor matching cursor_id was found."); 00291 return; 00292 } 00293 #elif defined( WIN32 ) 00294 // Load native cursor 00295 HCURSOR hIcon = LoadCursor(NULL, MAKEINTRESOURCE(cursor_id)); 00296 if (hIcon == static_cast<HCURSOR>(0)) { 00297 if (m_native_cursor != NULL) { 00298 SDL_FreeCursor(m_native_cursor); 00299 m_native_cursor = NULL; 00300 } 00301 FL_WARN(_log, "Cursor: No cursor matching cursor_id was found."); 00302 return; 00303 } 00304 #endif 00305 00306 WMcursor *cursor; 00307 SDL_Cursor *curs2; 00308 00309 // Allocate memory. Use SDL_FreeCursor to free cursor memory 00310 cursor = (WMcursor *)SDL_malloc(sizeof(*cursor)); 00311 curs2 = (SDL_Cursor *)SDL_malloc(sizeof *curs2); 00312 00313 //-- Set up some default values -- 00314 curs2->wm_cursor = cursor; 00315 curs2->data = NULL; 00316 curs2->mask = NULL; 00317 curs2->save[0] = NULL; 00318 curs2->save[1] = NULL; 00319 curs2->area.x = 0; 00320 curs2->area.y = 0; 00321 curs2->area.w = 32; 00322 curs2->area.h = 32; 00323 curs2->hot_x = 0; 00324 curs2->hot_y = 0; 00325 00326 #if defined(WIN32) 00327 cursor->curs = hIcon; 00328 #ifndef _WIN32_WCE 00329 cursor->ands = NULL; 00330 cursor->xors = NULL; 00331 #endif 00332 00333 // Get hot spot 00334 ICONINFO iconinfo; 00335 if (GetIconInfo(hIcon, &iconinfo)) { 00336 curs2->hot_x = static_cast<Sint16>(iconinfo.xHotspot); 00337 curs2->hot_y = static_cast<Sint16>(iconinfo.yHotspot); 00338 } 00339 00340 #elif defined(__unix__) 00341 cursor->x_cursor = xCursor; 00342 XSync(dsp, false); 00343 #endif 00344 00345 m_native_cursor = curs2; 00346 SDL_SetCursor(curs2); 00347 00348 #endif // WIN32 || __unix__ 00349 } 00350 }