/*************************************************************************** Cwindow.cpp Gambas extension using SDL (c) 2006 Laurent Carlier BenoƮt Minisini 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA. ***************************************************************************/ #define __CWINDOW_CPP #include #include "Cwindow.h" #include "Ckey.h" #include "Cmouse.h" #include "Cdraw.h" #include "SDL.h" #define THIS ((CWINDOW *)_object) #define WINDOWID ((CWINDOW *)_object)->id // number of frames before counting FPS #define FRAMECOUNT 100 // events DECLARE_EVENT(EVENT_Close); DECLARE_EVENT(EVENT_Resize); DECLARE_EVENT(EVENT_Activate); DECLARE_EVENT(EVENT_DeActivate); DECLARE_EVENT(EVENT_Enter); DECLARE_EVENT(EVENT_Leave); DECLARE_EVENT(EVENT_Refresh); DECLARE_EVENT(EVENT_KeyPressed); DECLARE_EVENT(EVENT_KeyReleased); DECLARE_EVENT(EVENT_MouseMove); DECLARE_EVENT(EVENT_MouseDown); DECLARE_EVENT(EVENT_MouseUp); DECLARE_EVENT(EVENT_Open); /***************************************************************************/ BEGIN_METHOD(CWINDOW_new, GB_BOOLEAN openGL) WINDOWID = new myWin(THIS); WINDOWID->SetTitle(GB.Application.Name()); THIS->openGL = VARGOPT(openGL, false); THIS->lastTime = SDL_GetTicks(); THIS->startTime = THIS->lastTime; END_METHOD BEGIN_METHOD_VOID(CWINDOW_free) delete WINDOWID; END_METHOD BEGIN_METHOD_VOID(CWINDOW_show) WINDOWID->Show(); WINDOWID->Refresh(); END_METHOD BEGIN_METHOD_VOID(CWINDOW_close) WINDOWID->Quit(); END_METHOD BEGIN_METHOD_VOID(CWINDOW_clear) WINDOWID->Clear(); END_METHOD BEGIN_METHOD(CWINDOW_fill, GB_INTEGER color;) WINDOWID->Clear(VARG(color)); END_METHOD BEGIN_METHOD_VOID(CWINDOW_refresh) WINDOWID->Refresh(); END_METHOD BEGIN_PROPERTY(CWINDOW_framerate) if (READ_PROPERTY) GB.ReturnInteger(THIS->currentFPS); else { if (VPROP(GB_INTEGER)<0) return; THIS->FPSLimit = 1000/VPROP(GB_INTEGER); THIS->lastTime = SDL_GetTicks(); } END_PROPERTY BEGIN_PROPERTY(CWINDOW_text) if (READ_PROPERTY) GB.ReturnNewZeroString(WINDOWID->GetTitle()); else WINDOWID->SetTitle(GB.ToZeroString(PROP(GB_STRING))); END_PROPERTY BEGIN_PROPERTY(CWINDOW_fullscreen) if (READ_PROPERTY) GB.ReturnBoolean(WINDOWID->IsFullScreen()); else WINDOWID->SetFullScreen(VPROP(GB_BOOLEAN)); END_PROPERTY BEGIN_PROPERTY(CWINDOW_border) if (READ_PROPERTY) GB.ReturnInteger(WINDOWID->IsResizable()); else { if (VPROP(GB_INTEGER) == 0) WINDOWID->SetResizable(false); if (VPROP(GB_INTEGER) == 1) WINDOWID->SetResizable(true); } END_PROPERTY BEGIN_PROPERTY(CWINDOW_mouse) if (READ_PROPERTY) GB.ReturnInteger(WINDOWID->GetCursor()->GetShape()); else WINDOWID->GetCursor()->SetShape(VPROP(GB_INTEGER)); END_PROPERTY BEGIN_PROPERTY(CWINDOW_cursor) if (READ_PROPERTY) GB.ReturnObject(0); else { CCURSOR *curs = (CCURSOR *)VPROP(GB_OBJECT); WINDOWID->SetCursor(curs->cursor); return; } END_PROPERTY BEGIN_PROPERTY(CWINDOW_width) if (READ_PROPERTY) GB.ReturnInteger(WINDOWID->GetWidth()); else THIS->id->SetWidth(VPROP(GB_INTEGER)); END_PROPERTY BEGIN_PROPERTY(CWINDOW_height) if (READ_PROPERTY) GB.ReturnInteger(WINDOWID->GetHeight()); else WINDOWID->SetHeight(VPROP(GB_INTEGER)); END_PROPERTY BEGIN_PROPERTY(CWINDOW_depth) GB.ReturnInteger(WINDOWID->GetDepth()); END_PROPERTY BEGIN_PROPERTY(CWINDOW_shown) GB.ReturnBoolean(WINDOWID->IsShown()); END_PROPERTY BEGIN_PROPERTY(CWINDOW_id) GB.ReturnInteger(WINDOWID->Id()); END_PROPERTY /***************************************************************************/ GB_DESC CWindow[] = { GB_DECLARE("Window", sizeof(CWINDOW)), GB_METHOD("_new", NULL, CWINDOW_new, "[(OpenGL)b]"), GB_METHOD("_free", NULL, CWINDOW_free, NULL), GB_METHOD("Show", NULL, CWINDOW_show, NULL), GB_METHOD("Close", NULL, CWINDOW_close, NULL), GB_METHOD("Clear", NULL, CWINDOW_clear, NULL), GB_METHOD("Fill", NULL, CWINDOW_fill, "(Color)i"), GB_METHOD("Refresh", NULL, CWINDOW_refresh, NULL), GB_METHOD("Update", NULL, CWINDOW_refresh, NULL), GB_PROPERTY("Cursor", "Cursor;", CWINDOW_cursor), GB_PROPERTY("Framerate", "i", CWINDOW_framerate), GB_PROPERTY("Text", "s", CWINDOW_text), GB_PROPERTY("Title", "s", CWINDOW_text), GB_PROPERTY("Caption", "s", CWINDOW_text), GB_PROPERTY("FullScreen", "b", CWINDOW_fullscreen), GB_PROPERTY("Border", "i", CWINDOW_border), GB_PROPERTY("Mouse", "i", CWINDOW_mouse), GB_PROPERTY("Height", "i", CWINDOW_height), GB_PROPERTY("Width", "i", CWINDOW_width), GB_PROPERTY_READ("Depth", "i", CWINDOW_depth), GB_PROPERTY_READ("Shown", "b", CWINDOW_shown), GB_PROPERTY_READ("Id", "i", CWINDOW_id), GB_EVENT("Close", "b", NULL, &EVENT_Close), GB_EVENT("Resize", NULL, NULL, &EVENT_Resize), GB_EVENT("Activate", NULL, NULL, &EVENT_Activate), GB_EVENT("DeActivate", NULL, NULL, &EVENT_DeActivate), GB_EVENT("Enter", NULL, NULL, &EVENT_Enter), GB_EVENT("Leave", NULL, NULL, &EVENT_Leave), GB_EVENT("Draw", "b", NULL, &EVENT_Refresh), GB_EVENT("KeyPress", NULL, NULL, &EVENT_KeyPressed), GB_EVENT("KeyRelease", NULL, NULL, &EVENT_KeyReleased), GB_EVENT("MouseMove", NULL, NULL, &EVENT_MouseMove), GB_EVENT("MouseDown", NULL, NULL, &EVENT_MouseDown), GB_EVENT("MouseUp", NULL, NULL, &EVENT_MouseUp), GB_EVENT("Open", NULL, NULL, &EVENT_Open), GB_CONSTANT("Fixed", "i", 0), GB_CONSTANT("Resizable", "i", 1), GB_END_DECLARE }; /***************************************************************************/ #define WINDOW(object) ((CWINDOW *)object) void myWin::Resize(void) { GB.Raise(hWindow, EVENT_Resize, 0); } void myWin::GotFocus(void) { GB.Raise(hWindow, EVENT_Activate, 0); } void myWin::LostFocus(void) { GB.Raise(hWindow, EVENT_DeActivate, 0); } void myWin::MouseEnter(void) { GB.Raise(hWindow, EVENT_Enter, 0); } void myWin::MouseLeave(void) { GB.Raise(hWindow, EVENT_Leave, 0); } void myWin::Quit(void) { bool cancel = GB.Raise(hWindow, EVENT_Close, 0); if (!cancel) this->Close(); } void myWin::Update(void) { // no refresh event if (!GB.CanRaise(hWindow, EVENT_Refresh)) { SDL_Delay(1); return; } // framerate limitation if (WINDOW(hWindow)->FPSLimit>0) { Uint32 value = SDL_GetTicks() - WINDOW(hWindow)->lastTime; if (valueFPSLimit) { SDL_Delay(1); return; } WINDOW(hWindow)->lastTime = SDL_GetTicks(); } DRAW_begin(hWindow); bool cancel = GB.Raise(hWindow, EVENT_Refresh, 0); DRAW_end(); // user doesn't want to refresh if (cancel) { SDL_Delay(1); return; } else this->Refresh(); // calculate the framerate if (WINDOW(hWindow)->countFrames>=FRAMECOUNT) { double value = double(SDL_GetTicks() - WINDOW(hWindow)->startTime)/FRAMECOUNT; if (value>0) WINDOW(hWindow)->currentFPS = Uint32(1000/value); else WINDOW(hWindow)->currentFPS = 0; WINDOW(hWindow)->countFrames = 0; WINDOW(hWindow)->startTime = SDL_GetTicks(); } else WINDOW(hWindow)->countFrames++; } void myWin::Open(void) { if (!(((CWINDOW *)hWindow)->openGL)) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glViewport(0, 0, this->GetWidth(), this->GetHeight()); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0f, GLdouble(this->GetWidth()), GLdouble(this->GetHeight()), 0.0f); // enable blending, should work like 2d sdl does glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // enable anti-aliasing glEnable(GL_POINT_SMOOTH); glEnable(GL_LINE_SMOOTH); glMatrixMode(GL_MODELVIEW); } if (GB.CanRaise(hWindow, EVENT_Open)) GB.Raise(hWindow, EVENT_Open,0); if ((((CWINDOW *)hWindow)->openGL)) { if (GB.CanRaise(hWindow, EVENT_Resize)) GB.Raise(hWindow, EVENT_Resize,0); } } void myWin::KeyEvent(SDL_KeyboardEvent *keyEvent, int eventType) { CKEY_info.valid = true; CKEY_info.code = XKeycodeToKeysym(SDLapp->X11appDisplay(), keyEvent->keysym.scancode, 0); CKEY_info.state = keyEvent->keysym.mod; if (eventType == SDL_KEYDOWN) GB.Raise(hWindow, EVENT_KeyPressed,0); else GB.Raise(hWindow, EVENT_KeyReleased,0); CKEY_info.valid = false; } void myWin::MouseButtonEvent(SDL_MouseButtonEvent *mouseEvent) { CMOUSE_info.valid = true; CMOUSE_info.x = mouseEvent->x; CMOUSE_info.y = mouseEvent->y; if (mouseEvent->type == SDL_MOUSEBUTTONDOWN) GB.Raise(hWindow, EVENT_MouseDown,0); else GB.Raise(hWindow, EVENT_MouseUp,0); CMOUSE_info.valid = false; } void myWin::MouseMotionEvent(SDL_MouseMotionEvent *mouseEvent) { CMOUSE_info.relx = mouseEvent->xrel; CMOUSE_info.rely = mouseEvent->yrel; // do not raise event if no mouse button are pressed/released if (!mouseEvent->state) return; CMOUSE_info.valid = true; CMOUSE_info.x = mouseEvent->x; CMOUSE_info.y = mouseEvent->y; GB.Raise(hWindow, EVENT_MouseMove,0); CMOUSE_info.valid = false; }