From f9969775e6d2f798a3bfea5c58fc5478dad07eae Mon Sep 17 00:00:00 2001 From: pixel Date: Sat, 27 Nov 2004 21:48:01 +0000 Subject: Large dos2unix commit... --- lib/base.cc | 356 ++++---- lib/engine.cc | 818 +++++++++---------- lib/font.cc | 1410 ++++++++++++++++---------------- lib/glbase.cc | 534 ++++++------ lib/glfont.cc | 144 ++-- lib/glshape.cc | 506 ++++++------ lib/glsprite.cc | 210 ++--- lib/glwidgets.cc | 58 +- lib/mcolor.cc | 132 +-- lib/shape.cc | 1856 +++++++++++++++++++++--------------------- lib/sprite.cc | 380 ++++----- lib/texture.cc | 722 ++++++++--------- lib/widgets.cc | 2364 +++++++++++++++++++++++++++--------------------------- 13 files changed, 4745 insertions(+), 4745 deletions(-) (limited to 'lib') diff --git a/lib/base.cc b/lib/base.cc index 61426eb..13d6052 100644 --- a/lib/base.cc +++ b/lib/base.cc @@ -1,178 +1,178 @@ -/* - * mogltk - * Copyright (C) 1999-2004 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: base.cc,v 1.13 2004-11-27 21:44:52 pixel Exp $ */ - -#include -#include -#include "base.h" -#include "engine.h" -#include "generic.h" -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include "gettext.h" - -mogltk::base::base(int w, int h, int flags) throw(GeneralException) : surface(0) { - width = w; - height = h; - - mogltk::engine::setup(); - if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) { - throw GeneralException(String("Couldn't initialise Video SubSystem: ") + SDL_GetError()); - } - - if (!(surface = SDL_SetVideoMode(width, height, 0, flags | SDL_HWSURFACE))) { - throw GeneralException(String("Couldn't set SDL mode: ") + SDL_GetError()); - } - - mogltk::engine::base_o = this; - - float ratio = surface->w; - ratio /= surface->h; - - printm(M_INFO, "Video resolution: %dx%dx%d (ratio = %3.2f)\n", surface->w, surface->h, surface->format->BitsPerPixel, ratio); - - SDL_ShowCursor(SDL_DISABLE); - SDL_FillRect(surface, NULL, 0); - SDL_Flip(surface); - SDL_FillRect(surface, NULL, 0); - mogltk::engine::postsetup(); -} - -mogltk::base::~base() { -} - -int mogltk::base::GetWidth(void) { - return width; -} - -int mogltk::base::GetHeight(void) { - return height; -} - -void mogltk::base::Flip(bool clear) { - mogltk::engine::pollevents(); - SDL_Flip(surface); - if (clear) - SDL_FillRect(surface, NULL, 0); -} - -mogltk::base::base(int w, int h, int flags, int) : surface(0) { - width = w; - height = h; - - SDL_ShowCursor(SDL_DISABLE); -} - -void mogltk::base::setsurface(SDL_Surface * _surface) throw (GeneralException) { - if (surface) - throw GeneralException("Can't set video surface twice"); - surface = _surface; -} - -SDL_Surface * mogltk::base::getsurface() { - return surface; -} - -void mogltk::base::Enter2DMode() { -} - -void mogltk::base::Leave2DMode() { -} - -bool mogltk::base::is2D() { - return true; -} - -void mogltk::base::changeviewport(int x, int y, unsigned int w, unsigned int h) { - SDL_Rect r; - - if ((w == 0) && (h == 0)) { - w = GetWidth() - x; - h = GetHeight() - y; - } - - r.x = x; - r.y = y; - r.w = w; - r.h = h; - - SDL_SetClipRect(surface, &r); -} - -void mogltk::base::ToggleFullscreen() { - int newflags = surface->flags; - - if (surface->flags & SDL_FULLSCREEN) - newflags &= ~SDL_FULLSCREEN; - else - newflags |= SDL_FULLSCREEN; - - texture::Taintall(); - - surface = SDL_SetVideoMode(surface->w, surface->h, surface->format->BitsPerPixel, - SDL_HWSURFACE | newflags); -} - -inline static unsigned int nextpower(unsigned int n) { - unsigned int i; - - if (!n) - return n; - - if (ISPOT(n)) - return n; - - for (i = 31; i >= 0; i--) { - if ((n >> i) & 1) { - return 1 << (i + 1); - } - } -} - -mogltk::texture * mogltk::base::GrabTexture() { - int w = nextpower(GetWidth()); - int h = nextpower(GetHeight()); - texture * r = new texture(w, h); - - SDL_BlitSurface(getsurface(), NULL, r->GetSurface(), NULL); - - return r; -} - -SDL_Surface * mogltk::base::GrabSurface() { - SDL_Surface * r = SDL_CreateRGBSurface(SDL_SWSURFACE, GetWidth(), GetHeight(), 24, -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - 0xff000000, - 0x00ff0000, - 0x0000ff00, - 0x00000000 -#else - 0x000000ff, - 0x0000ff00, - 0x00ff0000, - 0x00000000 -#endif - ); - - SDL_BlitSurface(getsurface(), NULL, r, NULL); - - return r; -} +/* + * mogltk + * Copyright (C) 1999-2004 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: base.cc,v 1.14 2004-11-27 21:48:03 pixel Exp $ */ + +#include +#include +#include "base.h" +#include "engine.h" +#include "generic.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "gettext.h" + +mogltk::base::base(int w, int h, int flags) throw(GeneralException) : surface(0) { + width = w; + height = h; + + mogltk::engine::setup(); + if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) { + throw GeneralException(String("Couldn't initialise Video SubSystem: ") + SDL_GetError()); + } + + if (!(surface = SDL_SetVideoMode(width, height, 0, flags | SDL_HWSURFACE))) { + throw GeneralException(String("Couldn't set SDL mode: ") + SDL_GetError()); + } + + mogltk::engine::base_o = this; + + float ratio = surface->w; + ratio /= surface->h; + + printm(M_INFO, "Video resolution: %dx%dx%d (ratio = %3.2f)\n", surface->w, surface->h, surface->format->BitsPerPixel, ratio); + + SDL_ShowCursor(SDL_DISABLE); + SDL_FillRect(surface, NULL, 0); + SDL_Flip(surface); + SDL_FillRect(surface, NULL, 0); + mogltk::engine::postsetup(); +} + +mogltk::base::~base() { +} + +int mogltk::base::GetWidth(void) { + return width; +} + +int mogltk::base::GetHeight(void) { + return height; +} + +void mogltk::base::Flip(bool clear) { + mogltk::engine::pollevents(); + SDL_Flip(surface); + if (clear) + SDL_FillRect(surface, NULL, 0); +} + +mogltk::base::base(int w, int h, int flags, int) : surface(0) { + width = w; + height = h; + + SDL_ShowCursor(SDL_DISABLE); +} + +void mogltk::base::setsurface(SDL_Surface * _surface) throw (GeneralException) { + if (surface) + throw GeneralException("Can't set video surface twice"); + surface = _surface; +} + +SDL_Surface * mogltk::base::getsurface() { + return surface; +} + +void mogltk::base::Enter2DMode() { +} + +void mogltk::base::Leave2DMode() { +} + +bool mogltk::base::is2D() { + return true; +} + +void mogltk::base::changeviewport(int x, int y, unsigned int w, unsigned int h) { + SDL_Rect r; + + if ((w == 0) && (h == 0)) { + w = GetWidth() - x; + h = GetHeight() - y; + } + + r.x = x; + r.y = y; + r.w = w; + r.h = h; + + SDL_SetClipRect(surface, &r); +} + +void mogltk::base::ToggleFullscreen() { + int newflags = surface->flags; + + if (surface->flags & SDL_FULLSCREEN) + newflags &= ~SDL_FULLSCREEN; + else + newflags |= SDL_FULLSCREEN; + + texture::Taintall(); + + surface = SDL_SetVideoMode(surface->w, surface->h, surface->format->BitsPerPixel, + SDL_HWSURFACE | newflags); +} + +inline static unsigned int nextpower(unsigned int n) { + unsigned int i; + + if (!n) + return n; + + if (ISPOT(n)) + return n; + + for (i = 31; i >= 0; i--) { + if ((n >> i) & 1) { + return 1 << (i + 1); + } + } +} + +mogltk::texture * mogltk::base::GrabTexture() { + int w = nextpower(GetWidth()); + int h = nextpower(GetHeight()); + texture * r = new texture(w, h); + + SDL_BlitSurface(getsurface(), NULL, r->GetSurface(), NULL); + + return r; +} + +SDL_Surface * mogltk::base::GrabSurface() { + SDL_Surface * r = SDL_CreateRGBSurface(SDL_SWSURFACE, GetWidth(), GetHeight(), 24, +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + 0xff000000, + 0x00ff0000, + 0x0000ff00, + 0x00000000 +#else + 0x000000ff, + 0x0000ff00, + 0x00ff0000, + 0x00000000 +#endif + ); + + SDL_BlitSurface(getsurface(), NULL, r, NULL); + + return r; +} diff --git a/lib/engine.cc b/lib/engine.cc index e0e1efd..d9e479f 100644 --- a/lib/engine.cc +++ b/lib/engine.cc @@ -1,409 +1,409 @@ -/* - * mogltk - * Copyright (C) 1999-2004 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: engine.cc,v 1.27 2004-11-27 21:44:52 pixel Exp $ */ - -#include -#include -#include "engine.h" -#include "glfont.h" -#include "glsprite.h" - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include "gettext.h" - -bool mogltk::engine::inited = false, mogltk::engine::postsetuped = false; -bool mogltk::engine::appactive = false, mogltk::engine::cursorvisible = false, mogltk::engine::quitrequest = false; -int mogltk::engine::mx, mogltk::engine::my, mogltk::engine::mz = 0, mogltk::engine::mbuttons; -int mogltk::engine::frames, mogltk::engine::locked = 0; -double mogltk::engine::curfps = -1; -Uint32 mogltk::engine::curticks; -mogltk::widget * mogltk::engine::root = 0; - -mogltk::glbase * mogltk::engine::glbase_o = 0; -mogltk::base * mogltk::engine::base_o = 0; - -mogltk::engine::keyevent * mogltk::engine::keyevent_h = 0; -mogltk::engine::mouseevent * mogltk::engine::mouseevent_h = 0; - -#define UPDATERATE 1000 - -mogltk::engine::keyevent::keyevent() { - new_handler = 0; - if ((old_handler = getkeyevent())) - old_handler->new_handler = this; - setkeyevent(this); -} - -mogltk::engine::keyevent::~keyevent() { - if (new_handler) - new_handler->old_handler = old_handler; - if (old_handler) - old_handler->new_handler = new_handler; - - if (getkeyevent() == this) - setkeyevent(old_handler); -} - -void mogltk::engine::keyevent::up(SDL_keysym) { - printm(M_INFO, "Generic keyevent::up called\n"); -} - -void mogltk::engine::keyevent::down(SDL_keysym) { - printm(M_INFO, "Generic keyevent::down called\n"); -} - -class keyhandler_t : public mogltk::engine::keyevent { - virtual void down(SDL_keysym keysym) { - if (keysym.sym == SDLK_ESCAPE) - mogltk::engine::quit(); - else if ((keysym.sym == SDLK_RETURN) && (keysym.mod & KMOD_ALT)) - mogltk::engine::base_o->ToggleFullscreen(); - else if (old_handler) - old_handler->down(keysym); - } - virtual void up(SDL_keysym keysym) { - if (old_handler) - old_handler->up(keysym); - } -} basic_keyhandler; - -mogltk::engine::mouseevent::mouseevent() { - new_handler = 0; - if ((old_handler = getmouseevent())) - old_handler->new_handler = this; - setmouseevent(this); -} - -mogltk::engine::mouseevent::~mouseevent() { - if (new_handler) - new_handler->old_handler = old_handler; - if (old_handler) - old_handler->new_handler = new_handler; - - if (getmouseevent() == this) - setmouseevent(old_handler); -} - -void mogltk::engine::mouseevent::move(SDL_MouseMotionEvent) { - printm(M_INFO, "Generic mouseevent::move called\n"); -} - -void mogltk::engine::mouseevent::action(SDL_MouseButtonEvent) { - printm(M_INFO, "Generic mouseevent::action called\n"); -} - -int mogltk::engine::setup() throw(GeneralException) { - if (inited) { - printm(M_WARNING, FUNCNAME + _(" called twice, ignoring second call.\n")); - return -1; - } - if (SDL_Init(0) < 0) { - throw GeneralException(FUNCNAME + _(": Unable to start SDL base system")); - } - atexit(SDL_Quit); - - inited = true; - - return 0; -} - -int mogltk::engine::postsetup() throw(GeneralException) { - if (postsetuped) { - printm(M_WARNING, FUNCNAME + _(" called twice, ignoring second call.\n")); - return -1; - } - - SDL_EnableUNICODE(1); - curticks = SDL_GetTicks(); - - postsetuped = true; - - if (glbase_o) { - mogltk::SystemFont = new mogltk::glfont(&Input("font.bin")); - mogltk::FixedFont = new mogltk::glfont(&Input("fixed-font.bin")); - Sprite::Cursor = new mogltk::glSprite(&Input("cursor.rgba"), 25, 25); - } else { - mogltk::SystemFont = new mogltk::font(&Input("font.bin")); - mogltk::FixedFont = new mogltk::font(&Input("fixed-font.bin")); - Sprite::Cursor = new mogltk::Sprite(&Input("cursor.rgba"), 25, 25); - } - - return 0; -} - -int mogltk::engine::GetInited() { - return inited; -} - -class embedRWops : public Base { - public: - embedRWops(Handle *); - int seek(int, int); - int read(void *, int, int); - int write(const void *, int, int); - private: - Handle * h; -}; - -embedRWops::embedRWops(Handle * ah) : h(ah) {} - -int embedRWops::seek(int offset, int whence) { - return h->seek(offset, whence); -} - -int embedRWops::read(void * ptr, int size, int num) { - return h->read(ptr, size * num); -} - -int embedRWops::write(const void * ptr, int size, int num) { - return h->write(ptr, size * num); -} - -static int embedRWseek(SDL_RWops * context, int offset, int whence) { - if (context->hidden.unknown.data1) - return ((embedRWops *)(context->hidden.unknown.data1))->seek(offset, whence); - return -1; -} - -static int embedRWread(SDL_RWops * context, void * ptr, int size, int num) { - if (context->hidden.unknown.data1) - return ((embedRWops *)(context->hidden.unknown.data1))->read(ptr, size, num); - return -1; -} - -static int embedRWwrite(SDL_RWops * context, const void * ptr, int size, int num) { - if (context->hidden.unknown.data1) - return ((embedRWops *)(context->hidden.unknown.data1))->write(ptr, size, num); - return -1; -} - -static int embedRWclose(SDL_RWops * context) { - if (context->hidden.unknown.data1) { - delete ((embedRWops *)(context->hidden.unknown.data1)); - context->hidden.unknown.data1 = 0; - return 0; - } - return -1; -} - -SDL_RWops * mogltk::engine::RWFromHandle(Handle * h) throw (GeneralException) { - SDL_RWops * r = 0; - if (h) { - if (!(r = SDL_AllocRW())) - throw GeneralException(_("Couldn't allocate memory for SDL_RWops")); - r->hidden.unknown.data1 = (void *) new embedRWops(h); - r->seek = embedRWseek; - r->read = embedRWread; - r->write = embedRWwrite; - r->close = embedRWclose; - } - return r; -} - -void mogltk::engine::pollevents() throw (GeneralException) { - SDL_Event event; - bool hastoreturn = appactive; - - if (!postsetuped) - postsetup(); - - if (appactive) { - Uint32 ticks = SDL_GetTicks(); - frames++; - if (ticks - curticks > UPDATERATE) { - curfps = (double) frames * 1000 / (ticks - curticks); - frames = 0; - curticks = ticks; - } - } else { - curfps = -1; - } - - while(true) { - if (hastoreturn || quitrequest) - if (!SDL_PollEvent(NULL)) { - updatemouse(); - return; - } - if (!SDL_WaitEvent(&event)) { - throw GeneralException("Error polling for SDL Event"); - } - switch(event.type) { - case SDL_ACTIVEEVENT: - switch (event.active.state) { - case SDL_APPMOUSEFOCUS: - printm(M_INFO, String("Application ") + (event.active.gain ? "gained" : "loosed") + " mouse focus\n"); - if (cursorvisible) - hastoreturn = true; - break; - case SDL_APPINPUTFOCUS: - printm(M_INFO, String("Application ") + (event.active.gain ? "gained" : "loosed") + " input focus\n"); - if (cursorvisible) - hastoreturn = true; - break; - case SDL_APPACTIVE: - printm(M_INFO, String("Application was ") + (event.active.gain ? "restored" : "iconified")); - if (cursorvisible) - hastoreturn = true; - break; - } - break; - case SDL_KEYDOWN: - case SDL_KEYUP: - printm(M_INFO, String("Key ") + event.key.keysym.scancode + " on keyboard " + event.key.which + (event.key.state == SDL_PRESSED ? " pressed" : " released") + "\n"); - printm(M_INFO, "SDL keysym: %i - Unicode: %04x = `%c`- modifiers: %04x\n", event.key.keysym.sym, event.key.keysym.unicode, event.key.keysym.unicode, event.key.keysym.mod); - if (keyevent_h) { - if (event.key.state == SDL_PRESSED) { - keyevent_h->down(event.key.keysym); - } else { - keyevent_h->up(event.key.keysym); - } - } - break; - case SDL_MOUSEMOTION: - printm(M_INFO, "Mouse slept over the screen - (%i, %i)\n", event.motion.x, event.motion.y); - if (locked) { - if (!((event.motion.x == mx) && (event.motion.y == my))) { - SDL_WarpMouse(mx, my); - } - } - if (cursorvisible) - hastoreturn = true; - if (mouseevent_h) { - mouseevent_h->move(event.motion); - } - break; - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - printm(M_INFO, String().set("Mouse button %02x ", event.button.button) + String((event.button.state == SDL_PRESSED ? "pressed" : "released")) + " at (" + event.button.x + ", " + event.button.y + ")\n"); - if (event.button.state == SDL_PRESSED) { - if (event.button.button == SDL_BUTTON_WHEELUP) { - mz--; - } - if (event.button.button == SDL_BUTTON_WHEELDOWN) { - mz++; - } - } - if (mouseevent_h) { - mouseevent_h->action(event.button); - } - break; - case SDL_QUIT: - printm(M_INFO, "Quit requested\n"); - hastoreturn = quitrequest = true; - break; - case SDL_VIDEOEXPOSE: - printm(M_INFO, "Needs to redraw\n"); - hastoreturn = true; - break; - default: - printm(M_INFO, "Unknow event: %i\n", event.type); - break; - } - } -} - -void mogltk::engine::setappactive(bool p) { - appactive = p; -} - -bool mogltk::engine::getappactive() { - return appactive; -} - -void mogltk::engine::setcursorvisible(bool p) { - cursorvisible = p; -} - -bool mogltk::engine::getcursorvisible() { - return cursorvisible; -} - -void mogltk::engine::quit() { - quitrequest = true; -} - -bool mogltk::engine::quitrequested() { - return quitrequest; -} - -void mogltk::engine::updatemouse() { - mbuttons = SDL_GetMouseState(&mx, &my); -} - -int mogltk::engine::mouseX() { - return mx; -} - -int mogltk::engine::mouseY() { - return my; -} - -int mogltk::engine::mouseZ() { - return mz; -} - -void mogltk::engine::setmouseX(int _mx) { - mx = _mx; - SDL_WarpMouse(mx, my); -} - -void mogltk::engine::setmouseY(int _my) { - my = _my; - SDL_WarpMouse(mx, my); -} - -void mogltk::engine::setmouseZ(int _mz) { - mz = _mz; -} - -int mogltk::engine::mousebuttons() { - return mbuttons; -} - -double mogltk::engine::FPS() { - return curfps; -} - -void mogltk::engine::lockmouse() { - locked = 1; -} - -void mogltk::engine::unlockmouse() { - locked = 0; -} - -void mogltk::engine::setkeyevent(keyevent * k) { - keyevent_h = k; -} - -void mogltk::engine::setmouseevent(mouseevent * m) { - mouseevent_h = m; -} - -mogltk::engine::keyevent * mogltk::engine::getkeyevent() { - return keyevent_h; -} - -mogltk::engine::mouseevent * mogltk::engine::getmouseevent() { - return mouseevent_h; -} +/* + * mogltk + * Copyright (C) 1999-2004 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: engine.cc,v 1.28 2004-11-27 21:48:03 pixel Exp $ */ + +#include +#include +#include "engine.h" +#include "glfont.h" +#include "glsprite.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "gettext.h" + +bool mogltk::engine::inited = false, mogltk::engine::postsetuped = false; +bool mogltk::engine::appactive = false, mogltk::engine::cursorvisible = false, mogltk::engine::quitrequest = false; +int mogltk::engine::mx, mogltk::engine::my, mogltk::engine::mz = 0, mogltk::engine::mbuttons; +int mogltk::engine::frames, mogltk::engine::locked = 0; +double mogltk::engine::curfps = -1; +Uint32 mogltk::engine::curticks; +mogltk::widget * mogltk::engine::root = 0; + +mogltk::glbase * mogltk::engine::glbase_o = 0; +mogltk::base * mogltk::engine::base_o = 0; + +mogltk::engine::keyevent * mogltk::engine::keyevent_h = 0; +mogltk::engine::mouseevent * mogltk::engine::mouseevent_h = 0; + +#define UPDATERATE 1000 + +mogltk::engine::keyevent::keyevent() { + new_handler = 0; + if ((old_handler = getkeyevent())) + old_handler->new_handler = this; + setkeyevent(this); +} + +mogltk::engine::keyevent::~keyevent() { + if (new_handler) + new_handler->old_handler = old_handler; + if (old_handler) + old_handler->new_handler = new_handler; + + if (getkeyevent() == this) + setkeyevent(old_handler); +} + +void mogltk::engine::keyevent::up(SDL_keysym) { + printm(M_INFO, "Generic keyevent::up called\n"); +} + +void mogltk::engine::keyevent::down(SDL_keysym) { + printm(M_INFO, "Generic keyevent::down called\n"); +} + +class keyhandler_t : public mogltk::engine::keyevent { + virtual void down(SDL_keysym keysym) { + if (keysym.sym == SDLK_ESCAPE) + mogltk::engine::quit(); + else if ((keysym.sym == SDLK_RETURN) && (keysym.mod & KMOD_ALT)) + mogltk::engine::base_o->ToggleFullscreen(); + else if (old_handler) + old_handler->down(keysym); + } + virtual void up(SDL_keysym keysym) { + if (old_handler) + old_handler->up(keysym); + } +} basic_keyhandler; + +mogltk::engine::mouseevent::mouseevent() { + new_handler = 0; + if ((old_handler = getmouseevent())) + old_handler->new_handler = this; + setmouseevent(this); +} + +mogltk::engine::mouseevent::~mouseevent() { + if (new_handler) + new_handler->old_handler = old_handler; + if (old_handler) + old_handler->new_handler = new_handler; + + if (getmouseevent() == this) + setmouseevent(old_handler); +} + +void mogltk::engine::mouseevent::move(SDL_MouseMotionEvent) { + printm(M_INFO, "Generic mouseevent::move called\n"); +} + +void mogltk::engine::mouseevent::action(SDL_MouseButtonEvent) { + printm(M_INFO, "Generic mouseevent::action called\n"); +} + +int mogltk::engine::setup() throw(GeneralException) { + if (inited) { + printm(M_WARNING, FUNCNAME + _(" called twice, ignoring second call.\n")); + return -1; + } + if (SDL_Init(0) < 0) { + throw GeneralException(FUNCNAME + _(": Unable to start SDL base system")); + } + atexit(SDL_Quit); + + inited = true; + + return 0; +} + +int mogltk::engine::postsetup() throw(GeneralException) { + if (postsetuped) { + printm(M_WARNING, FUNCNAME + _(" called twice, ignoring second call.\n")); + return -1; + } + + SDL_EnableUNICODE(1); + curticks = SDL_GetTicks(); + + postsetuped = true; + + if (glbase_o) { + mogltk::SystemFont = new mogltk::glfont(&Input("font.bin")); + mogltk::FixedFont = new mogltk::glfont(&Input("fixed-font.bin")); + Sprite::Cursor = new mogltk::glSprite(&Input("cursor.rgba"), 25, 25); + } else { + mogltk::SystemFont = new mogltk::font(&Input("font.bin")); + mogltk::FixedFont = new mogltk::font(&Input("fixed-font.bin")); + Sprite::Cursor = new mogltk::Sprite(&Input("cursor.rgba"), 25, 25); + } + + return 0; +} + +int mogltk::engine::GetInited() { + return inited; +} + +class embedRWops : public Base { + public: + embedRWops(Handle *); + int seek(int, int); + int read(void *, int, int); + int write(const void *, int, int); + private: + Handle * h; +}; + +embedRWops::embedRWops(Handle * ah) : h(ah) {} + +int embedRWops::seek(int offset, int whence) { + return h->seek(offset, whence); +} + +int embedRWops::read(void * ptr, int size, int num) { + return h->read(ptr, size * num); +} + +int embedRWops::write(const void * ptr, int size, int num) { + return h->write(ptr, size * num); +} + +static int embedRWseek(SDL_RWops * context, int offset, int whence) { + if (context->hidden.unknown.data1) + return ((embedRWops *)(context->hidden.unknown.data1))->seek(offset, whence); + return -1; +} + +static int embedRWread(SDL_RWops * context, void * ptr, int size, int num) { + if (context->hidden.unknown.data1) + return ((embedRWops *)(context->hidden.unknown.data1))->read(ptr, size, num); + return -1; +} + +static int embedRWwrite(SDL_RWops * context, const void * ptr, int size, int num) { + if (context->hidden.unknown.data1) + return ((embedRWops *)(context->hidden.unknown.data1))->write(ptr, size, num); + return -1; +} + +static int embedRWclose(SDL_RWops * context) { + if (context->hidden.unknown.data1) { + delete ((embedRWops *)(context->hidden.unknown.data1)); + context->hidden.unknown.data1 = 0; + return 0; + } + return -1; +} + +SDL_RWops * mogltk::engine::RWFromHandle(Handle * h) throw (GeneralException) { + SDL_RWops * r = 0; + if (h) { + if (!(r = SDL_AllocRW())) + throw GeneralException(_("Couldn't allocate memory for SDL_RWops")); + r->hidden.unknown.data1 = (void *) new embedRWops(h); + r->seek = embedRWseek; + r->read = embedRWread; + r->write = embedRWwrite; + r->close = embedRWclose; + } + return r; +} + +void mogltk::engine::pollevents() throw (GeneralException) { + SDL_Event event; + bool hastoreturn = appactive; + + if (!postsetuped) + postsetup(); + + if (appactive) { + Uint32 ticks = SDL_GetTicks(); + frames++; + if (ticks - curticks > UPDATERATE) { + curfps = (double) frames * 1000 / (ticks - curticks); + frames = 0; + curticks = ticks; + } + } else { + curfps = -1; + } + + while(true) { + if (hastoreturn || quitrequest) + if (!SDL_PollEvent(NULL)) { + updatemouse(); + return; + } + if (!SDL_WaitEvent(&event)) { + throw GeneralException("Error polling for SDL Event"); + } + switch(event.type) { + case SDL_ACTIVEEVENT: + switch (event.active.state) { + case SDL_APPMOUSEFOCUS: + printm(M_INFO, String("Application ") + (event.active.gain ? "gained" : "loosed") + " mouse focus\n"); + if (cursorvisible) + hastoreturn = true; + break; + case SDL_APPINPUTFOCUS: + printm(M_INFO, String("Application ") + (event.active.gain ? "gained" : "loosed") + " input focus\n"); + if (cursorvisible) + hastoreturn = true; + break; + case SDL_APPACTIVE: + printm(M_INFO, String("Application was ") + (event.active.gain ? "restored" : "iconified")); + if (cursorvisible) + hastoreturn = true; + break; + } + break; + case SDL_KEYDOWN: + case SDL_KEYUP: + printm(M_INFO, String("Key ") + event.key.keysym.scancode + " on keyboard " + event.key.which + (event.key.state == SDL_PRESSED ? " pressed" : " released") + "\n"); + printm(M_INFO, "SDL keysym: %i - Unicode: %04x = `%c`- modifiers: %04x\n", event.key.keysym.sym, event.key.keysym.unicode, event.key.keysym.unicode, event.key.keysym.mod); + if (keyevent_h) { + if (event.key.state == SDL_PRESSED) { + keyevent_h->down(event.key.keysym); + } else { + keyevent_h->up(event.key.keysym); + } + } + break; + case SDL_MOUSEMOTION: + printm(M_INFO, "Mouse slept over the screen - (%i, %i)\n", event.motion.x, event.motion.y); + if (locked) { + if (!((event.motion.x == mx) && (event.motion.y == my))) { + SDL_WarpMouse(mx, my); + } + } + if (cursorvisible) + hastoreturn = true; + if (mouseevent_h) { + mouseevent_h->move(event.motion); + } + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + printm(M_INFO, String().set("Mouse button %02x ", event.button.button) + String((event.button.state == SDL_PRESSED ? "pressed" : "released")) + " at (" + event.button.x + ", " + event.button.y + ")\n"); + if (event.button.state == SDL_PRESSED) { + if (event.button.button == SDL_BUTTON_WHEELUP) { + mz--; + } + if (event.button.button == SDL_BUTTON_WHEELDOWN) { + mz++; + } + } + if (mouseevent_h) { + mouseevent_h->action(event.button); + } + break; + case SDL_QUIT: + printm(M_INFO, "Quit requested\n"); + hastoreturn = quitrequest = true; + break; + case SDL_VIDEOEXPOSE: + printm(M_INFO, "Needs to redraw\n"); + hastoreturn = true; + break; + default: + printm(M_INFO, "Unknow event: %i\n", event.type); + break; + } + } +} + +void mogltk::engine::setappactive(bool p) { + appactive = p; +} + +bool mogltk::engine::getappactive() { + return appactive; +} + +void mogltk::engine::setcursorvisible(bool p) { + cursorvisible = p; +} + +bool mogltk::engine::getcursorvisible() { + return cursorvisible; +} + +void mogltk::engine::quit() { + quitrequest = true; +} + +bool mogltk::engine::quitrequested() { + return quitrequest; +} + +void mogltk::engine::updatemouse() { + mbuttons = SDL_GetMouseState(&mx, &my); +} + +int mogltk::engine::mouseX() { + return mx; +} + +int mogltk::engine::mouseY() { + return my; +} + +int mogltk::engine::mouseZ() { + return mz; +} + +void mogltk::engine::setmouseX(int _mx) { + mx = _mx; + SDL_WarpMouse(mx, my); +} + +void mogltk::engine::setmouseY(int _my) { + my = _my; + SDL_WarpMouse(mx, my); +} + +void mogltk::engine::setmouseZ(int _mz) { + mz = _mz; +} + +int mogltk::engine::mousebuttons() { + return mbuttons; +} + +double mogltk::engine::FPS() { + return curfps; +} + +void mogltk::engine::lockmouse() { + locked = 1; +} + +void mogltk::engine::unlockmouse() { + locked = 0; +} + +void mogltk::engine::setkeyevent(keyevent * k) { + keyevent_h = k; +} + +void mogltk::engine::setmouseevent(mouseevent * m) { + mouseevent_h = m; +} + +mogltk::engine::keyevent * mogltk::engine::getkeyevent() { + return keyevent_h; +} + +mogltk::engine::mouseevent * mogltk::engine::getmouseevent() { + return mouseevent_h; +} diff --git a/lib/font.cc b/lib/font.cc index 2a17d20..07ade78 100644 --- a/lib/font.cc +++ b/lib/font.cc @@ -1,705 +1,705 @@ -/* - * mogltk - * Copyright (C) 1999-2004 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: font.cc,v 1.15 2004-11-27 21:44:53 pixel Exp $ */ - -#include -#include -#include -#include "base.h" -#include "font.h" -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include "engine.h" - -Uint8 prescale2[4] = { 0, 85, 170, 255 }, prescale3[8] = { 0, 36, 72, 109, 145, 182, 218, 255 }; - -#define STRBUFSIZ 512 - -/* - -font file format -================ - -off|siz|description ----+---+------------------------------- - 0 | 2 | Number of entries = nbentries - 2 | 1 | Flags - 3 | 1 | maxX (maximum width) - 4 | 1 | maxY (maximum height) - 5 | 1 | base (bottom line from top) - 6 | 1 | inter (size of the interline) - 7 | X | char entries -7+X| Y | char map - -X = (maxX * maxY + 1) * nbentries -Y = nbentries * 4 - - -Flags: -===== - -0000000R - -R = RGBA (=1) or Alpha (=0) - -RGBA in 1232 format: -ABBGGGRR - - -Each entries: -============ - -off|siz|description ----+---+------------------------------- - 0 | 1 | True size of the entry - 1 | Z | Datas - -Z = maxX * maxY -Datas are stored in order X first, then Y. - -Char map: -======== - -nbentries entries, each entry = 4 bytes = 2 uint16 - -off|siz|description ----+---+------------------------------- - 0 | 2 | Unicode (?) - 2 | 2 | Corresponding char entry - -I'm not sure about my word 'Unicode'. I write this only to say it's an attempt -to make the fonts "internationals". If the "unicode" is < 255, then it should -match only one byte in the string. Otherwise, it should match two bytes. - - -Variables comments -================== - -nbcU = number of chars on X by texture -nbcV = number of chars on Y by texture -nbcT = number of char by texture -nbT = number of textures - -*/ - -mogltk::ColorP colorcached[16] = { - DOS_BLACK, - DOS_BLUE, - DOS_GREEN, - DOS_CYAN, - DOS_RED, - DOS_MAGENTA, - DOS_BRAWN, - DOS_WHITE, - DOS_GRAY, - DOS_HIGH_BLUE, - DOS_HIGH_GREEN, - DOS_HIGH_CYAN, - DOS_HIGH_RED, - DOS_HIGH_MAGENTA, - DOS_YELLOW, - DOS_HIGH_WHITE -}; - -mogltk::font::font(Handle * ffont) : textcolor(255, 255, 255, 255), shadow(0), wspace(0) { - int i, j; - - nbentries = ffont->readU16(); - flags = ffont->readU8(); - maxX = ffont->readU8(); - maxY = ffont->readU8(); - base = ffont->readU8(); - inter = ffont->readU8(); - - nbcU = 256 / maxX; - nbcV = 256 / maxY; - - nbcT = nbcU * nbcV; - - nbT = nbentries / nbcT; - - if (nbentries % nbcT) { - nbT++; - } - - printm(M_INFO, "Creating font texture: %i entries, flags = 0x%02x, maxX = %i, maxY = %i\n", nbentries, flags, maxX, maxY); - printm(M_INFO, "Which makes %i texture(s), with %i char by texture, %i on X, and %i on Y\n", nbT, nbcT, nbcU, nbcV); - - fonttex = (texture **) malloc(nbT * sizeof(texture *)); - for (i = 0; i < 16; i++) { - fontcache[i] = (texture **) malloc(nbT * sizeof(texture *)); - } - - for (i = 0; i < nbT; i++) { - fonttex[i] = alloctexture(); - for (j = 0; j < 15; j++) { - fontcache[j][i] = 0; - } - fontcache[15][i] = fonttex[i]; - } - - sizes = (Uint8 *) malloc(nbentries * sizeof(Uint8)); - - Uint8 * curtex = (Uint8 *) fonttex[0]->GetSurface()->pixels; - Uint32 curU = 0, curV = 0, curT = 0; - for (i = 0; i < nbentries; i++) { - sizes[i] = ffont->readU8(); - for (int v = 0; v < maxY; v++) { - for (int u = 0; u < maxX; u++) { - Uint8 f; - f = ffont->readU8(); - if (flags & 1) { - Uint8 r, g, b, a; - r = f & 3; - g = (f >> 2) & 7; - b = (f >> 5) & 3; - a = (f >> 7) & 1; - curtex[(curU + u + (curV + v) * 256) * 4 + 0] = prescale2[r]; - curtex[(curU + u + (curV + v) * 256) * 4 + 1] = prescale3[g]; - curtex[(curU + u + (curV + v) * 256) * 4 + 2] = prescale2[b]; - curtex[(curU + u + (curV + v) * 256) * 4 + 3] = a ? 255 : 0; - } else { - curtex[(curU + u + (curV + v) * 256) * 4 + 0] = 255; - curtex[(curU + u + (curV + v) * 256) * 4 + 1] = 255; - curtex[(curU + u + (curV + v) * 256) * 4 + 2] = 255; - curtex[(curU + u + (curV + v) * 256) * 4 + 3] = f; - } - } - } - if (((curU += maxX) + maxX) > 256) { - curU = 0; - if (((curV += maxY) + maxY) > 256) { - curV = 0; - if ((curT + 1) != nbT) - curtex = (Uint8 *) fonttex[++curT]->GetSurface()->pixels; - } - } - } - - corresp = (Uint16 *) malloc(nbentries * 2 * sizeof(Uint16)); - - for (i = 0; i < 2 * nbentries; i++) { - corresp[i] = ffont->readU16(); - } -} - -mogltk::font::~font() { - int i, j; - for (i = 0; i < nbT; i++) - for (j = 0; j < 16; j++) - if (fontcache[j][i]) - delete fontcache[j][i]; - - for (i = 0; i < 16; i++) - free((void *&) fontcache[i]); - - free((void *&) fonttex); - free(sizes); -} - -void mogltk::font::drawentry(Uint16 entry, int x, int y, ColorP c) { - bool locked = false; - int trueentry, cx, cy, px, py; - SDL_Rect src, dst; - - if (SDL_MUSTLOCK(mogltk::engine::base_o->getsurface())) { - locked = true; - SDL_LockSurface(mogltk::engine::base_o->getsurface()); - } - - if (shadow) { - int os = shadow; - shadow = 0; - - drawentry(entry, x + os, y + os, BLACK); - - shadow = os; - } - - checknbind(entry / nbcT, c); - - y -= base; - - trueentry = entry % nbcT; - cx = trueentry % nbcU; - cy = trueentry / nbcU; - px = cx * maxX; - py = cy * maxY; - - src.x = px; src.y = py; src.w = maxX; src.h = maxY; - dst.x = x; dst.y = y; dst.w = maxX; dst.h = maxY; - - SDL_BlitSurface(fonttex[entry / nbcT]->GetSurface(), &src, mogltk::engine::base_o->getsurface(), &dst); - - if (locked) - SDL_UnlockSurface(mogltk::engine::base_o->getsurface()); -} - -void mogltk::font::drawtotex(texture * t, Uint16 entry, int x, int y, ColorP c) { - bool locked = false; - int trueentry, cx, cy, px, py; - SDL_Rect src, dst; - - if (SDL_MUSTLOCK(t->GetSurface())) { - locked = true; - SDL_LockSurface(t->GetSurface()); - } - - if (shadow) { - int os = shadow; - shadow = 0; - - drawtotex(t, entry, x + os, y + os, BLACK); - - shadow = os; - } - - checknbind(entry / nbcT, c); - - y -= base; - - trueentry = entry % nbcT; - cx = trueentry % nbcU; - cy = trueentry / nbcU; - px = cx * maxX; - py = cy * maxY; - - src.x = px; src.y = py; src.w = maxX; src.h = maxY; - dst.x = x; dst.y = y; dst.w = maxX; dst.h = maxY; - - SDL_BlitSurface(fonttex[entry / nbcT]->GetSurface(), &src, t->GetSurface(), &dst); - - if (locked) - SDL_UnlockSurface(t->GetSurface()); -} - -void mogltk::font::putcursor(int x, int y) { - cx = ox = x; - cy = y; -} - -void mogltk::font::putentry(Uint16 entry, ColorP c) { - drawentry(entry, cx, cy, c); - cx += sizes[entry] + wspace; -} - -void mogltk::font::putentryontex(texture * t, Uint16 entry, ColorP c) { - drawtotex(t, entry, cx, cy, c); - cx += sizes[entry] + wspace; -} - -void mogltk::font::drawchar(char ch, ColorP c) { - Uint16 * p; - int i; - - for (i = 0, p = corresp; i < nbentries; i++, p++) { - if (*(p++) == ch) { - putentry(*p, c); - return; - } - } -} - -void mogltk::font::drawcharontex(texture * t, char ch, ColorP c) { - Uint16 * p; - int i; - - for (i = 0, p = corresp; i < nbentries; i++, p++) { - if (*(p++) == ch) { - putentryontex(t, *p, c); - return; - } - } -} - -int mogltk::font::findchar(char ch) const { - Uint16 * p; - int i; - - for (i = 0, p = corresp; i < nbentries; i++, p++) { - if (*(p++) == ch) { - return *p; - } - } - - return -1; -} - -void mogltk::font::newline(void) { - cx = ox; - cy += inter; -} - -int mogltk::font::printf(const ugly_string & m, va_list ap) { - char * p; - static char buffer[STRBUFSIZ + 1]; - int r; - -#ifdef HAVE_VSNPRINTF - r = vsnprintf(buffer, STRBUFSIZ, m.p, ap); -#else - r = vsprintf(buffer, m.p, ap); -#endif - - for (p = buffer; *p; p++) { - if (*p == '\n') { - newline(); - } else { - drawchar(*p, textcolor); - } - } - - return r; -} - -int mogltk::font::printf(const ugly_string & m, ...) { - va_list ap; - int r; - - va_start(ap, m); - r = printf(m, ap); - va_end(ap); - - return r; -} - -int mogltk::font::printf(const char * p, ...) { - ugly_string m; - va_list ap; - int r; - - m.p = p; - - va_start(ap, p); - r = printf(m, ap); - va_end(ap); - - return r; -} - -mogltk::rect mogltk::font::size(const ugly_string & m, va_list ap) { - char * p; - static char buffer[STRBUFSIZ + 1]; - rect r; - int mw, w; - - r.x = cx; - r.y = cy; - r.h = inter; - r.w = 0; - mw = 0; - w = 0; - -#ifdef HAVE_VSNPRINTF - vsnprintf(buffer, STRBUFSIZ, m.p, ap); -#else - vsprintf(buffer, m.p, ap); -#endif - - for (p = buffer; *p; p++) { - if (*p == '\n') { - if (*(p+1)) { - r.h += inter; - if (w > mw) { - mw = w; - } - w = 0; - } - } else { - w += sizes[findchar(*p)] + wspace; - } - } - - if (w > mw) { - mw = w; - } - - r.w = mw; - - return r; -} - -mogltk::rect mogltk::font::size(const ugly_string & m, ...) { - va_list ap; - rect r; - - va_start(ap, m); - r = size(m, ap); - va_end(ap); - - return r; -} - -mogltk::rect mogltk::font::size(const char * p, ...) { - ugly_string m; - va_list ap; - rect r; - - m.p = p; - - va_start(ap, p); - r = size(m, ap); - va_end(ap); - - return r; -} - -mogltk::rect mogltk::font::printtotex(texture * t, const ugly_string & m, va_list ap) { - char * p; - static char buffer[STRBUFSIZ + 1]; - rect r; - int mw, w; - - r.x = cx; - r.y = cy; - r.h = inter; - r.w = 0; - mw = 0; - w = 0; - -#ifdef HAVE_VSNPRINTF - vsnprintf(buffer, STRBUFSIZ, m.p, ap); -#else - vsprintf(buffer, m.p, ap); -#endif - - for (p = buffer; *p; p++) { - if (*p == '\n') { - if (*(p+1)) { - r.h += inter; - if (w > mw) { - mw = w; - } - w = 0; - } - } else { - w += sizes[findchar(*p)] + wspace; - } - } - - if (w > mw) { - mw = w; - } - - r.w = mw; - - for (p = buffer; *p; p++) { - if (*p == '\n') { - newline(); - } else { - drawcharontex(t, *p, textcolor); - } - } - - return r; -} - -mogltk::rect mogltk::font::printtotex(texture * t, const ugly_string & m, ...) { - va_list ap; - rect r; - - va_start(ap, m); - r = printtotex(t, m, ap); - va_end(ap); - - return r; -} - -mogltk::rect mogltk::font::printtotex(texture * t, const char * p, ...) { - ugly_string m; - va_list ap; - rect r; - - m.p = p; - - va_start(ap, p); - r = printtotex(t, m, ap); - va_end(ap); - - return r; -} - -inline static unsigned int nextpower(unsigned int n) { - unsigned int i; - - if (!n) - return n; - - if (ISPOT(n)) - return n; - - for (i = 31; i >= 0; i--) { - if ((n >> i) & 1) { - return 1 << (i + 1); - } - } -} - -mogltk::texture * mogltk::font::printtex(rect * _r, const ugly_string & m, va_list ap) { - rect r; - char * p; - static char buffer[STRBUFSIZ + 1]; - int mw, w, pw, ph; - texture * t; - int ocx, ocy, oox; - - ocx = cx; - ocy = cy; - oox = ox; - - cx = ox = 0; - cy = base; - - r.x = cx; - r.y = cy; - r.h = inter; - r.w = 0; - mw = 0; - w = 0; - -#ifdef HAVE_VSNPRINTF - vsnprintf(buffer, STRBUFSIZ, m.p, ap); -#else - vsprintf(buffer, m.p, ap); -#endif - - for (p = buffer; *p; p++) { - if (*p == '\n') { - if (*(p+1)) { - r.h += inter; - if (w > mw) { - mw = w; - } - w = 0; - } - } else { - w += sizes[findchar(*p)] + wspace; - } - } - - if (w > mw) { - mw = w; - } - - r.w = mw; - - pw = nextpower(r.w); - ph = nextpower(r.h); - - t = new texture(pw, ph); - - for (p = buffer; *p; p++) { - if (*p == '\n') { - newline(); - } else { - drawcharontex(t, *p, textcolor); - } - } - - if (_r) - *_r = r; - - return t; -} - -mogltk::texture * mogltk::font::printtex(rect * r, const ugly_string & m, ...) { - va_list ap; - texture * t; - - va_start(ap, m); - t = printtex(r, m, ap); - va_end(ap); - - return t; -} - -mogltk::texture * mogltk::font::printtex(rect * r, const char * p, ...) { - ugly_string m; - va_list ap; - texture * t; - - m.p = p; - - va_start(ap, p); - t = printtex(r, m, ap); - va_end(ap); - - return t; -} - -void mogltk::font::setcolor(ColorP c) { - textcolor = c; -} - -void mogltk::font::setshadow(int s) { - shadow = s; -} - -void mogltk::font::setwspace(int w) { - wspace = w; -} - -int mogltk::font::singletextsize(const String & s) const { - unsigned int i; - int r = 0; - - for (i = 0; i < s.strlen(); i++) { - r += sizes[findchar(s[i])] + wspace; - } - - return r; -} - -mogltk::font * mogltk::SystemFont; -mogltk::font * mogltk::FixedFont; - -mogltk::texture * mogltk::font::alloctexture() { - return new mogltk::texture(256, 256); -} - -void mogltk::font::Bind(int f) { - fonttex[f]->Bind(); -} - -void mogltk::font::checknbind(int index, ColorP c) { - int i, x, y; - ColorP oldmax = ColorP::Max, t; - ColorP::Max = c.c; - SDL_PixelFormat * f = fonttex[0]->GetSurface()->format; - - for (i = 0; i < 15; i++) - if (c == colorcached[i]) - break; - - if (!fontcache[i][index]) { - fontcache[i][index] = alloctexture(); - for (y = 0; y < 256; y++) { - for (x = 0; x < 256; x++) { - t.fromSDL(fontcache[15][index]->GetPixels()[(y << 8) + x], f); - fontcache[i][index]->GetPixels()[(y << 8) + x] = t.toSDL(f); - } - } - } - - fonttex[index] = fontcache[i][index]; - - ColorP::Max = oldmax.c; -} +/* + * mogltk + * Copyright (C) 1999-2004 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: font.cc,v 1.16 2004-11-27 21:48:03 pixel Exp $ */ + +#include +#include +#include +#include "base.h" +#include "font.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "engine.h" + +Uint8 prescale2[4] = { 0, 85, 170, 255 }, prescale3[8] = { 0, 36, 72, 109, 145, 182, 218, 255 }; + +#define STRBUFSIZ 512 + +/* + +font file format +================ + +off|siz|description +---+---+------------------------------- + 0 | 2 | Number of entries = nbentries + 2 | 1 | Flags + 3 | 1 | maxX (maximum width) + 4 | 1 | maxY (maximum height) + 5 | 1 | base (bottom line from top) + 6 | 1 | inter (size of the interline) + 7 | X | char entries +7+X| Y | char map + +X = (maxX * maxY + 1) * nbentries +Y = nbentries * 4 + + +Flags: +===== + +0000000R + +R = RGBA (=1) or Alpha (=0) + +RGBA in 1232 format: +ABBGGGRR + + +Each entries: +============ + +off|siz|description +---+---+------------------------------- + 0 | 1 | True size of the entry + 1 | Z | Datas + +Z = maxX * maxY +Datas are stored in order X first, then Y. + +Char map: +======== + +nbentries entries, each entry = 4 bytes = 2 uint16 + +off|siz|description +---+---+------------------------------- + 0 | 2 | Unicode (?) + 2 | 2 | Corresponding char entry + +I'm not sure about my word 'Unicode'. I write this only to say it's an attempt +to make the fonts "internationals". If the "unicode" is < 255, then it should +match only one byte in the string. Otherwise, it should match two bytes. + + +Variables comments +================== + +nbcU = number of chars on X by texture +nbcV = number of chars on Y by texture +nbcT = number of char by texture +nbT = number of textures + +*/ + +mogltk::ColorP colorcached[16] = { + DOS_BLACK, + DOS_BLUE, + DOS_GREEN, + DOS_CYAN, + DOS_RED, + DOS_MAGENTA, + DOS_BRAWN, + DOS_WHITE, + DOS_GRAY, + DOS_HIGH_BLUE, + DOS_HIGH_GREEN, + DOS_HIGH_CYAN, + DOS_HIGH_RED, + DOS_HIGH_MAGENTA, + DOS_YELLOW, + DOS_HIGH_WHITE +}; + +mogltk::font::font(Handle * ffont) : textcolor(255, 255, 255, 255), shadow(0), wspace(0) { + int i, j; + + nbentries = ffont->readU16(); + flags = ffont->readU8(); + maxX = ffont->readU8(); + maxY = ffont->readU8(); + base = ffont->readU8(); + inter = ffont->readU8(); + + nbcU = 256 / maxX; + nbcV = 256 / maxY; + + nbcT = nbcU * nbcV; + + nbT = nbentries / nbcT; + + if (nbentries % nbcT) { + nbT++; + } + + printm(M_INFO, "Creating font texture: %i entries, flags = 0x%02x, maxX = %i, maxY = %i\n", nbentries, flags, maxX, maxY); + printm(M_INFO, "Which makes %i texture(s), with %i char by texture, %i on X, and %i on Y\n", nbT, nbcT, nbcU, nbcV); + + fonttex = (texture **) malloc(nbT * sizeof(texture *)); + for (i = 0; i < 16; i++) { + fontcache[i] = (texture **) malloc(nbT * sizeof(texture *)); + } + + for (i = 0; i < nbT; i++) { + fonttex[i] = alloctexture(); + for (j = 0; j < 15; j++) { + fontcache[j][i] = 0; + } + fontcache[15][i] = fonttex[i]; + } + + sizes = (Uint8 *) malloc(nbentries * sizeof(Uint8)); + + Uint8 * curtex = (Uint8 *) fonttex[0]->GetSurface()->pixels; + Uint32 curU = 0, curV = 0, curT = 0; + for (i = 0; i < nbentries; i++) { + sizes[i] = ffont->readU8(); + for (int v = 0; v < maxY; v++) { + for (int u = 0; u < maxX; u++) { + Uint8 f; + f = ffont->readU8(); + if (flags & 1) { + Uint8 r, g, b, a; + r = f & 3; + g = (f >> 2) & 7; + b = (f >> 5) & 3; + a = (f >> 7) & 1; + curtex[(curU + u + (curV + v) * 256) * 4 + 0] = prescale2[r]; + curtex[(curU + u + (curV + v) * 256) * 4 + 1] = prescale3[g]; + curtex[(curU + u + (curV + v) * 256) * 4 + 2] = prescale2[b]; + curtex[(curU + u + (curV + v) * 256) * 4 + 3] = a ? 255 : 0; + } else { + curtex[(curU + u + (curV + v) * 256) * 4 + 0] = 255; + curtex[(curU + u + (curV + v) * 256) * 4 + 1] = 255; + curtex[(curU + u + (curV + v) * 256) * 4 + 2] = 255; + curtex[(curU + u + (curV + v) * 256) * 4 + 3] = f; + } + } + } + if (((curU += maxX) + maxX) > 256) { + curU = 0; + if (((curV += maxY) + maxY) > 256) { + curV = 0; + if ((curT + 1) != nbT) + curtex = (Uint8 *) fonttex[++curT]->GetSurface()->pixels; + } + } + } + + corresp = (Uint16 *) malloc(nbentries * 2 * sizeof(Uint16)); + + for (i = 0; i < 2 * nbentries; i++) { + corresp[i] = ffont->readU16(); + } +} + +mogltk::font::~font() { + int i, j; + for (i = 0; i < nbT; i++) + for (j = 0; j < 16; j++) + if (fontcache[j][i]) + delete fontcache[j][i]; + + for (i = 0; i < 16; i++) + free((void *&) fontcache[i]); + + free((void *&) fonttex); + free(sizes); +} + +void mogltk::font::drawentry(Uint16 entry, int x, int y, ColorP c) { + bool locked = false; + int trueentry, cx, cy, px, py; + SDL_Rect src, dst; + + if (SDL_MUSTLOCK(mogltk::engine::base_o->getsurface())) { + locked = true; + SDL_LockSurface(mogltk::engine::base_o->getsurface()); + } + + if (shadow) { + int os = shadow; + shadow = 0; + + drawentry(entry, x + os, y + os, BLACK); + + shadow = os; + } + + checknbind(entry / nbcT, c); + + y -= base; + + trueentry = entry % nbcT; + cx = trueentry % nbcU; + cy = trueentry / nbcU; + px = cx * maxX; + py = cy * maxY; + + src.x = px; src.y = py; src.w = maxX; src.h = maxY; + dst.x = x; dst.y = y; dst.w = maxX; dst.h = maxY; + + SDL_BlitSurface(fonttex[entry / nbcT]->GetSurface(), &src, mogltk::engine::base_o->getsurface(), &dst); + + if (locked) + SDL_UnlockSurface(mogltk::engine::base_o->getsurface()); +} + +void mogltk::font::drawtotex(texture * t, Uint16 entry, int x, int y, ColorP c) { + bool locked = false; + int trueentry, cx, cy, px, py; + SDL_Rect src, dst; + + if (SDL_MUSTLOCK(t->GetSurface())) { + locked = true; + SDL_LockSurface(t->GetSurface()); + } + + if (shadow) { + int os = shadow; + shadow = 0; + + drawtotex(t, entry, x + os, y + os, BLACK); + + shadow = os; + } + + checknbind(entry / nbcT, c); + + y -= base; + + trueentry = entry % nbcT; + cx = trueentry % nbcU; + cy = trueentry / nbcU; + px = cx * maxX; + py = cy * maxY; + + src.x = px; src.y = py; src.w = maxX; src.h = maxY; + dst.x = x; dst.y = y; dst.w = maxX; dst.h = maxY; + + SDL_BlitSurface(fonttex[entry / nbcT]->GetSurface(), &src, t->GetSurface(), &dst); + + if (locked) + SDL_UnlockSurface(t->GetSurface()); +} + +void mogltk::font::putcursor(int x, int y) { + cx = ox = x; + cy = y; +} + +void mogltk::font::putentry(Uint16 entry, ColorP c) { + drawentry(entry, cx, cy, c); + cx += sizes[entry] + wspace; +} + +void mogltk::font::putentryontex(texture * t, Uint16 entry, ColorP c) { + drawtotex(t, entry, cx, cy, c); + cx += sizes[entry] + wspace; +} + +void mogltk::font::drawchar(char ch, ColorP c) { + Uint16 * p; + int i; + + for (i = 0, p = corresp; i < nbentries; i++, p++) { + if (*(p++) == ch) { + putentry(*p, c); + return; + } + } +} + +void mogltk::font::drawcharontex(texture * t, char ch, ColorP c) { + Uint16 * p; + int i; + + for (i = 0, p = corresp; i < nbentries; i++, p++) { + if (*(p++) == ch) { + putentryontex(t, *p, c); + return; + } + } +} + +int mogltk::font::findchar(char ch) const { + Uint16 * p; + int i; + + for (i = 0, p = corresp; i < nbentries; i++, p++) { + if (*(p++) == ch) { + return *p; + } + } + + return -1; +} + +void mogltk::font::newline(void) { + cx = ox; + cy += inter; +} + +int mogltk::font::printf(const ugly_string & m, va_list ap) { + char * p; + static char buffer[STRBUFSIZ + 1]; + int r; + +#ifdef HAVE_VSNPRINTF + r = vsnprintf(buffer, STRBUFSIZ, m.p, ap); +#else + r = vsprintf(buffer, m.p, ap); +#endif + + for (p = buffer; *p; p++) { + if (*p == '\n') { + newline(); + } else { + drawchar(*p, textcolor); + } + } + + return r; +} + +int mogltk::font::printf(const ugly_string & m, ...) { + va_list ap; + int r; + + va_start(ap, m); + r = printf(m, ap); + va_end(ap); + + return r; +} + +int mogltk::font::printf(const char * p, ...) { + ugly_string m; + va_list ap; + int r; + + m.p = p; + + va_start(ap, p); + r = printf(m, ap); + va_end(ap); + + return r; +} + +mogltk::rect mogltk::font::size(const ugly_string & m, va_list ap) { + char * p; + static char buffer[STRBUFSIZ + 1]; + rect r; + int mw, w; + + r.x = cx; + r.y = cy; + r.h = inter; + r.w = 0; + mw = 0; + w = 0; + +#ifdef HAVE_VSNPRINTF + vsnprintf(buffer, STRBUFSIZ, m.p, ap); +#else + vsprintf(buffer, m.p, ap); +#endif + + for (p = buffer; *p; p++) { + if (*p == '\n') { + if (*(p+1)) { + r.h += inter; + if (w > mw) { + mw = w; + } + w = 0; + } + } else { + w += sizes[findchar(*p)] + wspace; + } + } + + if (w > mw) { + mw = w; + } + + r.w = mw; + + return r; +} + +mogltk::rect mogltk::font::size(const ugly_string & m, ...) { + va_list ap; + rect r; + + va_start(ap, m); + r = size(m, ap); + va_end(ap); + + return r; +} + +mogltk::rect mogltk::font::size(const char * p, ...) { + ugly_string m; + va_list ap; + rect r; + + m.p = p; + + va_start(ap, p); + r = size(m, ap); + va_end(ap); + + return r; +} + +mogltk::rect mogltk::font::printtotex(texture * t, const ugly_string & m, va_list ap) { + char * p; + static char buffer[STRBUFSIZ + 1]; + rect r; + int mw, w; + + r.x = cx; + r.y = cy; + r.h = inter; + r.w = 0; + mw = 0; + w = 0; + +#ifdef HAVE_VSNPRINTF + vsnprintf(buffer, STRBUFSIZ, m.p, ap); +#else + vsprintf(buffer, m.p, ap); +#endif + + for (p = buffer; *p; p++) { + if (*p == '\n') { + if (*(p+1)) { + r.h += inter; + if (w > mw) { + mw = w; + } + w = 0; + } + } else { + w += sizes[findchar(*p)] + wspace; + } + } + + if (w > mw) { + mw = w; + } + + r.w = mw; + + for (p = buffer; *p; p++) { + if (*p == '\n') { + newline(); + } else { + drawcharontex(t, *p, textcolor); + } + } + + return r; +} + +mogltk::rect mogltk::font::printtotex(texture * t, const ugly_string & m, ...) { + va_list ap; + rect r; + + va_start(ap, m); + r = printtotex(t, m, ap); + va_end(ap); + + return r; +} + +mogltk::rect mogltk::font::printtotex(texture * t, const char * p, ...) { + ugly_string m; + va_list ap; + rect r; + + m.p = p; + + va_start(ap, p); + r = printtotex(t, m, ap); + va_end(ap); + + return r; +} + +inline static unsigned int nextpower(unsigned int n) { + unsigned int i; + + if (!n) + return n; + + if (ISPOT(n)) + return n; + + for (i = 31; i >= 0; i--) { + if ((n >> i) & 1) { + return 1 << (i + 1); + } + } +} + +mogltk::texture * mogltk::font::printtex(rect * _r, const ugly_string & m, va_list ap) { + rect r; + char * p; + static char buffer[STRBUFSIZ + 1]; + int mw, w, pw, ph; + texture * t; + int ocx, ocy, oox; + + ocx = cx; + ocy = cy; + oox = ox; + + cx = ox = 0; + cy = base; + + r.x = cx; + r.y = cy; + r.h = inter; + r.w = 0; + mw = 0; + w = 0; + +#ifdef HAVE_VSNPRINTF + vsnprintf(buffer, STRBUFSIZ, m.p, ap); +#else + vsprintf(buffer, m.p, ap); +#endif + + for (p = buffer; *p; p++) { + if (*p == '\n') { + if (*(p+1)) { + r.h += inter; + if (w > mw) { + mw = w; + } + w = 0; + } + } else { + w += sizes[findchar(*p)] + wspace; + } + } + + if (w > mw) { + mw = w; + } + + r.w = mw; + + pw = nextpower(r.w); + ph = nextpower(r.h); + + t = new texture(pw, ph); + + for (p = buffer; *p; p++) { + if (*p == '\n') { + newline(); + } else { + drawcharontex(t, *p, textcolor); + } + } + + if (_r) + *_r = r; + + return t; +} + +mogltk::texture * mogltk::font::printtex(rect * r, const ugly_string & m, ...) { + va_list ap; + texture * t; + + va_start(ap, m); + t = printtex(r, m, ap); + va_end(ap); + + return t; +} + +mogltk::texture * mogltk::font::printtex(rect * r, const char * p, ...) { + ugly_string m; + va_list ap; + texture * t; + + m.p = p; + + va_start(ap, p); + t = printtex(r, m, ap); + va_end(ap); + + return t; +} + +void mogltk::font::setcolor(ColorP c) { + textcolor = c; +} + +void mogltk::font::setshadow(int s) { + shadow = s; +} + +void mogltk::font::setwspace(int w) { + wspace = w; +} + +int mogltk::font::singletextsize(const String & s) const { + unsigned int i; + int r = 0; + + for (i = 0; i < s.strlen(); i++) { + r += sizes[findchar(s[i])] + wspace; + } + + return r; +} + +mogltk::font * mogltk::SystemFont; +mogltk::font * mogltk::FixedFont; + +mogltk::texture * mogltk::font::alloctexture() { + return new mogltk::texture(256, 256); +} + +void mogltk::font::Bind(int f) { + fonttex[f]->Bind(); +} + +void mogltk::font::checknbind(int index, ColorP c) { + int i, x, y; + ColorP oldmax = ColorP::Max, t; + ColorP::Max = c.c; + SDL_PixelFormat * f = fonttex[0]->GetSurface()->format; + + for (i = 0; i < 15; i++) + if (c == colorcached[i]) + break; + + if (!fontcache[i][index]) { + fontcache[i][index] = alloctexture(); + for (y = 0; y < 256; y++) { + for (x = 0; x < 256; x++) { + t.fromSDL(fontcache[15][index]->GetPixels()[(y << 8) + x], f); + fontcache[i][index]->GetPixels()[(y << 8) + x] = t.toSDL(f); + } + } + } + + fonttex[index] = fontcache[i][index]; + + ColorP::Max = oldmax.c; +} diff --git a/lib/glbase.cc b/lib/glbase.cc index abd3f1e..2edeec5 100644 --- a/lib/glbase.cc +++ b/lib/glbase.cc @@ -1,267 +1,267 @@ -/* - * mogltk - * Copyright (C) 1999-2004 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: glbase.cc,v 1.21 2004-10-19 01:27:30 pixel Exp $ */ - -#include -#include -#include -#include -#include -#include "glbase.h" -#include "engine.h" -#include "generic.h" -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -mogltk::glbase::glbase(int w, int h, int flags) throw (GeneralException) : mogltk::base(w, h, flags, 0), twoD(0), fovy(60.0) { - SDL_Surface * surface; - GLint bits; - - mogltk::engine::setup(); - if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) { - throw GeneralException(String("Couldn't initialise Video SubSystem: ") + SDL_GetError()); - } - -#if 1 - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); -// SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 32); - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 8); -#endif - if (!(surface = SDL_SetVideoMode(w, h, 0, flags | SDL_OPENGL | SDL_HWSURFACE))) { - throw GeneralException(String("Couldn't set GL mode: ") + SDL_GetError()); - } - - mogltk::engine::glbase_o = this; - mogltk::engine::base_o = this; - - ratio = (GLdouble) surface->w / surface->h; - - glGetIntegerv(GL_STENCIL_BITS, &bits); - - printm(M_INFO, "Video resolution: %dx%dx%d (ratio = %3.2f)\n", surface->w, surface->h, surface->format->BitsPerPixel, ratio); - printm(M_INFO, "\n"); - printm(M_INFO, "OpenGL infos\n"); - printm(M_INFO, "------------\n"); - printm(M_INFO, String("Vendor : ") + (char *) glGetString(GL_VENDOR) + "\n"); - printm(M_INFO, String("Renderer : ") + (char *) glGetString(GL_RENDERER) + "\n"); - printm(M_INFO, String("Version : ") + (char *) glGetString(GL_VERSION) + "\n"); - printm(M_INFO, String("Extensions: ") + (char *) glGetString(GL_EXTENSIONS) + "\n"); - - glViewport(0, 0, surface->w, surface->h); - - glCullFace(GL_BACK); - glFrontFace(GL_CCW); - glEnable(GL_CULL_FACE); - - glClearColor(0, 0, 0, 0); - glShadeModel(GL_SMOOTH); - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(fovy, ratio, 1.0, 1024.0); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - SDL_GL_SwapBuffers(); - SDL_ShowCursor(SDL_DISABLE); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - setsurface(surface); - mogltk::engine::postsetup(); -} - -mogltk::glbase::~glbase() { -} - -void mogltk::glbase::Enter2DMode(void) { - if (twoD) - return; - - glPushAttrib(GL_ENABLE_BIT); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0.0, GetWidth(), GetHeight(), 0.0, 0.0, 1.0); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - twoD = 1; -} - -void mogltk::glbase::Leave2DMode(void) { - if (!twoD) - return; - - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - - glPopAttrib(); - - twoD = 0; -} - -void mogltk::glbase::Flip(bool clear) { - mogltk::engine::pollevents(); - SDL_GL_SwapBuffers(); - if (clear) - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -} - -bool mogltk::glbase::is2D() { - return twoD; -} - -void mogltk::glbase::glVertex(GLshort x, GLshort y, GLshort z, GLshort w) { -#ifdef DEBUG - printm(M_INFO, "Calling glVertex(%i, %i, %i, %i) (shorts)\n", x, y, z, w); -#endif - glVertex4i(x, y, z, w); -} - -void mogltk::glbase::glVertex(GLint x, GLint y, GLint z, GLint w) { -#ifdef DEBUG - printm(M_INFO, "Calling glVertex(%i, %i, %i, %i) (ints)\n", x, y, z, w); -#endif - glVertex4i(x, y, z, w); -} - -void mogltk::glbase::glVertex(GLfloat x, GLfloat y, GLfloat z, GLfloat w) { -#ifdef DEBUG - printm(M_INFO, "Calling glVertex(%f, %f, %f, %f) (floats)\n", x, y, z, w); -#endif - glVertex4f(x, y, z, w); -} - -void mogltk::glbase::glVertex(GLdouble x, GLdouble y, GLdouble z, GLdouble w) { -#ifdef DEBUG - printm(M_INFO, "Calling glVertex(%f, %f, %f, %f) (doubles)\n", x, y, z, w); -#endif - glVertex4d(x, y, z, w); -} - -void mogltk::glbase::changeviewport(int x, int y, unsigned int w, unsigned int h) { -#if 0 - if ((w == 0) && (h == 0)) { - w = GetWidth() - x; - h = GetHeight() - y; - } - - ratio = (GLdouble) w / h; - glViewport(x, y, w, h); - if (!engine::base_o->is2D()) - gluPerspective(fovy, ratio, 1.0, 1024.0); -#endif - glScissor(x, GetHeight() - y - h - 1, w + 1, h + 1); - glEnable(GL_SCISSOR_TEST); -} - -void mogltk::glbase::changefovy(GLdouble nfoyv) { - fovy = nfoyv; - if (!engine::base_o->is2D()) - gluPerspective(fovy, ratio, 1.0, 1024.0); -} - -inline static unsigned int nextpower(unsigned int n) { - unsigned int i; - - if (!n) - return n; - - if (ISPOT(n)) - return n; - - for (i = 31; i >= 0; i--) { - if ((n >> i) & 1) { - return 1 << (i + 1); - } - } -} - -mogltk::texture * mogltk::glbase::GrabTexture() { - int w = nextpower(GetWidth()); - int h = nextpower(GetHeight()); - texture * r = new texture(w, h); - SDL_Surface * t; - - t = GrabSurface(); - SDL_BlitSurface(t, NULL, r->GetSurface(), NULL); - SDL_FreeSurface(t); - - return r; -} - -SDL_Surface * mogltk::glbase::GrabSurface() { - int i; - SDL_Surface * r; - Uint8 * pixels = (Uint8 *) malloc(GetWidth() * GetHeight() * 3); - Uint8 * s, * d; - - glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGB, GL_UNSIGNED_BYTE, pixels); - - r = SDL_CreateRGBSurface(SDL_SWSURFACE, GetWidth(), GetHeight(), 24, -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - 0xff000000, - 0x00ff0000, - 0x0000ff00, - 0x00000000 -#else - 0x000000ff, - 0x0000ff00, - 0x00ff0000, - 0x00000000 -#endif - ); - - for (i = 0; i < GetHeight(); i++) { - s = pixels + i * GetWidth() * 3; - d = ((Uint8 *) r->pixels) + (GetHeight() - i - 1) * GetWidth() * 3; - memcpy(d, s, GetWidth() * 3); - } - - free(pixels); - - return r; -} +/* + * mogltk + * Copyright (C) 1999-2004 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: glbase.cc,v 1.22 2004-11-27 21:48:03 pixel Exp $ */ + +#include +#include +#include +#include +#include +#include "glbase.h" +#include "engine.h" +#include "generic.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +mogltk::glbase::glbase(int w, int h, int flags) throw (GeneralException) : mogltk::base(w, h, flags, 0), twoD(0), fovy(60.0) { + SDL_Surface * surface; + GLint bits; + + mogltk::engine::setup(); + if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) { + throw GeneralException(String("Couldn't initialise Video SubSystem: ") + SDL_GetError()); + } + +#if 1 + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); +// SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 32); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 8); +#endif + if (!(surface = SDL_SetVideoMode(w, h, 0, flags | SDL_OPENGL | SDL_HWSURFACE))) { + throw GeneralException(String("Couldn't set GL mode: ") + SDL_GetError()); + } + + mogltk::engine::glbase_o = this; + mogltk::engine::base_o = this; + + ratio = (GLdouble) surface->w / surface->h; + + glGetIntegerv(GL_STENCIL_BITS, &bits); + + printm(M_INFO, "Video resolution: %dx%dx%d (ratio = %3.2f)\n", surface->w, surface->h, surface->format->BitsPerPixel, ratio); + printm(M_INFO, "\n"); + printm(M_INFO, "OpenGL infos\n"); + printm(M_INFO, "------------\n"); + printm(M_INFO, String("Vendor : ") + (char *) glGetString(GL_VENDOR) + "\n"); + printm(M_INFO, String("Renderer : ") + (char *) glGetString(GL_RENDERER) + "\n"); + printm(M_INFO, String("Version : ") + (char *) glGetString(GL_VERSION) + "\n"); + printm(M_INFO, String("Extensions: ") + (char *) glGetString(GL_EXTENSIONS) + "\n"); + + glViewport(0, 0, surface->w, surface->h); + + glCullFace(GL_BACK); + glFrontFace(GL_CCW); + glEnable(GL_CULL_FACE); + + glClearColor(0, 0, 0, 0); + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(fovy, ratio, 1.0, 1024.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + SDL_GL_SwapBuffers(); + SDL_ShowCursor(SDL_DISABLE); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + setsurface(surface); + mogltk::engine::postsetup(); +} + +mogltk::glbase::~glbase() { +} + +void mogltk::glbase::Enter2DMode(void) { + if (twoD) + return; + + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0.0, GetWidth(), GetHeight(), 0.0, 0.0, 1.0); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + twoD = 1; +} + +void mogltk::glbase::Leave2DMode(void) { + if (!twoD) + return; + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glPopAttrib(); + + twoD = 0; +} + +void mogltk::glbase::Flip(bool clear) { + mogltk::engine::pollevents(); + SDL_GL_SwapBuffers(); + if (clear) + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +bool mogltk::glbase::is2D() { + return twoD; +} + +void mogltk::glbase::glVertex(GLshort x, GLshort y, GLshort z, GLshort w) { +#ifdef DEBUG + printm(M_INFO, "Calling glVertex(%i, %i, %i, %i) (shorts)\n", x, y, z, w); +#endif + glVertex4i(x, y, z, w); +} + +void mogltk::glbase::glVertex(GLint x, GLint y, GLint z, GLint w) { +#ifdef DEBUG + printm(M_INFO, "Calling glVertex(%i, %i, %i, %i) (ints)\n", x, y, z, w); +#endif + glVertex4i(x, y, z, w); +} + +void mogltk::glbase::glVertex(GLfloat x, GLfloat y, GLfloat z, GLfloat w) { +#ifdef DEBUG + printm(M_INFO, "Calling glVertex(%f, %f, %f, %f) (floats)\n", x, y, z, w); +#endif + glVertex4f(x, y, z, w); +} + +void mogltk::glbase::glVertex(GLdouble x, GLdouble y, GLdouble z, GLdouble w) { +#ifdef DEBUG + printm(M_INFO, "Calling glVertex(%f, %f, %f, %f) (doubles)\n", x, y, z, w); +#endif + glVertex4d(x, y, z, w); +} + +void mogltk::glbase::changeviewport(int x, int y, unsigned int w, unsigned int h) { +#if 0 + if ((w == 0) && (h == 0)) { + w = GetWidth() - x; + h = GetHeight() - y; + } + + ratio = (GLdouble) w / h; + glViewport(x, y, w, h); + if (!engine::base_o->is2D()) + gluPerspective(fovy, ratio, 1.0, 1024.0); +#endif + glScissor(x, GetHeight() - y - h - 1, w + 1, h + 1); + glEnable(GL_SCISSOR_TEST); +} + +void mogltk::glbase::changefovy(GLdouble nfoyv) { + fovy = nfoyv; + if (!engine::base_o->is2D()) + gluPerspective(fovy, ratio, 1.0, 1024.0); +} + +inline static unsigned int nextpower(unsigned int n) { + unsigned int i; + + if (!n) + return n; + + if (ISPOT(n)) + return n; + + for (i = 31; i >= 0; i--) { + if ((n >> i) & 1) { + return 1 << (i + 1); + } + } +} + +mogltk::texture * mogltk::glbase::GrabTexture() { + int w = nextpower(GetWidth()); + int h = nextpower(GetHeight()); + texture * r = new texture(w, h); + SDL_Surface * t; + + t = GrabSurface(); + SDL_BlitSurface(t, NULL, r->GetSurface(), NULL); + SDL_FreeSurface(t); + + return r; +} + +SDL_Surface * mogltk::glbase::GrabSurface() { + int i; + SDL_Surface * r; + Uint8 * pixels = (Uint8 *) malloc(GetWidth() * GetHeight() * 3); + Uint8 * s, * d; + + glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGB, GL_UNSIGNED_BYTE, pixels); + + r = SDL_CreateRGBSurface(SDL_SWSURFACE, GetWidth(), GetHeight(), 24, +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + 0xff000000, + 0x00ff0000, + 0x0000ff00, + 0x00000000 +#else + 0x000000ff, + 0x0000ff00, + 0x00ff0000, + 0x00000000 +#endif + ); + + for (i = 0; i < GetHeight(); i++) { + s = pixels + i * GetWidth() * 3; + d = ((Uint8 *) r->pixels) + (GetHeight() - i - 1) * GetWidth() * 3; + memcpy(d, s, GetWidth() * 3); + } + + free(pixels); + + return r; +} diff --git a/lib/glfont.cc b/lib/glfont.cc index 350f721..5b28591 100644 --- a/lib/glfont.cc +++ b/lib/glfont.cc @@ -1,72 +1,72 @@ -/* - * mogltk - * Copyright (C) 1999-2004 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: glfont.cc,v 1.24 2004-11-27 21:44:53 pixel Exp $ */ - -#include "engine.h" -#include "glbase.h" -#include "glfont.h" -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -mogltk::glfont::glfont(Handle * ffont) : font(ffont) { -} - -mogltk::glfont::~glfont() { -} - -void mogltk::glfont::drawentry(Uint16 entry, int x, int y, ColorP c) { - bool was2D; - int trueentry, cx, cy, px, py; - - was2D = mogltk::engine::glbase_o->is2D(); - - if (!was2D) - mogltk::engine::glbase_o->Enter2DMode(); - - if (shadow) { - int os = shadow; - shadow = 0; - - drawentry(entry, x + os, y + os, BLACK); - - shadow = os; - } - - y -= base; - - Bind(entry / nbcT); - c.Bind(); - trueentry = entry % nbcT; - cx = trueentry % nbcU; - cy = trueentry / nbcU; - px = cx * maxX; - py = cy * maxY; - - glBegin(GL_TRIANGLE_STRIP); - glTexCoord2i(px , py ); glVertex2i(x , y ); - glTexCoord2i(px + maxX , py ); glVertex2i(x + maxX , y ); - glTexCoord2i(px , py + maxY ); glVertex2i(x , y + maxY ); - glTexCoord2i(px + maxX , py + maxY ); glVertex2i(x + maxX , y + maxY ); - glEnd(); - - if (!was2D) - mogltk::engine::glbase_o->Leave2DMode(); -} +/* + * mogltk + * Copyright (C) 1999-2004 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: glfont.cc,v 1.25 2004-11-27 21:48:03 pixel Exp $ */ + +#include "engine.h" +#include "glbase.h" +#include "glfont.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +mogltk::glfont::glfont(Handle * ffont) : font(ffont) { +} + +mogltk::glfont::~glfont() { +} + +void mogltk::glfont::drawentry(Uint16 entry, int x, int y, ColorP c) { + bool was2D; + int trueentry, cx, cy, px, py; + + was2D = mogltk::engine::glbase_o->is2D(); + + if (!was2D) + mogltk::engine::glbase_o->Enter2DMode(); + + if (shadow) { + int os = shadow; + shadow = 0; + + drawentry(entry, x + os, y + os, BLACK); + + shadow = os; + } + + y -= base; + + Bind(entry / nbcT); + c.Bind(); + trueentry = entry % nbcT; + cx = trueentry % nbcU; + cy = trueentry / nbcU; + px = cx * maxX; + py = cy * maxY; + + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2i(px , py ); glVertex2i(x , y ); + glTexCoord2i(px + maxX , py ); glVertex2i(x + maxX , y ); + glTexCoord2i(px , py + maxY ); glVertex2i(x , y + maxY ); + glTexCoord2i(px + maxX , py + maxY ); glVertex2i(x + maxX , y + maxY ); + glEnd(); + + if (!was2D) + mogltk::engine::glbase_o->Leave2DMode(); +} diff --git a/lib/glshape.cc b/lib/glshape.cc index 937173d..8fa718e 100644 --- a/lib/glshape.cc +++ b/lib/glshape.cc @@ -1,253 +1,253 @@ -/* - * mogltk - * Copyright (C) 1999-2004 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: glshape.cc,v 1.15 2004-11-27 21:44:53 pixel Exp $ */ - -#include -#include "glbase.h" -#include "glshape.h" -#include "texture.h" -#include "glfont.h" -#include "engine.h" - -#define ENTER bool was2d = Enter(true) -#define ENTERT bool was2d = Enter(false) -#define LEAVE Leave(was2d) - -void mogltk::glshape::box(int x1, int y1, int x2, int y2, ColorP c) { - ENTER; - - c.Bind(); - glBegin(GL_TRIANGLE_STRIP); - glVertex2i(x1, y1); - glVertex2i(x2 + 1, y1); - glVertex2i(x1, y2 + 1); - glVertex2i(x2 + 1, y2 + 1); - glEnd(); - - LEAVE; -} - -void mogltk::glshape::box(int x1, int y1, int x2, int y2, ColorP c1, ColorP c2, ColorP c3, ColorP c4) { - ENTER; - - glBegin(GL_TRIANGLE_STRIP); - c1.Bind(); glVertex2i(x1, y1); - c2.Bind(); glVertex2i(x2 + 1, y1); - c3.Bind(); glVertex2i(x1, y2 + 1); - c4.Bind(); glVertex2i(x2 + 1, y2 + 1); - glEnd(); - - LEAVE; -} - -void mogltk::glshape::hline(int x1, int x2, int y, ColorP c1, ColorP c2) { - box(x1, y, x2, y, c1, c2, c1, c2); -} - -void mogltk::glshape::hline(int x1, int x2, int y, ColorP c) { - box(x1, y, x2, y, c, c, c, c); -} - -void mogltk::glshape::vline(int x, int y1, int y2, ColorP c1, ColorP c2) { - box(x, y1, x, y2, c1, c1, c2, c2); -} - -void mogltk::glshape::vline(int x, int y1, int y2, ColorP c) { - box(x, y1, x, y2, c, c, c, c); -} - -void mogltk::glshape::pixel(int x, int y, ColorP c) { - box(x, y, x, y, c); -} - -void mogltk::glshape::obox(int x1, int y1, int x2, int y2, ColorP c) { - ENTER; - shape::obox(x1, y1, x2, y2, c); - LEAVE; -} - -void mogltk::glshape::obox(int x1, int y1, int x2, int y2, ColorP c1, ColorP c2, ColorP c3, ColorP c4) { - ENTER; - - hline(x1, x2, y1, c1, c2); - hline(x1, x2, y2, c3, c4); - vline(x1, y1 + 1, y2 - 1, c1, c3); - vline(x2, y1 + 1, y2 - 1, c2, c4); - - LEAVE; -} - -void mogltk::glshape::tbox(mogltk::texture * t, int x1, int y1, int x2, int y2, int tx, int ty, double f, ColorP c) { - tbox(t, x1, y1, x2, y2, tx, ty, tx + (int) ((x2 - x1) * f), ty + (int) ((y2 - y1) * f), c); -} -void mogltk::glshape::tbox(mogltk::texture * t, int x1, int y1, int x2, int y2, int tx1, int ty1, int tx2, int ty2, ColorP c) { - ENTERT; - - c.Bind(); - t->Bind(); - glBegin(GL_TRIANGLE_STRIP); - glTexCoord2i(tx1, ty1); glVertex2i(x1, y1); - glTexCoord2i(tx2 + 1, ty1); glVertex2i(x2 + 1, y1); - glTexCoord2i(tx1, ty2 + 1); glVertex2i(x1, y2 + 1); - glTexCoord2i(tx2 + 1, ty2 + 1); glVertex2i(x2 + 1, y2 + 1); - glEnd(); - - LEAVE; -} - -void mogltk::glshape::tbox(mogltk::texture * t, int x1, int y1, int x2, int y2, ColorP c1, ColorP c2, ColorP c3, ColorP c4, int tx, int ty, double f) { - tbox(t, x1, y1, x2, y2, c1, c2, c3, c4, tx, ty, tx + (int) ((x2 - x1) * f), ty + (int) ((y2 - y1) * f)); -} - -void mogltk::glshape::tbox(mogltk::texture * t, int x1, int y1, int x2, int y2, ColorP c1, ColorP c2, ColorP c3, ColorP c4, int tx1, int ty1, int tx2, int ty2) { - ENTERT; - - t->Bind(); - glBegin(GL_TRIANGLE_STRIP); - c1.Bind(); glTexCoord2i(tx1, ty1); glVertex2i(x1, y1); - c2.Bind(); glTexCoord2i(tx2 + 1, ty1); glVertex2i(x2 + 1, y1); - c3.Bind(); glTexCoord2i(tx1, ty2 + 1); glVertex2i(x1, y2 + 1); - c4.Bind(); glTexCoord2i(tx2 + 1, ty2 + 1); glVertex2i(x2 + 1, y2 + 1); - glEnd(); - - LEAVE; -} - -void mogltk::glshape::box3d(int x1, int y1, int x2, int y2, ColorP face, ColorP shade1, ColorP shade2, int depth, bool bevel) { - ENTER; - - if (!bevel) { - shade1.Bind(); - } else { - shade2.Bind(); - } - glBegin(GL_TRIANGLE_FAN); - glVertex2i(x1, y1); - glVertex2i(x2 + 1, y1); - glVertex2i(x2 + 1 - depth, y1 + depth); - glVertex2i(x1 + depth, y2 + 1 - depth); - glVertex2i(x1, y2 + 1); - glEnd(); - - if (!bevel) { - shade2.Bind(); - } else { - shade1.Bind(); - } - glBegin(GL_TRIANGLE_FAN); - glVertex2i(x2 + 1, y2 + 1); - glVertex2i(x1, y2 + 1); - glVertex2i(x1 + depth, y2 + 1 - depth); - glVertex2i(x2 + 1 - depth, y1 + depth); - glVertex2i(x2 + 1, y1); - glEnd(); - - face.Bind(); - glBegin(GL_TRIANGLE_STRIP); - glVertex2i(x1 + depth, y1 + depth); - glVertex2i(x2 + 1 - depth, y1 + depth); - glVertex2i(x1 + depth, y2 + 1 - depth); - glVertex2i(x2 + 1 - depth, y2 + 1 - depth); - glEnd(); - - LEAVE; -} - -bool mogltk::glshape::Enter(bool unbind) { - bool was2D = mogltk::engine::glbase_o->is2D(); - - if (!was2D) - mogltk::engine::glbase_o->Enter2DMode(); - - if (unbind) mogltk::texture::Unbind(); - - return was2D; -} - -bool mogltk::glshape::Enter() { - return Enter(true); -} - -void mogltk::glshape::Leave(bool was2D) { - if (!was2D) - mogltk::engine::glbase_o->Leave2DMode(); -} - -void mogltk::glshape::fdraw(fill * f, ColorP c, int sx, int sy) { - ENTERT; - - if (!f) - return; - - texture * t = f->GetTexture(); - - if (!t) { - filldrawer * w = new filldrawer(f, t = f->Talloc(), WHITE); - f->walk(w); - delete w; - } - - c.Bind(); - t->Bind(); - int w = t->GetWidth(); - int h = t->GetHeight(); - int x = f->GetMinX() + sx; - int y = f->GetMinY() + sy; - - glBegin(GL_TRIANGLE_STRIP); - glTexCoord2i(0, 0); glVertex2i(x , y ); - glTexCoord2i(w, 0); glVertex2i(x + w, y ); - glTexCoord2i(0, h); glVertex2i(x , y + h); - glTexCoord2i(w, h); glVertex2i(x + w, y + h); - glEnd(); - - LEAVE; -} - -void mogltk::glshape::sdraw(fill * f, ColorP c, int sx, int sy) { - ENTERT; - - if (!f) - return; - - texture * t = f->GetSTexture(); - - if (!t) { - segdrawer * w = new segdrawer(f, t = f->STalloc(), WHITE); - f->swalk(w); - delete w; - } - - c.Bind(); - t->Bind(); - int w = t->GetWidth(); - int h = t->GetHeight(); - int x = f->GetMinX() + sx; - int y = f->GetMinY() + sy; - - glBegin(GL_TRIANGLE_STRIP); - glTexCoord2i(0, 0); glVertex2i(x , y ); - glTexCoord2i(w, 0); glVertex2i(x + w, y ); - glTexCoord2i(0, h); glVertex2i(x , y + h); - glTexCoord2i(w, h); glVertex2i(x + w, y + h); - glEnd(); - - LEAVE; -} +/* + * mogltk + * Copyright (C) 1999-2004 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: glshape.cc,v 1.16 2004-11-27 21:48:03 pixel Exp $ */ + +#include +#include "glbase.h" +#include "glshape.h" +#include "texture.h" +#include "glfont.h" +#include "engine.h" + +#define ENTER bool was2d = Enter(true) +#define ENTERT bool was2d = Enter(false) +#define LEAVE Leave(was2d) + +void mogltk::glshape::box(int x1, int y1, int x2, int y2, ColorP c) { + ENTER; + + c.Bind(); + glBegin(GL_TRIANGLE_STRIP); + glVertex2i(x1, y1); + glVertex2i(x2 + 1, y1); + glVertex2i(x1, y2 + 1); + glVertex2i(x2 + 1, y2 + 1); + glEnd(); + + LEAVE; +} + +void mogltk::glshape::box(int x1, int y1, int x2, int y2, ColorP c1, ColorP c2, ColorP c3, ColorP c4) { + ENTER; + + glBegin(GL_TRIANGLE_STRIP); + c1.Bind(); glVertex2i(x1, y1); + c2.Bind(); glVertex2i(x2 + 1, y1); + c3.Bind(); glVertex2i(x1, y2 + 1); + c4.Bind(); glVertex2i(x2 + 1, y2 + 1); + glEnd(); + + LEAVE; +} + +void mogltk::glshape::hline(int x1, int x2, int y, ColorP c1, ColorP c2) { + box(x1, y, x2, y, c1, c2, c1, c2); +} + +void mogltk::glshape::hline(int x1, int x2, int y, ColorP c) { + box(x1, y, x2, y, c, c, c, c); +} + +void mogltk::glshape::vline(int x, int y1, int y2, ColorP c1, ColorP c2) { + box(x, y1, x, y2, c1, c1, c2, c2); +} + +void mogltk::glshape::vline(int x, int y1, int y2, ColorP c) { + box(x, y1, x, y2, c, c, c, c); +} + +void mogltk::glshape::pixel(int x, int y, ColorP c) { + box(x, y, x, y, c); +} + +void mogltk::glshape::obox(int x1, int y1, int x2, int y2, ColorP c) { + ENTER; + shape::obox(x1, y1, x2, y2, c); + LEAVE; +} + +void mogltk::glshape::obox(int x1, int y1, int x2, int y2, ColorP c1, ColorP c2, ColorP c3, ColorP c4) { + ENTER; + + hline(x1, x2, y1, c1, c2); + hline(x1, x2, y2, c3, c4); + vline(x1, y1 + 1, y2 - 1, c1, c3); + vline(x2, y1 + 1, y2 - 1, c2, c4); + + LEAVE; +} + +void mogltk::glshape::tbox(mogltk::texture * t, int x1, int y1, int x2, int y2, int tx, int ty, double f, ColorP c) { + tbox(t, x1, y1, x2, y2, tx, ty, tx + (int) ((x2 - x1) * f), ty + (int) ((y2 - y1) * f), c); +} +void mogltk::glshape::tbox(mogltk::texture * t, int x1, int y1, int x2, int y2, int tx1, int ty1, int tx2, int ty2, ColorP c) { + ENTERT; + + c.Bind(); + t->Bind(); + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2i(tx1, ty1); glVertex2i(x1, y1); + glTexCoord2i(tx2 + 1, ty1); glVertex2i(x2 + 1, y1); + glTexCoord2i(tx1, ty2 + 1); glVertex2i(x1, y2 + 1); + glTexCoord2i(tx2 + 1, ty2 + 1); glVertex2i(x2 + 1, y2 + 1); + glEnd(); + + LEAVE; +} + +void mogltk::glshape::tbox(mogltk::texture * t, int x1, int y1, int x2, int y2, ColorP c1, ColorP c2, ColorP c3, ColorP c4, int tx, int ty, double f) { + tbox(t, x1, y1, x2, y2, c1, c2, c3, c4, tx, ty, tx + (int) ((x2 - x1) * f), ty + (int) ((y2 - y1) * f)); +} + +void mogltk::glshape::tbox(mogltk::texture * t, int x1, int y1, int x2, int y2, ColorP c1, ColorP c2, ColorP c3, ColorP c4, int tx1, int ty1, int tx2, int ty2) { + ENTERT; + + t->Bind(); + glBegin(GL_TRIANGLE_STRIP); + c1.Bind(); glTexCoord2i(tx1, ty1); glVertex2i(x1, y1); + c2.Bind(); glTexCoord2i(tx2 + 1, ty1); glVertex2i(x2 + 1, y1); + c3.Bind(); glTexCoord2i(tx1, ty2 + 1); glVertex2i(x1, y2 + 1); + c4.Bind(); glTexCoord2i(tx2 + 1, ty2 + 1); glVertex2i(x2 + 1, y2 + 1); + glEnd(); + + LEAVE; +} + +void mogltk::glshape::box3d(int x1, int y1, int x2, int y2, ColorP face, ColorP shade1, ColorP shade2, int depth, bool bevel) { + ENTER; + + if (!bevel) { + shade1.Bind(); + } else { + shade2.Bind(); + } + glBegin(GL_TRIANGLE_FAN); + glVertex2i(x1, y1); + glVertex2i(x2 + 1, y1); + glVertex2i(x2 + 1 - depth, y1 + depth); + glVertex2i(x1 + depth, y2 + 1 - depth); + glVertex2i(x1, y2 + 1); + glEnd(); + + if (!bevel) { + shade2.Bind(); + } else { + shade1.Bind(); + } + glBegin(GL_TRIANGLE_FAN); + glVertex2i(x2 + 1, y2 + 1); + glVertex2i(x1, y2 + 1); + glVertex2i(x1 + depth, y2 + 1 - depth); + glVertex2i(x2 + 1 - depth, y1 + depth); + glVertex2i(x2 + 1, y1); + glEnd(); + + face.Bind(); + glBegin(GL_TRIANGLE_STRIP); + glVertex2i(x1 + depth, y1 + depth); + glVertex2i(x2 + 1 - depth, y1 + depth); + glVertex2i(x1 + depth, y2 + 1 - depth); + glVertex2i(x2 + 1 - depth, y2 + 1 - depth); + glEnd(); + + LEAVE; +} + +bool mogltk::glshape::Enter(bool unbind) { + bool was2D = mogltk::engine::glbase_o->is2D(); + + if (!was2D) + mogltk::engine::glbase_o->Enter2DMode(); + + if (unbind) mogltk::texture::Unbind(); + + return was2D; +} + +bool mogltk::glshape::Enter() { + return Enter(true); +} + +void mogltk::glshape::Leave(bool was2D) { + if (!was2D) + mogltk::engine::glbase_o->Leave2DMode(); +} + +void mogltk::glshape::fdraw(fill * f, ColorP c, int sx, int sy) { + ENTERT; + + if (!f) + return; + + texture * t = f->GetTexture(); + + if (!t) { + filldrawer * w = new filldrawer(f, t = f->Talloc(), WHITE); + f->walk(w); + delete w; + } + + c.Bind(); + t->Bind(); + int w = t->GetWidth(); + int h = t->GetHeight(); + int x = f->GetMinX() + sx; + int y = f->GetMinY() + sy; + + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2i(0, 0); glVertex2i(x , y ); + glTexCoord2i(w, 0); glVertex2i(x + w, y ); + glTexCoord2i(0, h); glVertex2i(x , y + h); + glTexCoord2i(w, h); glVertex2i(x + w, y + h); + glEnd(); + + LEAVE; +} + +void mogltk::glshape::sdraw(fill * f, ColorP c, int sx, int sy) { + ENTERT; + + if (!f) + return; + + texture * t = f->GetSTexture(); + + if (!t) { + segdrawer * w = new segdrawer(f, t = f->STalloc(), WHITE); + f->swalk(w); + delete w; + } + + c.Bind(); + t->Bind(); + int w = t->GetWidth(); + int h = t->GetHeight(); + int x = f->GetMinX() + sx; + int y = f->GetMinY() + sy; + + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2i(0, 0); glVertex2i(x , y ); + glTexCoord2i(w, 0); glVertex2i(x + w, y ); + glTexCoord2i(0, h); glVertex2i(x , y + h); + glTexCoord2i(w, h); glVertex2i(x + w, y + h); + glEnd(); + + LEAVE; +} diff --git a/lib/glsprite.cc b/lib/glsprite.cc index 7091ca3..49db695 100644 --- a/lib/glsprite.cc +++ b/lib/glsprite.cc @@ -1,105 +1,105 @@ -/* - * mogltk - * Copyright (C) 1999-2004 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: glsprite.cc,v 1.10 2004-11-27 21:44:53 pixel Exp $ */ - -#include -#include "glbase.h" -#include "glsprite.h" -#include "engine.h" - -#define TEXSIZE 256 - -mogltk::glSprite::glSprite(Handle * h, int asx, int asy) : Sprite(h, asx, asy) { -} - -mogltk::glSprite::glSprite(Uint8 * p, int asx, int asy) : Sprite(p, asx, asy) { -} - -mogltk::glSprite::~glSprite() { -} - -void mogltk::glSprite::draw(int dx, int dy, ColorP c, float sx, float sy) { - bool was2D; - - if (!(was2D = mogltk::engine::glbase_o->is2D())) - mogltk::engine::glbase_o->Enter2DMode(); - - c.Bind(); - - Bind(); - glBegin(GL_TRIANGLE_STRIP); - glTexCoord2i(GetPX() , GetPY() ); glVertex2i(dx , dy ); - glTexCoord2i(GetPX() + GetSX(), GetPY() ); glVertex2i(dx + GetSX() * sx, dy ); - glTexCoord2i(GetPX() , GetPY() + GetSY()); glVertex2i(dx , dy + GetSY() * sy); - glTexCoord2i(GetPX() + GetSX(), GetPY() + GetSY()); glVertex2i(dx + GetSX() * sx, dy + GetSY() * sy); - glEnd(); - - if (!was2D) - mogltk::engine::glbase_o->Leave2DMode(); -} - -void mogltk::glSprite::bindcorner(float fx, float fy) { - if (fx > 1) - fx = 1; - if (fy > 1) - fy = 1; - if (fx < 0) - fx = 0; - if (fy < 0) - fy = 0; - glTexCoord2i(GetPX() + fx * GetSX(), GetPY() + fy * GetSY()); -} - -void mogltk::glSprite::drawrotate(int cx, int cy, double a, ColorP c) { - bool was2D; - - int sx, sy; - - sx = GetSX() / 2; - sy = GetSY() / 2; - - was2D = mogltk::engine::glbase_o->is2D(); - - if (!was2D) - mogltk::engine::glbase_o->Enter2DMode(); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glTranslated(cx, cy, 0); - glRotated(a, 0, 0, 1); - -// glMatrixMode(GL_TEXTURE); -// glRotated(a, 0, 0, 1); - - c.Bind(); - - Bind(); - glBegin(GL_TRIANGLE_STRIP); - glTexCoord2i(GetPX() , GetPY() ); glVertex2i( - sx, - sy); - glTexCoord2i(GetPX() + GetSX(), GetPY() ); glVertex2i(GetSX() - sx, - sy); - glTexCoord2i(GetPX() , GetPY() + GetSY()); glVertex2i( - sx, GetSY() - sy); - glTexCoord2i(GetPX() + GetSX(), GetPY() + GetSY()); glVertex2i(GetSX() - sx, GetSY() - sy); - glEnd(); - - glPopMatrix(); - - if (!was2D) - mogltk::engine::glbase_o->Leave2DMode(); -} +/* + * mogltk + * Copyright (C) 1999-2004 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: glsprite.cc,v 1.11 2004-11-27 21:48:03 pixel Exp $ */ + +#include +#include "glbase.h" +#include "glsprite.h" +#include "engine.h" + +#define TEXSIZE 256 + +mogltk::glSprite::glSprite(Handle * h, int asx, int asy) : Sprite(h, asx, asy) { +} + +mogltk::glSprite::glSprite(Uint8 * p, int asx, int asy) : Sprite(p, asx, asy) { +} + +mogltk::glSprite::~glSprite() { +} + +void mogltk::glSprite::draw(int dx, int dy, ColorP c, float sx, float sy) { + bool was2D; + + if (!(was2D = mogltk::engine::glbase_o->is2D())) + mogltk::engine::glbase_o->Enter2DMode(); + + c.Bind(); + + Bind(); + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2i(GetPX() , GetPY() ); glVertex2i(dx , dy ); + glTexCoord2i(GetPX() + GetSX(), GetPY() ); glVertex2i(dx + GetSX() * sx, dy ); + glTexCoord2i(GetPX() , GetPY() + GetSY()); glVertex2i(dx , dy + GetSY() * sy); + glTexCoord2i(GetPX() + GetSX(), GetPY() + GetSY()); glVertex2i(dx + GetSX() * sx, dy + GetSY() * sy); + glEnd(); + + if (!was2D) + mogltk::engine::glbase_o->Leave2DMode(); +} + +void mogltk::glSprite::bindcorner(float fx, float fy) { + if (fx > 1) + fx = 1; + if (fy > 1) + fy = 1; + if (fx < 0) + fx = 0; + if (fy < 0) + fy = 0; + glTexCoord2i(GetPX() + fx * GetSX(), GetPY() + fy * GetSY()); +} + +void mogltk::glSprite::drawrotate(int cx, int cy, double a, ColorP c) { + bool was2D; + + int sx, sy; + + sx = GetSX() / 2; + sy = GetSY() / 2; + + was2D = mogltk::engine::glbase_o->is2D(); + + if (!was2D) + mogltk::engine::glbase_o->Enter2DMode(); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glTranslated(cx, cy, 0); + glRotated(a, 0, 0, 1); + +// glMatrixMode(GL_TEXTURE); +// glRotated(a, 0, 0, 1); + + c.Bind(); + + Bind(); + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2i(GetPX() , GetPY() ); glVertex2i( - sx, - sy); + glTexCoord2i(GetPX() + GetSX(), GetPY() ); glVertex2i(GetSX() - sx, - sy); + glTexCoord2i(GetPX() , GetPY() + GetSY()); glVertex2i( - sx, GetSY() - sy); + glTexCoord2i(GetPX() + GetSX(), GetPY() + GetSY()); glVertex2i(GetSX() - sx, GetSY() - sy); + glEnd(); + + glPopMatrix(); + + if (!was2D) + mogltk::engine::glbase_o->Leave2DMode(); +} diff --git a/lib/glwidgets.cc b/lib/glwidgets.cc index be3617f..5ff8c23 100644 --- a/lib/glwidgets.cc +++ b/lib/glwidgets.cc @@ -1,29 +1,29 @@ -/* - * mogltk - * Copyright (C) 1999-2004 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: glwidgets.cc,v 1.8 2004-11-27 21:44:53 pixel Exp $ */ - -#include -#include -#include "mcolor.h" -#include "glwidgets.h" - -void mogltk::widgets::glRoot::draw() { - Shaper()->box(GetAX(), GetAY(), GetAX2(), GetAY2()); -} +/* + * mogltk + * Copyright (C) 1999-2004 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: glwidgets.cc,v 1.9 2004-11-27 21:48:03 pixel Exp $ */ + +#include +#include +#include "mcolor.h" +#include "glwidgets.h" + +void mogltk::widgets::glRoot::draw() { + Shaper()->box(GetAX(), GetAY(), GetAX2(), GetAY2()); +} diff --git a/lib/mcolor.cc b/lib/mcolor.cc index df75007..e2a921d 100644 --- a/lib/mcolor.cc +++ b/lib/mcolor.cc @@ -1,66 +1,66 @@ -/* - * mogltk - * Copyright (C) 1999-2004 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: mcolor.cc,v 1.7 2004-11-27 21:44:53 pixel Exp $ */ - -#include -#include -#include "engine.h" -#include "mcolor.h" - -Color mogltk::ColorP::Min(0, 0, 0, 0), mogltk::ColorP::Max = WHITE; - -mogltk::ColorP::ColorP(const Color & ac) : c(ac) { -} - -mogltk::ColorP::ColorP(Uint8 ar, Uint8 ag, Uint8 ab, Uint8 aa) : c(ar, ag, ab, aa) { -} - -void mogltk::ColorP::Bind() { - glColor4d((double) MIN(MAX(c.R, Min.R), Max.R) / 255, (double) MIN(MAX(c.G, Min.G), Max.G) / 255, (double) MIN(MAX(c.B, Min.B), Max.B) / 255, (double) MIN(MAX(c.A, Min.A), Max.A) / 255); -} - -Uint32 mogltk::ColorP::toSDL(SDL_PixelFormat * f) { - if (!f) - f = mogltk::engine::base_o->getsurface()->format; - - return SDL_MapRGBA(f, MIN(MAX(c.R, Min.R), Max.R), MIN(MAX(c.G, Min.G), Max.G), MIN(MAX(c.B, Min.B), Max.B), MIN(MAX(c.A, Min.A), Max.A)); -} - -void mogltk::ColorP::fromSDL(Uint32 p, SDL_PixelFormat * f) { - if (!f) - f = mogltk::engine::base_o->getsurface()->format; - - SDL_GetRGBA(p, f, &c.R, &c.G, &c.B, &c.A); -} - -void mogltk::ColorP::Norm() { - c.R = MIN(MAX(c.R, Min.R), Max.R); - c.G = MIN(MAX(c.R, Min.G), Max.G); - c.B = MIN(MAX(c.R, Min.B), Max.B); - c.A = MIN(MAX(c.R, Min.A), Max.A); -} - -bool mogltk::ColorP::operator==(const ColorP & nc) { - return c == nc.c; -} - -Color * mogltk::ColorP::operator->() { - return &c; -} +/* + * mogltk + * Copyright (C) 1999-2004 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: mcolor.cc,v 1.8 2004-11-27 21:48:03 pixel Exp $ */ + +#include +#include +#include "engine.h" +#include "mcolor.h" + +Color mogltk::ColorP::Min(0, 0, 0, 0), mogltk::ColorP::Max = WHITE; + +mogltk::ColorP::ColorP(const Color & ac) : c(ac) { +} + +mogltk::ColorP::ColorP(Uint8 ar, Uint8 ag, Uint8 ab, Uint8 aa) : c(ar, ag, ab, aa) { +} + +void mogltk::ColorP::Bind() { + glColor4d((double) MIN(MAX(c.R, Min.R), Max.R) / 255, (double) MIN(MAX(c.G, Min.G), Max.G) / 255, (double) MIN(MAX(c.B, Min.B), Max.B) / 255, (double) MIN(MAX(c.A, Min.A), Max.A) / 255); +} + +Uint32 mogltk::ColorP::toSDL(SDL_PixelFormat * f) { + if (!f) + f = mogltk::engine::base_o->getsurface()->format; + + return SDL_MapRGBA(f, MIN(MAX(c.R, Min.R), Max.R), MIN(MAX(c.G, Min.G), Max.G), MIN(MAX(c.B, Min.B), Max.B), MIN(MAX(c.A, Min.A), Max.A)); +} + +void mogltk::ColorP::fromSDL(Uint32 p, SDL_PixelFormat * f) { + if (!f) + f = mogltk::engine::base_o->getsurface()->format; + + SDL_GetRGBA(p, f, &c.R, &c.G, &c.B, &c.A); +} + +void mogltk::ColorP::Norm() { + c.R = MIN(MAX(c.R, Min.R), Max.R); + c.G = MIN(MAX(c.R, Min.G), Max.G); + c.B = MIN(MAX(c.R, Min.B), Max.B); + c.A = MIN(MAX(c.R, Min.A), Max.A); +} + +bool mogltk::ColorP::operator==(const ColorP & nc) { + return c == nc.c; +} + +Color * mogltk::ColorP::operator->() { + return &c; +} diff --git a/lib/shape.cc b/lib/shape.cc index 2a493cb..a7ed137 100644 --- a/lib/shape.cc +++ b/lib/shape.cc @@ -1,928 +1,928 @@ -/* - * mogltk - * Copyright (C) 1999-2004 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: shape.cc,v 1.18 2004-11-27 21:44:53 pixel Exp $ */ - -#include -#include -#include -#include -#include -#include "engine.h" -#include "base.h" -#include "shape.h" -#include "texture.h" -#include "font.h" - -#define ENTER bool flag = Enter() -#define LEAVE Leave(flag) - -mogltk::fillwalker::fillwalker() { -} - -mogltk::fillwalker::~fillwalker() { -} - -void mogltk::fillwalker::step(int x, int y) { -} - -mogltk::segwalker::segwalker() { -} - -mogltk::segwalker::~segwalker() { -} - -void mogltk::segwalker::step(int x1, int y1, int x2, int y2) { -} - -mogltk::fill::fill() : minX(INT_MAX), minY(INT_MAX), maxX(INT_MIN), maxY(INT_MIN), cached(0), scached(0), header(0) { -} - -mogltk::fill::~fill() { - if (header) - delete header; - - if (cached) - delete cached; - - if (scached) - delete scached; -} - -void mogltk::fill::walk(fillwalker * w) { - if (header) - header->walk(w); -} - -void mogltk::fill::swalk(segwalker * s) { - std::vector::iterator i; - - for (i = segments.begin(); i != segments.end(); i++) { - s->step(i->x1, i->y1, i->x2, i->y2); - } -} - -void mogltk::fill::insert(int x, int y) { - if (cached) { - delete cached; - cached = 0; - } - - if (scached) { - delete scached; - scached = 0; - } - - if (!header) { - new sline(y, this); - } - header->insert(x, y); - - if (x > maxX) - maxX = x; - - if (x < minX) - minX = x; - - if (y > maxY) - maxY = y; - - if (y < minY) - minY = y; -} - -void mogltk::fill::insert(int x1, int y1, int x2, int y2) { - int dx, dy, y; - double x, i, i2; - - struct segment s; - s.x1 = x1; - s.y1 = y1; - s.x2 = x2; - s.y2 = y2; - segments.push_back(s); - - if (y1 == y2) - return; - - if (y2 < y1) { - SWAP(x1, x2); - SWAP(y1, y2); - } - - dx = x1 - x2; - dy = y1 - y2; - - x = x1; - i = ((double) dx) / ((double) dy); - i2 = i / 2; - for (y = y1; y < y2; y++, x += i) - insert(x + i2, y); -} - -void mogltk::fill::insertfix(int x, int y) { - if (!header) - return; - - header->insertfix(x, y); -} - -int mogltk::fill::GetMaxX() const { - return maxX; -} - -int mogltk::fill::GetMaxY() const { - return maxY; -} - -int mogltk::fill::GetMinX() const { - return minX; -} - -int mogltk::fill::GetMinY() const { - return minY; -} - -mogltk::texture * mogltk::fill::GetTexture() { - return cached; -} - -mogltk::texture * mogltk::fill::GetSTexture() { - return scached; -} - -mogltk::texture * mogltk::fill::Talloc() { - if (cached) - return cached; - - int x; int y; - - for (x = 1; x <= (maxX - minX); x <<= 1); - for (y = 1; y <= (maxY - minY); y <<= 1); - - cached = new texture(x, y, true); - return cached; -} - -mogltk::texture * mogltk::fill::STalloc() { - if (scached) - return scached; - - int x; int y; - - for (x = 1; x <= (maxX - minX); x <<= 1); - for (y = 1; y <= (maxY - minY); y <<= 1); - - scached = new texture(x, y, true); - return scached; -} - -mogltk::fill::sline::sline(int _y, fill * _header) : y(_y), header(_header), pheader(0) { - if (!header->header) { - header->header = this; - } else { - if (header->header->y > y) { - next = header->header; - header->header = this; - } else { - sline * p; - for (p = header->header; p->next; p = p->next) { - if (p->next->y > y) { - next = p->next; - p->next = this; - return; - } - } - p->next = this; - next = 0; - } - } -} - -mogltk::fill::sline::~sline() { - if (pheader) - delete pheader; - if (next) - delete next; -} - -int mogltk::fill::sline::GetY() const { - return y; -} - -void mogltk::fill::sline::insert(int ax, int ay) { - sline * f; - - if (ay == y) { - if (!pheader) - new point(ax, this); - else if (!pheader->look(ax)) - new point(ax, this); - } else { - f = header->header->look(ay); - - if (!f) { - f = new sline(ay, header); - } - - f->insert(ax, ay); - } -} - -void mogltk::fill::sline::insertfix(int ax, int ay) { - sline * f; - - if (ay == y) { - if (count() & 1) { - insert(ax, ay); - } - } else { - f = header->header->look(ay); - if (!f) - return; - - f->insertfix(ax, ay); - } -} - -int mogltk::fill::sline::count() const { - int r = 0; - - if (next) - r = next->count(); - - return r + 1; -} - -void mogltk::fill::sline::walk(fillwalker * w) { - if (pheader) - pheader->walk(w); - if (next) - next->walk(w); -} - -mogltk::fill::sline::point::point(int _x, sline * _header) : x(_x), header(_header) { - if (!header->pheader) { - header->pheader = this; - } else { - if (header->pheader->x > x) { - next = header->pheader; - header->pheader = this; - } else { - point * p; - for (p = header->pheader; p->next; p = p->next) { - if (p->next->x > x) { - next = p->next; - p->next = this; - return; - } - } - p->next = this; - next = 0; - } - } -} - -mogltk::fill::sline::point::~point() { - if (next) - delete next; -} - -int mogltk::fill::sline::point::GetX() const { - return x; -} - -int mogltk::fill::sline::point::GetY() const { - return header->GetY(); -} - -void mogltk::fill::sline::point::walk(fillwalker * w) { - w->step(GetX(), GetY()); - if (next) - next->walk(w); -} - -mogltk::fill::sline::point * mogltk::fill::sline::point::look(int _x) { - if (x > _x) - return 0; - - if (x == _x) - return this; - - if (!next) - return 0; - - return next->look(_x); -} - -mogltk::fill::sline * mogltk::fill::sline::look(int _y) { - if (y > _y) - return 0; - - if (y == _y) - return this; - - if (!next) - return 0; - - return next->look(_y); -} - -mogltk::shape::shape(SDL_Surface * _surf) : surf(_surf) { - if (!surf) - surf = mogltk::engine::base_o->getsurface(); -} - -SDL_Surface * mogltk::shape::GetSurf() { - return surf; -} - -void mogltk::shape::box(int x1, int y1, int x2, int y2, ColorP c) { - ENTER; - - SDL_Rect rect; - - rect.x = x1; rect.y = y1; rect.w = x2 - x1 + 1; rect.h = y2 - y1 + 1; - SDL_FillRect(surf, &rect, c.toSDL(surf->format)); - - LEAVE; -} - -void mogltk::shape::hline(int x1, int x2, int y, ColorP c) { - for (; x1 <= x2; x1++) { - pixel(x1, y, c); - } -} - -void mogltk::shape::hline3d(int x1, int x2, int y, ColorP shade1, ColorP shade2, bool bevel) { - ENTER; - - if (!bevel) { - hline(x1, x2, y, shade2); - hline(x1, x2, y + 1, shade1); - } else { - hline(x1, x2, y, shade1); - hline(x1, x2, y + 1, shade2); - } - - LEAVE; -} - -void mogltk::shape::vline(int x, int y1, int y2, ColorP c) { - for (; y1 <= y2; y1++) { - pixel(x, y1, c); - } -} - -void mogltk::shape::vline3d(int x, int y1, int y2, ColorP shade1, ColorP shade2, bool bevel) { - ENTER; - - if (!bevel) { - vline(x, y1, y2, shade2); - vline(x + 1, y1, y2, shade1); - } else { - vline(x, y1, y2, shade1); - vline(x + 1, y1, y2, shade2); - } - - LEAVE; -} - -void mogltk::shape::bsubline_1(int x1, int y1, int x2, int y2, ColorP c) { - int x, y, ddx, ddy, e; - ddx = abs(x2 - x1); - ddy = abs(y2 - y1) << 1; - e = ddx - ddy; - ddx <<= 1; - - if (x1 > x2) { - SWAP(x1, x2); - SWAP(y1, y2); - } - - ENTER; - - for (x = x1, y = y1; x <= x2; x++) { - pixel(x, y, c); - if (e < 0) { - y++; - e += ddx - ddy; - } else { - e -= ddy; - } - } - - LEAVE; -} - -void mogltk::shape::bsubline_2(int x1, int y1, int x2, int y2, ColorP c) { - int x, y, ddx, ddy, e; - ddx = abs(x2 - x1) << 1; - ddy = abs(y2 - y1); - e = ddy - ddx; - ddy <<= 1; - - if (y1 > y2) { - SWAP(x1, x2); - SWAP(y1, y2); - } - - ENTER; - - for (y = y1, x = x1; y <= y2; y++) { - pixel(x, y, c); - if (e < 0) { - x++; - e += ddy - ddx; - } else { - e -= ddx; - } - } - - LEAVE; -} - -void mogltk::shape::bsubline_3(int x1, int y1, int x2, int y2, ColorP c) { - int x, y, ddx, ddy, e; - ddx = abs(x1 - x2) << 1; - ddy = abs(y2 - y1); - e = ddy - ddx; - ddy <<= 1; - - if (y1 > y2) { - SWAP(x1, x2); - SWAP(y1, y2); - } - - ENTER; - - for (y = y1, x = x1; y <= y2; y++) { - pixel(x, y, c); - if (e < 0) { - x--; - e += ddy - ddx; - } else { - e -= ddx; - } - } - - LEAVE; -} - -void mogltk::shape::bsubline_4(int x1, int y1, int x2, int y2, ColorP c) { - int x, y, ddx, ddy, e; - ddy = abs(y2 - y1) << 1; - ddx = abs(x1 - x2); - e = ddx - ddy; - ddx <<= 1; - - if (x1 > x2) { - SWAP(x1, x2); - SWAP(y1, y2); - } - - for (x = x1, y = y1; x <= x2; x++) { - pixel(x, y, c); - if (e < 0) { - y--; - e += ddx - ddy; - } else { - e -= ddy; - } - } -} - -void mogltk::shape::line(int x1, int y1, int x2, int y2, ColorP c) { - if ((x1 == x2) && (y1 == y2)) { - printm(M_INFO, "Line is a pixel...\n"); - pixel(x1, y1, c); - return; - } - - if (x1 == x2) { - vline(x1, MIN(y1, y2), MAX(y1, y2), c); - return; - } - - if (y1 == y2) { - hline(MIN(x1, x2), MAX(x1, x2), y1, c); - return; - } - - float k = float(y2 - y1) / float(x2 - x1); - - if ((k >= 0) && (k <= 1)) { - bsubline_1(x1, y1, x2, y2, c); - } else if (k > 1) { - bsubline_2(x1, y1, x2, y2, c); - } else if ((k < 0) && (k >= -1)) { - bsubline_4(x1, y1, x2, y2, c); - } else { - bsubline_3(x1, y1, x2, y2, c); - } -} - -void mogltk::shape::pixel(int x, int y, ColorP c) { - ENTER; - - int bpp = surf->format->BytesPerPixel; - Uint8 *p = (Uint8 *)surf->pixels + y * surf->pitch + x * bpp; - Uint32 pixel = c.toSDL(surf->format); - - if ((x < 0) || (y < 0) || (x >= surf->w) || (y >= surf->h)) { - printm(M_INFO, "Pixel culling, out of bounds.\n"); - return; - } - - 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; - } - - LEAVE; -} - -void mogltk::shape::circle(int x0, int y0, int r, ColorP c) { - ENTER; - - int x = 0; - int y = r - 1; - int d = 3 - 2 * r; - int dI = 10 - 4 * r; - int rI = 6; - - while (x <= y) { - pixel(x0 + x, y0 + y, c); - pixel(x0 - x, y0 + y, c); - pixel(x0 + x, y0 - y, c); - pixel(x0 - x, y0 - y, c); - pixel(x0 + y, y0 + x, c); - pixel(x0 - y, y0 + x, c); - pixel(x0 + y, y0 - x, c); - pixel(x0 - y, y0 - x, c); - if (d >= 0) { - d += dI; - dI += 8; - y -= 1; - } else { - d += rI; - dI += 4; - } - rI += 4; - x += 1; - } - - LEAVE; -} - -mogltk::fill * mogltk::shape::fcircle(int x0, int y0, int r) { - int x = 0; - int y = r - 1; - int d = 3 - 2 * r; - int dI = 10 - 4 * r; - int rI = 6; - mogltk::fill * f = new fill(); - bool t = false; - int ox = 0, oy = 0; - - while (x <= y) { -/* - if (t) { - f->insert(x0 - x, y0 - y); - f->insert(x0 + x, y0 - y); - f->insert(x0 - x, y0 + y); - f->insert(x0 + x, y0 + y); - } - f->insert(x0 - y, y0 - x); - f->insert(x0 + y, y0 - x); - f->insert(x0 - y, y0 + x); - f->insert(x0 + y, y0 + x); -*/ - if (t) { - f->insert(x0 - ox, y0 - oy, x0 - x, y0 - y); - f->insert(x0 + ox, y0 - oy, x0 + x, y0 - y); - f->insert(x0 - ox, y0 + oy, x0 - x, y0 + y); - f->insert(x0 + ox, y0 + oy, x0 + x, y0 + y); - f->insert(x0 - oy, y0 - ox, x0 - y, y0 - x); - f->insert(x0 + oy, y0 - ox, x0 + y, y0 - x); - f->insert(x0 - oy, y0 + ox, x0 - y, y0 + x); - f->insert(x0 + oy, y0 + ox, x0 + y, y0 + x); - } - ox = x; - oy = y; - t = true; - if (d >= 0) { - d += dI; - dI += 8; - y -= 1; - } else { - d += rI; - dI += 4; - } - rI += 4; - x += 1; - } - return f; -} - -void mogltk::shape::pcircle(int x, int y, int r, ColorP c) { - fill * f = fcircle(x, y, r); - fdraw(f, c); - delete f; -} - -mogltk::filldrawer::filldrawer(fill * _f, texture * _t, ColorP _c) : f(_f), t(_t), c(_c), oldx(-1), oldy(-1) { -} - -mogltk::filldrawer::~filldrawer() { -} - -void mogltk::filldrawer::step(int x, int y) { - if (oldy != y) { - oldx = -1; - } - if (oldx == -1) { - oldx = x; - } else { -/* s->hline(oldx, x, y, c); */ - Uint32 * p = t->GetPixels(); - int i, - first = t->GetWidth() * (y - f->GetMinY()) + oldx - f->GetMinX(), - last = first - oldx + x; - SDL_PixelFormat * format = t->GetFormat(); - - for (i = first; i <= last; i++) { - if (i > (t->GetWidth() * t->GetHeight())) { - printm(M_ERROR, "Big problem here. i = %i and W, H = %i, %i\n", i, t->GetWidth(), t->GetHeight()); - printm(M_ERROR, "Initially, wanted to draw hline(%i, %i, %i)\n", oldx, x, y); - printm(M_ERROR, "With MinX = %i and MinY = %i --> hline(%i, %i, %i)\n", f->GetMinX(), f->GetMinY(), oldx - f->GetMinX(), x - f->GetMinX(), y - f->GetMinY()); - printm(M_ERROR, "For info, MaxX = %i and MaxY = %i\n", f->GetMaxX(), f->GetMaxY()); - exit(-1); - } - p[i] = c.toSDL(format); - } - - oldx = -1; - } - oldy = y; -} - -void mogltk::shape::fdraw(fill * f, ColorP c, int sx, int sy) { - ENTER; - if (!f) - return; - if (!f->GetTexture()) { - filldrawer * w = new filldrawer(f, f->Talloc(), c); - f->walk(w); - delete w; - f->last = c.c; - } - SDL_PixelFormat * format = f->GetTexture()->GetFormat(); - - if (f->last == c.c) { - Uint32 * p = f->GetTexture()->GetPixels(); - int i, n = f->GetTexture()->GetWidth() * f->GetTexture()->GetHeight(); - for (i = 0; i < n; i++) - if (p[i] & 0xff000000) - p[i] = c.toSDL(format); - } - SDL_Rect r; - r.x = f->GetMinX() + sx; - r.y = f->GetMinY() + sy; - SDL_BlitSurface(f->GetTexture()->GetSurface(), 0, surf, &r); - - f->last = c.c; - LEAVE; -} - -mogltk::segdrawer::segdrawer(fill * _f, texture * _t, ColorP _c) : f(_f), t(_t), c(_c), sh(new shape(_t->GetSurface())) { -} - -mogltk::segdrawer::~segdrawer() { - delete sh; -} - -void mogltk::segdrawer::step(int x1, int y1, int x2, int y2) { - sh->line(x1 - f->GetMinX(), y1 - f->GetMinY(), x2 - f->GetMinX(), y2 - f->GetMinY(), c); -} - -void mogltk::shape::sdraw(fill * f, ColorP c, int sx, int sy) { - ENTER; - - if (!f) - return; - - if (!f->GetSTexture()) { - segdrawer * w = new segdrawer(f, f->STalloc(), c); - f->swalk(w); - delete w; - f->last = c.c; - } - SDL_PixelFormat * format = f->GetSTexture()->GetFormat(); - - if (f->last == c.c) { - Uint32 * p = f->GetSTexture()->GetPixels(); - int i, n = f->GetSTexture()->GetWidth() * f->GetSTexture()->GetHeight(); - for (i = 0; i < n; i++) - if (p[i] & 0xff000000) - p[i] = c.toSDL(format); - } - SDL_Rect r; - r.x = f->GetMinX() + sx; - r.y = f->GetMinY() + sy; - SDL_BlitSurface(f->GetSTexture()->GetSurface(), 0, surf, &r); - - f->last = c.c; - LEAVE; -} - -void mogltk::shape::obox(int x1, int y1, int x2, int y2, ColorP c) { - ENTER; - - hline(x1, x2, y1, c); - hline(x1, x2, y2, c); - vline(x1, y1 + 1, y2 - 1, c); - vline(x2, y1 + 1, y2 - 1, c); - - LEAVE; -} - -void mogltk::shape::box3d(int x1, int y1, int x2, int y2, ColorP face, ColorP shade1, ColorP shade2, int depth, bool bevel) { - ENTER; - - int i; - - for (i = 0; i < depth; i++) { - hline(x1 + i, x2 - i, y1 + i, bevel ? shade2 : shade1); - vline(x1 + i, y1 + i, y2 - i, bevel ? shade2 : shade1); - } - - for (i = 0; i < depth; i++) { - hline(x1 + i, x2 - i, y2 - i, bevel ? shade1 : shade2); - vline(x2 - i, y1 + i, y2 - i, bevel ? shade1 : shade2); - } - - box(x1 + depth, y1 + depth, x2 - depth, y2 - depth, face); - - LEAVE; -} - -void mogltk::shape::obox3d(int x1, int y1, int x2, int y2, ColorP shade1, ColorP shade2, bool bevel) { - ENTER; - - if (!bevel) { - obox(x1 + 1, y1 + 1, x2, y2, shade1); - obox(x1, y1, x2 - 1, y2 - 1, shade2); - } else { - obox(x1, y1, x2 - 1, y2 - 1, shade1); - obox(x1 + 1, y1 + 1, x2, y2, shade2); - } - - LEAVE; -} - -void mogltk::shape::window(int x1, int y1, int x2, int y2, const String & title, - ColorP titlecolor, ColorP titlebackcolor, - ColorP front, ColorP shade1, ColorP shade2) { - ENTER; - - box3d(x1, y1, x2, y2, front, shade1, shade2); - hline3d(x1 + 2, x2 - 2, y1 + 19, shade1, shade2, 1); - box(x1 + 2, y1 + 2, x2 - 2, y1 + 18, titlebackcolor); - text((x1 + x2) / 2, y1 + 2, title, titlecolor, CENTER); - - LEAVE; -} - -void mogltk::shape::text(int x, int y, const String & text, ColorP textcolor, align_t align) { - int tsize = SystemFont->singletextsize(text); - switch (align) { - case LEFT: - SystemFont->putcursor(x, y); - break; - case CENTER: - SystemFont->putcursor(x - (tsize / 2), y); - break; - case RIGHT: - SystemFont->putcursor(x - tsize, y); - break; - } - SystemFont->setcolor(textcolor); - SystemFont->setshadow(0); - SystemFont->printf(text); -} - -void mogltk::shape::text3d(int x, int y, const String & atext, ColorP textcolor, - ColorP shade1, ColorP shade2, - align_t align, bool bevel) { - ENTER; - - SystemFont->setwspace(1); - if (!bevel) { - text(x - 1, y - 1, atext, shade2, align); - text(x + 1, y + 1, atext, shade1, align); - } else { - text(x - 1, y - 1, atext, shade1, align); - text(x + 1, y + 1, atext, shade2, align); - } - text(x, y, atext, textcolor, align); - SystemFont->setwspace(0); - - LEAVE; -} - -void mogltk::shape::button(int x1, int y1, int x2, int y2, - const String & atext, bool bevel, - ColorP front, ColorP shade1, ColorP shade2, - ColorP round, ColorP textcolor, - ColorP tshade1, ColorP tshade2) { - ENTER; - - box3d(x1, y1, x2, y2, front, shade1, shade2, 2, bevel); - hline(x1, x2, y1 - 1, round); - hline(x1, x2, y2 + 1, round); - vline(x1 - 1, y1, y2, round); - vline(x2 + 1, y1, y2, round); - pixel(x1, y1, round); - pixel(x1, y2, round); - pixel(x2, y1, round); - pixel(x2, y2, round); - text3d((x1 + x2) / 2, (y1 + y2) / 2 - 8, atext, textcolor, tshade1, tshade2, CENTER, bevel); - - LEAVE; -} - -bool mogltk::shape::Enter() { - if (SDL_MUSTLOCK(surf)) { - SDL_LockSurface(surf); - return true; - } else { - return false; - } -} - -void mogltk::shape::Leave(bool locked) { - if (locked) - SDL_UnlockSurface(surf); -} - -void mogltk::shape::tbox(texture *, int x1, int y1, int x2, int y2, int tx, int ty, double f, ColorP c) { -} - -void mogltk::shape::tbox(texture *, int x1, int y1, int x2, int y2, int tx1, int ty1, int tx2, int ty2, ColorP c) { -} - -void mogltk::shape::tbox(texture *, int x1, int y1, int x2, int y2, ColorP, ColorP, ColorP, ColorP, int tx, int ty, double f) { -} - -void mogltk::shape::tbox(texture *, int x1, int y1, int x2, int y2, ColorP, ColorP, ColorP, ColorP, int tx1, int ty1, int tx2, int ty2) { -} - -void mogltk::shape::vline(int x, int y1, int y2, ColorP c1, ColorP c2) { -} - -void mogltk::shape::hline(int x1, int x2, int y, ColorP c1, ColorP c2) { -} - -void mogltk::shape::box(int x1, int y1, int x2, int y2, ColorP c1, ColorP c2, ColorP c3, ColorP c4) { -} - -void mogltk::shape::obox(int x1, int y1, int x2, int y2, ColorP c1, ColorP c2, ColorP c3, ColorP c4) { -} +/* + * mogltk + * Copyright (C) 1999-2004 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: shape.cc,v 1.19 2004-11-27 21:48:03 pixel Exp $ */ + +#include +#include +#include +#include +#include +#include "engine.h" +#include "base.h" +#include "shape.h" +#include "texture.h" +#include "font.h" + +#define ENTER bool flag = Enter() +#define LEAVE Leave(flag) + +mogltk::fillwalker::fillwalker() { +} + +mogltk::fillwalker::~fillwalker() { +} + +void mogltk::fillwalker::step(int x, int y) { +} + +mogltk::segwalker::segwalker() { +} + +mogltk::segwalker::~segwalker() { +} + +void mogltk::segwalker::step(int x1, int y1, int x2, int y2) { +} + +mogltk::fill::fill() : minX(INT_MAX), minY(INT_MAX), maxX(INT_MIN), maxY(INT_MIN), cached(0), scached(0), header(0) { +} + +mogltk::fill::~fill() { + if (header) + delete header; + + if (cached) + delete cached; + + if (scached) + delete scached; +} + +void mogltk::fill::walk(fillwalker * w) { + if (header) + header->walk(w); +} + +void mogltk::fill::swalk(segwalker * s) { + std::vector::iterator i; + + for (i = segments.begin(); i != segments.end(); i++) { + s->step(i->x1, i->y1, i->x2, i->y2); + } +} + +void mogltk::fill::insert(int x, int y) { + if (cached) { + delete cached; + cached = 0; + } + + if (scached) { + delete scached; + scached = 0; + } + + if (!header) { + new sline(y, this); + } + header->insert(x, y); + + if (x > maxX) + maxX = x; + + if (x < minX) + minX = x; + + if (y > maxY) + maxY = y; + + if (y < minY) + minY = y; +} + +void mogltk::fill::insert(int x1, int y1, int x2, int y2) { + int dx, dy, y; + double x, i, i2; + + struct segment s; + s.x1 = x1; + s.y1 = y1; + s.x2 = x2; + s.y2 = y2; + segments.push_back(s); + + if (y1 == y2) + return; + + if (y2 < y1) { + SWAP(x1, x2); + SWAP(y1, y2); + } + + dx = x1 - x2; + dy = y1 - y2; + + x = x1; + i = ((double) dx) / ((double) dy); + i2 = i / 2; + for (y = y1; y < y2; y++, x += i) + insert(x + i2, y); +} + +void mogltk::fill::insertfix(int x, int y) { + if (!header) + return; + + header->insertfix(x, y); +} + +int mogltk::fill::GetMaxX() const { + return maxX; +} + +int mogltk::fill::GetMaxY() const { + return maxY; +} + +int mogltk::fill::GetMinX() const { + return minX; +} + +int mogltk::fill::GetMinY() const { + return minY; +} + +mogltk::texture * mogltk::fill::GetTexture() { + return cached; +} + +mogltk::texture * mogltk::fill::GetSTexture() { + return scached; +} + +mogltk::texture * mogltk::fill::Talloc() { + if (cached) + return cached; + + int x; int y; + + for (x = 1; x <= (maxX - minX); x <<= 1); + for (y = 1; y <= (maxY - minY); y <<= 1); + + cached = new texture(x, y, true); + return cached; +} + +mogltk::texture * mogltk::fill::STalloc() { + if (scached) + return scached; + + int x; int y; + + for (x = 1; x <= (maxX - minX); x <<= 1); + for (y = 1; y <= (maxY - minY); y <<= 1); + + scached = new texture(x, y, true); + return scached; +} + +mogltk::fill::sline::sline(int _y, fill * _header) : y(_y), header(_header), pheader(0) { + if (!header->header) { + header->header = this; + } else { + if (header->header->y > y) { + next = header->header; + header->header = this; + } else { + sline * p; + for (p = header->header; p->next; p = p->next) { + if (p->next->y > y) { + next = p->next; + p->next = this; + return; + } + } + p->next = this; + next = 0; + } + } +} + +mogltk::fill::sline::~sline() { + if (pheader) + delete pheader; + if (next) + delete next; +} + +int mogltk::fill::sline::GetY() const { + return y; +} + +void mogltk::fill::sline::insert(int ax, int ay) { + sline * f; + + if (ay == y) { + if (!pheader) + new point(ax, this); + else if (!pheader->look(ax)) + new point(ax, this); + } else { + f = header->header->look(ay); + + if (!f) { + f = new sline(ay, header); + } + + f->insert(ax, ay); + } +} + +void mogltk::fill::sline::insertfix(int ax, int ay) { + sline * f; + + if (ay == y) { + if (count() & 1) { + insert(ax, ay); + } + } else { + f = header->header->look(ay); + if (!f) + return; + + f->insertfix(ax, ay); + } +} + +int mogltk::fill::sline::count() const { + int r = 0; + + if (next) + r = next->count(); + + return r + 1; +} + +void mogltk::fill::sline::walk(fillwalker * w) { + if (pheader) + pheader->walk(w); + if (next) + next->walk(w); +} + +mogltk::fill::sline::point::point(int _x, sline * _header) : x(_x), header(_header) { + if (!header->pheader) { + header->pheader = this; + } else { + if (header->pheader->x > x) { + next = header->pheader; + header->pheader = this; + } else { + point * p; + for (p = header->pheader; p->next; p = p->next) { + if (p->next->x > x) { + next = p->next; + p->next = this; + return; + } + } + p->next = this; + next = 0; + } + } +} + +mogltk::fill::sline::point::~point() { + if (next) + delete next; +} + +int mogltk::fill::sline::point::GetX() const { + return x; +} + +int mogltk::fill::sline::point::GetY() const { + return header->GetY(); +} + +void mogltk::fill::sline::point::walk(fillwalker * w) { + w->step(GetX(), GetY()); + if (next) + next->walk(w); +} + +mogltk::fill::sline::point * mogltk::fill::sline::point::look(int _x) { + if (x > _x) + return 0; + + if (x == _x) + return this; + + if (!next) + return 0; + + return next->look(_x); +} + +mogltk::fill::sline * mogltk::fill::sline::look(int _y) { + if (y > _y) + return 0; + + if (y == _y) + return this; + + if (!next) + return 0; + + return next->look(_y); +} + +mogltk::shape::shape(SDL_Surface * _surf) : surf(_surf) { + if (!surf) + surf = mogltk::engine::base_o->getsurface(); +} + +SDL_Surface * mogltk::shape::GetSurf() { + return surf; +} + +void mogltk::shape::box(int x1, int y1, int x2, int y2, ColorP c) { + ENTER; + + SDL_Rect rect; + + rect.x = x1; rect.y = y1; rect.w = x2 - x1 + 1; rect.h = y2 - y1 + 1; + SDL_FillRect(surf, &rect, c.toSDL(surf->format)); + + LEAVE; +} + +void mogltk::shape::hline(int x1, int x2, int y, ColorP c) { + for (; x1 <= x2; x1++) { + pixel(x1, y, c); + } +} + +void mogltk::shape::hline3d(int x1, int x2, int y, ColorP shade1, ColorP shade2, bool bevel) { + ENTER; + + if (!bevel) { + hline(x1, x2, y, shade2); + hline(x1, x2, y + 1, shade1); + } else { + hline(x1, x2, y, shade1); + hline(x1, x2, y + 1, shade2); + } + + LEAVE; +} + +void mogltk::shape::vline(int x, int y1, int y2, ColorP c) { + for (; y1 <= y2; y1++) { + pixel(x, y1, c); + } +} + +void mogltk::shape::vline3d(int x, int y1, int y2, ColorP shade1, ColorP shade2, bool bevel) { + ENTER; + + if (!bevel) { + vline(x, y1, y2, shade2); + vline(x + 1, y1, y2, shade1); + } else { + vline(x, y1, y2, shade1); + vline(x + 1, y1, y2, shade2); + } + + LEAVE; +} + +void mogltk::shape::bsubline_1(int x1, int y1, int x2, int y2, ColorP c) { + int x, y, ddx, ddy, e; + ddx = abs(x2 - x1); + ddy = abs(y2 - y1) << 1; + e = ddx - ddy; + ddx <<= 1; + + if (x1 > x2) { + SWAP(x1, x2); + SWAP(y1, y2); + } + + ENTER; + + for (x = x1, y = y1; x <= x2; x++) { + pixel(x, y, c); + if (e < 0) { + y++; + e += ddx - ddy; + } else { + e -= ddy; + } + } + + LEAVE; +} + +void mogltk::shape::bsubline_2(int x1, int y1, int x2, int y2, ColorP c) { + int x, y, ddx, ddy, e; + ddx = abs(x2 - x1) << 1; + ddy = abs(y2 - y1); + e = ddy - ddx; + ddy <<= 1; + + if (y1 > y2) { + SWAP(x1, x2); + SWAP(y1, y2); + } + + ENTER; + + for (y = y1, x = x1; y <= y2; y++) { + pixel(x, y, c); + if (e < 0) { + x++; + e += ddy - ddx; + } else { + e -= ddx; + } + } + + LEAVE; +} + +void mogltk::shape::bsubline_3(int x1, int y1, int x2, int y2, ColorP c) { + int x, y, ddx, ddy, e; + ddx = abs(x1 - x2) << 1; + ddy = abs(y2 - y1); + e = ddy - ddx; + ddy <<= 1; + + if (y1 > y2) { + SWAP(x1, x2); + SWAP(y1, y2); + } + + ENTER; + + for (y = y1, x = x1; y <= y2; y++) { + pixel(x, y, c); + if (e < 0) { + x--; + e += ddy - ddx; + } else { + e -= ddx; + } + } + + LEAVE; +} + +void mogltk::shape::bsubline_4(int x1, int y1, int x2, int y2, ColorP c) { + int x, y, ddx, ddy, e; + ddy = abs(y2 - y1) << 1; + ddx = abs(x1 - x2); + e = ddx - ddy; + ddx <<= 1; + + if (x1 > x2) { + SWAP(x1, x2); + SWAP(y1, y2); + } + + for (x = x1, y = y1; x <= x2; x++) { + pixel(x, y, c); + if (e < 0) { + y--; + e += ddx - ddy; + } else { + e -= ddy; + } + } +} + +void mogltk::shape::line(int x1, int y1, int x2, int y2, ColorP c) { + if ((x1 == x2) && (y1 == y2)) { + printm(M_INFO, "Line is a pixel...\n"); + pixel(x1, y1, c); + return; + } + + if (x1 == x2) { + vline(x1, MIN(y1, y2), MAX(y1, y2), c); + return; + } + + if (y1 == y2) { + hline(MIN(x1, x2), MAX(x1, x2), y1, c); + return; + } + + float k = float(y2 - y1) / float(x2 - x1); + + if ((k >= 0) && (k <= 1)) { + bsubline_1(x1, y1, x2, y2, c); + } else if (k > 1) { + bsubline_2(x1, y1, x2, y2, c); + } else if ((k < 0) && (k >= -1)) { + bsubline_4(x1, y1, x2, y2, c); + } else { + bsubline_3(x1, y1, x2, y2, c); + } +} + +void mogltk::shape::pixel(int x, int y, ColorP c) { + ENTER; + + int bpp = surf->format->BytesPerPixel; + Uint8 *p = (Uint8 *)surf->pixels + y * surf->pitch + x * bpp; + Uint32 pixel = c.toSDL(surf->format); + + if ((x < 0) || (y < 0) || (x >= surf->w) || (y >= surf->h)) { + printm(M_INFO, "Pixel culling, out of bounds.\n"); + return; + } + + 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; + } + + LEAVE; +} + +void mogltk::shape::circle(int x0, int y0, int r, ColorP c) { + ENTER; + + int x = 0; + int y = r - 1; + int d = 3 - 2 * r; + int dI = 10 - 4 * r; + int rI = 6; + + while (x <= y) { + pixel(x0 + x, y0 + y, c); + pixel(x0 - x, y0 + y, c); + pixel(x0 + x, y0 - y, c); + pixel(x0 - x, y0 - y, c); + pixel(x0 + y, y0 + x, c); + pixel(x0 - y, y0 + x, c); + pixel(x0 + y, y0 - x, c); + pixel(x0 - y, y0 - x, c); + if (d >= 0) { + d += dI; + dI += 8; + y -= 1; + } else { + d += rI; + dI += 4; + } + rI += 4; + x += 1; + } + + LEAVE; +} + +mogltk::fill * mogltk::shape::fcircle(int x0, int y0, int r) { + int x = 0; + int y = r - 1; + int d = 3 - 2 * r; + int dI = 10 - 4 * r; + int rI = 6; + mogltk::fill * f = new fill(); + bool t = false; + int ox = 0, oy = 0; + + while (x <= y) { +/* + if (t) { + f->insert(x0 - x, y0 - y); + f->insert(x0 + x, y0 - y); + f->insert(x0 - x, y0 + y); + f->insert(x0 + x, y0 + y); + } + f->insert(x0 - y, y0 - x); + f->insert(x0 + y, y0 - x); + f->insert(x0 - y, y0 + x); + f->insert(x0 + y, y0 + x); +*/ + if (t) { + f->insert(x0 - ox, y0 - oy, x0 - x, y0 - y); + f->insert(x0 + ox, y0 - oy, x0 + x, y0 - y); + f->insert(x0 - ox, y0 + oy, x0 - x, y0 + y); + f->insert(x0 + ox, y0 + oy, x0 + x, y0 + y); + f->insert(x0 - oy, y0 - ox, x0 - y, y0 - x); + f->insert(x0 + oy, y0 - ox, x0 + y, y0 - x); + f->insert(x0 - oy, y0 + ox, x0 - y, y0 + x); + f->insert(x0 + oy, y0 + ox, x0 + y, y0 + x); + } + ox = x; + oy = y; + t = true; + if (d >= 0) { + d += dI; + dI += 8; + y -= 1; + } else { + d += rI; + dI += 4; + } + rI += 4; + x += 1; + } + return f; +} + +void mogltk::shape::pcircle(int x, int y, int r, ColorP c) { + fill * f = fcircle(x, y, r); + fdraw(f, c); + delete f; +} + +mogltk::filldrawer::filldrawer(fill * _f, texture * _t, ColorP _c) : f(_f), t(_t), c(_c), oldx(-1), oldy(-1) { +} + +mogltk::filldrawer::~filldrawer() { +} + +void mogltk::filldrawer::step(int x, int y) { + if (oldy != y) { + oldx = -1; + } + if (oldx == -1) { + oldx = x; + } else { +/* s->hline(oldx, x, y, c); */ + Uint32 * p = t->GetPixels(); + int i, + first = t->GetWidth() * (y - f->GetMinY()) + oldx - f->GetMinX(), + last = first - oldx + x; + SDL_PixelFormat * format = t->GetFormat(); + + for (i = first; i <= last; i++) { + if (i > (t->GetWidth() * t->GetHeight())) { + printm(M_ERROR, "Big problem here. i = %i and W, H = %i, %i\n", i, t->GetWidth(), t->GetHeight()); + printm(M_ERROR, "Initially, wanted to draw hline(%i, %i, %i)\n", oldx, x, y); + printm(M_ERROR, "With MinX = %i and MinY = %i --> hline(%i, %i, %i)\n", f->GetMinX(), f->GetMinY(), oldx - f->GetMinX(), x - f->GetMinX(), y - f->GetMinY()); + printm(M_ERROR, "For info, MaxX = %i and MaxY = %i\n", f->GetMaxX(), f->GetMaxY()); + exit(-1); + } + p[i] = c.toSDL(format); + } + + oldx = -1; + } + oldy = y; +} + +void mogltk::shape::fdraw(fill * f, ColorP c, int sx, int sy) { + ENTER; + if (!f) + return; + if (!f->GetTexture()) { + filldrawer * w = new filldrawer(f, f->Talloc(), c); + f->walk(w); + delete w; + f->last = c.c; + } + SDL_PixelFormat * format = f->GetTexture()->GetFormat(); + + if (f->last == c.c) { + Uint32 * p = f->GetTexture()->GetPixels(); + int i, n = f->GetTexture()->GetWidth() * f->GetTexture()->GetHeight(); + for (i = 0; i < n; i++) + if (p[i] & 0xff000000) + p[i] = c.toSDL(format); + } + SDL_Rect r; + r.x = f->GetMinX() + sx; + r.y = f->GetMinY() + sy; + SDL_BlitSurface(f->GetTexture()->GetSurface(), 0, surf, &r); + + f->last = c.c; + LEAVE; +} + +mogltk::segdrawer::segdrawer(fill * _f, texture * _t, ColorP _c) : f(_f), t(_t), c(_c), sh(new shape(_t->GetSurface())) { +} + +mogltk::segdrawer::~segdrawer() { + delete sh; +} + +void mogltk::segdrawer::step(int x1, int y1, int x2, int y2) { + sh->line(x1 - f->GetMinX(), y1 - f->GetMinY(), x2 - f->GetMinX(), y2 - f->GetMinY(), c); +} + +void mogltk::shape::sdraw(fill * f, ColorP c, int sx, int sy) { + ENTER; + + if (!f) + return; + + if (!f->GetSTexture()) { + segdrawer * w = new segdrawer(f, f->STalloc(), c); + f->swalk(w); + delete w; + f->last = c.c; + } + SDL_PixelFormat * format = f->GetSTexture()->GetFormat(); + + if (f->last == c.c) { + Uint32 * p = f->GetSTexture()->GetPixels(); + int i, n = f->GetSTexture()->GetWidth() * f->GetSTexture()->GetHeight(); + for (i = 0; i < n; i++) + if (p[i] & 0xff000000) + p[i] = c.toSDL(format); + } + SDL_Rect r; + r.x = f->GetMinX() + sx; + r.y = f->GetMinY() + sy; + SDL_BlitSurface(f->GetSTexture()->GetSurface(), 0, surf, &r); + + f->last = c.c; + LEAVE; +} + +void mogltk::shape::obox(int x1, int y1, int x2, int y2, ColorP c) { + ENTER; + + hline(x1, x2, y1, c); + hline(x1, x2, y2, c); + vline(x1, y1 + 1, y2 - 1, c); + vline(x2, y1 + 1, y2 - 1, c); + + LEAVE; +} + +void mogltk::shape::box3d(int x1, int y1, int x2, int y2, ColorP face, ColorP shade1, ColorP shade2, int depth, bool bevel) { + ENTER; + + int i; + + for (i = 0; i < depth; i++) { + hline(x1 + i, x2 - i, y1 + i, bevel ? shade2 : shade1); + vline(x1 + i, y1 + i, y2 - i, bevel ? shade2 : shade1); + } + + for (i = 0; i < depth; i++) { + hline(x1 + i, x2 - i, y2 - i, bevel ? shade1 : shade2); + vline(x2 - i, y1 + i, y2 - i, bevel ? shade1 : shade2); + } + + box(x1 + depth, y1 + depth, x2 - depth, y2 - depth, face); + + LEAVE; +} + +void mogltk::shape::obox3d(int x1, int y1, int x2, int y2, ColorP shade1, ColorP shade2, bool bevel) { + ENTER; + + if (!bevel) { + obox(x1 + 1, y1 + 1, x2, y2, shade1); + obox(x1, y1, x2 - 1, y2 - 1, shade2); + } else { + obox(x1, y1, x2 - 1, y2 - 1, shade1); + obox(x1 + 1, y1 + 1, x2, y2, shade2); + } + + LEAVE; +} + +void mogltk::shape::window(int x1, int y1, int x2, int y2, const String & title, + ColorP titlecolor, ColorP titlebackcolor, + ColorP front, ColorP shade1, ColorP shade2) { + ENTER; + + box3d(x1, y1, x2, y2, front, shade1, shade2); + hline3d(x1 + 2, x2 - 2, y1 + 19, shade1, shade2, 1); + box(x1 + 2, y1 + 2, x2 - 2, y1 + 18, titlebackcolor); + text((x1 + x2) / 2, y1 + 2, title, titlecolor, CENTER); + + LEAVE; +} + +void mogltk::shape::text(int x, int y, const String & text, ColorP textcolor, align_t align) { + int tsize = SystemFont->singletextsize(text); + switch (align) { + case LEFT: + SystemFont->putcursor(x, y); + break; + case CENTER: + SystemFont->putcursor(x - (tsize / 2), y); + break; + case RIGHT: + SystemFont->putcursor(x - tsize, y); + break; + } + SystemFont->setcolor(textcolor); + SystemFont->setshadow(0); + SystemFont->printf(text); +} + +void mogltk::shape::text3d(int x, int y, const String & atext, ColorP textcolor, + ColorP shade1, ColorP shade2, + align_t align, bool bevel) { + ENTER; + + SystemFont->setwspace(1); + if (!bevel) { + text(x - 1, y - 1, atext, shade2, align); + text(x + 1, y + 1, atext, shade1, align); + } else { + text(x - 1, y - 1, atext, shade1, align); + text(x + 1, y + 1, atext, shade2, align); + } + text(x, y, atext, textcolor, align); + SystemFont->setwspace(0); + + LEAVE; +} + +void mogltk::shape::button(int x1, int y1, int x2, int y2, + const String & atext, bool bevel, + ColorP front, ColorP shade1, ColorP shade2, + ColorP round, ColorP textcolor, + ColorP tshade1, ColorP tshade2) { + ENTER; + + box3d(x1, y1, x2, y2, front, shade1, shade2, 2, bevel); + hline(x1, x2, y1 - 1, round); + hline(x1, x2, y2 + 1, round); + vline(x1 - 1, y1, y2, round); + vline(x2 + 1, y1, y2, round); + pixel(x1, y1, round); + pixel(x1, y2, round); + pixel(x2, y1, round); + pixel(x2, y2, round); + text3d((x1 + x2) / 2, (y1 + y2) / 2 - 8, atext, textcolor, tshade1, tshade2, CENTER, bevel); + + LEAVE; +} + +bool mogltk::shape::Enter() { + if (SDL_MUSTLOCK(surf)) { + SDL_LockSurface(surf); + return true; + } else { + return false; + } +} + +void mogltk::shape::Leave(bool locked) { + if (locked) + SDL_UnlockSurface(surf); +} + +void mogltk::shape::tbox(texture *, int x1, int y1, int x2, int y2, int tx, int ty, double f, ColorP c) { +} + +void mogltk::shape::tbox(texture *, int x1, int y1, int x2, int y2, int tx1, int ty1, int tx2, int ty2, ColorP c) { +} + +void mogltk::shape::tbox(texture *, int x1, int y1, int x2, int y2, ColorP, ColorP, ColorP, ColorP, int tx, int ty, double f) { +} + +void mogltk::shape::tbox(texture *, int x1, int y1, int x2, int y2, ColorP, ColorP, ColorP, ColorP, int tx1, int ty1, int tx2, int ty2) { +} + +void mogltk::shape::vline(int x, int y1, int y2, ColorP c1, ColorP c2) { +} + +void mogltk::shape::hline(int x1, int x2, int y, ColorP c1, ColorP c2) { +} + +void mogltk::shape::box(int x1, int y1, int x2, int y2, ColorP c1, ColorP c2, ColorP c3, ColorP c4) { +} + +void mogltk::shape::obox(int x1, int y1, int x2, int y2, ColorP c1, ColorP c2, ColorP c3, ColorP c4) { +} diff --git a/lib/sprite.cc b/lib/sprite.cc index ef5d7a8..bd0df94 100644 --- a/lib/sprite.cc +++ b/lib/sprite.cc @@ -1,190 +1,190 @@ -/* - * mogltk - * Copyright (C) 1999-2004 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: sprite.cc,v 1.14 2004-11-27 21:44:53 pixel Exp $ */ - -#include -#include "engine.h" -#include "base.h" -#include "sprite.h" - -#define TEXSIZE 1024 - -mogltk::Sprite * mogltk::Sprite::Cursor; - -mogltk::Sprite::TexList * mogltk::Sprite::TexList::header = 0; - -mogltk::Sprite::Sprite(Handle * h, int asx, int asy) throw (GeneralException) : sx(asx), sy(asy) { - alloc(); - for (int y = 0; y < sy; y++) { - h->read(tlist->GetTex()->GetPixels() + TEXSIZE * y + posx, sx * 4); - } -} - -mogltk::Sprite::Sprite(Uint8 * p, int asx, int asy) : sx(asx), sy(asy) { - alloc(); - for (int y = 0; y < sy; y++) { - bcopy(p, tlist->GetTex()->GetPixels() + TEXSIZE * y + posx, sx * 4); - p += sx * 4; - } -} - -mogltk::Sprite::~Sprite() { - if (prev) - prev->next = next; - else - tlist->sprheader = next; - - if (next) - next->prev = prev; - - if (!tlist->sprheader) { - delete tlist; - } -} - -void mogltk::Sprite::alloc() { - /* FIXMEEEEEEEEEEEEE */ - bool found = false; - TexList * p; - - for (p = tlist; p && !found; p = p->GetNext()) { - for (posy = 0; (posy < (TEXSIZE - sy)) && !found; posy++) { - for (posx = 0; (posx < (TEXSIZE - sx)) && !found; posx++) { - if (p->sprheader->canfit(posx, posy, posx + sx, posy + sy)) { - found = true; - } - } - } - } - - if (!found) { - printm(M_INFO, "Allocating a new texture for sprites\n"); - posx = posy = 0; - p = new TexList(TEXSIZE); - } - - tlist = p; -} - -mogltk::Sprite::TexList::TexList(int size) { - tex = new texture(size, size, true); - - if (header) - header->prev = this; - prev = 0; - next = header; - header = this; -} - -mogltk::Sprite::TexList::~TexList() { - delete tex; - - if (prev) - prev->next = next; - else - header = next; - - if (next) - next->prev = prev; -} - -const mogltk::texture * mogltk::Sprite::TexList::GetTex() const { - return tex; -} - -mogltk::texture * mogltk::Sprite::TexList::GetTex() { - return tex; -} - -const mogltk::Sprite::TexList * mogltk::Sprite::TexList::GetHead() { - return header; -} - -const mogltk::Sprite::TexList * mogltk::Sprite::TexList::GetNext() const { - return next; -} - -mogltk::Sprite::TexList * mogltk::Sprite::TexList::GetNext() { - return next; -} - -void mogltk::Sprite::TexList::Bind() const { - tex->Bind(); -} - -SDL_Surface * mogltk::Sprite::TexList::GetSurface() { - return tex->GetSurface(); -} - - -bool mogltk::Sprite::intersect(int x1, int y1, int x2, int y2) const { - int sx1 = posx, sy1 = posy, sx2 = posx + sx, sy2 = posy + sy; - - return !((sx1 >= x2) || (sx2 <= x1) || (sy1 >= y1) || (sy2 <= y2)); -} - -bool mogltk::Sprite::canfit(int x1, int y1, int x2, int y2) const { - if (!intersect(x1, y1, x2, y2)) - return true; - else - if (next) - return next->canfit(x1, y1, x2, y2); - else - return false; -} - -void mogltk::Sprite::draw(int dx, int dy, ColorP c, float sx, float sy) { - bool locked = false; - - if (SDL_MUSTLOCK(mogltk::engine::base_o->getsurface())) { - locked = true; - SDL_LockSurface(mogltk::engine::base_o->getsurface()); - } - - SDL_Rect src, dst; - - src.x = posx; src.y = posy; src.w = sx; src.h = sy; - dst.x = dx; dst.y = dy; dst.w = sx; dst.h = sy; - - SDL_BlitSurface(tlist->GetSurface(), &src, mogltk::engine::base_o->getsurface(), &dst); - - if (locked) - SDL_UnlockSurface(mogltk::engine::base_o->getsurface()); -} - -void mogltk::Sprite::Bind() { - tlist->Bind(); -} - -int mogltk::Sprite::GetPX() { - return posx; -} - -int mogltk::Sprite::GetPY() { - return posy; -} - -int mogltk::Sprite::GetSX() { - return sx; -} - -int mogltk::Sprite::GetSY() { - return sy; -} +/* + * mogltk + * Copyright (C) 1999-2004 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: sprite.cc,v 1.15 2004-11-27 21:48:03 pixel Exp $ */ + +#include +#include "engine.h" +#include "base.h" +#include "sprite.h" + +#define TEXSIZE 1024 + +mogltk::Sprite * mogltk::Sprite::Cursor; + +mogltk::Sprite::TexList * mogltk::Sprite::TexList::header = 0; + +mogltk::Sprite::Sprite(Handle * h, int asx, int asy) throw (GeneralException) : sx(asx), sy(asy) { + alloc(); + for (int y = 0; y < sy; y++) { + h->read(tlist->GetTex()->GetPixels() + TEXSIZE * y + posx, sx * 4); + } +} + +mogltk::Sprite::Sprite(Uint8 * p, int asx, int asy) : sx(asx), sy(asy) { + alloc(); + for (int y = 0; y < sy; y++) { + bcopy(p, tlist->GetTex()->GetPixels() + TEXSIZE * y + posx, sx * 4); + p += sx * 4; + } +} + +mogltk::Sprite::~Sprite() { + if (prev) + prev->next = next; + else + tlist->sprheader = next; + + if (next) + next->prev = prev; + + if (!tlist->sprheader) { + delete tlist; + } +} + +void mogltk::Sprite::alloc() { + /* FIXMEEEEEEEEEEEEE */ + bool found = false; + TexList * p; + + for (p = tlist; p && !found; p = p->GetNext()) { + for (posy = 0; (posy < (TEXSIZE - sy)) && !found; posy++) { + for (posx = 0; (posx < (TEXSIZE - sx)) && !found; posx++) { + if (p->sprheader->canfit(posx, posy, posx + sx, posy + sy)) { + found = true; + } + } + } + } + + if (!found) { + printm(M_INFO, "Allocating a new texture for sprites\n"); + posx = posy = 0; + p = new TexList(TEXSIZE); + } + + tlist = p; +} + +mogltk::Sprite::TexList::TexList(int size) { + tex = new texture(size, size, true); + + if (header) + header->prev = this; + prev = 0; + next = header; + header = this; +} + +mogltk::Sprite::TexList::~TexList() { + delete tex; + + if (prev) + prev->next = next; + else + header = next; + + if (next) + next->prev = prev; +} + +const mogltk::texture * mogltk::Sprite::TexList::GetTex() const { + return tex; +} + +mogltk::texture * mogltk::Sprite::TexList::GetTex() { + return tex; +} + +const mogltk::Sprite::TexList * mogltk::Sprite::TexList::GetHead() { + return header; +} + +const mogltk::Sprite::TexList * mogltk::Sprite::TexList::GetNext() const { + return next; +} + +mogltk::Sprite::TexList * mogltk::Sprite::TexList::GetNext() { + return next; +} + +void mogltk::Sprite::TexList::Bind() const { + tex->Bind(); +} + +SDL_Surface * mogltk::Sprite::TexList::GetSurface() { + return tex->GetSurface(); +} + + +bool mogltk::Sprite::intersect(int x1, int y1, int x2, int y2) const { + int sx1 = posx, sy1 = posy, sx2 = posx + sx, sy2 = posy + sy; + + return !((sx1 >= x2) || (sx2 <= x1) || (sy1 >= y1) || (sy2 <= y2)); +} + +bool mogltk::Sprite::canfit(int x1, int y1, int x2, int y2) const { + if (!intersect(x1, y1, x2, y2)) + return true; + else + if (next) + return next->canfit(x1, y1, x2, y2); + else + return false; +} + +void mogltk::Sprite::draw(int dx, int dy, ColorP c, float sx, float sy) { + bool locked = false; + + if (SDL_MUSTLOCK(mogltk::engine::base_o->getsurface())) { + locked = true; + SDL_LockSurface(mogltk::engine::base_o->getsurface()); + } + + SDL_Rect src, dst; + + src.x = posx; src.y = posy; src.w = sx; src.h = sy; + dst.x = dx; dst.y = dy; dst.w = sx; dst.h = sy; + + SDL_BlitSurface(tlist->GetSurface(), &src, mogltk::engine::base_o->getsurface(), &dst); + + if (locked) + SDL_UnlockSurface(mogltk::engine::base_o->getsurface()); +} + +void mogltk::Sprite::Bind() { + tlist->Bind(); +} + +int mogltk::Sprite::GetPX() { + return posx; +} + +int mogltk::Sprite::GetPY() { + return posy; +} + +int mogltk::Sprite::GetSX() { + return sx; +} + +int mogltk::Sprite::GetSY() { + return sy; +} diff --git a/lib/texture.cc b/lib/texture.cc index ea504ab..a06c345 100644 --- a/lib/texture.cc +++ b/lib/texture.cc @@ -1,361 +1,361 @@ -/* - * mogltk - * Copyright (C) 1999-2004 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: texture.cc,v 1.10 2004-11-27 21:44:53 pixel Exp $ */ - -#include -#include -#include -#include -#include "texture.h" -#include "engine.h" -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include "gettext.h" - -#define DEBUG 1 - -mogltk::texture * mogltk::texture::header = 0; -mogltk::texture * mogltk::texture::footer = 0; - -mogltk::texture * mogltk::texture::active = 0; - -mogltk::texture::texture(int w, int h, bool plane) throw (GeneralException) : width(w), height(h), - texture_allocated(false), planar(plane), tainted(true), taintable(true) { - if ((!ISPOT(w)) || (!ISPOT(h))) - throw GeneralException(_("Size of the texture not a power of 2!")); - - if (!(surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - 0xff000000, - 0x00ff0000, - 0x0000ff00, - 0x000000ff -#else - 0x000000ff, - 0x0000ff00, - 0x00ff0000, - 0xff000000 -#endif - ))) { - throw GeneralException(_("Can't create RGB Surface")); - } - - SDL_FillRect(surface, 0, 0); - - next = 0; - prev = footer; - footer = this; - if (!header) { - header = this; - } - if (prev) { - prev->next = this; - } -} - -mogltk::texture::texture(Handle * h, bool plane) throw (GeneralException) : - texture_allocated(false), planar(plane), tainted(true), taintable(true) { - - SDL_Surface * temp; - - temp = LoadNTEX(h); - width = temp->w; - height = temp->h; - -#ifdef DEBUG - printm(M_INFO, "Creating texture from file: size %ix%i\n", height, width); -#endif - - if ((!ISPOT(width)) || (!ISPOT(height))) { - SDL_FreeSurface(temp); - throw GeneralException(_("Size of the texture not a power of 2!")); - } - - SDL_PixelFormat f; - - f.palette = 0; - f.BitsPerPixel = 32; - f.BytesPerPixel = 4; -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - f.Amask = 0x000000ff; - f.Bmask = 0x0000ff00; - f.Gmask = 0x00ff0000; - f.Rmask = 0xff000000; - f.Ashift = 0; - f.Bshift = 8; - f.Gshift = 16; - f.Rshift = 24; -#else - f.Rmask = 0x000000ff; - f.Gmask = 0x0000ff00; - f.Bmask = 0x00ff0000; - f.Amask = 0xff000000; - f.Rshift = 0; - f.Gshift = 8; - f.Bshift = 16; - f.Ashift = 24; -#endif - f.Rloss = 0; - f.Gloss = 0; - f.Bloss = 0; - f.Aloss = 0; - - if (!(surface = SDL_ConvertSurface(temp, &f, 0))) { - throw GeneralException("Could not convert texture to OpenGL format"); - } - - SDL_FreeSurface(temp); - - next = 0; - prev = footer; - footer = this; - if (!header) { - header = this; - } - if (prev) { - prev->next = this; - } -} - -inline static unsigned int nextpower(unsigned int n) { - unsigned int i; - - if (!n) - return n; - - if (ISPOT(n)) - return n; - - for (i = 31; i >= 0; i--) { - if ((n >> i) & 1) { - return 1 << (i + 1); - } - } -} - -mogltk::texture::texture(int x, int y, int w, int h) : width(nextpower(w)), height(nextpower(h)), - texture_allocated(true), planar(false), tainted(false), taintable(false) { - glGenTextures(1, &tex); - glBindTexture(GL_TEXTURE_2D, tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, x, y, w, h); -} - -mogltk::texture::~texture() { - if (surface) { - SDL_FreeSurface(surface); - } - - if (texture_allocated) { - glDeleteTextures(1, &tex); - } - - if (prev) { - prev->next = next; - } - - if (next) { - next->prev = prev; - } - - if (this == footer) { - footer = prev; - } - - if (this == header) { - header = next; - } -} - -Uint32 * mogltk::texture::GetPixels() { - if (surface) - return (Uint32 *) surface->pixels; - else - return 0; -} - -SDL_Surface * mogltk::texture::GetSurface() { - return surface; -} - -SDL_PixelFormat * mogltk::texture::GetFormat() { - if (surface) - return surface->format; - else - return 0; -} - -void mogltk::texture::Generate() { - if (texture_allocated) { - glDeleteTextures(1, &tex); - } - - glGenTextures(1, &tex); -#ifdef DEBUG - printm(M_INFO, _("Generated texture index: %i\n"), tex); -#endif - - glBindTexture(GL_TEXTURE_2D, tex); - -#if 0 - if (planar) { -#ifdef DEBUG - printm(M_INFO, _("Generating planar texture: %i\n"), tex); -#endif - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels); - } else { -#endif -#ifdef DEBUG - printm(M_INFO, _("Generating 3D texture: %i\n"), tex); -#endif - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels); -// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels); -#if 0 - } -#endif - - texture_allocated = true; - tainted = false; -} - -void mogltk::texture::Bind(bool expand) { - if ((!texture_allocated) || tainted) - Generate(); - glEnable(GL_TEXTURE_2D); - if (active == this) - return; - glBindTexture(GL_TEXTURE_2D, tex); - if (expand) { - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glScaled(1 / (double) width, 1 / (double) height, 1); - glMatrixMode(GL_MODELVIEW); - } - - active = this; - - if (header == this) - return; - - if (prev) { - prev->next = next; - } - - if (next) { - next->prev = prev; - } - - if (footer = this) { - footer = prev; - } - - next = header; - prev = 0; - header->prev = this; - header = this; -} - -GLuint mogltk::texture::GetWidth() { - return width; -} - -GLuint mogltk::texture::GetHeight() { - return height; -} - -void mogltk::texture::Unbind(void) { - if (active) { - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); - active = 0; - } -} - -void mogltk::texture::Taint(void) { - if (taintable) - tainted = true; -} - -void mogltk::texture::Taintall(void) { - if (header) - header->recTaint(); -} - -void mogltk::texture::recTaint(void) { - Taint(); - if (next) - next->recTaint(); -} - -#ifdef WORDS_BIGENDIAN -#define NTEX_SIGNATURE 0x4e544558 -#else -#define NTEX_SIGNATURE 0x5845544e -#endif - -SDL_Surface * mogltk::texture::LoadNTEX(Handle * h) throw (GeneralException) { - SDL_Surface * r; - char buffer[5]; - Uint16 height, width; - - h->read(buffer, 4); - buffer[4] = 0; - if (*((Uint32 *) buffer) != NTEX_SIGNATURE) - throw GeneralException("Texture file " + h->GetName() + " corrupted"); - - height = h->readU16(); - width = h->readU16(); - - if (!(r = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - 0xff000000, - 0x00ff0000, - 0x0000ff00, - 0x000000ff -#else - 0x000000ff, - 0x0000ff00, - 0x00ff0000, - 0xff000000 -#endif - ))) { - throw GeneralException(_("Can't create RGB Surface for LoadNTEX")); - } - - h->read(r->pixels, height * width * 4); - - return r; -} - -void mogltk::texture::DumpBMP(const String & n) { - if (surface) - SDL_SaveBMP(surface, n.to_charp()); -} +/* + * mogltk + * Copyright (C) 1999-2004 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: texture.cc,v 1.11 2004-11-27 21:48:03 pixel Exp $ */ + +#include +#include +#include +#include +#include "texture.h" +#include "engine.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "gettext.h" + +#define DEBUG 1 + +mogltk::texture * mogltk::texture::header = 0; +mogltk::texture * mogltk::texture::footer = 0; + +mogltk::texture * mogltk::texture::active = 0; + +mogltk::texture::texture(int w, int h, bool plane) throw (GeneralException) : width(w), height(h), + texture_allocated(false), planar(plane), tainted(true), taintable(true) { + if ((!ISPOT(w)) || (!ISPOT(h))) + throw GeneralException(_("Size of the texture not a power of 2!")); + + if (!(surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + 0xff000000, + 0x00ff0000, + 0x0000ff00, + 0x000000ff +#else + 0x000000ff, + 0x0000ff00, + 0x00ff0000, + 0xff000000 +#endif + ))) { + throw GeneralException(_("Can't create RGB Surface")); + } + + SDL_FillRect(surface, 0, 0); + + next = 0; + prev = footer; + footer = this; + if (!header) { + header = this; + } + if (prev) { + prev->next = this; + } +} + +mogltk::texture::texture(Handle * h, bool plane) throw (GeneralException) : + texture_allocated(false), planar(plane), tainted(true), taintable(true) { + + SDL_Surface * temp; + + temp = LoadNTEX(h); + width = temp->w; + height = temp->h; + +#ifdef DEBUG + printm(M_INFO, "Creating texture from file: size %ix%i\n", height, width); +#endif + + if ((!ISPOT(width)) || (!ISPOT(height))) { + SDL_FreeSurface(temp); + throw GeneralException(_("Size of the texture not a power of 2!")); + } + + SDL_PixelFormat f; + + f.palette = 0; + f.BitsPerPixel = 32; + f.BytesPerPixel = 4; +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + f.Amask = 0x000000ff; + f.Bmask = 0x0000ff00; + f.Gmask = 0x00ff0000; + f.Rmask = 0xff000000; + f.Ashift = 0; + f.Bshift = 8; + f.Gshift = 16; + f.Rshift = 24; +#else + f.Rmask = 0x000000ff; + f.Gmask = 0x0000ff00; + f.Bmask = 0x00ff0000; + f.Amask = 0xff000000; + f.Rshift = 0; + f.Gshift = 8; + f.Bshift = 16; + f.Ashift = 24; +#endif + f.Rloss = 0; + f.Gloss = 0; + f.Bloss = 0; + f.Aloss = 0; + + if (!(surface = SDL_ConvertSurface(temp, &f, 0))) { + throw GeneralException("Could not convert texture to OpenGL format"); + } + + SDL_FreeSurface(temp); + + next = 0; + prev = footer; + footer = this; + if (!header) { + header = this; + } + if (prev) { + prev->next = this; + } +} + +inline static unsigned int nextpower(unsigned int n) { + unsigned int i; + + if (!n) + return n; + + if (ISPOT(n)) + return n; + + for (i = 31; i >= 0; i--) { + if ((n >> i) & 1) { + return 1 << (i + 1); + } + } +} + +mogltk::texture::texture(int x, int y, int w, int h) : width(nextpower(w)), height(nextpower(h)), + texture_allocated(true), planar(false), tainted(false), taintable(false) { + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, x, y, w, h); +} + +mogltk::texture::~texture() { + if (surface) { + SDL_FreeSurface(surface); + } + + if (texture_allocated) { + glDeleteTextures(1, &tex); + } + + if (prev) { + prev->next = next; + } + + if (next) { + next->prev = prev; + } + + if (this == footer) { + footer = prev; + } + + if (this == header) { + header = next; + } +} + +Uint32 * mogltk::texture::GetPixels() { + if (surface) + return (Uint32 *) surface->pixels; + else + return 0; +} + +SDL_Surface * mogltk::texture::GetSurface() { + return surface; +} + +SDL_PixelFormat * mogltk::texture::GetFormat() { + if (surface) + return surface->format; + else + return 0; +} + +void mogltk::texture::Generate() { + if (texture_allocated) { + glDeleteTextures(1, &tex); + } + + glGenTextures(1, &tex); +#ifdef DEBUG + printm(M_INFO, _("Generated texture index: %i\n"), tex); +#endif + + glBindTexture(GL_TEXTURE_2D, tex); + +#if 0 + if (planar) { +#ifdef DEBUG + printm(M_INFO, _("Generating planar texture: %i\n"), tex); +#endif + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels); + } else { +#endif +#ifdef DEBUG + printm(M_INFO, _("Generating 3D texture: %i\n"), tex); +#endif + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels); +// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels); +#if 0 + } +#endif + + texture_allocated = true; + tainted = false; +} + +void mogltk::texture::Bind(bool expand) { + if ((!texture_allocated) || tainted) + Generate(); + glEnable(GL_TEXTURE_2D); + if (active == this) + return; + glBindTexture(GL_TEXTURE_2D, tex); + if (expand) { + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glScaled(1 / (double) width, 1 / (double) height, 1); + glMatrixMode(GL_MODELVIEW); + } + + active = this; + + if (header == this) + return; + + if (prev) { + prev->next = next; + } + + if (next) { + next->prev = prev; + } + + if (footer = this) { + footer = prev; + } + + next = header; + prev = 0; + header->prev = this; + header = this; +} + +GLuint mogltk::texture::GetWidth() { + return width; +} + +GLuint mogltk::texture::GetHeight() { + return height; +} + +void mogltk::texture::Unbind(void) { + if (active) { + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + active = 0; + } +} + +void mogltk::texture::Taint(void) { + if (taintable) + tainted = true; +} + +void mogltk::texture::Taintall(void) { + if (header) + header->recTaint(); +} + +void mogltk::texture::recTaint(void) { + Taint(); + if (next) + next->recTaint(); +} + +#ifdef WORDS_BIGENDIAN +#define NTEX_SIGNATURE 0x4e544558 +#else +#define NTEX_SIGNATURE 0x5845544e +#endif + +SDL_Surface * mogltk::texture::LoadNTEX(Handle * h) throw (GeneralException) { + SDL_Surface * r; + char buffer[5]; + Uint16 height, width; + + h->read(buffer, 4); + buffer[4] = 0; + if (*((Uint32 *) buffer) != NTEX_SIGNATURE) + throw GeneralException("Texture file " + h->GetName() + " corrupted"); + + height = h->readU16(); + width = h->readU16(); + + if (!(r = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + 0xff000000, + 0x00ff0000, + 0x0000ff00, + 0x000000ff +#else + 0x000000ff, + 0x0000ff00, + 0x00ff0000, + 0xff000000 +#endif + ))) { + throw GeneralException(_("Can't create RGB Surface for LoadNTEX")); + } + + h->read(r->pixels, height * width * 4); + + return r; +} + +void mogltk::texture::DumpBMP(const String & n) { + if (surface) + SDL_SaveBMP(surface, n.to_charp()); +} diff --git a/lib/widgets.cc b/lib/widgets.cc index c70ad95..55c709c 100644 --- a/lib/widgets.cc +++ b/lib/widgets.cc @@ -1,1182 +1,1182 @@ -/* - * mogltk - * Copyright (C) 1999-2004 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: widgets.cc,v 1.9 2004-10-19 01:27:30 pixel Exp $ */ - -#include -#include -#include -#include "font.h" -#include "engine.h" -#include "widgets.h" -#include "sprite.h" - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gettext.h" - -mogltk::widget * dragged_widget = 0; - -std::vector out_move, out_click; -std::vector mogltk::widget::timed_events; - - -class widget_mouse_event : public mogltk::engine::mouseevent { - public: - widget_mouse_event(mogltk::widget *); - virtual void move(SDL_MouseMotionEvent); - virtual void action(SDL_MouseButtonEvent); - private: - mogltk::widget * root; - int mouse_x_down, mouse_y_down; - bool mouse_down, mouse_drag; - Uint32 old_click; -}; - -widget_mouse_event::widget_mouse_event(mogltk::widget * _root) : root(_root), mouse_down(false), mouse_drag(false) { -} - -void widget_mouse_event::move(SDL_MouseMotionEvent m) { - int mx, my; - bool out_threshold; - std::vector::iterator i; - std::vector out_move_stack; - - mx = mogltk::engine::mouseX(); - my = mogltk::engine::mouseY(); - - if (mouse_down) { - int dx, dy; - - dx = ABS(mouse_x_down - mx); - dy = ABS(mouse_y_down - my); - - out_threshold = (dx <= 1) && (dy <= 1); - } - - if (mouse_down && (out_threshold || mouse_drag)) { - if (!mouse_drag) { - printm(M_INFO, "mouse_start_drag\n"); - // generate a mouse_start_drag event - root->m_event(mouse_x_down, mouse_y_down, mogltk::E_MOUSE_START_DRAG); - } - if (dragged_widget) { - printm(M_INFO, "mouse_drag_over"); - // generate a mouse_drag_over event - dragged_widget->m_event(mx, my, mogltk::E_MOUSE_DRAG_OVER); - } - - printm(M_INFO, "mouse_drag\n"); - // generate a mouse_drag event - root->m_event(mx, my, mogltk::E_MOUSE_DRAG); - mouse_drag = true; - } else { - printm(M_INFO, "mouse_move\n"); - root->m_event(mx, my, mogltk::E_MOUSE_MOVE); - // generate a mouse_move event - } - - for (i = out_move.begin(); i != out_move.end(); i++) { - out_move_stack.push_back(*i); - } - - for (i = out_move_stack.begin(); i != out_move_stack.end(); i++) { - if (!(*i)->inside(mx, my)) { - (*i)->m_event(mx, my, mogltk::E_MOUSE_OUT); - // generate a mouse_out event - } - } - - out_move_stack.empty(); -} - -void widget_mouse_event::action(SDL_MouseButtonEvent b) { - int mx, my; - std::vector::iterator i; - std::vector out_click_stack; - - mx = mogltk::engine::mouseX(); - my = mogltk::engine::mouseY(); - - if (b.button == 1) { - if (b.state) { - mouse_x_down = mx; - mouse_y_down = my; - mouse_down = true; - printm(M_INFO, "mouse_down\n"); - root->m_event(mx, my, mogltk::E_MOUSE_DOWN); - // generate a mouse_down event; - for (i = out_click.begin(); i != out_click.end(); i++) { - out_click_stack.push_back(*i); - } - - for (i = out_click_stack.begin(); i != out_click_stack.end(); i++) { - if (!(*i)->inside(mx, my)) { - (*i)->m_event(mx, my, mogltk::E_MOUSE_OUT_CLICK); - // generate a mouse_out_click event - } - } - - out_click_stack.empty(); - - } else { - mouse_down = false; - if (mouse_drag) { - mouse_drag = false; - printm(M_INFO, "mouse_end_drag\n"); - root->m_event(mx, my, mogltk::E_MOUSE_END_DRAG); - // generate a mouse_end_drag event - if (dragged_widget) { - printm(M_INFO, "mouse_end_drag_over"); - dragged_widget->m_event(mx, my, mogltk::E_MOUSE_END_DRAG_OVER); - // generate a mouse_end_drag_over event - dragged_widget = 0; - } - } else { - printm(M_INFO, "mouse_click\n"); - root->m_event(mx, my, mogltk::E_MOUSE_CLICK); - // generate a mouse_click event - - for (i = out_click.begin(); i != out_click.end(); i++) { - out_click_stack.push_back(*i); - } - - for (i = out_click_stack.begin(); i != out_click_stack.end(); i++) { - if (!(*i)->inside(mx, my)) { - (*i)->m_event(mx, my, mogltk::E_MOUSE_OUT_CLICK); - // generate a mouse_out_click event - } - } - - out_click_stack.empty(); - - if ((SDL_GetTicks() - old_click) < 500) { - printm(M_INFO, "mouse_dbl_click\n"); - root->m_event(mx, my, mogltk::E_MOUSE_DBL_CLICK); - // generate a mouse_dbl_click event - } - - old_click = SDL_GetTicks(); - } - printm(M_INFO, "mouse_up\n"); - root->m_event(mx, my, mogltk::E_MOUSE_UP); - // generate a mouse_up event. - } - } -} - -mogltk::widget * mogltk::widget::focused = 0; - -mogltk::widget::widget(widget * _father, int _x, int _y, int _sx, int _sy, int _type, String _name, mogltk::shape * _sh) : - x(_x), y(_y), sx(_sx), sy(_sy), father(_father), prev(0), child(0), last(0), panel(0), type(_type), name(_name), sh(_sh), exclusive(0), visible(true), enabled(true) { - if (!father) { - root = this; - father = this; - next = 0; - x = 0; - y = 0; - sx = engine::base_o->GetWidth(); - sy = engine::base_o->GetHeight(); - } else { - next = father->child; - if (next) - next->prev = this; - if (!father->last) - father->last = this; - father->child = this; - root = father->root; - } - - computeabs(); -} - -mogltk::widget::~widget() { - while(child) - delete child; - - if (prev) - prev->next = next; - else - father->child = next; - - if (next) - next->prev = prev; - else - father->last = prev; -} - -void mogltk::widget::computeabs() { - if (father != this) { - ax = father->ax + x; - ay = father->ay + y; - } else { - ax = x; - ay = y; - } - ax2 = ax + sx; - ay2 = ay + sy; -} - -void mogltk::widget::move(int nx, int ny) { - x = nx; - y = ny; - - computeabs(); - - if (child) - child->icomputeabs(); -} - -void mogltk::widget::resize(int nsx, int nsy) { - sx = nsx; - sy = nsy; - - ax2 = ax + sx; - ay2 = ay + sy; - - if (child) - child->iresize_notify(); -} - -int mogltk::widget::GetX() { - return x; -} - -int mogltk::widget::GetY() { - return y; -} - -int mogltk::widget::GetH() { - return sy; -} - -int mogltk::widget::GetW() { - return sx; -} - -int mogltk::widget::GetAX() { - return ax; -} - -int mogltk::widget::GetAY() { - return ay; -} - -int mogltk::widget::GetAX2() { - return ax2; -} - -int mogltk::widget::GetAY2() { - return ay2; -} - -mogltk::rect mogltk::widget::GetDrawRect() { - rect r; - r.x = 0; - r.y = 0; - r.w = GetW(); - r.h = GetH(); - - return r; -} - -mogltk::widget * mogltk::widget::Father() { - return father; -} - -mogltk::widget * mogltk::widget::Child() { - return child; -} - -mogltk::widget * mogltk::widget::Next() { - return next; -} - -mogltk::widget * mogltk::widget::Prev() { - return prev; -} - -mogltk::widget * mogltk::widget::InnerPanel() { - if (!panel) - panel = create_panel(); - return panel; -} - -mogltk::widget * mogltk::widget::find_widget(int _x, int _y) { - widget * r = 0; - - if (visible && enabled && (_x >= ax) && (_y >= ay) && (_x <= ax2) && (_y <= ay2)) { - if (child) - r = child->find_widget(_x, _y); - if (!r) - r = this; - } - - if (!r && next) { - r = next->find_widget(_x, _y); - } - - return r; -} - -mogltk::shape * mogltk::widget::Shaper() { - return sh; -} - -void mogltk::widget::fulldraw() { - bool was2D = true; - - if (mogltk::engine::glbase_o) - if (!(was2D = mogltk::engine::glbase_o->is2D())) - mogltk::engine::glbase_o->Enter2DMode(); - - texture::Unbind(); - mogltk::ColorP::Max = WHITE; - mogltk::ColorP::Min = BLACK; - mogltk::ColorP::Min.A = 0; - - root->idraw(); - - if (!was2D) - mogltk::engine::glbase_o->Leave2DMode(); -} - -void mogltk::widget::idraw() { - int x1, y1, x2, y2; - - if (next) - next->idraw(); - - if (!visible) - return; - - x1 = MAX(GetAX(), father->GetAX()); - y1 = MAX(GetAY(), father->GetAY()); - - x2 = MIN(GetAX2(), father->GetAX2()); - y2 = MIN(GetAY2(), father->GetAY2()); - - engine::base_o->changeviewport(x1, y1, x2 - x1, y2 - y1); - - draw(); - - if (child) - child->idraw(); -} - -bool mogltk::widget::inside(int xe, int ye) { - if (!visible) - return false; - return !((xe < ax) || (xe > ax2) || (ye < ay) || (ye > ay2)); -} - -void mogltk::widget::m_event(int x, int y, mogltk::event_t event) { - switch (event) { - case E_MOUSE_DRAG_OVER: - case E_MOUSE_END_DRAG_OVER: - case E_MOUSE_OUT: - case E_MOUSE_OUT_CLICK: - process_event(x, y, event); - break; - default: - ievent(x, y, event); - } -} - -bool mogltk::widget::ievent(int xe, int ye, mogltk::event_t event) { - if (prev) - if (prev->ievent(xe, ye, event)) - return true; - - if (!inside(xe, ye)) - return false; - - if (exclusive) - return exclusive->ievent(xe, ye, event); - - if (last) - if (last->ievent(xe, ye, event)) - return true; - - if (!enabled || !visible) - return false; - - return process_event(xe, ye, event); -} - -void mogltk::widget::draw() { -} - -bool mogltk::widget::process_event(int, int, mogltk::event_t) { - return false; -} - -void mogltk::widget::resize_notify() { -} - -mogltk::widget * mogltk::widget::create_panel() { - mogltk::rect r = GetDrawRect(); - return new widgets::Panel(Shaper(), this, r.x, r.y, r.w, r.h); -} - -void mogltk::widget::icomputeabs() { - computeabs(); - - if (next) - next->computeabs(); - - if (child) - child->computeabs(); -} - -void mogltk::widget::iresize_notify() { - if (next) - next->iresize_notify(); - if (child) - child->iresize_notify(); - resize_notify(); -} - -void mogltk::widget::set_exclusive(mogltk::widget * w) { - w->exclusive = this; -} - -void mogltk::widget::unset_exclusive(mogltk::widget * w) { - w->exclusive = 0; -} - -bool mogltk::widget::GetVisible() { - return visible; -} - -void mogltk::widget::SetVisible(bool _visible) { - visible = _visible; -} - -bool mogltk::widget::GetEnabled() { - return enabled; -} - -void mogltk::widget::SetEnabled(bool _enabled) { - enabled = _enabled; -} - -void mogltk::widget::MoveOnTop() { - if (!prev) - return; - - if (!next) { - father->last = prev; - } else { - next->prev = prev; - } - prev->next = next; - prev = 0; - next = father->child; - - next->prev = this; - father->child = this; -} - -void mogltk::widget::check_timed_events() { - std::vector::iterator i; - Uint32 t = SDL_GetTicks(); - widget * w; - - for (i = timed_events.begin(); i != timed_events.end(); i++) { - if (i->t <= t) { - w = i->w; - timed_events.erase(i); - w->process_event(engine::mouseX(), engine::mouseY(), E_TIMER); - i = timed_events.begin(); - if (i == timed_events.end()) - return ; - } - } -} - -void mogltk::widget::add_out_move() { - std::vector::iterator i; - - for (i = out_move.begin(); i != out_move.end(); i++) { - if (*i == this) - return; - } - - out_move.push_back(this); -} - -void mogltk::widget::remove_out_move() { - std::vector::iterator i; - - for (i = out_move.begin(); i != out_move.end(); i++) { - if (*i == this) { - out_move.erase(i); - return; - } - } -} - -void mogltk::widget::add_out_click() { - std::vector::iterator i; - - for (i = out_click.begin(); i != out_click.end(); i++) { - if (*i == this) - return; - } - - out_click.push_back(this); -} - -void mogltk::widget::remove_out_click() { - std::vector::iterator i; - - for (i = out_click.begin(); i != out_click.end(); i++) { - if (*i == this) { - out_click.erase(i); - return; - } - } -} - -void mogltk::widget::set_timed_event(Uint32 t) { - timed_events.push_back(timed_event(this, SDL_GetTicks() + t)); -} - -void mogltk::widget::set_absolute_timed_event(Uint32 t) { - timed_events.push_back(timed_event(this, t)); -} - - -/* - * Predefined widgets. - */ - -/*************** -* Here is Root * -***************/ - -mogltk::widgets::Root::Root(mogltk::shape * sh, mogltk::widgets::drawer * _dr) : widget(0, 0, 0, 0, 0, 0, "Root", sh), dr(_dr) { - if (engine::root) - delete engine::root; - engine::root = this; -} - -void mogltk::widgets::Root::draw() { - if (dr) - dr->draw(this); - else - Shaper()->box(GetAX(), GetAY(), GetAX2(), GetAY2()); -} - -void mogltk::widgets::Root::setdrawer(drawer * _dr) { - dr = _dr; -} - - -/************************** -* A simple clipping Panel * -**************************/ - -mogltk::widgets::Panel::Panel(shape * sh, widget * father, int x, int y, int w, int h) : widget(father, x, y, w, h, 0, "Panel", sh) { -} - - -/*********************** -* The classical Button * -***********************/ - -mogltk::widgets::Button::Button(action * _a, shape * sh, widget * father, int x, int y, int w, int h, const String & _caption) : widget(father, x, y, w, h, 0, "Button", sh), bevel(false), dragging(false), a(_a) { - caption = _caption; -} - -void mogltk::widgets::Button::draw() { - Shaper()->button(GetAX() + 1, GetAY() + 1, GetAX2() - 1, GetAY2() - 1, caption, bevel); -} - -bool mogltk::widgets::Button::process_event(int xe, int ye, mogltk::event_t event) { - switch (event) { - case E_MOUSE_DOWN: - bevel = true; - return true; - case E_MOUSE_CLICK: - bevel = false; - // action here. - if (a) - a->do_action(this); - return true; - case E_MOUSE_START_DRAG: - dragged_widget = this; - dragging = true; - return true; - case E_MOUSE_DRAG_OVER: - bevel = inside(xe, ye); - return true; - case E_MOUSE_END_DRAG_OVER: - dragging = false; - if (bevel) - // action here. - if (a) - a->do_action(this); - bevel = false; - return true; - } - return false; -} - - -/********************** -* The SmartBox window * -**********************/ - -mogltk::widgets::SmartBox::SmartBox(shape * sh, mogltk::widget * father, int x, int y, int w, int h, const String & _caption) : widget(father, x, y, w, h, 0, "SmartBox", sh) { - caption = _caption; -} - -void mogltk::widgets::SmartBox::draw() { - Shaper()->window(GetAX(), GetAY(), GetAX2(), GetAY2(), caption); -} - -bool mogltk::widgets::SmartBox::process_event(int x, int y, mogltk::event_t event) { - switch (event) { - case E_MOUSE_START_DRAG: - if ((GetAY() + 20) > y) { - dragged_widget = this; - ox = x; - oy = y; - oax = GetX(); - oay = GetY(); - return true; - } - break; - case E_MOUSE_DRAG_OVER: - move(x - ox + oax, y - oy + oay); - MoveOnTop(); - return true; - } - return false; -} - -mogltk::rect mogltk::widgets::SmartBox::GetDrawRect() { - rect r; - - r.x = 2; - r.y = 21; - r.w = GetW() - 4; - r.h = GetH() - 23; - - return r; -} - - -/*********************** -* The MessageBox child * -***********************/ - -class MessageBoxAction : public mogltk::widgets::action { - public: - MessageBoxAction(mogltk::widget * _parent) : parent(_parent) { } - virtual void do_action(mogltk::widget *) { - delete parent; - delete this; - } - private: - mogltk::widget * parent; -}; - -mogltk::widgets::MsgBox::MsgBox(shape * sh, mogltk::widget * father, const String & caption, const String & text) : SmartBox(sh, father, 0, 0, 0, 0, caption) { - rect size = SystemFont->size(text); - rect lsize = size; - - size.w += 12; - size.h += 60; - - size.x = (father->GetW() - size.w) / 2; - size.y = (father->GetH() - size.h) / 2; - resize(size.w, size.h); - move(size.x, size.y); - - new Button(new MessageBoxAction(this), sh, this, size.w / 2 - 25, size.h - 30, 50, 24, "Ok"); - new Label(sh, this, 6, 24, lsize.w, lsize.h, text, BLACK); - - set_exclusive(father); -} - -mogltk::widgets::MsgBox::~MsgBox() { - unset_exclusive(Father()); -} - - -/***************** -* A simple Label * -*****************/ - -mogltk::widgets::Label::Label(shape * sh, mogltk::widget * father, int x, int y, int w, int h, const String & _caption, const ColorP & _color) : widget(father, x, y, w, h, 0, "Label", sh), color(_color) { - caption = _caption; -} - -void mogltk::widgets::Label::draw() { - Shaper()->text(GetAX(), GetAY(), caption, color); -} - - -/************************* -* The classical 3D Frame * -*************************/ - -mogltk::widgets::Frame::Frame(shape * sh, widget * father, int x, int y, int w, int h) : widget(father, x, y, w, h, 0, "Frame", sh) { -} - -void mogltk::widgets::Frame::draw() { - Shaper()->obox3d(GetAX(), GetAY(), GetAX2(), GetAY2()); -} - -mogltk::rect mogltk::widgets::Frame::GetDrawRect() { - rect r; - - r.x = 4; - r.y = 4; - r.w = GetW() - 8; - r.h = GetH() - 8; - - return r; -} - - -/*********************************** -* The huge and bloated ContextMenu * -***********************************/ - -mogltk::widgets::ContextMenu::node::node(const String & _caption, int _x, int _y, int _w, int _h, mogltk::widgets::action * _a, mogltk::widgets::ContextMenu * _sub, mogltk::widgets::ContextMenu * _father, bool _line) : caption(_caption), x(_x), y(_y), w(_w), h(_h), a(_a), sub(_sub), father(_father), line(_line), enabled(true) { -} - -String mogltk::widgets::ContextMenu::node::GetCaption() { - return caption; -} - -mogltk::widgets::action * mogltk::widgets::ContextMenu::node::GetAction() { - return a; -} - -mogltk::widgets::ContextMenu * mogltk::widgets::ContextMenu::node::GetFather() { - return father; -} - -mogltk::widgets::ContextMenu * mogltk::widgets::ContextMenu::node::GetSub() { - return sub; -} - -bool mogltk::widgets::ContextMenu::node::GetLine() { - return line; -} - -bool mogltk::widgets::ContextMenu::node::GetEnabled() { - return enabled; -} - -void mogltk::widgets::ContextMenu::node::SetEnabled(bool _enabled) { - enabled = _enabled; -} - -int mogltk::widgets::ContextMenu::node::GetX() { - return x; -} - -int mogltk::widgets::ContextMenu::node::GetY() { - return y; -} - -int mogltk::widgets::ContextMenu::node::GetW() { - return w; -} - -int mogltk::widgets::ContextMenu::node::GetH() { - return h; -} - -mogltk::widgets::ContextMenu::ContextMenu(shape * sh, mogltk::widget * father, int x, int y) : widget(father, x, y, 8, 4, 1, "ContextMenu", sh), selected(-1), subselected(0), in_click(false), sticky(false) { -} - -mogltk::widgets::ContextMenu::~ContextMenu() { - std::vector::iterator i; - ContextMenu * sub; - - for (i = nodes.begin(); i != nodes.end(); i++) { - if ((sub = i->GetSub())) - delete sub; - } -} - -void mogltk::widgets::ContextMenu::addnode(const String & caption, mogltk::widgets::action * a) { - rect size; - - size = SystemFont->size(caption); - nodes.push_back(node(caption, 4, GetH() - 2, size.w, size.h, a, 0, this, false)); - size.w += 8; - if (GetW() > size.w) - size.w = GetW(); - resize(size.w, GetH() + size.h); -} - -void mogltk::widgets::ContextMenu::addsub(const String & caption, mogltk::widgets::ContextMenu * sub) { - rect size; - - size = SystemFont->size(caption + " >"); - nodes.push_back(node(caption + " >", 4, GetH() - 2, size.w, size.h, 0, sub, this, false)); - size.w += 8; - if (GetW() > size.w) - size.w = GetW(); - resize(size.w, GetH() + size.h); -} - -void mogltk::widgets::ContextMenu::addline() { - nodes.push_back(node("", 2, GetH() - 1, 0, 0, 0, 0, this, true)); - resize(GetW(), GetH() + 4); -} - -mogltk::widgets::ContextMenu * mogltk::widgets::ContextMenu::createsub(const String & caption) { - ContextMenu * r; - - r = new ContextMenu(Shaper(), Father(), GetX() + GetW(), GetY() + GetH()); - r->SetVisible(false); - - addsub(caption, r); - - return r; -} - -void mogltk::widgets::ContextMenu::move(int x, int y) { - int dx, dy; - std::vector::iterator i; - ContextMenu * sub; - - dx = x - GetX(); - dy = y - GetY(); - widget::move(x, y); - - for (i = nodes.begin(); i != nodes.end(); i++) { - if ((sub = i->GetSub())) - sub->move(sub->GetX() + dx, sub->GetY() + dy); - } -} - -void mogltk::widgets::ContextMenu::resize(int w, int h) { - int dw; - std::vector::iterator i; - ContextMenu * sub; - - dw = w - GetW(); - widget::resize(w, h); - - for (i = nodes.begin(); i != nodes.end(); i++) { - if ((sub = i->GetSub())) - sub->move(sub->GetX() + dw, sub->GetY()); - } -} - -void mogltk::widgets::ContextMenu::SetVisible(bool visible) { - if (!visible && sticky) - return; - widget::SetVisible(visible); - if (!visible && subselected) { - subselected->SetVisible(false); - } - - if (visible) { - add_out_click(); - MoveOnTop(); - } -} - -void mogltk::widgets::ContextMenu::SetEnabled(int i, bool e) { - nodes[i].SetEnabled(e); -} - -void mogltk::widgets::ContextMenu::StickyDisplay() { - sticky = true; - SetVisible(true); -} - -void mogltk::widgets::ContextMenu::draw() { - std::vector::iterator i; - int n; - rect size; - - Shaper()->box3d(GetAX(), GetAY(), GetAX2(), GetAY2()); - - for (i = nodes.begin(), n = 0; i != nodes.end(); i++, n++) { - size = SystemFont->size(i->GetCaption()); - if (i->GetLine()) { - Shaper()->hline3d(GetAX() + i->GetX(), GetAX() + i->GetX() + GetW() - 4, GetAY() + i->GetY()); - } else { - if (n == selected) { - Shaper()->box(GetAX() + 2, GetAY() + i->GetY(), GetAX() + GetW() - 2, GetAY() + i->GetY() + i->GetH(), DOS_MAGENTA); - } - Shaper()->text(GetAX() + i->GetX(), GetAY() + i->GetY(), i->GetCaption(), i->GetEnabled() ? BLACK : DOS_GRAY); - } - } -} - -bool mogltk::widgets::ContextMenu::process_event(int xe, int ye, mogltk::event_t event) { - std::vector::iterator i; - action * a; - int n; - - switch (event) { - case E_MOUSE_MOVE: - sticky = false; - selected = -1; - for (i = nodes.begin(), n = 0; i != nodes.end(); i++, n++) { - if (!i->GetLine()) { - int ax, ax2, ay, ay2; - - ax = GetAX() + 2; - ay = GetAY() + i->GetY(); - ax2 = GetAX() + GetW() - 2; - ay2 = GetAY() + i->GetY() + i->GetH(); - - if (!((xe < ax) || (xe > ax2) || (ye < ay) || (ye > ay2))) { - selected = n; - if (subselected) { - subselected->SetVisible(false); - subselected->selected = -1; - subselected->subselected = 0; - } - if ((subselected = i->GetSub())) { - subselected->SetVisible(true); - subselected->selected = -1; - subselected->subselected = 0; - } - } - } - } - add_out_move(); - return true; - case E_MOUSE_CLICK: - a = 0; - if (selected != -1) { - if ((a = nodes[selected].GetAction()) && nodes[selected].GetEnabled()) { - a->do_action(this); - in_click = false; - SetVisible(false); - return true; - } - } - in_click = true; - break; - case E_MOUSE_DOWN: - in_click = true; - break; - case E_MOUSE_OUT: - selected = -1; - remove_out_move(); - in_click = false; - return true; - case E_MOUSE_OUT_CLICK: - if (iin_click()) - return true; - selected = -1; - subselected = 0; - SetVisible(false); - return true; - } - - return false; -} - -bool mogltk::widgets::ContextMenu::iin_click() { - if (in_click) - return true; - - if (subselected) - return subselected->iin_click(); - - return false; -} - - -/******************** -* The Menu topframe * -********************/ - -mogltk::widgets::Menu::node::node(const String & _caption, mogltk::widgets::ContextMenu * _sub, mogltk::widgets::action * _a, int _x) : caption(_caption), sub(_sub), a(_a), x(_x) { -} - -String mogltk::widgets::Menu::node::GetCaption() { - return caption; -} - -void mogltk::widgets::Menu::node::SetCaption(const String & s) { - caption = s; -} - -mogltk::widgets::ContextMenu * mogltk::widgets::Menu::node::GetSub() { - return sub; -} - -mogltk::widgets::action * mogltk::widgets::Menu::node::GetAction() { - return a; -} - -int mogltk::widgets::Menu::node::GetX() { - return x; -} - -bool mogltk::widgets::Menu::node::GetEnabled() { - return enabled; -} - -void mogltk::widgets::Menu::node::SetEnabled(bool _enabled) { - enabled = _enabled; -} - -mogltk::widgets::Menu::Menu(shape * sh, mogltk::widget * father) : widget(father, 0, 0, 0, 0, 0, "Menu", sh), cur_x(0), selected(-1) { - rect r = father->GetDrawRect(); - move(r.x, r.y); - resize(r.w, 16); -} - -void mogltk::widgets::Menu::resize_notify() { - rect r = Father()->GetDrawRect(); - resize(r.w, 16); -} - -void mogltk::widgets::Menu::addnode(const String & caption, mogltk::widgets::action * a) { - nodes.push_back(node(caption, 0, a, cur_x)); - cur_x += SystemFont->singletextsize(caption) + 6; -} - -void mogltk::widgets::Menu::addsub(const String & caption, mogltk::widgets::ContextMenu * sub) { - nodes.push_back(node(caption, sub, 0, cur_x)); - cur_x += SystemFont->singletextsize(caption) + 6; -} - -mogltk::widgets::ContextMenu * mogltk::widgets::Menu::createsub(const String & caption) { - ContextMenu * r = new ContextMenu(Shaper(), Father(), GetX() + cur_x, GetY() + 16); - addsub(caption, r); - r->SetVisible(false); - return r; -} - -void mogltk::widgets::Menu::SetEnabled(int i, bool e) { - nodes[i].SetEnabled(e); -} - -void mogltk::widgets::Menu::SetCaption(int i, const String & s) { - nodes[i].SetCaption(s); -} - -void mogltk::widgets::Menu::draw(void) { - std::vector::iterator i; - int n; - - Shaper()->box(GetAX(), GetAY(), GetAX2(), GetAY2(), DOS_WHITE); - - for (i = nodes.begin(), n = 0; i != nodes.end(); i++, n++) { - if (selected == n) { - if ((i + 1) == nodes.end()) { - Shaper()->box(GetAX() + i->GetX(), GetAY(), cur_x, GetAY2(), DOS_MAGENTA); - } else { - Shaper()->box(GetAX() + i->GetX(), GetAY(), GetAX() + i[1].GetX(), GetAY2(), DOS_MAGENTA); - } - } - Shaper()->text(GetAX() + i->GetX() + 3, GetAY(), i->GetCaption(), BLACK); - } -} - -bool mogltk::widgets::Menu::process_event(int mx, int my, mogltk::event_t event) { - std::vector::iterator i; - action * a; - ContextMenu * sub; - int n; - - switch (event) { - case E_MOUSE_MOVE: - selected = -1; - for (i = nodes.begin(), n = 0; i != nodes.end(); i++, n++) { - int ax, ax2, ay, ay2; - - ax = GetAX() + i->GetX(); - ay = GetAY(); - if ((i + 1) != nodes.end()) { - ax2 = GetAX() + i[1].GetX(); - } else { - ax2 = GetAX() + cur_x; - } - ay2 = GetAY2(); - - if (!((mx < ax) || (mx > ax2) || (my < ay) || (my > ay2))) { - selected = n; - } - } - add_out_move(); - return true; - case E_MOUSE_CLICK: - a = 0; - if (selected != -1) { - if ((a = nodes[selected].GetAction()) && nodes[selected].GetEnabled()) { - a->do_action(this); - return true; - } else if ((sub = nodes[selected].GetSub()) && nodes[selected].GetEnabled()) { - sub->StickyDisplay(); - return true; - } - } - break; - case E_MOUSE_OUT: - selected = -1; - remove_out_move(); - return true; - } - return false; -} - - -/* - * The mainloop widget thing. - */ - -void mogltk::widget::mainloop() { - bool end_event_loop = false; - widget_mouse_event * mouse = new widget_mouse_event(this); - widget * w; - int mx, my; - - while (!end_event_loop && !engine::quitrequested()) { - root->fulldraw(); - mx = mogltk::engine::mouseX(); - my = mogltk::engine::mouseY(); - - mogltk::ColorP::Max.A = 50; - Sprite::Cursor->draw(mx - 6, my - 3, BLACK); - mogltk::ColorP::Max.A = 255; - Sprite::Cursor->draw(mx - 8, my - 6); - - if (w = root->find_widget(mx, my)) { - sh->box(w->GetAX(), w->GetAY(), w->GetAX2(), w->GetAY2(), Color(100, 150, 60, 50)); - } - - engine::base_o->Flip(); - widget::check_timed_events(); - } - - delete mouse; -} +/* + * mogltk + * Copyright (C) 1999-2004 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: widgets.cc,v 1.10 2004-11-27 21:48:03 pixel Exp $ */ + +#include +#include +#include +#include "font.h" +#include "engine.h" +#include "widgets.h" +#include "sprite.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gettext.h" + +mogltk::widget * dragged_widget = 0; + +std::vector out_move, out_click; +std::vector mogltk::widget::timed_events; + + +class widget_mouse_event : public mogltk::engine::mouseevent { + public: + widget_mouse_event(mogltk::widget *); + virtual void move(SDL_MouseMotionEvent); + virtual void action(SDL_MouseButtonEvent); + private: + mogltk::widget * root; + int mouse_x_down, mouse_y_down; + bool mouse_down, mouse_drag; + Uint32 old_click; +}; + +widget_mouse_event::widget_mouse_event(mogltk::widget * _root) : root(_root), mouse_down(false), mouse_drag(false) { +} + +void widget_mouse_event::move(SDL_MouseMotionEvent m) { + int mx, my; + bool out_threshold; + std::vector::iterator i; + std::vector out_move_stack; + + mx = mogltk::engine::mouseX(); + my = mogltk::engine::mouseY(); + + if (mouse_down) { + int dx, dy; + + dx = ABS(mouse_x_down - mx); + dy = ABS(mouse_y_down - my); + + out_threshold = (dx <= 1) && (dy <= 1); + } + + if (mouse_down && (out_threshold || mouse_drag)) { + if (!mouse_drag) { + printm(M_INFO, "mouse_start_drag\n"); + // generate a mouse_start_drag event + root->m_event(mouse_x_down, mouse_y_down, mogltk::E_MOUSE_START_DRAG); + } + if (dragged_widget) { + printm(M_INFO, "mouse_drag_over"); + // generate a mouse_drag_over event + dragged_widget->m_event(mx, my, mogltk::E_MOUSE_DRAG_OVER); + } + + printm(M_INFO, "mouse_drag\n"); + // generate a mouse_drag event + root->m_event(mx, my, mogltk::E_MOUSE_DRAG); + mouse_drag = true; + } else { + printm(M_INFO, "mouse_move\n"); + root->m_event(mx, my, mogltk::E_MOUSE_MOVE); + // generate a mouse_move event + } + + for (i = out_move.begin(); i != out_move.end(); i++) { + out_move_stack.push_back(*i); + } + + for (i = out_move_stack.begin(); i != out_move_stack.end(); i++) { + if (!(*i)->inside(mx, my)) { + (*i)->m_event(mx, my, mogltk::E_MOUSE_OUT); + // generate a mouse_out event + } + } + + out_move_stack.empty(); +} + +void widget_mouse_event::action(SDL_MouseButtonEvent b) { + int mx, my; + std::vector::iterator i; + std::vector out_click_stack; + + mx = mogltk::engine::mouseX(); + my = mogltk::engine::mouseY(); + + if (b.button == 1) { + if (b.state) { + mouse_x_down = mx; + mouse_y_down = my; + mouse_down = true; + printm(M_INFO, "mouse_down\n"); + root->m_event(mx, my, mogltk::E_MOUSE_DOWN); + // generate a mouse_down event; + for (i = out_click.begin(); i != out_click.end(); i++) { + out_click_stack.push_back(*i); + } + + for (i = out_click_stack.begin(); i != out_click_stack.end(); i++) { + if (!(*i)->inside(mx, my)) { + (*i)->m_event(mx, my, mogltk::E_MOUSE_OUT_CLICK); + // generate a mouse_out_click event + } + } + + out_click_stack.empty(); + + } else { + mouse_down = false; + if (mouse_drag) { + mouse_drag = false; + printm(M_INFO, "mouse_end_drag\n"); + root->m_event(mx, my, mogltk::E_MOUSE_END_DRAG); + // generate a mouse_end_drag event + if (dragged_widget) { + printm(M_INFO, "mouse_end_drag_over"); + dragged_widget->m_event(mx, my, mogltk::E_MOUSE_END_DRAG_OVER); + // generate a mouse_end_drag_over event + dragged_widget = 0; + } + } else { + printm(M_INFO, "mouse_click\n"); + root->m_event(mx, my, mogltk::E_MOUSE_CLICK); + // generate a mouse_click event + + for (i = out_click.begin(); i != out_click.end(); i++) { + out_click_stack.push_back(*i); + } + + for (i = out_click_stack.begin(); i != out_click_stack.end(); i++) { + if (!(*i)->inside(mx, my)) { + (*i)->m_event(mx, my, mogltk::E_MOUSE_OUT_CLICK); + // generate a mouse_out_click event + } + } + + out_click_stack.empty(); + + if ((SDL_GetTicks() - old_click) < 500) { + printm(M_INFO, "mouse_dbl_click\n"); + root->m_event(mx, my, mogltk::E_MOUSE_DBL_CLICK); + // generate a mouse_dbl_click event + } + + old_click = SDL_GetTicks(); + } + printm(M_INFO, "mouse_up\n"); + root->m_event(mx, my, mogltk::E_MOUSE_UP); + // generate a mouse_up event. + } + } +} + +mogltk::widget * mogltk::widget::focused = 0; + +mogltk::widget::widget(widget * _father, int _x, int _y, int _sx, int _sy, int _type, String _name, mogltk::shape * _sh) : + x(_x), y(_y), sx(_sx), sy(_sy), father(_father), prev(0), child(0), last(0), panel(0), type(_type), name(_name), sh(_sh), exclusive(0), visible(true), enabled(true) { + if (!father) { + root = this; + father = this; + next = 0; + x = 0; + y = 0; + sx = engine::base_o->GetWidth(); + sy = engine::base_o->GetHeight(); + } else { + next = father->child; + if (next) + next->prev = this; + if (!father->last) + father->last = this; + father->child = this; + root = father->root; + } + + computeabs(); +} + +mogltk::widget::~widget() { + while(child) + delete child; + + if (prev) + prev->next = next; + else + father->child = next; + + if (next) + next->prev = prev; + else + father->last = prev; +} + +void mogltk::widget::computeabs() { + if (father != this) { + ax = father->ax + x; + ay = father->ay + y; + } else { + ax = x; + ay = y; + } + ax2 = ax + sx; + ay2 = ay + sy; +} + +void mogltk::widget::move(int nx, int ny) { + x = nx; + y = ny; + + computeabs(); + + if (child) + child->icomputeabs(); +} + +void mogltk::widget::resize(int nsx, int nsy) { + sx = nsx; + sy = nsy; + + ax2 = ax + sx; + ay2 = ay + sy; + + if (child) + child->iresize_notify(); +} + +int mogltk::widget::GetX() { + return x; +} + +int mogltk::widget::GetY() { + return y; +} + +int mogltk::widget::GetH() { + return sy; +} + +int mogltk::widget::GetW() { + return sx; +} + +int mogltk::widget::GetAX() { + return ax; +} + +int mogltk::widget::GetAY() { + return ay; +} + +int mogltk::widget::GetAX2() { + return ax2; +} + +int mogltk::widget::GetAY2() { + return ay2; +} + +mogltk::rect mogltk::widget::GetDrawRect() { + rect r; + r.x = 0; + r.y = 0; + r.w = GetW(); + r.h = GetH(); + + return r; +} + +mogltk::widget * mogltk::widget::Father() { + return father; +} + +mogltk::widget * mogltk::widget::Child() { + return child; +} + +mogltk::widget * mogltk::widget::Next() { + return next; +} + +mogltk::widget * mogltk::widget::Prev() { + return prev; +} + +mogltk::widget * mogltk::widget::InnerPanel() { + if (!panel) + panel = create_panel(); + return panel; +} + +mogltk::widget * mogltk::widget::find_widget(int _x, int _y) { + widget * r = 0; + + if (visible && enabled && (_x >= ax) && (_y >= ay) && (_x <= ax2) && (_y <= ay2)) { + if (child) + r = child->find_widget(_x, _y); + if (!r) + r = this; + } + + if (!r && next) { + r = next->find_widget(_x, _y); + } + + return r; +} + +mogltk::shape * mogltk::widget::Shaper() { + return sh; +} + +void mogltk::widget::fulldraw() { + bool was2D = true; + + if (mogltk::engine::glbase_o) + if (!(was2D = mogltk::engine::glbase_o->is2D())) + mogltk::engine::glbase_o->Enter2DMode(); + + texture::Unbind(); + mogltk::ColorP::Max = WHITE; + mogltk::ColorP::Min = BLACK; + mogltk::ColorP::Min.A = 0; + + root->idraw(); + + if (!was2D) + mogltk::engine::glbase_o->Leave2DMode(); +} + +void mogltk::widget::idraw() { + int x1, y1, x2, y2; + + if (next) + next->idraw(); + + if (!visible) + return; + + x1 = MAX(GetAX(), father->GetAX()); + y1 = MAX(GetAY(), father->GetAY()); + + x2 = MIN(GetAX2(), father->GetAX2()); + y2 = MIN(GetAY2(), father->GetAY2()); + + engine::base_o->changeviewport(x1, y1, x2 - x1, y2 - y1); + + draw(); + + if (child) + child->idraw(); +} + +bool mogltk::widget::inside(int xe, int ye) { + if (!visible) + return false; + return !((xe < ax) || (xe > ax2) || (ye < ay) || (ye > ay2)); +} + +void mogltk::widget::m_event(int x, int y, mogltk::event_t event) { + switch (event) { + case E_MOUSE_DRAG_OVER: + case E_MOUSE_END_DRAG_OVER: + case E_MOUSE_OUT: + case E_MOUSE_OUT_CLICK: + process_event(x, y, event); + break; + default: + ievent(x, y, event); + } +} + +bool mogltk::widget::ievent(int xe, int ye, mogltk::event_t event) { + if (prev) + if (prev->ievent(xe, ye, event)) + return true; + + if (!inside(xe, ye)) + return false; + + if (exclusive) + return exclusive->ievent(xe, ye, event); + + if (last) + if (last->ievent(xe, ye, event)) + return true; + + if (!enabled || !visible) + return false; + + return process_event(xe, ye, event); +} + +void mogltk::widget::draw() { +} + +bool mogltk::widget::process_event(int, int, mogltk::event_t) { + return false; +} + +void mogltk::widget::resize_notify() { +} + +mogltk::widget * mogltk::widget::create_panel() { + mogltk::rect r = GetDrawRect(); + return new widgets::Panel(Shaper(), this, r.x, r.y, r.w, r.h); +} + +void mogltk::widget::icomputeabs() { + computeabs(); + + if (next) + next->computeabs(); + + if (child) + child->computeabs(); +} + +void mogltk::widget::iresize_notify() { + if (next) + next->iresize_notify(); + if (child) + child->iresize_notify(); + resize_notify(); +} + +void mogltk::widget::set_exclusive(mogltk::widget * w) { + w->exclusive = this; +} + +void mogltk::widget::unset_exclusive(mogltk::widget * w) { + w->exclusive = 0; +} + +bool mogltk::widget::GetVisible() { + return visible; +} + +void mogltk::widget::SetVisible(bool _visible) { + visible = _visible; +} + +bool mogltk::widget::GetEnabled() { + return enabled; +} + +void mogltk::widget::SetEnabled(bool _enabled) { + enabled = _enabled; +} + +void mogltk::widget::MoveOnTop() { + if (!prev) + return; + + if (!next) { + father->last = prev; + } else { + next->prev = prev; + } + prev->next = next; + prev = 0; + next = father->child; + + next->prev = this; + father->child = this; +} + +void mogltk::widget::check_timed_events() { + std::vector::iterator i; + Uint32 t = SDL_GetTicks(); + widget * w; + + for (i = timed_events.begin(); i != timed_events.end(); i++) { + if (i->t <= t) { + w = i->w; + timed_events.erase(i); + w->process_event(engine::mouseX(), engine::mouseY(), E_TIMER); + i = timed_events.begin(); + if (i == timed_events.end()) + return ; + } + } +} + +void mogltk::widget::add_out_move() { + std::vector::iterator i; + + for (i = out_move.begin(); i != out_move.end(); i++) { + if (*i == this) + return; + } + + out_move.push_back(this); +} + +void mogltk::widget::remove_out_move() { + std::vector::iterator i; + + for (i = out_move.begin(); i != out_move.end(); i++) { + if (*i == this) { + out_move.erase(i); + return; + } + } +} + +void mogltk::widget::add_out_click() { + std::vector::iterator i; + + for (i = out_click.begin(); i != out_click.end(); i++) { + if (*i == this) + return; + } + + out_click.push_back(this); +} + +void mogltk::widget::remove_out_click() { + std::vector::iterator i; + + for (i = out_click.begin(); i != out_click.end(); i++) { + if (*i == this) { + out_click.erase(i); + return; + } + } +} + +void mogltk::widget::set_timed_event(Uint32 t) { + timed_events.push_back(timed_event(this, SDL_GetTicks() + t)); +} + +void mogltk::widget::set_absolute_timed_event(Uint32 t) { + timed_events.push_back(timed_event(this, t)); +} + + +/* + * Predefined widgets. + */ + +/*************** +* Here is Root * +***************/ + +mogltk::widgets::Root::Root(mogltk::shape * sh, mogltk::widgets::drawer * _dr) : widget(0, 0, 0, 0, 0, 0, "Root", sh), dr(_dr) { + if (engine::root) + delete engine::root; + engine::root = this; +} + +void mogltk::widgets::Root::draw() { + if (dr) + dr->draw(this); + else + Shaper()->box(GetAX(), GetAY(), GetAX2(), GetAY2()); +} + +void mogltk::widgets::Root::setdrawer(drawer * _dr) { + dr = _dr; +} + + +/************************** +* A simple clipping Panel * +**************************/ + +mogltk::widgets::Panel::Panel(shape * sh, widget * father, int x, int y, int w, int h) : widget(father, x, y, w, h, 0, "Panel", sh) { +} + + +/*********************** +* The classical Button * +***********************/ + +mogltk::widgets::Button::Button(action * _a, shape * sh, widget * father, int x, int y, int w, int h, const String & _caption) : widget(father, x, y, w, h, 0, "Button", sh), bevel(false), dragging(false), a(_a) { + caption = _caption; +} + +void mogltk::widgets::Button::draw() { + Shaper()->button(GetAX() + 1, GetAY() + 1, GetAX2() - 1, GetAY2() - 1, caption, bevel); +} + +bool mogltk::widgets::Button::process_event(int xe, int ye, mogltk::event_t event) { + switch (event) { + case E_MOUSE_DOWN: + bevel = true; + return true; + case E_MOUSE_CLICK: + bevel = false; + // action here. + if (a) + a->do_action(this); + return true; + case E_MOUSE_START_DRAG: + dragged_widget = this; + dragging = true; + return true; + case E_MOUSE_DRAG_OVER: + bevel = inside(xe, ye); + return true; + case E_MOUSE_END_DRAG_OVER: + dragging = false; + if (bevel) + // action here. + if (a) + a->do_action(this); + bevel = false; + return true; + } + return false; +} + + +/********************** +* The SmartBox window * +**********************/ + +mogltk::widgets::SmartBox::SmartBox(shape * sh, mogltk::widget * father, int x, int y, int w, int h, const String & _caption) : widget(father, x, y, w, h, 0, "SmartBox", sh) { + caption = _caption; +} + +void mogltk::widgets::SmartBox::draw() { + Shaper()->window(GetAX(), GetAY(), GetAX2(), GetAY2(), caption); +} + +bool mogltk::widgets::SmartBox::process_event(int x, int y, mogltk::event_t event) { + switch (event) { + case E_MOUSE_START_DRAG: + if ((GetAY() + 20) > y) { + dragged_widget = this; + ox = x; + oy = y; + oax = GetX(); + oay = GetY(); + return true; + } + break; + case E_MOUSE_DRAG_OVER: + move(x - ox + oax, y - oy + oay); + MoveOnTop(); + return true; + } + return false; +} + +mogltk::rect mogltk::widgets::SmartBox::GetDrawRect() { + rect r; + + r.x = 2; + r.y = 21; + r.w = GetW() - 4; + r.h = GetH() - 23; + + return r; +} + + +/*********************** +* The MessageBox child * +***********************/ + +class MessageBoxAction : public mogltk::widgets::action { + public: + MessageBoxAction(mogltk::widget * _parent) : parent(_parent) { } + virtual void do_action(mogltk::widget *) { + delete parent; + delete this; + } + private: + mogltk::widget * parent; +}; + +mogltk::widgets::MsgBox::MsgBox(shape * sh, mogltk::widget * father, const String & caption, const String & text) : SmartBox(sh, father, 0, 0, 0, 0, caption) { + rect size = SystemFont->size(text); + rect lsize = size; + + size.w += 12; + size.h += 60; + + size.x = (father->GetW() - size.w) / 2; + size.y = (father->GetH() - size.h) / 2; + resize(size.w, size.h); + move(size.x, size.y); + + new Button(new MessageBoxAction(this), sh, this, size.w / 2 - 25, size.h - 30, 50, 24, "Ok"); + new Label(sh, this, 6, 24, lsize.w, lsize.h, text, BLACK); + + set_exclusive(father); +} + +mogltk::widgets::MsgBox::~MsgBox() { + unset_exclusive(Father()); +} + + +/***************** +* A simple Label * +*****************/ + +mogltk::widgets::Label::Label(shape * sh, mogltk::widget * father, int x, int y, int w, int h, const String & _caption, const ColorP & _color) : widget(father, x, y, w, h, 0, "Label", sh), color(_color) { + caption = _caption; +} + +void mogltk::widgets::Label::draw() { + Shaper()->text(GetAX(), GetAY(), caption, color); +} + + +/************************* +* The classical 3D Frame * +*************************/ + +mogltk::widgets::Frame::Frame(shape * sh, widget * father, int x, int y, int w, int h) : widget(father, x, y, w, h, 0, "Frame", sh) { +} + +void mogltk::widgets::Frame::draw() { + Shaper()->obox3d(GetAX(), GetAY(), GetAX2(), GetAY2()); +} + +mogltk::rect mogltk::widgets::Frame::GetDrawRect() { + rect r; + + r.x = 4; + r.y = 4; + r.w = GetW() - 8; + r.h = GetH() - 8; + + return r; +} + + +/*********************************** +* The huge and bloated ContextMenu * +***********************************/ + +mogltk::widgets::ContextMenu::node::node(const String & _caption, int _x, int _y, int _w, int _h, mogltk::widgets::action * _a, mogltk::widgets::ContextMenu * _sub, mogltk::widgets::ContextMenu * _father, bool _line) : caption(_caption), x(_x), y(_y), w(_w), h(_h), a(_a), sub(_sub), father(_father), line(_line), enabled(true) { +} + +String mogltk::widgets::ContextMenu::node::GetCaption() { + return caption; +} + +mogltk::widgets::action * mogltk::widgets::ContextMenu::node::GetAction() { + return a; +} + +mogltk::widgets::ContextMenu * mogltk::widgets::ContextMenu::node::GetFather() { + return father; +} + +mogltk::widgets::ContextMenu * mogltk::widgets::ContextMenu::node::GetSub() { + return sub; +} + +bool mogltk::widgets::ContextMenu::node::GetLine() { + return line; +} + +bool mogltk::widgets::ContextMenu::node::GetEnabled() { + return enabled; +} + +void mogltk::widgets::ContextMenu::node::SetEnabled(bool _enabled) { + enabled = _enabled; +} + +int mogltk::widgets::ContextMenu::node::GetX() { + return x; +} + +int mogltk::widgets::ContextMenu::node::GetY() { + return y; +} + +int mogltk::widgets::ContextMenu::node::GetW() { + return w; +} + +int mogltk::widgets::ContextMenu::node::GetH() { + return h; +} + +mogltk::widgets::ContextMenu::ContextMenu(shape * sh, mogltk::widget * father, int x, int y) : widget(father, x, y, 8, 4, 1, "ContextMenu", sh), selected(-1), subselected(0), in_click(false), sticky(false) { +} + +mogltk::widgets::ContextMenu::~ContextMenu() { + std::vector::iterator i; + ContextMenu * sub; + + for (i = nodes.begin(); i != nodes.end(); i++) { + if ((sub = i->GetSub())) + delete sub; + } +} + +void mogltk::widgets::ContextMenu::addnode(const String & caption, mogltk::widgets::action * a) { + rect size; + + size = SystemFont->size(caption); + nodes.push_back(node(caption, 4, GetH() - 2, size.w, size.h, a, 0, this, false)); + size.w += 8; + if (GetW() > size.w) + size.w = GetW(); + resize(size.w, GetH() + size.h); +} + +void mogltk::widgets::ContextMenu::addsub(const String & caption, mogltk::widgets::ContextMenu * sub) { + rect size; + + size = SystemFont->size(caption + " >"); + nodes.push_back(node(caption + " >", 4, GetH() - 2, size.w, size.h, 0, sub, this, false)); + size.w += 8; + if (GetW() > size.w) + size.w = GetW(); + resize(size.w, GetH() + size.h); +} + +void mogltk::widgets::ContextMenu::addline() { + nodes.push_back(node("", 2, GetH() - 1, 0, 0, 0, 0, this, true)); + resize(GetW(), GetH() + 4); +} + +mogltk::widgets::ContextMenu * mogltk::widgets::ContextMenu::createsub(const String & caption) { + ContextMenu * r; + + r = new ContextMenu(Shaper(), Father(), GetX() + GetW(), GetY() + GetH()); + r->SetVisible(false); + + addsub(caption, r); + + return r; +} + +void mogltk::widgets::ContextMenu::move(int x, int y) { + int dx, dy; + std::vector::iterator i; + ContextMenu * sub; + + dx = x - GetX(); + dy = y - GetY(); + widget::move(x, y); + + for (i = nodes.begin(); i != nodes.end(); i++) { + if ((sub = i->GetSub())) + sub->move(sub->GetX() + dx, sub->GetY() + dy); + } +} + +void mogltk::widgets::ContextMenu::resize(int w, int h) { + int dw; + std::vector::iterator i; + ContextMenu * sub; + + dw = w - GetW(); + widget::resize(w, h); + + for (i = nodes.begin(); i != nodes.end(); i++) { + if ((sub = i->GetSub())) + sub->move(sub->GetX() + dw, sub->GetY()); + } +} + +void mogltk::widgets::ContextMenu::SetVisible(bool visible) { + if (!visible && sticky) + return; + widget::SetVisible(visible); + if (!visible && subselected) { + subselected->SetVisible(false); + } + + if (visible) { + add_out_click(); + MoveOnTop(); + } +} + +void mogltk::widgets::ContextMenu::SetEnabled(int i, bool e) { + nodes[i].SetEnabled(e); +} + +void mogltk::widgets::ContextMenu::StickyDisplay() { + sticky = true; + SetVisible(true); +} + +void mogltk::widgets::ContextMenu::draw() { + std::vector::iterator i; + int n; + rect size; + + Shaper()->box3d(GetAX(), GetAY(), GetAX2(), GetAY2()); + + for (i = nodes.begin(), n = 0; i != nodes.end(); i++, n++) { + size = SystemFont->size(i->GetCaption()); + if (i->GetLine()) { + Shaper()->hline3d(GetAX() + i->GetX(), GetAX() + i->GetX() + GetW() - 4, GetAY() + i->GetY()); + } else { + if (n == selected) { + Shaper()->box(GetAX() + 2, GetAY() + i->GetY(), GetAX() + GetW() - 2, GetAY() + i->GetY() + i->GetH(), DOS_MAGENTA); + } + Shaper()->text(GetAX() + i->GetX(), GetAY() + i->GetY(), i->GetCaption(), i->GetEnabled() ? BLACK : DOS_GRAY); + } + } +} + +bool mogltk::widgets::ContextMenu::process_event(int xe, int ye, mogltk::event_t event) { + std::vector::iterator i; + action * a; + int n; + + switch (event) { + case E_MOUSE_MOVE: + sticky = false; + selected = -1; + for (i = nodes.begin(), n = 0; i != nodes.end(); i++, n++) { + if (!i->GetLine()) { + int ax, ax2, ay, ay2; + + ax = GetAX() + 2; + ay = GetAY() + i->GetY(); + ax2 = GetAX() + GetW() - 2; + ay2 = GetAY() + i->GetY() + i->GetH(); + + if (!((xe < ax) || (xe > ax2) || (ye < ay) || (ye > ay2))) { + selected = n; + if (subselected) { + subselected->SetVisible(false); + subselected->selected = -1; + subselected->subselected = 0; + } + if ((subselected = i->GetSub())) { + subselected->SetVisible(true); + subselected->selected = -1; + subselected->subselected = 0; + } + } + } + } + add_out_move(); + return true; + case E_MOUSE_CLICK: + a = 0; + if (selected != -1) { + if ((a = nodes[selected].GetAction()) && nodes[selected].GetEnabled()) { + a->do_action(this); + in_click = false; + SetVisible(false); + return true; + } + } + in_click = true; + break; + case E_MOUSE_DOWN: + in_click = true; + break; + case E_MOUSE_OUT: + selected = -1; + remove_out_move(); + in_click = false; + return true; + case E_MOUSE_OUT_CLICK: + if (iin_click()) + return true; + selected = -1; + subselected = 0; + SetVisible(false); + return true; + } + + return false; +} + +bool mogltk::widgets::ContextMenu::iin_click() { + if (in_click) + return true; + + if (subselected) + return subselected->iin_click(); + + return false; +} + + +/******************** +* The Menu topframe * +********************/ + +mogltk::widgets::Menu::node::node(const String & _caption, mogltk::widgets::ContextMenu * _sub, mogltk::widgets::action * _a, int _x) : caption(_caption), sub(_sub), a(_a), x(_x) { +} + +String mogltk::widgets::Menu::node::GetCaption() { + return caption; +} + +void mogltk::widgets::Menu::node::SetCaption(const String & s) { + caption = s; +} + +mogltk::widgets::ContextMenu * mogltk::widgets::Menu::node::GetSub() { + return sub; +} + +mogltk::widgets::action * mogltk::widgets::Menu::node::GetAction() { + return a; +} + +int mogltk::widgets::Menu::node::GetX() { + return x; +} + +bool mogltk::widgets::Menu::node::GetEnabled() { + return enabled; +} + +void mogltk::widgets::Menu::node::SetEnabled(bool _enabled) { + enabled = _enabled; +} + +mogltk::widgets::Menu::Menu(shape * sh, mogltk::widget * father) : widget(father, 0, 0, 0, 0, 0, "Menu", sh), cur_x(0), selected(-1) { + rect r = father->GetDrawRect(); + move(r.x, r.y); + resize(r.w, 16); +} + +void mogltk::widgets::Menu::resize_notify() { + rect r = Father()->GetDrawRect(); + resize(r.w, 16); +} + +void mogltk::widgets::Menu::addnode(const String & caption, mogltk::widgets::action * a) { + nodes.push_back(node(caption, 0, a, cur_x)); + cur_x += SystemFont->singletextsize(caption) + 6; +} + +void mogltk::widgets::Menu::addsub(const String & caption, mogltk::widgets::ContextMenu * sub) { + nodes.push_back(node(caption, sub, 0, cur_x)); + cur_x += SystemFont->singletextsize(caption) + 6; +} + +mogltk::widgets::ContextMenu * mogltk::widgets::Menu::createsub(const String & caption) { + ContextMenu * r = new ContextMenu(Shaper(), Father(), GetX() + cur_x, GetY() + 16); + addsub(caption, r); + r->SetVisible(false); + return r; +} + +void mogltk::widgets::Menu::SetEnabled(int i, bool e) { + nodes[i].SetEnabled(e); +} + +void mogltk::widgets::Menu::SetCaption(int i, const String & s) { + nodes[i].SetCaption(s); +} + +void mogltk::widgets::Menu::draw(void) { + std::vector::iterator i; + int n; + + Shaper()->box(GetAX(), GetAY(), GetAX2(), GetAY2(), DOS_WHITE); + + for (i = nodes.begin(), n = 0; i != nodes.end(); i++, n++) { + if (selected == n) { + if ((i + 1) == nodes.end()) { + Shaper()->box(GetAX() + i->GetX(), GetAY(), cur_x, GetAY2(), DOS_MAGENTA); + } else { + Shaper()->box(GetAX() + i->GetX(), GetAY(), GetAX() + i[1].GetX(), GetAY2(), DOS_MAGENTA); + } + } + Shaper()->text(GetAX() + i->GetX() + 3, GetAY(), i->GetCaption(), BLACK); + } +} + +bool mogltk::widgets::Menu::process_event(int mx, int my, mogltk::event_t event) { + std::vector::iterator i; + action * a; + ContextMenu * sub; + int n; + + switch (event) { + case E_MOUSE_MOVE: + selected = -1; + for (i = nodes.begin(), n = 0; i != nodes.end(); i++, n++) { + int ax, ax2, ay, ay2; + + ax = GetAX() + i->GetX(); + ay = GetAY(); + if ((i + 1) != nodes.end()) { + ax2 = GetAX() + i[1].GetX(); + } else { + ax2 = GetAX() + cur_x; + } + ay2 = GetAY2(); + + if (!((mx < ax) || (mx > ax2) || (my < ay) || (my > ay2))) { + selected = n; + } + } + add_out_move(); + return true; + case E_MOUSE_CLICK: + a = 0; + if (selected != -1) { + if ((a = nodes[selected].GetAction()) && nodes[selected].GetEnabled()) { + a->do_action(this); + return true; + } else if ((sub = nodes[selected].GetSub()) && nodes[selected].GetEnabled()) { + sub->StickyDisplay(); + return true; + } + } + break; + case E_MOUSE_OUT: + selected = -1; + remove_out_move(); + return true; + } + return false; +} + + +/* + * The mainloop widget thing. + */ + +void mogltk::widget::mainloop() { + bool end_event_loop = false; + widget_mouse_event * mouse = new widget_mouse_event(this); + widget * w; + int mx, my; + + while (!end_event_loop && !engine::quitrequested()) { + root->fulldraw(); + mx = mogltk::engine::mouseX(); + my = mogltk::engine::mouseY(); + + mogltk::ColorP::Max.A = 50; + Sprite::Cursor->draw(mx - 6, my - 3, BLACK); + mogltk::ColorP::Max.A = 255; + Sprite::Cursor->draw(mx - 8, my - 6); + + if (w = root->find_widget(mx, my)) { + sh->box(w->GetAX(), w->GetAY(), w->GetAX2(), w->GetAY2(), Color(100, 150, 60, 50)); + } + + engine::base_o->Flip(); + widget::check_timed_events(); + } + + delete mouse; +} -- cgit v1.2.3