From 5b713bd785c793fc4eca9b32cbc3afaac40c741f Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Tue, 23 Mar 2010 02:35:55 +0000 Subject: [PATCH] Added camera zoom (from GAE) into mega-glest (middle mouse button zooms in and out like in GAE) --- source/glest_game/game/game.cpp | 103 +++-- source/glest_game/game/game.h | 137 ++++++ source/glest_game/game/game_camera.cpp | 329 ++++++++++++++ source/glest_game/game/game_camera.h | 133 ++++++ source/glest_game/game/script_manager.cpp | 402 ++++++++++++++++++ source/glest_game/game/script_manager.h | 183 ++++++++ source/glest_game/main/main.cpp | 22 +- source/glest_game/main/main.h | 56 +++ source/glest_game/main/program.cpp | 59 +-- source/glest_game/main/program.h | 7 +- .../shared_lib/include/platform/sdl/window.h | 148 +++++++ .../include/platform/win32/window.h | 159 +++++++ .../sources/platform/sdl/window.cpp | 325 ++++++++++++++ 13 files changed, 1988 insertions(+), 75 deletions(-) create mode 100644 source/glest_game/game/game.h create mode 100644 source/glest_game/game/game_camera.cpp create mode 100644 source/glest_game/game/game_camera.h create mode 100644 source/glest_game/game/script_manager.cpp create mode 100644 source/glest_game/game/script_manager.h create mode 100644 source/glest_game/main/main.h create mode 100644 source/shared_lib/include/platform/sdl/window.h create mode 100644 source/shared_lib/include/platform/win32/window.h create mode 100644 source/shared_lib/sources/platform/sdl/window.cpp diff --git a/source/glest_game/game/game.cpp b/source/glest_game/game/game.cpp index 2bc98c9d8..c5641c713 100644 --- a/source/glest_game/game/game.cpp +++ b/source/glest_game/game/game.cpp @@ -42,6 +42,7 @@ Game::Game(Program *program, const GameSettings *gameSettings): ProgramState(program) { this->gameSettings= *gameSettings; + scrollSpeed = Config::getInstance().getFloat("UiScrollSpeed","1.5"); mouseX=0; mouseY=0; @@ -415,49 +416,69 @@ void Game::mouseDoubleClickLeft(int x, int y){ void Game::mouseMove(int x, int y, const MouseState *ms){ - const Metrics &metrics= Metrics::getInstance(); + const Metrics &metrics = Metrics::getInstance(); - mouseX= x; - mouseY= y; + mouseX = x; + mouseY = y; - //main window - if(y<10){ - gameCamera.setMoveZ(-1); - } - else if(y> metrics.getVirtualH()-10){ - gameCamera.setMoveZ(1); - } - else{ - gameCamera.stopMoveZ(); + /* + if (ms.get(mbCenter)) { + if (input.isCtrlDown()) { + float speed = input.isShiftDown() ? 1.f : 0.125f; + float response = input.isShiftDown() ? 0.1875f : 0.0625f; + gameCamera.moveForwardH((y - lastMousePos.y) * speed, response); + gameCamera.moveSideH((x - lastMousePos.x) * speed, response); + } else { + //float ymult = Config::getInstance().getCameraInvertYAxis() ? -0.2f : 0.2f; + //float xmult = Config::getInstance().getCameraInvertXAxis() ? -0.2f : 0.2f; + float ymult = 0.2f; + float xmult = 0.2f; + + gameCamera.transitionVH(-(y - lastMousePos.y) * ymult, (lastMousePos.x - x) * xmult); + } + } else */ + { + //main window + if (y < 10) { + gameCamera.setMoveZ(-scrollSpeed); + } else if (y > metrics.getVirtualH() - 10) { + gameCamera.setMoveZ(scrollSpeed); + } else { + gameCamera.setMoveZ(0); + } + + if (x < 10) { + gameCamera.setMoveX(-scrollSpeed); + } else if (x > metrics.getVirtualW() - 10) { + gameCamera.setMoveX(scrollSpeed); + } else { + gameCamera.setMoveX(0); + } + + if (mainMessageBox.getEnabled()) { + mainMessageBox.mouseMove(x, y); + } else if (ScriptManager::getMessageBox()->getEnabled()) { + ScriptManager::getMessageBox()->mouseMove(x, y); + //} else if (saveBox) { + // saveBox->mouseMove(x, y); + } else { + //graphics + gui.mouseMoveGraphics(x, y); + } } - if(x<10){ - gameCamera.setMoveX(-1); - } - else if(x> metrics.getVirtualW()-10){ - gameCamera.setMoveX(1); - } - else{ - gameCamera.stopMoveX(); - } - - if(mainMessageBox.getEnabled()){ - mainMessageBox.mouseMove(x, y); - } - - if(scriptManager.getMessageBox()->getEnabled()){ - scriptManager.getMessageBox()->mouseMove(x, y); - } - - //graphics - gui.mouseMoveGraphics(x, y); - - //display - if(metrics.isInDisplay(x, y) && !gui.isSelecting() && !gui.isSelectingPos()){ - if(!gui.isSelectingPos()){ + //display + if (metrics.isInDisplay(x, y) && !gui.isSelecting() && !gui.isSelectingPos()) { + if (!gui.isSelectingPos()) { gui.mouseMoveDisplay(x - metrics.getDisplayX(), y - metrics.getDisplayY()); - } - } + } + } +} + +void Game::eventMouseWheel(int x, int y, int zDelta) { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + //gameCamera.transitionXYZ(0.0f, -(float)zDelta / 30.0f, 0.0f); + gameCamera.zoom((float)zDelta / 30.0f); } void Game::keyDown(char key){ @@ -595,17 +616,17 @@ void Game::keyUp(char key){ case 'W': case 'S': - gameCamera.stopMoveY(); + gameCamera.setMoveY(0); break; case vkUp: case vkDown: - gameCamera.stopMoveZ(); + gameCamera.setMoveZ(0); break; case vkLeft: case vkRight: - gameCamera.stopMoveX(); + gameCamera.setMoveX(0); break; } } diff --git a/source/glest_game/game/game.h b/source/glest_game/game/game.h new file mode 100644 index 000000000..00a68fded --- /dev/null +++ b/source/glest_game/game/game.h @@ -0,0 +1,137 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2008 Martiņo Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#ifndef _GLEST_GAME_GAME_H_ +#define _GLEST_GAME_GAME_H_ + +#include + +#include "gui.h" +#include "game_camera.h" +#include "world.h" +#include "ai_interface.h" +#include "program.h" +#include "chat_manager.h" +#include "script_manager.h" +#include "game_settings.h" + +using std::vector; + +namespace Glest{ namespace Game{ + +class GraphicMessageBox; + +// ===================================================== +// class Game +// +// Main game class +// ===================================================== + +class Game: public ProgramState{ +public: + enum Speed{ + sFast, + sNormal, + sSlow + }; + +private: + typedef vector Ais; + typedef vector AiInterfaces; + +private: + //main data + World world; + AiInterfaces aiInterfaces; + Gui gui; + GameCamera gameCamera; + Commander commander; + Console console; + ChatManager chatManager; + ScriptManager scriptManager; + + //misc + Checksum checksum; + string loadingText; + int mouse2d; + int mouseX, mouseY; //coords win32Api + int updateFps, lastUpdateFps; + int renderFps, lastRenderFps; + bool paused; + bool gameOver; + bool renderNetworkStatus; + float scrollSpeed; + Speed speed; + GraphicMessageBox mainMessageBox; + + //misc ptr + ParticleSystem *weatherParticleSystem; + GameSettings gameSettings; + +public: + Game(Program *program, const GameSettings *gameSettings); + ~Game(); + + //get + GameSettings *getGameSettings() {return &gameSettings;} + + const GameCamera *getGameCamera() const {return &gameCamera;} + GameCamera *getGameCamera() {return &gameCamera;} + const Commander *getCommander() const {return &commander;} + Gui *getGui() {return &gui;} + const Gui *getGui() const {return &gui;} + Commander *getCommander() {return &commander;} + Console *getConsole() {return &console;} + ScriptManager *getScriptManager() {return &scriptManager;} + World *getWorld() {return &world;} + const World *getWorld() const {return &world;} + + //init + virtual void load(); + virtual void init(); + virtual void update(); + virtual void updateCamera(); + virtual void render(); + virtual void tick(); + + //event managing + virtual void keyDown(char key); + virtual void keyUp(char key); + virtual void keyPress(char c); + virtual void mouseDownLeft(int x, int y); + virtual void mouseDownRight(int x, int y); + virtual void mouseUpLeft(int x, int y); + virtual void mouseDoubleClickLeft(int x, int y); + virtual void eventMouseWheel(int x, int y, int zDelta); + virtual void mouseMove(int x, int y, const MouseState *mouseState); + + void quitGame(); +private: + //render + void render3d(); + void render2d(); + + //misc + void checkWinner(); + void checkWinnerStandard(); + void checkWinnerScripted(); + bool hasBuilding(const Faction *faction); + void incSpeed(); + void decSpeed(); + int getUpdateLoops(); + void showLoseMessageBox(); + void showWinMessageBox(); + void showMessageBox(const string &text, const string &header, bool toggle); +}; + +}}//end namespace + +#endif diff --git a/source/glest_game/game/game_camera.cpp b/source/glest_game/game/game_camera.cpp new file mode 100644 index 000000000..c15711e72 --- /dev/null +++ b/source/glest_game/game/game_camera.cpp @@ -0,0 +1,329 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2008 Martiņo Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#include "game_camera.h" + +#include + +#include "config.h" +#include "game_constants.h" +#include "xml_parser.h" + +#include "leak_dumper.h" + + +using namespace Shared::Graphics; +using Shared::Xml::XmlNode; + +namespace Glest { namespace Game { + +// ===================================================== +// class GameCamera +// ===================================================== + +// ================== PUBLIC ===================== + +const float GameCamera::startingVAng= -60.f; +const float GameCamera::startingHAng= 0.f; +const float GameCamera::vTransitionMult= 0.125f; +const float GameCamera::hTransitionMult= 0.125f; +const float GameCamera::defaultHeight= 20.f; +const float GameCamera::centerOffsetZ= 8.0f; + +// ================= Constructor ================= + +GameCamera::GameCamera() : pos(0.f, defaultHeight, 0.f), + destPos(0.f, defaultHeight, 0.f), destAng(startingVAng, startingHAng) { + Config &config = Config::getInstance(); + state= sGame; + + //config + speed= 15.f / GameConstants::cameraFps; + clampBounds= !Config::getInstance().getBool("PhotoMode"); + + vAng= startingVAng; + hAng= startingHAng; + + rotate=0; + + move= Vec3f(0.f); + + maxRenderDistance = Config::getInstance().getFloat("RenderDistanceMax","64"); + maxHeight = Config::getInstance().getFloat("CameraMaxDistance","35"); + minHeight = Config::getInstance().getFloat("CameraMinDistance","8"); + maxCameraDist = maxHeight; + minCameraDist = minHeight; + minVAng = -Config::getInstance().getFloat("CameraMaxYaw","77.5"); + maxVAng = -Config::getInstance().getFloat("CameraMinYaw","20"); + fov = Config::getInstance().getFloat("CameraFov","45"); +} + +void GameCamera::init(int limitX, int limitY){ + this->limitX= limitX; + this->limitY= limitY; +} + +// ==================== Misc ===================== + +void GameCamera::setPos(Vec2f pos){ + this->pos= Vec3f(pos.x, this->pos.y, pos.y); + clampPosXZ(0.0f, (float)limitX, 0.0f, (float)limitY); + destPos.x = pos.x; + destPos.z = pos.y; +} + +void GameCamera::update(){ + + //move XZ + if(move.z){ + moveForwardH(speed * move.z, 0.9f); + } + if(move.x){ + moveSideH(speed * move.x, 0.9f); + } + + //free state + if(state==sFree){ + if(fabs(rotate) == 1){ + rotateHV(speed*5*rotate, 0); + } + if(move.y>0){ + moveUp(speed * move.y); + if(clampBounds && pos.yminHeight){ + rotateHV(0.f, -speed * 1.7f * move.y); + } + } + } + + //game state + if(abs(destAng.x - vAng) > 0.01f) { + vAng+= (destAng.x - vAng) * hTransitionMult; + } + if(abs(destAng.y - hAng) > 0.01f) { + if(abs(destAng.y - hAng) > 180) { + if(destAng.y > hAng) { + hAng+= (destAng.y - hAng - 360) * vTransitionMult; + } else { + hAng+= (destAng.y - hAng + 360) * vTransitionMult; + } + } else { + hAng+= (destAng.y - hAng) * vTransitionMult; + } + } + if(abs(destPos.x - pos.x) > 0.01f) { + pos.x += (destPos.x - pos.x) / 32.0f; + } + if(abs(destPos.y - pos.y) > 0.01f) { + pos.y += (destPos.y - pos.y) / 32.0f; + } + if(abs(destPos.z - pos.z) > 0.01f) { + pos.z += (destPos.z - pos.z) / 32.0f; + } + + clampAng(); + + if(clampBounds){ + clampPosXYZ(0.0f, (float)limitX, minHeight, maxHeight, 0.0f, (float)limitY); + } +} + +Quad2i GameCamera::computeVisibleQuad() const{ + /* + //maxRenderDistance + float flatDist = maxRenderDistance * -cos(degToRad(vAng + fov / 2.f)); + Vec3f p1(flatDist * sin(degToRad(hAng + fov / 2.f)), maxRenderDistance * sin(degToRad(vAng + fov / 2.f)), flatDist * -cos(degToRad(hAng + fov / 2.f))); + Vec3f p2(flatDist * sin(degToRad(hAng - fov / 2.f)), maxRenderDistance * sin(degToRad(vAng + fov / 2.f)), flatDist * -cos(degToRad(hAng - fov / 2.f))); + flatDist = maxRenderDistance * -cos(degToRad(vAng - fov / 2.f)); + Vec3f p3(flatDist * sin(degToRad(hAng + fov / 2.f)), maxRenderDistance * sin(degToRad(vAng - fov / 2.f)), flatDist * -cos(degToRad(hAng + fov / 2.f))); + Vec3f p4(flatDist * sin(degToRad(hAng - fov / 2.f)), maxRenderDistance * sin(degToRad(vAng - fov / 2.f)), flatDist * -cos(degToRad(hAng - fov / 2.f))); + // find the floor + if(-p1.y > pos.y) { + p1 = p1 * pos.y / abs(p1.y); + } + if(-p2.y > pos.y) { + p2 = p2 * pos.y / abs(p2.y); + } + if(-p3.y > pos.y) { + p3 = p3 * pos.y / abs(p3.y); + } + if(-p4.y > pos.y) { + p4 = p4 * pos.y / abs(p4.y); + } + Vec2i pi1(p1.x, p1.z), pi2(p2.x, p2.z), pi3(p3.x, p3.z), pi4(p4.x, p4.z); + + if(hAng>=135 && hAng<=225){ + return Quad2i(pi1, pi2, pi3, pi4); + } + if(hAng>=45 && hAng<=135){ + return Quad2i(pi3, pi1, pi4, pi2); + } + if(hAng>=225 && hAng<=315) { + return Quad2i(pi2, pi4, pi1, pi3); + } + return Quad2i(pi4, pi3, pi2, pi1); + */ + + float nearDist = 20.f; + float dist = pos.y > 20.f ? pos.y * 1.2f : 20.f; + float farDist = 90.f * (pos.y > 20.f ? pos.y / 15.f : 1.f); + float fov = Config::getInstance().getFloat("CameraFov","45"); + + Vec2f v(sinf(degToRad(180 - hAng)), cosf(degToRad(180 - hAng))); + Vec2f v1(sinf(degToRad(180 - hAng - fov)), cosf(degToRad(180 - hAng - fov))); + Vec2f v2(sinf(degToRad(180 - hAng + fov)), cosf(degToRad(180 - hAng + fov))); + v.normalize(); + v1.normalize(); + v2.normalize(); + + Vec2f p = Vec2f(pos.x, pos.z) - v * dist; + Vec2i p1(static_cast(p.x + v1.x * nearDist), static_cast(p.y + v1.y * nearDist)); + Vec2i p2(static_cast(p.x + v1.x * farDist), static_cast(p.y + v1.y * farDist)); + Vec2i p3(static_cast(p.x + v2.x * nearDist), static_cast(p.y + v2.y * nearDist)); + Vec2i p4(static_cast(p.x + v2.x * farDist), static_cast(p.y + v2.y * farDist)); + + if (hAng >= 135 && hAng <= 225) { + return Quad2i(p1, p2, p3, p4); + } + if (hAng >= 45 && hAng <= 135) { + return Quad2i(p3, p1, p4, p2); + } + if (hAng >= 225 && hAng <= 315) { + return Quad2i(p2, p4, p1, p3); + } + return Quad2i(p4, p3, p2, p1); +} + +void GameCamera::switchState(){ + if(state==sGame){ + state= sFree; + } + else{ + state= sGame; + destAng.x = startingVAng; + destAng.y = startingHAng; + destPos.y = defaultHeight; + } +} + +void GameCamera::centerXZ(float x, float z){ + destPos.x = pos.x= x; + destPos.z = pos.z= z+centerOffsetZ; +} + +void GameCamera::transitionXYZ(float x, float y, float z) { + destPos.x += x; + destPos.y += y; + destPos.z += z; + clampPosXYZ(0.0f, (float)limitX, minHeight, maxHeight, 0.0f, (float)limitY); +} + +void GameCamera::transitionVH(float v, float h) { + destAng.x += v; + destPos.y -= v * destPos.y / 100.f; + destAng.y += h; + clampAng(); +} + +void GameCamera::zoom(float dist) { + float flatDist = dist * cosf(degToRad(vAng)); + Vec3f offset(flatDist * sinf(degToRad(hAng)), dist * sinf(degToRad(vAng)), flatDist * -cosf(degToRad(hAng))); + float mult = 1.f; + if(destPos.y + offset.y < minHeight) { + mult = abs((destPos.y - minHeight) / offset.y); + } else if(destPos.y + offset.y > maxHeight) { + mult = abs((maxHeight - destPos.y) / offset.y); + } + destPos += offset * mult; +} + +void GameCamera::load(const XmlNode *node) { + //destPos = node->getChildVec3fValue("pos"); + //destAng = node->getChildVec2fValue("angle"); +} + +void GameCamera::save(XmlNode *node) const { + //node->addChild("pos", pos); + //node->addChild("angle", Vec2f(vAng, hAng)); +} + +// ==================== PRIVATE ==================== + +void GameCamera::clampPosXZ(float x1, float x2, float z1, float z2){ + if(pos.x < x1) pos.x = x1; + if(destPos.x < x1) destPos.x = x1; + if(pos.z < z1) pos.z = z1; + if(destPos.z < z1) destPos.z = z1; + if(pos.x > x2) pos.x = x2; + if(destPos.x > x2) destPos.x = x2; + if(pos.z > z2) pos.z = z2; + if(destPos.z > z2) destPos.z = z2; +} + +void GameCamera::clampPosXYZ(float x1, float x2, float y1, float y2, float z1, float z2){ + if(pos.x < x1) pos.x = x1; + if(destPos.x < x1) destPos.x = x1; + if(pos.y < y1) pos.y = y1; + if(destPos.y < y1) destPos.y = y1; + if(pos.z < z1) pos.z = z1; + if(destPos.z < z1) destPos.z = z1; + if(pos.x > x2) pos.x = x2; + if(destPos.x > x2) destPos.x = x2; + if(pos.y > y2) pos.y = y2; + if(destPos.y > y2) destPos.y = y2; + if(pos.z > z2) pos.z = z2; + if(destPos.z > z2) destPos.z = z2; +} + +void GameCamera::rotateHV(float h, float v){ + destAng.x = vAng += v; + destAng.y = hAng += h; + clampAng(); +} + +void GameCamera::clampAng() { + if(vAng > maxVAng) vAng = maxVAng; + if(destAng.x > maxVAng) destAng.x = maxVAng; + if(vAng < minVAng) vAng = minVAng; + if(destAng.x < minVAng) destAng.x = minVAng; + if(hAng > 360.f) hAng -= 360.f; + if(destAng.y > 360.f) destAng.y -= 360.f; + if(hAng < 0.f) hAng += 360.f; + if(destAng.y < 0.f) destAng.y = 360.f; +} + +//move camera forwad but never change heightFactor +void GameCamera::moveForwardH(float d, float response) { + Vec3f offset(sinf(degToRad(hAng)) * d, 0.f, -cosf(degToRad(hAng)) * d); + destPos += offset; + pos.x += offset.x * response; + pos.z += offset.z * response; +} + +//move camera to a side but never change heightFactor +void GameCamera::moveSideH(float d, float response){ + Vec3f offset(sinf(degToRad(hAng+90)) * d, 0.f, -cosf(degToRad(hAng+90)) * d); + destPos += offset; + pos.x += (destPos.x - pos.x) * response; + pos.z += (destPos.z - pos.z) * response; +} + +void GameCamera::moveUp(float d){ +// pos.y+= d; + destPos.y += d; +} + +}}//end namespace diff --git a/source/glest_game/game/game_camera.h b/source/glest_game/game/game_camera.h new file mode 100644 index 000000000..5d70243c8 --- /dev/null +++ b/source/glest_game/game/game_camera.h @@ -0,0 +1,133 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2008 Martiņo Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#ifndef _GLEST_GAME_GAMECAMERA_H_ +#define _GLEST_GAME_GAMECAMERA_H_ + +#include "vec.h" +#include "math_util.h" + +namespace Shared { namespace Xml { + class XmlNode; +}} + +namespace Glest{ namespace Game{ + +using Shared::Graphics::Quad2i; +using Shared::Graphics::Vec3f; +using Shared::Graphics::Vec2f; +using Shared::Xml::XmlNode; + +class Config; + +// ===================================================== +// class GameCamera +// +/// A basic camera that holds information about the game view +// ===================================================== + +class GameCamera{ +public: + static const float startingVAng; + static const float startingHAng; + static const float vTransitionMult; + static const float hTransitionMult; + static const float defaultHeight; + static const float centerOffsetZ; + +public: + enum State{ + sGame, + sFree + }; + +private: + Vec3f pos; + Vec3f destPos; + + float hAng; //YZ plane positive -Z axis + float vAng; //XZ plane positive +Z axis + float lastHAng; + float lastVAng; + Vec2f destAng; + + float rotate; + + Vec3f move; + + State state; + + int limitX; + int limitY; + + //config + float speed; + bool clampBounds; + float maxRenderDistance; + float maxHeight; + float minHeight; + float maxCameraDist; + float minCameraDist; + float minVAng; + float maxVAng; + float fov; + +public: + GameCamera(); + + void init(int limitX, int limitY); + + //get + float getHAng() const {return hAng;}; + float getVAng() const {return vAng;} + State getState() const {return state;} + const Vec3f &getPos() const {return pos;} + + //set + void setRotate(float rotate){this->rotate= rotate;} + void setPos(Vec2f pos); + + void setMoveX(float f) {this->move.x= f;} + void setMoveY(float f) {this->move.y= f;} + void setMoveZ(float f) {this->move.z= f;} + + void stop() { + destPos = pos; + destAng.x = vAng; + destAng.y = hAng; + } + + //other + void update(); + Quad2i computeVisibleQuad() const; + void switchState(); + + void centerXZ(float x, float z); + void rotateHV(float h, float v); + void transitionXYZ(float x, float y, float z); + void transitionVH(float v, float h); + void zoom(float dist); + void moveForwardH(float dist, float response); // response: 1.0 for immediate, 0 for full inertia + void moveSideH(float dist, float response); + + void load(const XmlNode *node); + void save(XmlNode *node) const; + +private: + void clampPosXYZ(float x1, float x2, float y1, float y2, float z1, float z2); + void clampPosXZ(float x1, float x2, float z1, float z2); + void clampAng(); + void moveUp(float dist); +}; + +}} //end namespace + +#endif diff --git a/source/glest_game/game/script_manager.cpp b/source/glest_game/game/script_manager.cpp new file mode 100644 index 000000000..7e05eb208 --- /dev/null +++ b/source/glest_game/game/script_manager.cpp @@ -0,0 +1,402 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2005 Martiņo Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#include "script_manager.h" + +#include "world.h" +#include "lang.h" +#include "game_camera.h" + +#include "leak_dumper.h" + +using namespace Shared::Platform; +using namespace Shared::Lua; + +namespace Glest{ namespace Game{ + +// ===================================================== +// class PlayerModifiers +// ===================================================== + +PlayerModifiers::PlayerModifiers(){ + winner= false; + aiEnabled= true; +} + +// ===================================================== +// class ScriptManager +// ===================================================== + +GraphicMessageBox ScriptManager::messageBox; + +ScriptManager* ScriptManager::thisScriptManager= NULL; +const int ScriptManager::messageWrapCount= 30; +const int ScriptManager::displayTextWrapCount= 64; + +void ScriptManager::init(World* world, GameCamera *gameCamera){ + const Scenario* scenario= world->getScenario(); + + this->world= world; + this->gameCamera= gameCamera; + + //set static instance + thisScriptManager= this; + + //register functions + luaScript.registerFunction(showMessage, "showMessage"); + luaScript.registerFunction(setDisplayText, "setDisplayText"); + luaScript.registerFunction(clearDisplayText, "clearDisplayText"); + luaScript.registerFunction(setCameraPosition, "setCameraPosition"); + luaScript.registerFunction(createUnit, "createUnit"); + luaScript.registerFunction(giveResource, "giveResource"); + luaScript.registerFunction(givePositionCommand, "givePositionCommand"); + luaScript.registerFunction(giveProductionCommand, "giveProductionCommand"); + luaScript.registerFunction(giveUpgradeCommand, "giveUpgradeCommand"); + luaScript.registerFunction(disableAi, "disableAi"); + luaScript.registerFunction(setPlayerAsWinner, "setPlayerAsWinner"); + luaScript.registerFunction(endGame, "endGame"); + + luaScript.registerFunction(getStartLocation, "startLocation"); + luaScript.registerFunction(getUnitPosition, "unitPosition"); + luaScript.registerFunction(getUnitFaction, "unitFaction"); + luaScript.registerFunction(getResourceAmount, "resourceAmount"); + luaScript.registerFunction(getLastCreatedUnitName, "lastCreatedUnitName"); + luaScript.registerFunction(getLastCreatedUnitId, "lastCreatedUnit"); + luaScript.registerFunction(getLastDeadUnitName, "lastDeadUnitName"); + luaScript.registerFunction(getLastDeadUnitId, "lastDeadUnit"); + luaScript.registerFunction(getUnitCount, "unitCount"); + luaScript.registerFunction(getUnitCountOfType, "unitCountOfType"); + + + //load code + for(int i= 0; igetScriptCount(); ++i){ + const Script* script= scenario->getScript(i); + luaScript.loadCode("function " + script->getName() + "()" + script->getCode() + "end\n", script->getName()); + } + + //setup message box + messageBox.init( Lang::getInstance().get("Ok") ); + messageBox.setEnabled(false); + + //last created unit + lastCreatedUnitId= -1; + lastDeadUnitId= -1; + gameOver= false; + + //call startup function + luaScript.beginCall("startup"); + luaScript.endCall(); +} + +// ========================== events =============================================== + +void ScriptManager::onMessageBoxOk(){ + Lang &lang= Lang::getInstance(); + + if(!messageQueue.empty()){ + messageQueue.pop(); + if(!messageQueue.empty()){ + messageBox.setText(wrapString(lang.getScenarioString(messageQueue.front().getText()), messageWrapCount)); + messageBox.setHeader(lang.getScenarioString(messageQueue.front().getHeader())); + } + } +} + +void ScriptManager::onResourceHarvested(){ + luaScript.beginCall("resourceHarvested"); + luaScript.endCall(); +} + +void ScriptManager::onUnitCreated(const Unit* unit){ + lastCreatedUnitName= unit->getType()->getName(); + lastCreatedUnitId= unit->getId(); + luaScript.beginCall("unitCreated"); + luaScript.endCall(); + luaScript.beginCall("unitCreatedOfType_"+unit->getType()->getName()); + luaScript.endCall(); +} + +void ScriptManager::onUnitDied(const Unit* unit){ + lastDeadUnitName= unit->getType()->getName(); + lastDeadUnitId= unit->getId(); + luaScript.beginCall("unitDied"); + luaScript.endCall(); +} + +// ========================== lua wrappers =============================================== + +string ScriptManager::wrapString(const string &str, int wrapCount){ + + string returnString; + + int letterCount= 0; + for(int i= 0; iwrapCount && str[i]==' '){ + returnString+= '\n'; + letterCount= 0; + } + else + { + returnString+= str[i]; + } + ++letterCount; + } + + return returnString; +} + +void ScriptManager::showMessage(const string &text, const string &header){ + Lang &lang= Lang::getInstance(); + + messageQueue.push(ScriptManagerMessage(text, header)); + messageBox.setEnabled(true); + messageBox.setText(wrapString(lang.getScenarioString(messageQueue.front().getText()), messageWrapCount)); + messageBox.setHeader(lang.getScenarioString(messageQueue.front().getHeader())); +} + +void ScriptManager::clearDisplayText(){ + displayText= ""; +} + +void ScriptManager::setDisplayText(const string &text){ + displayText= wrapString(Lang::getInstance().getScenarioString(text), displayTextWrapCount); +} + +void ScriptManager::setCameraPosition(const Vec2i &pos){ + gameCamera->centerXZ(pos.x, pos.y); +} + +void ScriptManager::createUnit(const string &unitName, int factionIndex, Vec2i pos){ + world->createUnit(unitName, factionIndex, pos); +} + +void ScriptManager::giveResource(const string &resourceName, int factionIndex, int amount){ + world->giveResource(resourceName, factionIndex, amount); +} + +void ScriptManager::givePositionCommand(int unitId, const string &commandName, const Vec2i &pos){ + world->givePositionCommand(unitId, commandName, pos); +} + +void ScriptManager::giveProductionCommand(int unitId, const string &producedName){ + world->giveProductionCommand(unitId, producedName); +} + +void ScriptManager::giveUpgradeCommand(int unitId, const string &producedName){ + world->giveUpgradeCommand(unitId, producedName); +} + +void ScriptManager::disableAi(int factionIndex){ + if(factionIndexgetStartLocation(factionIndex); +} + + +Vec2i ScriptManager::getUnitPosition(int unitId){ + return world->getUnitPosition(unitId); +} + +int ScriptManager::getUnitFaction(int unitId){ + return world->getUnitFactionIndex(unitId); +} + +int ScriptManager::getResourceAmount(const string &resourceName, int factionIndex){ + return world->getResourceAmount(resourceName, factionIndex); +} + +const string &ScriptManager::getLastCreatedUnitName(){ + return lastCreatedUnitName; +} + +int ScriptManager::getLastCreatedUnitId(){ + return lastCreatedUnitId; +} + +const string &ScriptManager::getLastDeadUnitName(){ + return lastDeadUnitName; +} + +int ScriptManager::getLastDeadUnitId(){ + return lastDeadUnitId; +} + +int ScriptManager::getUnitCount(int factionIndex){ + return world->getUnitCount(factionIndex); +} + +int ScriptManager::getUnitCountOfType(int factionIndex, const string &typeName){ + return world->getUnitCountOfType(factionIndex, typeName); +} + +// ========================== lua callbacks =============================================== + +int ScriptManager::showMessage(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + thisScriptManager->showMessage(luaArguments.getString(-2), luaArguments.getString(-1)); + return luaArguments.getReturnCount(); +} + +int ScriptManager::setDisplayText(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + thisScriptManager->setDisplayText(luaArguments.getString(-1)); + return luaArguments.getReturnCount(); +} + +int ScriptManager::clearDisplayText(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + thisScriptManager->clearDisplayText(); + return luaArguments.getReturnCount(); +} + +int ScriptManager::setCameraPosition(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + thisScriptManager->setCameraPosition(Vec2i(luaArguments.getVec2i(-1))); + return luaArguments.getReturnCount(); +} + +int ScriptManager::createUnit(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + thisScriptManager->createUnit( + luaArguments.getString(-3), + luaArguments.getInt(-2), + luaArguments.getVec2i(-1)); + return luaArguments.getReturnCount(); +} + +int ScriptManager::giveResource(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + thisScriptManager->giveResource(luaArguments.getString(-3), luaArguments.getInt(-2), luaArguments.getInt(-1)); + return luaArguments.getReturnCount(); +} + +int ScriptManager::givePositionCommand(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + thisScriptManager->givePositionCommand( + luaArguments.getInt(-3), + luaArguments.getString(-2), + luaArguments.getVec2i(-1)); + return luaArguments.getReturnCount(); +} + + +int ScriptManager::giveProductionCommand(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + thisScriptManager->giveProductionCommand( + luaArguments.getInt(-2), + luaArguments.getString(-1)); + return luaArguments.getReturnCount(); +} + +int ScriptManager::giveUpgradeCommand(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + thisScriptManager->giveUpgradeCommand( + luaArguments.getInt(-2), + luaArguments.getString(-1)); + return luaArguments.getReturnCount(); +} + +int ScriptManager::disableAi(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + thisScriptManager->disableAi(luaArguments.getInt(-1)); + return luaArguments.getReturnCount(); +} + +int ScriptManager::setPlayerAsWinner(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + thisScriptManager->setPlayerAsWinner(luaArguments.getInt(-1)); + return luaArguments.getReturnCount(); +} + +int ScriptManager::endGame(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + thisScriptManager->endGame(); + return luaArguments.getReturnCount(); +} + +int ScriptManager::getStartLocation(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + Vec2i pos= thisScriptManager->getStartLocation(luaArguments.getInt(-1)); + luaArguments.returnVec2i(pos); + return luaArguments.getReturnCount(); +} + +int ScriptManager::getUnitPosition(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + Vec2i pos= thisScriptManager->getUnitPosition(luaArguments.getInt(-1)); + luaArguments.returnVec2i(pos); + return luaArguments.getReturnCount(); +} + +int ScriptManager::getUnitFaction(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + int factionIndex= thisScriptManager->getUnitFaction(luaArguments.getInt(-1)); + luaArguments.returnInt(factionIndex); + return luaArguments.getReturnCount(); +} + +int ScriptManager::getResourceAmount(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + luaArguments.returnInt(thisScriptManager->getResourceAmount(luaArguments.getString(-2), luaArguments.getInt(-1))); + return luaArguments.getReturnCount(); +} + +int ScriptManager::getLastCreatedUnitName(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + luaArguments.returnString(thisScriptManager->getLastCreatedUnitName()); + return luaArguments.getReturnCount(); +} + +int ScriptManager::getLastCreatedUnitId(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + luaArguments.returnInt(thisScriptManager->getLastCreatedUnitId()); + return luaArguments.getReturnCount(); +} + +int ScriptManager::getLastDeadUnitName(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + luaArguments.returnString(thisScriptManager->getLastDeadUnitName()); + return luaArguments.getReturnCount(); +} + +int ScriptManager::getLastDeadUnitId(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + luaArguments.returnInt(thisScriptManager->getLastDeadUnitId()); + return luaArguments.getReturnCount(); +} + +int ScriptManager::getUnitCount(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + luaArguments.returnInt(thisScriptManager->getUnitCount(luaArguments.getInt(-1))); + return luaArguments.getReturnCount(); +} + +int ScriptManager::getUnitCountOfType(LuaHandle* luaHandle){ + LuaArguments luaArguments(luaHandle); + luaArguments.returnInt(thisScriptManager->getUnitCountOfType(luaArguments.getInt(-2), luaArguments.getString(-1))); + return luaArguments.getReturnCount(); +} + +}}//end namespace diff --git a/source/glest_game/game/script_manager.h b/source/glest_game/game/script_manager.h new file mode 100644 index 000000000..61de09468 --- /dev/null +++ b/source/glest_game/game/script_manager.h @@ -0,0 +1,183 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2005 Martiņo Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#ifndef _GLEST_GAME_SCRIPT_MANAGER_H_ +#define _GLEST_GAME_SCRIPT_MANAGER_H_ + +#include +#include + +#include "lua_script.h" +#include "vec.h" + +#include "components.h" +#include "game_constants.h" + +using std::string; +using std::queue; +using Shared::Graphics::Vec2i; +using Shared::Lua::LuaScript; +using Shared::Lua::LuaHandle; + +namespace Glest{ namespace Game{ + +class World; +class Unit; +class GameCamera; + +// ===================================================== +// class ScriptManagerMessage +// ===================================================== + +class ScriptManagerMessage{ +private: + string text; + string header; + +public: + ScriptManagerMessage(string text, string header) {this->text= text, this->header= header;} + const string &getText() const {return text;} + const string &getHeader() const {return header;} +}; + +class PlayerModifiers{ +public: + PlayerModifiers(); + + void disableAi() {aiEnabled= false;} + void setAsWinner() {winner= true;} + + bool getWinner() const {return winner;} + bool getAiEnabled() const {return aiEnabled;} + +private: + bool winner; + bool aiEnabled; +}; + +// ===================================================== +// class ScriptManager +// ===================================================== + +class ScriptManager{ +private: + typedef queue MessageQueue; + +private: + + //lua + string code; + LuaScript luaScript; + + //world + World *world; + GameCamera *gameCamera; + + //misc + MessageQueue messageQueue; + static GraphicMessageBox messageBox; + string displayText; + + //last created unit + string lastCreatedUnitName; + int lastCreatedUnitId; + + //last dead unit + string lastDeadUnitName; + int lastDeadUnitId; + + // end game state + bool gameOver; + PlayerModifiers playerModifiers[GameConstants::maxPlayers]; + +private: + static ScriptManager* thisScriptManager; + +private: + static const int messageWrapCount; + static const int displayTextWrapCount; + +public: + void init(World* world, GameCamera *gameCamera); + + //message box functions + bool getMessageBoxEnabled() const {return !messageQueue.empty();} + static GraphicMessageBox* getMessageBox() {return &messageBox;} + string getDisplayText() const {return displayText;} + bool getGameOver() const {return gameOver;} + const PlayerModifiers *getPlayerModifiers(int factionIndex) const {return &playerModifiers[factionIndex];} + + //events + void onMessageBoxOk(); + void onResourceHarvested(); + void onUnitCreated(const Unit* unit); + void onUnitDied(const Unit* unit); + +private: + + string wrapString(const string &str, int wrapCount); + + //wrappers, commands + void showMessage(const string &text, const string &header); + void clearDisplayText(); + void setDisplayText(const string &text); + void setCameraPosition(const Vec2i &pos); + void createUnit(const string &unitName, int factionIndex, Vec2i pos); + void giveResource(const string &resourceName, int factionIndex, int amount); + void givePositionCommand(int unitId, const string &producedName, const Vec2i &pos); + void giveProductionCommand(int unitId, const string &producedName); + void giveUpgradeCommand(int unitId, const string &upgradeName); + void disableAi(int factionIndex); + void setPlayerAsWinner(int factionIndex); + void endGame(); + + //wrappers, queries + Vec2i getStartLocation(int factionIndex); + Vec2i getUnitPosition(int unitId); + int getUnitFaction(int unitId); + int getResourceAmount(const string &resourceName, int factionIndex); + const string &getLastCreatedUnitName(); + int getLastCreatedUnitId(); + const string &getLastDeadUnitName(); + int getLastDeadUnitId(); + int getUnitCount(int factionIndex); + int getUnitCountOfType(int factionIndex, const string &typeName); + + //callbacks, commands + static int showMessage(LuaHandle* luaHandle); + static int setDisplayText(LuaHandle* luaHandle); + static int clearDisplayText(LuaHandle* luaHandle); + static int setCameraPosition(LuaHandle* luaHandle); + static int createUnit(LuaHandle* luaHandle); + static int giveResource(LuaHandle* luaHandle); + static int givePositionCommand(LuaHandle* luaHandle); + static int giveProductionCommand(LuaHandle* luaHandle); + static int giveUpgradeCommand(LuaHandle* luaHandle); + static int disableAi(LuaHandle* luaHandle); + static int setPlayerAsWinner(LuaHandle* luaHandle); + static int endGame(LuaHandle* luaHandle); + + //callbacks, queries + static int getStartLocation(LuaHandle* luaHandle); + static int getUnitPosition(LuaHandle* luaHandle); + static int getUnitFaction(LuaHandle* luaHandle); + static int getResourceAmount(LuaHandle* luaHandle); + static int getLastCreatedUnitName(LuaHandle* luaHandle); + static int getLastCreatedUnitId(LuaHandle* luaHandle); + static int getLastDeadUnitName(LuaHandle* luaHandle); + static int getLastDeadUnitId(LuaHandle* luaHandle); + static int getUnitCount(LuaHandle* luaHandle); + static int getUnitCountOfType(LuaHandle* luaHandle); +}; + +}}//end namespace + +#endif diff --git a/source/glest_game/main/main.cpp b/source/glest_game/main/main.cpp index 33be1e70e..69ed9ad10 100644 --- a/source/glest_game/main/main.cpp +++ b/source/glest_game/main/main.cpp @@ -90,16 +90,22 @@ MainWindow::~MainWindow(){ delete program; } +void MainWindow::eventMouseWheel(int x, int y, int zDelta) { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + program->eventMouseWheel(x, y, zDelta); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); +} + void MainWindow::eventMouseDown(int x, int y, MouseButton mouseButton){ switch(mouseButton){ - case mbLeft: - program->mouseDownLeft(x, getH() - y); - break; - case mbRight: - program->mouseDownRight(x, getH() - y); - break; - default: - break; + case mbLeft: + program->mouseDownLeft(x, getH() - y); + break; + case mbRight: + program->mouseDownRight(x, getH() - y); + break; + default: + break; } } diff --git a/source/glest_game/main/main.h b/source/glest_game/main/main.h new file mode 100644 index 000000000..7ea4b7eab --- /dev/null +++ b/source/glest_game/main/main.h @@ -0,0 +1,56 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2008 Martiņo Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#ifndef _GLEST_GAME_MAIN_H_ +#define _GLEST_GAME_MAIN_H_ + +#include + +#include "program.h" +#include "window_gl.h" + +using Shared::Platform::MouseButton; +using Shared::Platform::MouseState; + +namespace Glest{ namespace Game{ + +// ===================================================== +// class MainWindow +// +/// Main program window +// ===================================================== + +class MainWindow: public WindowGl{ +private: + Program* program; + +public: + MainWindow(Program *program); + ~MainWindow(); + + void setProgram(Program *program) {this->program= program;} + + virtual void eventMouseDown(int x, int y, MouseButton mouseButton); + virtual void eventMouseUp(int x, int y, MouseButton mouseButton); + virtual void eventMouseDoubleClick(int x, int y, MouseButton mouseButton); + virtual void eventMouseMove(int x, int y, const MouseState *mouseState); + virtual void eventKeyDown(char key); + virtual void eventMouseWheel(int x, int y, int zDelta); + virtual void eventKeyUp(char key); + virtual void eventKeyPress(char c); + virtual void eventActivate(bool active); + virtual void eventResize(SizeState sizeState); + virtual void eventClose(); +}; + +}}//end namespace + +#endif diff --git a/source/glest_game/main/program.cpp b/source/glest_game/main/program.cpp index 23fd4ac76..3b831b195 100644 --- a/source/glest_game/main/program.cpp +++ b/source/glest_game/main/program.cpp @@ -49,11 +49,11 @@ Program *Program::singleton = NULL; Program::ShowMessageProgramState::ShowMessageProgramState(Program *program, const char *msg) : ProgramState(program) { - //if(Socket::enableDebugText) printf("In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); userWantsExit = false; msgBox.init("Ok"); - //if(Socket::enableDebugText) printf("In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); if(msg) { fprintf(stderr, "%s\n", msg); @@ -61,12 +61,12 @@ Program::ShowMessageProgramState::ShowMessageProgramState(Program *program, cons } else { msgBox.setText("Mega-Glest has crashed."); } - //if(Socket::enableDebugText) printf("In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); mouse2dAnim = mouseY = mouseX = 0; this->msg = (msg ? msg : ""); - //if(Socket::enableDebugText) printf("In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); } void Program::ShowMessageProgramState::render() { @@ -79,16 +79,16 @@ void Program::ShowMessageProgramState::render() { } void Program::ShowMessageProgramState::mouseDownLeft(int x, int y) { - //if(Socket::enableDebugText) printf("In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); if(msgBox.mouseClick(x,y)) { - //if(Socket::enableDebugText) printf("In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); program->exit(); userWantsExit = true; } - //if(Socket::enableDebugText) printf("In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); } void Program::ShowMessageProgramState::mouseMove(int x, int y, const MouseState &mouseState) { @@ -162,6 +162,17 @@ void Program::mouseDoubleClickLeft(int x, int y){ programState->mouseDoubleClickLeft(metrics.toVirtualX(x), metrics.toVirtualY(y)); } +void Program::eventMouseWheel(int x, int y, int zDelta) { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + + const Metrics &metrics= Metrics::getInstance(); + int vx = metrics.toVirtualX(x); + int vy = metrics.toVirtualY(window->getH() - y); + + programState->eventMouseWheel(vx, vy, zDelta); +} + + void Program::mouseMove(int x, int y, const MouseState *ms){ const Metrics &metrics= Metrics::getInstance(); programState->mouseMove(metrics.toVirtualX(x), metrics.toVirtualY(y), ms); @@ -223,35 +234,35 @@ void Program::resize(SizeState sizeState){ void Program::setState(ProgramState *programState) { - //if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] START\n",__FILE__,__FUNCTION__); delete this->programState; - //if(Socket::enableDebugText) printf("In [%s::%s] %d\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] %d\n",__FILE__,__FUNCTION__,__LINE__); this->programState= programState; programState->load(); - //if(Socket::enableDebugText) printf("In [%s::%s] %d\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] %d\n",__FILE__,__FUNCTION__,__LINE__); programState->init(); - //if(Socket::enableDebugText) printf("In [%s::%s] %d\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] %d\n",__FILE__,__FUNCTION__,__LINE__); updateTimer.reset(); updateCameraTimer.reset(); fpsTimer.reset(); - //if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] END\n",__FILE__,__FUNCTION__); } void Program::exit() { - //if(Socket::enableDebugText) printf("In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); window->destroy(); - //if(Socket::enableDebugText) printf("In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); } // ==================== PRIVATE ==================== @@ -349,7 +360,7 @@ void Program::restoreDisplaySettings(){ } void Program::showMessage(const char *msg) { - //if(Socket::enableDebugText) printf("In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); ProgramState *originalState = NULL; if(this->programState) { @@ -357,7 +368,7 @@ void Program::showMessage(const char *msg) { originalState = this->programState; } - //if(Socket::enableDebugText) printf("In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); showCursor(true); @@ -368,18 +379,18 @@ void Program::showMessage(const char *msg) { this->programState = NULL; setState(showMsg); - //if(Socket::enableDebugText) printf("In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); while(Window::handleEvent() && showMsg->wantExit() == false) { loop(); } - //if(Socket::enableDebugText) printf("In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); delete this->programState; this->programState = NULL; - //if(Socket::enableDebugText) printf("In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); showCursor(Config::getInstance().getBool("Windowed")); @@ -387,20 +398,20 @@ void Program::showMessage(const char *msg) { init(this->window,false); //setState(originalState); - //if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] START\n",__FILE__,__FUNCTION__); delete this->programState; - //if(Socket::enableDebugText) printf("In [%s::%s] %d\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] %d\n",__FILE__,__FUNCTION__,__LINE__); this->programState= originalState; //programState->load(); - //if(Socket::enableDebugText) printf("In [%s::%s] %d\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] %d\n",__FILE__,__FUNCTION__,__LINE__); //programState->init(); - //if(Socket::enableDebugText) printf("In [%s::%s] %d\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] %d\n",__FILE__,__FUNCTION__,__LINE__); //updateTimer.reset(); //updateCameraTimer.reset(); @@ -409,7 +420,7 @@ void Program::showMessage(const char *msg) { //this->programState = originalState; - //if(Socket::enableDebugText) printf("In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s %d]\n",__FILE__,__FUNCTION__,__LINE__); } diff --git a/source/glest_game/main/program.h b/source/glest_game/main/program.h index e77d4c896..4b64487a5 100644 --- a/source/glest_game/main/program.h +++ b/source/glest_game/main/program.h @@ -55,7 +55,8 @@ public: virtual void mouseDownLeft(int x, int y){}; virtual void mouseUpLeft(int x, int y){}; virtual void mouseDownRight(int x, int y){}; - virtual void mouseDoubleClickLeft(int x, int y){}; + virtual void mouseDoubleClickLeft(int x, int y){}; + virtual void eventMouseWheel(int x, int y, int zDelta){} virtual void mouseMove(int x, int y, const MouseState *mouseState) {}; virtual void keyDown(char key){}; virtual void keyUp(char key){}; @@ -113,7 +114,9 @@ public: void mouseDownLeft(int x, int y); void mouseUpLeft(int x, int y); void mouseDownRight(int x, int y); - void mouseDoubleClickLeft(int x, int y); + void mouseDoubleClickLeft(int x, int y); + void eventMouseWheel(int x, int y, int zDelta); + void mouseMove(int x, int y, const MouseState *mouseState); void keyDown(char key); void keyUp(char key); diff --git a/source/shared_lib/include/platform/sdl/window.h b/source/shared_lib/include/platform/sdl/window.h new file mode 100644 index 000000000..d6b90b43f --- /dev/null +++ b/source/shared_lib/include/platform/sdl/window.h @@ -0,0 +1,148 @@ +// ============================================================== +// This file is part of Glest Shared Library (www.glest.org) +// +// Copyright (C) 2005 Matthias Braun +// +// You can redistribute this code 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 +// ============================================================== + +#ifndef _SHARED_PLATFORM_WINDOW_H_ +#define _SHARED_PLATFORM_WINDOW_H_ + +#include +#include +#include + +#include "types.h" + +using std::map; +using std::string; + +namespace Shared{ namespace Platform{ + +class Timer; +class PlatformContextGl; + +enum MouseButton{ + mbLeft, + mbRight, + mbCenter, + mbWheelUp, + mbWheelDown + +}; + +enum SizeState{ + ssMaximized, + ssMinimized, + ssRestored +}; + +// keycode constants (unfortunately designed after DirectInput and therefore not +// very specific) +// They also have to fit into a char. The positive numbers seem to be equal +// to ascii, for the rest we have to find sensefull mappings from SDL (which is +// alot more fine grained like left/right control instead of just control...) +const char vkAdd = -1; +const char vkSubtract = -2; +const char vkAlt = -3; +const char vkControl = -4; +const char vkShift = -5; +const char vkEscape = -6; +const char vkUp = -7; +const char vkLeft = -8; +const char vkRight = -9; +const char vkDown = -10; +const char vkReturn = -11; +const char vkBack = -12; + +struct MouseState{ + bool leftMouse; + bool rightMouse; + bool centerMouse; +}; + +enum WindowStyle{ + wsFullscreen, + wsWindowedFixed, + wsWindowedResizable +}; + +// ===================================================== +// class Window +// ===================================================== + +class Window { +private: + Uint32 lastMouseDown[3]; + int lastMouseX[3]; + int lastMouseY[3]; + +protected: + int w, h; + +public: + static bool handleEvent(); + + Window(); + virtual ~Window(); + + WindowHandle getHandle() {return 0;} + string getText(); + int getX() { return 0; } + int getY() { return 0; } + int getW() { return w; } + int getH() { return h; } + + //component state + int getClientW() { return getW(); } + int getClientH() { return getH(); } + float getAspect(); + + //object state + void setText(string text); + void setStyle(WindowStyle windowStyle); + void setSize(int w, int h); + void setPos(int x, int y); + void setEnabled(bool enabled); + void setVisible(bool visible); + + //misc + void create(); + void destroy(); + void minimize(); + +protected: + virtual void eventCreate(){} + virtual void eventMouseDown(int x, int y, MouseButton mouseButton){} + virtual void eventMouseUp(int x, int y, MouseButton mouseButton){} + virtual void eventMouseMove(int x, int y, const MouseState* mouseState){} + virtual void eventMouseDoubleClick(int x, int y, MouseButton mouseButton){} + virtual void eventMouseWheel(int x, int y, int zDelta) {} + virtual void eventKeyDown(char key){} + virtual void eventKeyUp(char key){} + virtual void eventKeyPress(char c){} + virtual void eventResize(){}; + virtual void eventPaint(){} + virtual void eventTimer(int timerId){} + virtual void eventActivate(bool activated){}; + virtual void eventResize(SizeState sizeState){}; + virtual void eventMenu(int menuId){} + virtual void eventClose(){}; + virtual void eventDestroy(){}; + +private: + /// needed to detect double clicks + void handleMouseDown(SDL_Event event); + + static MouseButton getMouseButton(int sdlButton); + static char getKey(SDL_keysym keysym); + static void toggleFullscreen(); +}; + +}}//end namespace + +#endif diff --git a/source/shared_lib/include/platform/win32/window.h b/source/shared_lib/include/platform/win32/window.h new file mode 100644 index 000000000..ff6116ede --- /dev/null +++ b/source/shared_lib/include/platform/win32/window.h @@ -0,0 +1,159 @@ +// ============================================================== +// This file is part of Glest Shared Library (www.glest.org) +// +// Copyright (C) 2001-2008 Martiņo Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#ifndef _SHARED_PLATFORM_WINDOW_H_ +#define _SHARED_PLATFORM_WINDOW_H_ + +#include +#include + +#include "types.h" +#include "platform_menu.h" + +using std::map; +using std::string; + +namespace Shared{ namespace Platform{ + +class Timer; +class PlatformContextGl; + +enum MouseButton{ + mbLeft, + mbRight, + mbCenter +}; + +enum SizeState{ + ssMaximized, + ssMinimized, + ssRestored +}; + +const int vkAdd= VK_ADD; +const int vkSubtract= VK_SUBTRACT; +const int vkAlt= VK_MENU; +const int vkControl= VK_CONTROL; +const int vkShift= VK_SHIFT; +const int vkEscape= VK_ESCAPE; +const int vkUp= VK_UP; +const int vkLeft= VK_LEFT; +const int vkRight= VK_RIGHT; +const int vkDown= VK_DOWN; +const int vkReturn= VK_RETURN; +const int vkBack= VK_BACK; +const int vkDelete= VK_DELETE; +const int vkF1= VK_F1; + +struct MouseState{ + bool leftMouse; + bool rightMouse; + bool centerMouse; +}; + +enum WindowStyle{ + wsFullscreen, + wsWindowedFixed, + wsWindowedResizeable +}; + +// ===================================================== +// class Window +// ===================================================== + +class Window{ +private: + typedef map WindowMap; + +private: + static const DWORD fullscreenStyle; + static const DWORD windowedFixedStyle; + static const DWORD windowedResizeableStyle; + + static int nextClassName; + static WindowMap createdWindows; + +protected: + WindowHandle handle; + WindowStyle windowStyle; + string text; + int x; + int y; + int w; + int h; + string className; + DWORD style; + DWORD exStyle; + bool ownDc; + +public: + static bool handleEvent(); + + //contructor & destructor + Window(); + virtual ~Window(); + + WindowHandle getHandle() {return handle;} + string getText(); + int getX() {return x;} + int getY() {return y;} + int getW() {return w;} + int getH() {return h;} + + //component state + int getClientW(); + int getClientH(); + float getAspect(); + + //object state + void setText(string text); + void setStyle(WindowStyle windowStyle); + void setSize(int w, int h); + void setPos(int x, int y); + void setEnabled(bool enabled); + void setVisible(bool visible); + + //misc + void create(); + void minimize(); + void maximize(); + void restore(); + void showPopupMenu(Menu *menu, int x, int y); + void destroy(); + +protected: + virtual void eventCreate(){} + virtual void eventMouseDown(int x, int y, MouseButton mouseButton){} + virtual void eventMouseUp(int x, int y, MouseButton mouseButton){} + virtual void eventMouseMove(int x, int y, const MouseState *mouseState){} + virtual void eventMouseDoubleClick(int x, int y, MouseButton mouseButton){} + virtual void eventKeyDown(char key){} + virtual void eventMouseWheel(int x, int y, int zDelta){} + virtual void eventKeyUp(char key){} + virtual void eventKeyPress(char c){}; + virtual void eventResize(){}; + virtual void eventPaint(){} + virtual void eventActivate(bool activated){}; + virtual void eventResize(SizeState sizeState){}; + virtual void eventMenu(int menuId){} + virtual void eventClose(){}; + virtual void eventDestroy(){}; + +private: + static LRESULT CALLBACK eventRouter(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + static int getNextClassName(); + void registerWindow(WNDPROC wndProc= NULL); + void createWindow(LPVOID creationData= NULL); +}; + +}}//end namespace + +#endif diff --git a/source/shared_lib/sources/platform/sdl/window.cpp b/source/shared_lib/sources/platform/sdl/window.cpp new file mode 100644 index 000000000..7f9e7c87b --- /dev/null +++ b/source/shared_lib/sources/platform/sdl/window.cpp @@ -0,0 +1,325 @@ +//This file is part of Glest Shared Library (www.glest.org) +//Copyright (C) 2005 Matthias Braun + +//You can redistribute this code 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. + +#include "window.h" + +#include +#include +#include +#include + +#include "conversion.h" +#include "platform_util.h" +#include "leak_dumper.h" +#include "sdl_private.h" +#include "noimpl.h" + +using namespace Shared::Util; +using namespace std; + +namespace Shared{ namespace Platform{ + +// ======================================= +// WINDOW +// ======================================= + +// ========== STATIC INICIALIZATIONS ========== + +// Matze: hack for now... +static Window* global_window = 0; + +// ========== PUBLIC ========== + +Window::Window() { + memset(lastMouseDown, 0, sizeof(lastMouseDown)); + + assert(global_window == 0); + global_window = this; +} + +Window::~Window() { + assert(global_window == this); + global_window = 0; +} + +bool Window::handleEvent() { + SDL_Event event; + while(SDL_PollEvent(&event)) { + try { + //printf("[%d]\n",event.type); + + switch(event.type) { + case SDL_QUIT: + return false; + case SDL_MOUSEBUTTONDOWN: + global_window->handleMouseDown(event); + break; + case SDL_MOUSEBUTTONUP: { + global_window->eventMouseUp(event.button.x, + event.button.y,getMouseButton(event.button.button)); + break; + } + case SDL_MOUSEMOTION: { + MouseState ms; + ms.leftMouse = (event.motion.state & SDL_BUTTON_LMASK) != 0; + ms.rightMouse = (event.motion.state & SDL_BUTTON_RMASK) != 0; + ms.centerMouse = (event.motion.state & SDL_BUTTON_MMASK) != 0; + global_window->eventMouseMove(event.motion.x, event.motion.y, &ms); + break; + } + case SDL_KEYDOWN: + /* handle ALT+Return */ + if(event.key.keysym.sym == SDLK_RETURN + && (event.key.keysym.mod & (KMOD_LALT | KMOD_RALT))) { + toggleFullscreen(); + } + global_window->eventKeyDown(getKey(event.key.keysym)); + global_window->eventKeyPress(static_cast(event.key.keysym.unicode)); + break; + case SDL_KEYUP: + global_window->eventKeyUp(getKey(event.key.keysym)); + break; + } + } catch(std::exception& e) { + std::cerr << "Couldn't process event: " << e.what() << "\n"; + } + } + + return true; +} + +string Window::getText() { + char* c = 0; + SDL_WM_GetCaption(&c, 0); + + return string(c); +} + +float Window::getAspect() { + return static_cast(getClientH())/getClientW(); +} + +void Window::setText(string text) { + SDL_WM_SetCaption(text.c_str(), 0); +} + +void Window::setSize(int w, int h) { + this->w = w; + this->h = h; + Private::ScreenWidth = w; + Private::ScreenHeight = h; +} + +void Window::setPos(int x, int y) { + if(x != 0 || y != 0) { + NOIMPL; + return; + } +} + +void Window::minimize() { + NOIMPL; +} + +void Window::setEnabled(bool enabled) { + NOIMPL; +} + +void Window::setVisible(bool visible) { + NOIMPL; +} + +void Window::setStyle(WindowStyle windowStyle) { + if(windowStyle == wsFullscreen) + return; + // NOIMPL; +} + +void Window::create() { + // nothing here +} + +void Window::destroy() { + SDL_Event event; + event.type = SDL_QUIT; + SDL_PushEvent(&event); +} + +void Window::toggleFullscreen() { + SDL_WM_ToggleFullScreen(SDL_GetVideoSurface()); +} + +void Window::handleMouseDown(SDL_Event event) { + static const Uint32 DOUBLECLICKTIME = 500; + static const int DOUBLECLICKDELTA = 5; + + MouseButton button = getMouseButton(event.button.button); + + // windows implementation uses 120 for the resolution of a standard mouse + // wheel notch. However, newer mice have finer resolutions. I dunno if SDL + // handles those, but for now we're going to say that each mouse wheel + // movement is 120. + if(button == mbWheelUp) { + //printf("button == mbWheelUp\n"); + eventMouseWheel(event.button.x, event.button.y, 120); + return; + } else if(button == mbWheelDown) { + //printf("button == mbWheelDown\n"); + eventMouseWheel(event.button.x, event.button.y, -120); + return; + } + + + Uint32 ticks = SDL_GetTicks(); + int n = (int) button; + if(ticks - lastMouseDown[n] < DOUBLECLICKTIME + && abs(lastMouseX[n] - event.button.x) < DOUBLECLICKDELTA + && abs(lastMouseY[n] - event.button.y) < DOUBLECLICKDELTA) { + eventMouseDown(event.button.x, event.button.y, button); + eventMouseDoubleClick(event.button.x, event.button.y, button); + } else { + eventMouseDown(event.button.x, event.button.y, button); + } + lastMouseDown[n] = ticks; + lastMouseX[n] = event.button.x; + lastMouseY[n] = event.button.y; +} + +MouseButton Window::getMouseButton(int sdlButton) { + switch(sdlButton) { + case SDL_BUTTON_LEFT: + return mbLeft; + case SDL_BUTTON_RIGHT: + return mbRight; + case SDL_BUTTON_MIDDLE: + return mbCenter; + case SDL_BUTTON_WHEELUP: + return mbWheelUp; + case SDL_BUTTON_WHEELDOWN: + return mbWheelDown; + default: + throw std::runtime_error("Mouse Button > 3 not handled."); + } +} + +char Window::getKey(SDL_keysym keysym) { + switch(keysym.sym) { + case SDLK_PLUS: + case SDLK_KP_PLUS: + return vkAdd; + case SDLK_MINUS: + case SDLK_KP_MINUS: + return vkSubtract; + case SDLK_LALT: + case SDLK_RALT: + return vkAlt; + case SDLK_LCTRL: + case SDLK_RCTRL: + return vkControl; + case SDLK_LSHIFT: + case SDLK_RSHIFT: + return vkShift; + case SDLK_ESCAPE: + return vkEscape; + case SDLK_UP: + return vkUp; + case SDLK_LEFT: + return vkLeft; + case SDLK_RIGHT: + return vkRight; + case SDLK_DOWN: + return vkDown; + case SDLK_RETURN: + case SDLK_KP_ENTER: + return vkReturn; + case SDLK_BACKSPACE: + return vkBack; + case SDLK_0: + return '0'; + case SDLK_1: + return '1'; + case SDLK_2: + return '2'; + case SDLK_3: + return '3'; + case SDLK_4: + return '4'; + case SDLK_5: + return '5'; + case SDLK_6: + return '6'; + case SDLK_7: + return '7'; + case SDLK_8: + return '8'; + case SDLK_9: + return '9'; + case SDLK_a: + return 'A'; + case SDLK_b: + return 'B'; + case SDLK_c: + return 'C'; + case SDLK_d: + return 'D'; + case SDLK_e: + return 'E'; + case SDLK_f: + return 'F'; + case SDLK_g: + return 'G'; + case SDLK_h: + return 'H'; + case SDLK_i: + return 'I'; + case SDLK_j: + return 'J'; + case SDLK_k: + return 'K'; + case SDLK_l: + return 'L'; + case SDLK_m: + return 'M'; + case SDLK_n: + return 'N'; + case SDLK_o: + return 'O'; + case SDLK_p: + return 'P'; + case SDLK_q: + return 'Q'; + case SDLK_r: + return 'R'; + case SDLK_s: + return 'S'; + case SDLK_t: + return 'T'; + case SDLK_u: + return 'U'; + case SDLK_v: + return 'V'; + case SDLK_w: + return 'W'; + case SDLK_x: + return 'X'; + case SDLK_y: + return 'Y'; + case SDLK_z: + return 'Z'; + default: + Uint16 c = keysym.unicode; + if((c & 0xFF80) == 0) { + return toupper(c); + } + break; + } + + return 0; +} + +}}//end namespace