Made changes to properly isolate new unit rotation code so that it is disabled by default
This commit is contained in:
parent
c983eab0af
commit
2012b7e22c
|
@ -342,6 +342,26 @@ when they are issued a command"/>
|
|||
<enum value="0"/>
|
||||
</enums>
|
||||
</field>
|
||||
<field type="Enum">
|
||||
<name value="Client and Server data file synch check"/>
|
||||
<variable-name value="AllowGameDataSynchCheck"/>
|
||||
<description value=""/>
|
||||
<default value="0"/>
|
||||
<enums>
|
||||
<enum value="1"/>
|
||||
<enum value="0"/>
|
||||
</enums>
|
||||
</field>
|
||||
<field type="Enum">
|
||||
<name value="Client and Server data file transfer support"/>
|
||||
<variable-name value="AllowDownloadDataSynch"/>
|
||||
<description value=""/>
|
||||
<default value="0"/>
|
||||
<enums>
|
||||
<enum value="1"/>
|
||||
<enum value="0"/>
|
||||
</enums>
|
||||
</field>
|
||||
</field-group>
|
||||
|
||||
<field-group name="Advanced">
|
||||
|
@ -373,6 +393,16 @@ when they are issued a command"/>
|
|||
<enum value="0"/>
|
||||
</enums>
|
||||
</field>
|
||||
<field type="Enum">
|
||||
<name value="Allow players to rotate Units when building new Units"/>
|
||||
<variable-name value="AllowRotateUnits"/>
|
||||
<description value=""/>
|
||||
<default value="0"/>
|
||||
<enums>
|
||||
<enum value="1"/>
|
||||
<enum value="0"/>
|
||||
</enums>
|
||||
</field>
|
||||
</field-group>
|
||||
</field-groups>
|
||||
</configuration>
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
AiLog=0
|
||||
AiRedir=0
|
||||
AllowDownloadDataSynch=0
|
||||
AllowGameDataSynchCheck=0
|
||||
AllowRotateUnits=0
|
||||
AutoTest=0
|
||||
CheckGlCaps=1
|
||||
ColorBits=32
|
||||
|
@ -30,7 +33,7 @@ PhotoMode=0
|
|||
RefreshFrequency=75
|
||||
ScreenHeight=984
|
||||
ScreenWidth=1680
|
||||
ServerIp=192.168.1.1
|
||||
ServerIp=192.168.0.107
|
||||
ServerPort=6666
|
||||
ShadowAlpha=0.2
|
||||
ShadowFrameSkip=2
|
||||
|
|
|
@ -70,7 +70,7 @@ void Configuration::loadValues(const string &path){
|
|||
FieldGroup *fg= fieldGroups[i];
|
||||
for(int j=0; j<fg->getFieldCount(); ++j){
|
||||
Field *f= fg->getField(j);
|
||||
f->setValue(properties.getString(f->getVariableName()));
|
||||
f->setValue(properties.getString(f->getVariableName(),""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,897 @@
|
|||
// ==============================================================
|
||||
// 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.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "renderer.h"
|
||||
#include "particle_renderer.h"
|
||||
#include "commander.h"
|
||||
#include "battle_end.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "profiler.h"
|
||||
#include "core_data.h"
|
||||
#include "metrics.h"
|
||||
#include "faction.h"
|
||||
#include "network_manager.h"
|
||||
#include "checksum.h"
|
||||
#include "auto_test.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Graphics;
|
||||
using namespace Shared::Util;
|
||||
using namespace Shared::Platform;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Game
|
||||
// =====================================================
|
||||
|
||||
// ===================== PUBLIC ========================
|
||||
|
||||
Game::Game(Program *program, const GameSettings *gameSettings):
|
||||
ProgramState(program)
|
||||
{
|
||||
this->gameSettings= *gameSettings;
|
||||
|
||||
mouseX=0;
|
||||
mouseY=0;
|
||||
mouse2d= 0;
|
||||
loadingText="";
|
||||
weatherParticleSystem= NULL;
|
||||
updateFps=0;
|
||||
renderFps=0;
|
||||
lastUpdateFps=0;
|
||||
lastRenderFps=0;
|
||||
paused= false;
|
||||
gameOver= false;
|
||||
renderNetworkStatus= false;
|
||||
speed= sNormal;
|
||||
}
|
||||
|
||||
Game::~Game(){
|
||||
Logger &logger= Logger::getInstance();
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
logger.setState(Lang::getInstance().get("Deleting"));
|
||||
logger.add("Game", true);
|
||||
|
||||
renderer.endGame();
|
||||
SoundRenderer::getInstance().stopAllSounds();
|
||||
|
||||
deleteValues(aiInterfaces.begin(), aiInterfaces.end());
|
||||
|
||||
gui.end(); //selection must be cleared before deleting units
|
||||
world.end(); //must die before selection because of referencers
|
||||
}
|
||||
|
||||
|
||||
// ==================== init and load ====================
|
||||
|
||||
void Game::load(){
|
||||
Logger &logger= Logger::getInstance();
|
||||
string mapName= gameSettings.getMap();
|
||||
string tilesetName= gameSettings.getTileset();
|
||||
string techName= gameSettings.getTech();
|
||||
string scenarioName= gameSettings.getScenario();
|
||||
|
||||
logger.setState(Lang::getInstance().get("Loading"));
|
||||
|
||||
if(scenarioName.empty()){
|
||||
logger.setSubtitle(formatString(mapName)+" - "+formatString(tilesetName)+" - "+formatString(techName));
|
||||
}
|
||||
else{
|
||||
logger.setSubtitle(formatString(scenarioName));
|
||||
}
|
||||
|
||||
//tileset
|
||||
world.loadTileset("tilesets/"+tilesetName, &checksum);
|
||||
|
||||
set<string> factions;
|
||||
for ( int i=0; i < gameSettings.getFactionCount(); ++i ) {
|
||||
factions.insert(gameSettings.getFactionTypeName(i));
|
||||
}
|
||||
|
||||
//tech, load before map because of resources
|
||||
world.loadTech("techs/"+techName, factions, &checksum);
|
||||
|
||||
//map
|
||||
world.loadMap(Map::getMapPath(mapName), &checksum);
|
||||
|
||||
//scenario
|
||||
if(!scenarioName.empty()){
|
||||
Lang::getInstance().loadScenarioStrings(gameSettings.getScenarioDir(), scenarioName);
|
||||
world.loadScenario(Scenario::getScenarioPath(gameSettings.getScenarioDir(), scenarioName), &checksum);
|
||||
}
|
||||
}
|
||||
|
||||
void Game::init()
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
Lang &lang= Lang::getInstance();
|
||||
Logger &logger= Logger::getInstance();
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
Map *map= world.getMap();
|
||||
NetworkManager &networkManager= NetworkManager::getInstance();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] Initializing\n",__FILE__,__FUNCTION__);
|
||||
logger.setState(lang.get("Initializing"));
|
||||
|
||||
//mesage box
|
||||
mainMessageBox.init(lang.get("Yes"), lang.get("No"));
|
||||
mainMessageBox.setEnabled(false);
|
||||
|
||||
//check fog of war
|
||||
if(!Config::getInstance().getBool("FogOfWar") && networkManager.isNetworkGame() ){
|
||||
throw runtime_error("Can not play online games with for of war disabled");
|
||||
}
|
||||
|
||||
//init world, and place camera
|
||||
commander.init(&world);
|
||||
world.init(this, gameSettings.getDefaultUnits());
|
||||
gui.init(this);
|
||||
chatManager.init(&console, world.getThisTeamIndex());
|
||||
const Vec2i &v= map->getStartLocation(world.getThisFaction()->getStartLocationIndex());
|
||||
gameCamera.init(map->getW(), map->getH());
|
||||
gameCamera.setPos(Vec2f(v.x, v.y));
|
||||
scriptManager.init(&world, &gameCamera);
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] creating AI's\n",__FILE__,__FUNCTION__);
|
||||
|
||||
//create IAs
|
||||
aiInterfaces.resize(world.getFactionCount());
|
||||
for(int i=0; i<world.getFactionCount(); ++i){
|
||||
Faction *faction= world.getFaction(i);
|
||||
if(faction->getCpuControl()){
|
||||
aiInterfaces[i]= new AiInterface(*this, i, faction->getTeam());
|
||||
logger.add("Creating AI for faction " + intToStr(i), true);
|
||||
}
|
||||
else{
|
||||
aiInterfaces[i]= NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//wheather particle systems
|
||||
if(world.getTileset()->getWeather() == wRainy){
|
||||
logger.add("Creating rain particle system", true);
|
||||
weatherParticleSystem= new RainParticleSystem();
|
||||
weatherParticleSystem->setSpeed(12.f/GameConstants::updateFps);
|
||||
weatherParticleSystem->setPos(gameCamera.getPos());
|
||||
renderer.manageParticleSystem(weatherParticleSystem, rsGame);
|
||||
}
|
||||
else if(world.getTileset()->getWeather() == wSnowy){
|
||||
logger.add("Creating snow particle system", true);
|
||||
weatherParticleSystem= new SnowParticleSystem(1200);
|
||||
weatherParticleSystem->setSpeed(1.5f/GameConstants::updateFps);
|
||||
weatherParticleSystem->setPos(gameCamera.getPos());
|
||||
weatherParticleSystem->setTexture(coreData.getSnowTexture());
|
||||
renderer.manageParticleSystem(weatherParticleSystem, rsGame);
|
||||
}
|
||||
|
||||
//init renderer state
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] Initializing renderer\n",__FILE__,__FUNCTION__);
|
||||
logger.add("Initializing renderer", true);
|
||||
renderer.initGame(this);
|
||||
|
||||
//sounds
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
|
||||
Tileset *tileset= world.getTileset();
|
||||
AmbientSounds *ambientSounds= tileset->getAmbientSounds();
|
||||
|
||||
//rain
|
||||
if(tileset->getWeather()==wRainy && ambientSounds->isEnabledRain()){
|
||||
logger.add("Starting ambient stream", true);
|
||||
soundRenderer.playAmbient(ambientSounds->getRain());
|
||||
}
|
||||
|
||||
//snow
|
||||
if(tileset->getWeather()==wSnowy && ambientSounds->isEnabledSnow()){
|
||||
logger.add("Starting ambient stream", true);
|
||||
soundRenderer.playAmbient(ambientSounds->getSnow());
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] Waiting for network\n",__FILE__,__FUNCTION__);
|
||||
logger.add("Waiting for network", true);
|
||||
networkManager.getGameNetworkInterface()->waitUntilReady(&checksum);
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] Starting music stream\n",__FILE__,__FUNCTION__);
|
||||
logger.add("Starting music stream", true);
|
||||
StrSound *gameMusic= world.getThisFaction()->getType()->getMusic();
|
||||
soundRenderer.playMusic(gameMusic);
|
||||
|
||||
logger.add("Launching game");
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
|
||||
|
||||
// ==================== update ====================
|
||||
|
||||
//update
|
||||
void Game::update(){
|
||||
|
||||
// a) Updates non dependant on speed
|
||||
|
||||
//misc
|
||||
updateFps++;
|
||||
mouse2d= (mouse2d+1) % Renderer::maxMouse2dAnim;
|
||||
|
||||
//console
|
||||
console.update();
|
||||
|
||||
// b) Updates depandant on speed
|
||||
|
||||
int updateLoops= getUpdateLoops();
|
||||
|
||||
//update
|
||||
for(int i=0; i<updateLoops; ++i){
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
//AiInterface
|
||||
for(int i=0; i<world.getFactionCount(); ++i){
|
||||
if(world.getFaction(i)->getCpuControl() && scriptManager.getPlayerModifiers(i)->getAiEnabled()){
|
||||
aiInterfaces[i]->update();
|
||||
}
|
||||
}
|
||||
|
||||
//World
|
||||
world.update();
|
||||
|
||||
// Commander
|
||||
commander.updateNetwork();
|
||||
|
||||
//Gui
|
||||
gui.update();
|
||||
|
||||
//Particle systems
|
||||
if(weatherParticleSystem != NULL){
|
||||
weatherParticleSystem->setPos(gameCamera.getPos());
|
||||
}
|
||||
renderer.updateParticleManager(rsGame);
|
||||
}
|
||||
|
||||
//call the chat manager
|
||||
chatManager.updateNetwork();
|
||||
|
||||
//check for quiting status
|
||||
if(NetworkManager::getInstance().getGameNetworkInterface()->getQuit()){
|
||||
quitGame();
|
||||
}
|
||||
|
||||
//update auto test
|
||||
if(Config::getInstance().getBool("AutoTest")){
|
||||
AutoTest::getInstance().updateGame(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Game::updateCamera(){
|
||||
gameCamera.update();
|
||||
}
|
||||
|
||||
|
||||
// ==================== render ====================
|
||||
|
||||
//render
|
||||
void Game::render(){
|
||||
renderFps++;
|
||||
render3d();
|
||||
render2d();
|
||||
Renderer::getInstance().swapBuffers();
|
||||
}
|
||||
|
||||
// ==================== tick ====================
|
||||
|
||||
void Game::tick(){
|
||||
lastUpdateFps= updateFps;
|
||||
lastRenderFps= renderFps;
|
||||
updateFps= 0;
|
||||
renderFps= 0;
|
||||
|
||||
//Win/lose check
|
||||
checkWinner();
|
||||
gui.tick();
|
||||
}
|
||||
|
||||
|
||||
// ==================== events ====================
|
||||
|
||||
void Game::mouseDownLeft(int x, int y){
|
||||
|
||||
Map *map= world.getMap();
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
NetworkManager &networkManager= NetworkManager::getInstance();
|
||||
bool messageBoxClick= false;
|
||||
|
||||
//scrip message box, only if the exit box is not enabled
|
||||
if(!mainMessageBox.getEnabled() && scriptManager.getMessageBox()->getEnabled()){
|
||||
int button= 1;
|
||||
if(scriptManager.getMessageBox()->mouseClick(x, y, button)){
|
||||
scriptManager.onMessageBoxOk();
|
||||
messageBoxClick= true;
|
||||
}
|
||||
}
|
||||
|
||||
//minimap panel
|
||||
if(!messageBoxClick){
|
||||
if(metrics.isInMinimap(x, y) && !gui.isSelectingPos()){
|
||||
|
||||
int xm= x - metrics.getMinimapX();
|
||||
int ym= y - metrics.getMinimapY();
|
||||
int xCell= static_cast<int>(xm * (static_cast<float>(map->getW()) / metrics.getMinimapW()));
|
||||
int yCell= static_cast<int>(map->getH() - ym * (static_cast<float>(map->getH()) / metrics.getMinimapH()));
|
||||
|
||||
if(map->isInside(xCell, yCell)){
|
||||
if(!gui.isSelectingPos()){
|
||||
gameCamera.setPos(Vec2f(static_cast<float>(xCell), static_cast<float>(yCell)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//display panel
|
||||
else if(metrics.isInDisplay(x, y) && !gui.isSelectingPos()){
|
||||
int xd= x - metrics.getDisplayX();
|
||||
int yd= y - metrics.getDisplayY();
|
||||
if(gui.mouseValid(xd, yd)){
|
||||
gui.mouseDownLeftDisplay(xd, yd);
|
||||
}
|
||||
else{
|
||||
gui.mouseDownLeftGraphics(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
//graphics panel
|
||||
else{
|
||||
gui.mouseDownLeftGraphics(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
//exit message box, has to be the last thing to do in this function
|
||||
if(mainMessageBox.getEnabled()){
|
||||
int button= 1;
|
||||
if(mainMessageBox.mouseClick(x, y, button))
|
||||
{
|
||||
if(button==1)
|
||||
{
|
||||
networkManager.getGameNetworkInterface()->quitGame(true);
|
||||
quitGame();
|
||||
}
|
||||
else
|
||||
{
|
||||
//close message box
|
||||
mainMessageBox.setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::mouseDownRight(int x, int y){
|
||||
gui.mouseDownRightGraphics(x, y);
|
||||
}
|
||||
|
||||
void Game::mouseUpLeft(int x, int y){
|
||||
gui.mouseUpLeftGraphics(x, y);
|
||||
}
|
||||
|
||||
void Game::mouseDoubleClickLeft(int x, int y){
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
|
||||
//display panel
|
||||
if(metrics.isInDisplay(x, y) && !gui.isSelectingPos()){
|
||||
int xd= x - metrics.getDisplayX();
|
||||
int yd= y - metrics.getDisplayY();
|
||||
if(gui.mouseValid(xd, yd)){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//graphics panel
|
||||
gui.mouseDoubleClickLeftGraphics(x, y);
|
||||
}
|
||||
|
||||
void Game::mouseMove(int x, int y, const MouseState *ms){
|
||||
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
|
||||
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(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()){
|
||||
gui.mouseMoveDisplay(x - metrics.getDisplayX(), y - metrics.getDisplayY());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::keyDown(char key){
|
||||
|
||||
Lang &lang= Lang::getInstance();
|
||||
bool speedChangesAllowed= !NetworkManager::getInstance().isNetworkGame();
|
||||
|
||||
//send ley to the chat manager
|
||||
chatManager.keyDown(key);
|
||||
|
||||
if(!chatManager.getEditEnabled()){
|
||||
|
||||
if(key=='N'){
|
||||
renderNetworkStatus= true;
|
||||
}
|
||||
else if(key=='E'){
|
||||
for(int i=0; i<100; ++i){
|
||||
string path= "screens/screen" + intToStr(i) + ".tga";
|
||||
|
||||
FILE *f= fopen(path.c_str(), "rb");
|
||||
if(f==NULL){
|
||||
Renderer::getInstance().saveScreen(path);
|
||||
break;
|
||||
}
|
||||
else{
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//move camera left
|
||||
else if(key==vkLeft){
|
||||
gameCamera.setMoveX(-1);
|
||||
}
|
||||
|
||||
//move camera right
|
||||
else if(key==vkRight){
|
||||
gameCamera.setMoveX(1);
|
||||
}
|
||||
|
||||
//move camera up
|
||||
else if(key==vkUp){
|
||||
gameCamera.setMoveZ(1);
|
||||
}
|
||||
|
||||
//move camera down
|
||||
else if(key==vkDown){
|
||||
gameCamera.setMoveZ(-1);
|
||||
}
|
||||
|
||||
//change camera mode
|
||||
else if(key=='F'){
|
||||
gameCamera.switchState();
|
||||
string stateString= gameCamera.getState()==GameCamera::sGame? lang.get("GameCamera"): lang.get("FreeCamera");
|
||||
console.addLine(lang.get("CameraModeSet")+" "+ stateString);
|
||||
}
|
||||
|
||||
//pause
|
||||
else if(key=='P'){
|
||||
if(speedChangesAllowed){
|
||||
if(paused){
|
||||
console.addLine(lang.get("GameResumed"));
|
||||
paused= false;
|
||||
}
|
||||
else{
|
||||
console.addLine(lang.get("GamePaused"));
|
||||
paused= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//increment speed
|
||||
else if(key==vkAdd){
|
||||
if(speedChangesAllowed){
|
||||
incSpeed();
|
||||
}
|
||||
}
|
||||
|
||||
//decrement speed
|
||||
else if(key==vkSubtract){
|
||||
if(speedChangesAllowed){
|
||||
decSpeed();
|
||||
}
|
||||
}
|
||||
|
||||
//exit
|
||||
else if(key==vkEscape){
|
||||
showMessageBox(lang.get("ExitGame?"), "", true);
|
||||
}
|
||||
|
||||
//group
|
||||
else if(key>='0' && key<'0'+Selection::maxGroups){
|
||||
gui.groupKey(key-'0');
|
||||
}
|
||||
|
||||
//hotkeys
|
||||
if(gameCamera.getState()==GameCamera::sGame){
|
||||
gui.hotKey(key);
|
||||
}
|
||||
else{
|
||||
//rotate camera leftt
|
||||
if(key=='A'){
|
||||
gameCamera.setRotate(-1);
|
||||
}
|
||||
|
||||
//rotate camera right
|
||||
else if(key=='D'){
|
||||
gameCamera.setRotate(1);
|
||||
}
|
||||
|
||||
//camera up
|
||||
else if(key=='S'){
|
||||
gameCamera.setMoveY(1);
|
||||
}
|
||||
|
||||
//camera down
|
||||
else if(key=='W'){
|
||||
gameCamera.setMoveY(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::keyUp(char key){
|
||||
|
||||
if(!chatManager.getEditEnabled()){
|
||||
switch(key){
|
||||
case 'N':
|
||||
renderNetworkStatus= false;
|
||||
break;
|
||||
case 'A':
|
||||
case 'D':
|
||||
gameCamera.setRotate(0);
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
case 'S':
|
||||
gameCamera.stopMoveY();
|
||||
break;
|
||||
|
||||
case vkUp:
|
||||
case vkDown:
|
||||
gameCamera.stopMoveZ();
|
||||
break;
|
||||
|
||||
case vkLeft:
|
||||
case vkRight:
|
||||
gameCamera.stopMoveX();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::keyPress(char c){
|
||||
chatManager.keyPress(c);
|
||||
}
|
||||
|
||||
void Game::quitGame(){
|
||||
program->setState(new BattleEnd(program, world.getStats()));
|
||||
}
|
||||
|
||||
// ==================== PRIVATE ====================
|
||||
|
||||
// ==================== render ====================
|
||||
|
||||
void Game::render3d(){
|
||||
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
//init
|
||||
renderer.reset3d();
|
||||
renderer.computeVisibleQuad();
|
||||
renderer.loadGameCameraMatrix();
|
||||
renderer.setupLighting();
|
||||
|
||||
//shadow map
|
||||
renderer.renderShadowsToTexture();
|
||||
|
||||
//clear buffers
|
||||
renderer.clearBuffers();
|
||||
|
||||
//surface
|
||||
renderer.renderSurface();
|
||||
|
||||
//selection circles
|
||||
renderer.renderSelectionEffects();
|
||||
|
||||
//units
|
||||
renderer.renderUnits();
|
||||
|
||||
//objects
|
||||
renderer.renderObjects();
|
||||
|
||||
//water
|
||||
renderer.renderWater();
|
||||
renderer.renderWaterEffects();
|
||||
|
||||
//particles
|
||||
renderer.renderParticleManager(rsGame);
|
||||
|
||||
//mouse 3d
|
||||
renderer.renderMouse3d();
|
||||
}
|
||||
|
||||
void Game::render2d(){
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
Config &config= Config::getInstance();
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
|
||||
//init
|
||||
renderer.reset2d();
|
||||
|
||||
//display
|
||||
renderer.renderDisplay();
|
||||
|
||||
//minimap
|
||||
if(!config.getBool("PhotoMode")){
|
||||
renderer.renderMinimap();
|
||||
}
|
||||
|
||||
//selection
|
||||
renderer.renderSelectionQuad();
|
||||
|
||||
//exit message box
|
||||
if(mainMessageBox.getEnabled()){
|
||||
renderer.renderMessageBox(&mainMessageBox);
|
||||
}
|
||||
|
||||
//script message box
|
||||
if(!mainMessageBox.getEnabled() && scriptManager.getMessageBoxEnabled()){
|
||||
renderer.renderMessageBox(scriptManager.getMessageBox());
|
||||
}
|
||||
|
||||
//script display text
|
||||
if(!scriptManager.getDisplayText().empty() && !scriptManager.getMessageBoxEnabled()){
|
||||
renderer.renderText(
|
||||
scriptManager.getDisplayText(), coreData.getMenuFontNormal(),
|
||||
Vec3f(1.0f), 200, 680, false);
|
||||
}
|
||||
|
||||
|
||||
renderer.renderChatManager(&chatManager);
|
||||
|
||||
//debug info
|
||||
if(config.getBool("DebugMode")){
|
||||
string str;
|
||||
|
||||
str+= "MouseXY: " + intToStr(mouseX) + "," + intToStr(mouseY)+"\n";
|
||||
str+= "PosObjWord: " + intToStr(gui.getPosObjWorld().x) + "," + intToStr(gui.getPosObjWorld().y)+"\n";
|
||||
str+= "Render FPS: "+intToStr(lastRenderFps)+"\n";
|
||||
str+= "Update FPS: "+intToStr(lastUpdateFps)+"\n";
|
||||
str+= "GameCamera pos: "+floatToStr(gameCamera.getPos().x)+","+floatToStr(gameCamera.getPos().y)+","+floatToStr(gameCamera.getPos().z)+"\n";
|
||||
str+= "Time: "+floatToStr(world.getTimeFlow()->getTime())+"\n";
|
||||
str+= "Triangle count: "+intToStr(renderer.getTriangleCount())+"\n";
|
||||
str+= "Vertex count: "+intToStr(renderer.getPointCount())+"\n";
|
||||
str+= "Frame count:"+intToStr(world.getFrameCount())+"\n";
|
||||
|
||||
//visible quad
|
||||
Quad2i visibleQuad= renderer.getVisibleQuad();
|
||||
|
||||
str+= "Visible quad: ";
|
||||
for(int i= 0; i<4; ++i){
|
||||
str+= "(" + intToStr(visibleQuad.p[i].x) + "," +intToStr(visibleQuad.p[i].y) + ") ";
|
||||
}
|
||||
str+= "\n";
|
||||
str+= "Visible quad area: " + floatToStr(visibleQuad.area()) +"\n";
|
||||
|
||||
// resources
|
||||
for(int i=0; i<world.getFactionCount(); ++i){
|
||||
str+= "Player "+intToStr(i)+" res: ";
|
||||
for(int j=0; j<world.getTechTree()->getResourceTypeCount(); ++j){
|
||||
str+= intToStr(world.getFaction(i)->getResource(j)->getAmount());
|
||||
str+=" ";
|
||||
}
|
||||
str+="\n";
|
||||
}
|
||||
|
||||
renderer.renderText(
|
||||
str, coreData.getMenuFontNormal(),
|
||||
Vec3f(1.0f), 10, 500, false);
|
||||
}
|
||||
|
||||
//network status
|
||||
if(renderNetworkStatus){
|
||||
renderer.renderText(
|
||||
NetworkManager::getInstance().getGameNetworkInterface()->getNetworkStatus(),
|
||||
coreData.getMenuFontNormal(),
|
||||
Vec3f(1.0f), 20, 500, false);
|
||||
}
|
||||
|
||||
//resource info
|
||||
if(!config.getBool("PhotoMode")){
|
||||
renderer.renderResourceStatus();
|
||||
renderer.renderConsole(&console);
|
||||
}
|
||||
|
||||
//2d mouse
|
||||
renderer.renderMouse2d(mouseX, mouseY, mouse2d, gui.isSelectingPos()? 1.f: 0.f);
|
||||
}
|
||||
|
||||
|
||||
// ==================== misc ====================
|
||||
|
||||
void Game::checkWinner(){
|
||||
if(!gameOver){
|
||||
if(gameSettings.getDefaultVictoryConditions()){
|
||||
checkWinnerStandard();
|
||||
}
|
||||
else
|
||||
{
|
||||
checkWinnerScripted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::checkWinnerStandard(){
|
||||
//lose
|
||||
bool lose= false;
|
||||
if(!hasBuilding(world.getThisFaction())){
|
||||
lose= true;
|
||||
for(int i=0; i<world.getFactionCount(); ++i){
|
||||
if(!world.getFaction(i)->isAlly(world.getThisFaction())){
|
||||
world.getStats()->setVictorious(i);
|
||||
}
|
||||
}
|
||||
gameOver= true;
|
||||
showLoseMessageBox();
|
||||
}
|
||||
|
||||
//win
|
||||
if(!lose){
|
||||
bool win= true;
|
||||
for(int i=0; i<world.getFactionCount(); ++i){
|
||||
if(i!=world.getThisFactionIndex()){
|
||||
if(hasBuilding(world.getFaction(i)) && !world.getFaction(i)->isAlly(world.getThisFaction())){
|
||||
win= false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if win
|
||||
if(win){
|
||||
for(int i=0; i< world.getFactionCount(); ++i){
|
||||
if(world.getFaction(i)->isAlly(world.getThisFaction())){
|
||||
world.getStats()->setVictorious(i);
|
||||
}
|
||||
}
|
||||
gameOver= true;
|
||||
showWinMessageBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::checkWinnerScripted(){
|
||||
if(scriptManager.getGameOver()){
|
||||
gameOver= true;
|
||||
for(int i= 0; i<world.getFactionCount(); ++i){
|
||||
if(scriptManager.getPlayerModifiers(i)->getWinner()){
|
||||
world.getStats()->setVictorious(i);
|
||||
}
|
||||
}
|
||||
if(scriptManager.getPlayerModifiers(world.getThisFactionIndex())->getWinner()){
|
||||
showWinMessageBox();
|
||||
}
|
||||
else{
|
||||
showLoseMessageBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Game::hasBuilding(const Faction *faction){
|
||||
for(int i=0; i<faction->getUnitCount(); ++i){
|
||||
if(faction->getUnit(i)->getType()->hasSkillClass(scBeBuilt)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Game::incSpeed(){
|
||||
Lang &lang= Lang::getInstance();
|
||||
switch(speed){
|
||||
case sSlow:
|
||||
speed= sNormal;
|
||||
console.addLine(lang.get("GameSpeedSet")+" "+lang.get("Normal"));
|
||||
break;
|
||||
case sNormal:
|
||||
speed= sFast;
|
||||
console.addLine(lang.get("GameSpeedSet")+" "+lang.get("Fast"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Game::decSpeed(){
|
||||
Lang &lang= Lang::getInstance();
|
||||
switch(speed){
|
||||
case sNormal:
|
||||
speed= sSlow;
|
||||
console.addLine(lang.get("GameSpeedSet")+" "+lang.get("Slow"));
|
||||
break;
|
||||
case sFast:
|
||||
speed= sNormal;
|
||||
console.addLine(lang.get("GameSpeedSet")+" "+lang.get("Normal"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int Game::getUpdateLoops(){
|
||||
if(paused){
|
||||
return 0;
|
||||
}
|
||||
else if(speed==sFast){
|
||||
return Config::getInstance().getInt("FastSpeedLoops");
|
||||
}
|
||||
else if(speed==sSlow){
|
||||
return updateFps % 2 == 0? 1: 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Game::showLoseMessageBox(){
|
||||
Lang &lang= Lang::getInstance();
|
||||
showMessageBox(lang.get("YouLose")+", "+lang.get("ExitGame?"), lang.get("BattleOver"), false);
|
||||
}
|
||||
|
||||
void Game::showWinMessageBox(){
|
||||
Lang &lang= Lang::getInstance();
|
||||
showMessageBox(lang.get("YouWin")+", "+lang.get("ExitGame?"), lang.get("BattleOver"), false);
|
||||
}
|
||||
|
||||
void Game::showMessageBox(const string &text, const string &header, bool toggle){
|
||||
if(!toggle){
|
||||
mainMessageBox.setEnabled(false);
|
||||
}
|
||||
|
||||
if(!mainMessageBox.getEnabled()){
|
||||
mainMessageBox.setText(text);
|
||||
mainMessageBox.setHeader(header);
|
||||
mainMessageBox.setEnabled(true);
|
||||
}
|
||||
else{
|
||||
mainMessageBox.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,89 @@
|
|||
// ==============================================================
|
||||
// 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 "config.h"
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class Config
|
||||
// =====================================================
|
||||
|
||||
Config::Config(){
|
||||
properties.load("glest.ini");
|
||||
}
|
||||
|
||||
Config &Config::getInstance(){
|
||||
static Config config;
|
||||
return config;
|
||||
}
|
||||
|
||||
void Config::save(const string &path){
|
||||
properties.save(path);
|
||||
}
|
||||
|
||||
int Config::getInt(const char *key,const char *defaultValueIfNotFound) const {
|
||||
return properties.getInt(key,defaultValueIfNotFound);
|
||||
}
|
||||
|
||||
bool Config::getBool(const char *key,const char *defaultValueIfNotFound) const {
|
||||
return properties.getBool(key,defaultValueIfNotFound);
|
||||
}
|
||||
|
||||
float Config::getFloat(const char *key,const char *defaultValueIfNotFound) const {
|
||||
return properties.getFloat(key,defaultValueIfNotFound);
|
||||
}
|
||||
|
||||
const string Config::getString(const char *key,const char *defaultValueIfNotFound) const {
|
||||
return properties.getString(key,defaultValueIfNotFound);
|
||||
}
|
||||
|
||||
int Config::getInt(const string &key,const char *defaultValueIfNotFound) const{
|
||||
return properties.getInt(key,defaultValueIfNotFound);
|
||||
}
|
||||
|
||||
bool Config::getBool(const string &key,const char *defaultValueIfNotFound) const{
|
||||
return properties.getBool(key,defaultValueIfNotFound);
|
||||
}
|
||||
|
||||
float Config::getFloat(const string &key,const char *defaultValueIfNotFound) const{
|
||||
return properties.getFloat(key,defaultValueIfNotFound);
|
||||
}
|
||||
|
||||
const string Config::getString(const string &key,const char *defaultValueIfNotFound) const{
|
||||
return properties.getString(key,defaultValueIfNotFound);
|
||||
}
|
||||
|
||||
void Config::setInt(const string &key, int value){
|
||||
properties.setInt(key, value);
|
||||
}
|
||||
|
||||
void Config::setBool(const string &key, bool value){
|
||||
properties.setBool(key, value);
|
||||
}
|
||||
|
||||
void Config::setFloat(const string &key, float value){
|
||||
properties.setFloat(key, value);
|
||||
}
|
||||
|
||||
void Config::setString(const string &key, const string &value){
|
||||
properties.setString(key, value);
|
||||
}
|
||||
|
||||
string Config::toString(){
|
||||
return properties.toString();
|
||||
}
|
||||
|
||||
}}// end namespace
|
|
@ -0,0 +1,58 @@
|
|||
// ==============================================================
|
||||
// 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_CONFIG_H_
|
||||
#define _GLEST_GAME_CONFIG_H_
|
||||
|
||||
#include "properties.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
using Shared::Util::Properties;
|
||||
|
||||
// =====================================================
|
||||
// class Config
|
||||
//
|
||||
// Game configuration
|
||||
// =====================================================
|
||||
|
||||
class Config{
|
||||
private:
|
||||
Properties properties;
|
||||
|
||||
private:
|
||||
Config();
|
||||
|
||||
public:
|
||||
static Config &getInstance();
|
||||
void save(const string &path="glest.ini");
|
||||
|
||||
int getInt(const string &key,const char *defaultValueIfNotFound=NULL) const;
|
||||
bool getBool(const string &key,const char *defaultValueIfNotFound=NULL) const;
|
||||
float getFloat(const string &key,const char *defaultValueIfNotFound=NULL) const;
|
||||
const string getString(const string &key,const char *defaultValueIfNotFound=NULL) const;
|
||||
|
||||
int getInt(const char *key,const char *defaultValueIfNotFound=NULL) const;
|
||||
bool getBool(const char *key,const char *defaultValueIfNotFound=NULL) const;
|
||||
float getFloat(const char *key,const char *defaultValueIfNotFound=NULL) const;
|
||||
const string getString(const char *key,const char *defaultValueIfNotFound=NULL) const;
|
||||
|
||||
void setInt(const string &key, int value);
|
||||
void setBool(const string &key, bool value);
|
||||
void setFloat(const string &key, float value);
|
||||
void setString(const string &key, const string &value);
|
||||
|
||||
string toString();
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,309 @@
|
|||
// ==============================================================
|
||||
// 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_RENDERER_H_
|
||||
#define _GLEST_GAME_RENDERER_H_
|
||||
|
||||
#include "vec.h"
|
||||
#include "math_util.h"
|
||||
#include "model.h"
|
||||
#include "particle.h"
|
||||
#include "pixmap.h"
|
||||
#include "font.h"
|
||||
#include "matrix.h"
|
||||
#include "selection.h"
|
||||
#include "components.h"
|
||||
#include "texture.h"
|
||||
#include "model_manager.h"
|
||||
#include "graphics_factory_gl.h"
|
||||
#include "font_manager.h"
|
||||
#include "camera.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
using Shared::Graphics::Texture2D;
|
||||
using Shared::Graphics::Texture3D;
|
||||
using Shared::Graphics::ModelRenderer;
|
||||
using Shared::Graphics::TextRenderer2D;
|
||||
using Shared::Graphics::ParticleRenderer;
|
||||
using Shared::Graphics::ParticleManager;
|
||||
using Shared::Graphics::ModelManager;
|
||||
using Shared::Graphics::TextureManager;
|
||||
using Shared::Graphics::FontManager;
|
||||
using Shared::Graphics::Font2D;
|
||||
using Shared::Graphics::Matrix4f;
|
||||
using Shared::Graphics::Vec2i;
|
||||
using Shared::Graphics::Quad2i;
|
||||
using Shared::Graphics::Vec3f;
|
||||
using Shared::Graphics::Model;
|
||||
using Shared::Graphics::ParticleSystem;
|
||||
using Shared::Graphics::Pixmap2D;
|
||||
using Shared::Graphics::Camera;
|
||||
|
||||
//non shared classes
|
||||
class Config;
|
||||
class Game;
|
||||
class MainMenu;
|
||||
class Console;
|
||||
class MenuBackground;
|
||||
class ChatManager;
|
||||
|
||||
enum ResourceScope{
|
||||
rsGlobal,
|
||||
rsMenu,
|
||||
rsGame,
|
||||
|
||||
rsCount
|
||||
};
|
||||
|
||||
// ===========================================================
|
||||
// class Renderer
|
||||
//
|
||||
/// OpenGL renderer, uses the shared library
|
||||
// ===========================================================
|
||||
|
||||
class Renderer{
|
||||
public:
|
||||
//progress bar
|
||||
static const int maxProgressBar;
|
||||
static const Vec4f progressBarBack1;
|
||||
static const Vec4f progressBarBack2;
|
||||
static const Vec4f progressBarFront1;
|
||||
static const Vec4f progressBarFront2;
|
||||
|
||||
//sun and moon
|
||||
static const float sunDist;
|
||||
static const float moonDist;
|
||||
static const float lightAmbFactor;
|
||||
|
||||
//mouse
|
||||
static const int maxMouse2dAnim;
|
||||
|
||||
//texture units
|
||||
static const GLenum baseTexUnit;
|
||||
static const GLenum fowTexUnit;
|
||||
static const GLenum shadowTexUnit;
|
||||
|
||||
//selection
|
||||
static const float selectionCircleRadius;
|
||||
static const float magicCircleRadius;
|
||||
|
||||
//perspective values
|
||||
static const float perspFov;
|
||||
static const float perspNearPlane;
|
||||
static const float perspFarPlane;
|
||||
|
||||
//default values
|
||||
static const float ambFactor;
|
||||
static const Vec4f defSpecularColor;
|
||||
static const Vec4f defDiffuseColor;
|
||||
static const Vec4f defAmbientColor;
|
||||
static const Vec4f defColor;
|
||||
static const Vec4f fowColor;
|
||||
|
||||
//light
|
||||
static const float maxLightDist;
|
||||
|
||||
public:
|
||||
enum Shadows{
|
||||
sDisabled,
|
||||
sProjected,
|
||||
sShadowMapping,
|
||||
|
||||
sCount
|
||||
};
|
||||
|
||||
private:
|
||||
//config
|
||||
int maxLights;
|
||||
bool photoMode;
|
||||
int shadowTextureSize;
|
||||
int shadowFrameSkip;
|
||||
float shadowAlpha;
|
||||
bool focusArrows;
|
||||
bool textures3D;
|
||||
Shadows shadows;
|
||||
|
||||
//game
|
||||
const Game *game;
|
||||
|
||||
//misc
|
||||
int triangleCount;
|
||||
int pointCount;
|
||||
Quad2i visibleQuad;
|
||||
Vec4f nearestLightPos;
|
||||
|
||||
//renderers
|
||||
ModelRenderer *modelRenderer;
|
||||
TextRenderer2D *textRenderer;
|
||||
ParticleRenderer *particleRenderer;
|
||||
|
||||
//texture managers
|
||||
ModelManager *modelManager[rsCount];
|
||||
TextureManager *textureManager[rsCount];
|
||||
FontManager *fontManager[rsCount];
|
||||
ParticleManager *particleManager[rsCount];
|
||||
|
||||
//state lists
|
||||
GLuint list3d;
|
||||
GLuint list2d;
|
||||
GLuint list3dMenu;
|
||||
|
||||
//shadows
|
||||
GLuint shadowMapHandle;
|
||||
Matrix4f shadowMapMatrix;
|
||||
int shadowMapFrame;
|
||||
|
||||
//water
|
||||
float waterAnim;
|
||||
|
||||
bool allowRotateUnits;
|
||||
|
||||
private:
|
||||
Renderer();
|
||||
~Renderer();
|
||||
|
||||
public:
|
||||
static Renderer &getInstance();
|
||||
|
||||
//init
|
||||
void init();
|
||||
void initGame(Game *game);
|
||||
void initMenu(MainMenu *mm);
|
||||
void reset3d();
|
||||
void reset2d();
|
||||
void reset3dMenu();
|
||||
|
||||
//end
|
||||
void end();
|
||||
void endMenu();
|
||||
void endGame();
|
||||
|
||||
//get
|
||||
int getTriangleCount() const {return triangleCount;}
|
||||
int getPointCount() const {return pointCount;}
|
||||
|
||||
//misc
|
||||
void reloadResources();
|
||||
|
||||
//engine interface
|
||||
Model *newModel(ResourceScope rs);
|
||||
Texture2D *newTexture2D(ResourceScope rs);
|
||||
Texture3D *newTexture3D(ResourceScope rs);
|
||||
Font2D *newFont(ResourceScope rs);
|
||||
TextRenderer2D *getTextRenderer() const {return textRenderer;}
|
||||
void manageParticleSystem(ParticleSystem *particleSystem, ResourceScope rs);
|
||||
void updateParticleManager(ResourceScope rs);
|
||||
void renderParticleManager(ResourceScope rs);
|
||||
void swapBuffers();
|
||||
|
||||
//lights and camera
|
||||
void setupLighting();
|
||||
void loadGameCameraMatrix();
|
||||
void loadCameraMatrix(const Camera *camera);
|
||||
void computeVisibleQuad();
|
||||
|
||||
//basic rendering
|
||||
void renderMouse2d(int mouseX, int mouseY, int anim, float fade= 0.f);
|
||||
void renderMouse3d();
|
||||
void renderBackground(const Texture2D *texture);
|
||||
void renderTextureQuad(int x, int y, int w, int h, const Texture2D *texture, float alpha=1.f);
|
||||
void renderConsole(const Console *console);
|
||||
void renderChatManager(const ChatManager *chatManager);
|
||||
void renderResourceStatus();
|
||||
void renderSelectionQuad();
|
||||
void renderText(const string &text, const Font2D *font, float alpha, int x, int y, bool centered= false);
|
||||
void renderText(const string &text, const Font2D *font, const Vec3f &color, int x, int y, bool centered= false);
|
||||
void renderTextShadow(const string &text, const Font2D *font, int x, int y, bool centered= false);
|
||||
|
||||
//components
|
||||
void renderLabel(const GraphicLabel *label);
|
||||
void renderButton(const GraphicButton *button);
|
||||
void renderListBox(const GraphicListBox *listBox);
|
||||
void renderMessageBox(const GraphicMessageBox *listBox);
|
||||
|
||||
//complex rendering
|
||||
void renderSurface();
|
||||
void renderObjects();
|
||||
void renderWater();
|
||||
void renderUnits();
|
||||
void renderSelectionEffects();
|
||||
void renderWaterEffects();
|
||||
void renderMinimap();
|
||||
void renderDisplay();
|
||||
void renderMenuBackground(const MenuBackground *menuBackground);
|
||||
|
||||
//computing
|
||||
bool computePosition(const Vec2i &screenPos, Vec2i &worldPos);
|
||||
void computeSelected(Selection::UnitContainer &units, const Vec2i &posDown, const Vec2i &posUp);
|
||||
|
||||
//gl wrap
|
||||
string getGlInfo();
|
||||
string getGlMoreInfo();
|
||||
void autoConfig();
|
||||
|
||||
//clear
|
||||
void clearBuffers();
|
||||
void clearZBuffer();
|
||||
|
||||
//shadows
|
||||
void renderShadowsToTexture();
|
||||
|
||||
//misc
|
||||
void loadConfig();
|
||||
void saveScreen(const string &path);
|
||||
Quad2i getVisibleQuad() const {return visibleQuad;}
|
||||
|
||||
//static
|
||||
static Shadows strToShadows(const string &s);
|
||||
static string shadowsToStr(Shadows shadows);
|
||||
|
||||
private:
|
||||
//private misc
|
||||
float computeSunAngle(float time);
|
||||
float computeMoonAngle(float time);
|
||||
Vec4f computeSunPos(float time);
|
||||
Vec4f computeMoonPos(float time);
|
||||
Vec3f computeLightColor(float time);
|
||||
Vec4f computeWaterColor(float waterLevel, float cellHeight);
|
||||
void checkExtension(const string &extension, const string &msg);
|
||||
|
||||
//selection render
|
||||
void renderObjectsFast();
|
||||
void renderUnitsFast();
|
||||
|
||||
//gl requirements
|
||||
void checkGlCaps();
|
||||
void checkGlOptionalCaps();
|
||||
|
||||
//gl init
|
||||
void init3dList();
|
||||
void init2dList();
|
||||
void init3dListMenu(MainMenu *mm);
|
||||
|
||||
//misc
|
||||
void loadProjectionMatrix();
|
||||
void enableProjectiveTexturing();
|
||||
|
||||
//private aux drawing
|
||||
void renderSelectionCircle(Vec3f v, int size, float radius);
|
||||
void renderArrow(const Vec3f &pos1, const Vec3f &pos2, const Vec3f &color, float width);
|
||||
void renderProgressBar(int size, int x, int y, Font2D *font);
|
||||
void renderTile(const Vec2i &pos);
|
||||
void renderQuad(int x, int y, int w, int h, const Texture2D *texture);
|
||||
|
||||
//static
|
||||
static Texture2D::Filter strToTextureFilter(const string &s);
|
||||
};
|
||||
|
||||
}} //end namespace
|
||||
|
||||
#endif
|
|
@ -90,6 +90,8 @@ void SelectionQuad::disable(){
|
|||
Gui::Gui(){
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
allowRotateUnits = Config::getInstance().getBool("AllowRotateUnits","0");
|
||||
|
||||
posObjWorld= Vec2i(54, 14);
|
||||
computeSelection= false;
|
||||
validPosObjWorld= false;
|
||||
|
@ -309,11 +311,11 @@ void Gui::groupKey(int groupIndex){
|
|||
}
|
||||
}
|
||||
|
||||
float Gui::getUnitTypeBuildRotation(int unitId) const {
|
||||
float Gui::getUnitTypeBuildRotation(string unitKey) const {
|
||||
float rotationValue = -1;
|
||||
|
||||
if(unitTypeBuildRotation.find(unitId) != unitTypeBuildRotation.end()) {
|
||||
rotationValue = unitTypeBuildRotation.find(unitId)->second;
|
||||
if(unitTypeBuildRotation.find(unitKey) != unitTypeBuildRotation.end()) {
|
||||
rotationValue = unitTypeBuildRotation.find(unitKey)->second;
|
||||
}
|
||||
|
||||
return rotationValue;
|
||||
|
@ -334,11 +336,14 @@ void Gui::hotKey(char key){
|
|||
}
|
||||
else if(key=='R'){
|
||||
//!!!
|
||||
if(0 && isPlacingBuilding()) {
|
||||
if(allowRotateUnits == true && isPlacingBuilding()) {
|
||||
const UnitType *unitType = getBuilding();
|
||||
float unitTypeRotation = getUnitTypeBuildRotation(unitType->getId());
|
||||
int factionIndex = world->getThisFactionIndex();
|
||||
char unitKey[50]="";
|
||||
sprintf(unitKey,"%d_%d",unitType->getId(),factionIndex);
|
||||
float unitTypeRotation = getUnitTypeBuildRotation(unitKey);
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] unitType->getId() = %d unitTypeRotation = %f\n",__FILE__,__FUNCTION__,unitType->getId(),unitTypeRotation);
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] factionIndex = %d unitType->getId() = %d unitTypeRotation = %f\n",__FILE__,__FUNCTION__,factionIndex,unitType->getId(),unitTypeRotation);
|
||||
|
||||
if(unitTypeRotation < 0) {
|
||||
unitTypeRotation = 0;
|
||||
|
@ -347,7 +352,7 @@ void Gui::hotKey(char key){
|
|||
if(unitTypeRotation >= 360) {
|
||||
unitTypeRotation = 0;
|
||||
}
|
||||
unitTypeBuildRotation[unitType->getId()] = unitTypeRotation;
|
||||
unitTypeBuildRotation[unitKey] = unitTypeRotation;
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] unitType->getId() = %d NEW unitTypeRotation = %f\n",__FILE__,__FUNCTION__,unitType->getId(),unitTypeRotation);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,207 @@
|
|||
// ==============================================================
|
||||
// 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_GUI_H_
|
||||
#define _GLEST_GAME_GUI_H_
|
||||
|
||||
#include "resource.h"
|
||||
#include "command_type.h"
|
||||
#include "display.h"
|
||||
#include "commander.h"
|
||||
#include "console.h"
|
||||
#include "selection.h"
|
||||
#include "random.h"
|
||||
#include <map>
|
||||
|
||||
using Shared::Util::Random;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
class Unit;
|
||||
class World;
|
||||
class CommandType;
|
||||
class GameCamera;
|
||||
class Game;
|
||||
|
||||
enum DisplayState{
|
||||
dsEmpty,
|
||||
dsUnitSkills,
|
||||
dsUnitBuild,
|
||||
dsEnemy
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class Mouse3d
|
||||
// =====================================================
|
||||
|
||||
class Mouse3d{
|
||||
public:
|
||||
static const float fadeSpeed;
|
||||
|
||||
private:
|
||||
bool enabled;
|
||||
int rot;
|
||||
float fade;
|
||||
|
||||
public:
|
||||
Mouse3d();
|
||||
|
||||
void enable();
|
||||
void update();
|
||||
|
||||
bool isEnabled() const {return enabled;}
|
||||
float getFade() const {return fade;}
|
||||
int getRot() const {return rot;}
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class SelectionQuad
|
||||
// =====================================================
|
||||
|
||||
class SelectionQuad{
|
||||
private:
|
||||
Vec2i posDown;
|
||||
Vec2i posUp;
|
||||
bool enabled;
|
||||
|
||||
public:
|
||||
SelectionQuad();
|
||||
|
||||
bool isEnabled() const {return enabled;}
|
||||
Vec2i getPosDown() const {return posDown;}
|
||||
Vec2i getPosUp() const {return posUp;}
|
||||
|
||||
void setPosDown(const Vec2i &posDown);
|
||||
void setPosUp(const Vec2i &posUp);
|
||||
void disable();
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class Gui
|
||||
//
|
||||
/// In game GUI
|
||||
// =====================================================
|
||||
|
||||
class Gui{
|
||||
public:
|
||||
static const int maxSelBuff= 128*5;
|
||||
static const int upgradeDisplayIndex= 8;
|
||||
static const int cancelPos= 15;
|
||||
static const int meetingPointPos= 14;
|
||||
static const int imageCount= 16;
|
||||
static const int invalidPos= -1;
|
||||
static const int doubleClickSelectionRadius= 20;
|
||||
|
||||
private:
|
||||
//External objects
|
||||
Random random;
|
||||
const Commander *commander;
|
||||
const World *world;
|
||||
GameCamera *gameCamera;
|
||||
Console *console;
|
||||
|
||||
//Positions
|
||||
Vec2i posObjWorld; //world coords
|
||||
bool validPosObjWorld;
|
||||
bool computeSelection;
|
||||
|
||||
//display
|
||||
const UnitType *choosenBuildingType;
|
||||
const CommandType *activeCommandType;
|
||||
CommandClass activeCommandClass;
|
||||
int activePos;
|
||||
|
||||
//composite
|
||||
Display display;
|
||||
Mouse3d mouse3d;
|
||||
Selection selection;
|
||||
SelectionQuad selectionQuad;
|
||||
|
||||
//states
|
||||
bool selectingBuilding;
|
||||
bool selectingPos;
|
||||
bool selectingMeetingPoint;
|
||||
|
||||
bool allowRotateUnits;
|
||||
std::map<string, float> unitTypeBuildRotation;
|
||||
|
||||
public:
|
||||
Gui();
|
||||
void init(Game *game);
|
||||
void end();
|
||||
|
||||
//get
|
||||
Vec2i getPosObjWorld() const {return posObjWorld;}
|
||||
const UnitType *getBuilding() const;
|
||||
|
||||
const Mouse3d *getMouse3d() const {return &mouse3d;}
|
||||
const Display *getDisplay() const {return &display;}
|
||||
const Selection *getSelection() const {return &selection;}
|
||||
const SelectionQuad *getSelectionQuad() const {return &selectionQuad;}
|
||||
bool isSelected(const Unit *unit) const {return selection.hasUnit(unit);}
|
||||
|
||||
bool isValidPosObjWorld() const {return validPosObjWorld;}
|
||||
bool isSelecting() const {return selectionQuad.isEnabled();}
|
||||
bool isSelectingPos() const {return selectingPos;}
|
||||
bool isSelectingBuilding() const {return selectingBuilding;}
|
||||
bool isPlacingBuilding() const;
|
||||
|
||||
//set
|
||||
void invalidatePosObjWorld();
|
||||
void setComputeSelectionFlag();
|
||||
|
||||
//events
|
||||
void update();
|
||||
void tick();
|
||||
bool mouseValid(int x, int y);
|
||||
void mouseDownLeftDisplay(int x, int y);
|
||||
void mouseMoveDisplay(int x, int y);
|
||||
void mouseDownLeftGraphics(int x, int y);
|
||||
void mouseDownRightGraphics(int x, int y);
|
||||
void mouseUpLeftGraphics(int x, int y);
|
||||
void mouseMoveGraphics(int x, int y);
|
||||
void mouseDoubleClickLeftGraphics(int x, int y);
|
||||
void groupKey(int groupIndex);
|
||||
void hotKey(char key);
|
||||
|
||||
//misc
|
||||
void onSelectionChanged();
|
||||
|
||||
float getUnitTypeBuildRotation(string unitKey) const;
|
||||
|
||||
private:
|
||||
|
||||
//orders
|
||||
void giveDefaultOrders(int x, int y);
|
||||
void giveOneClickOrders();
|
||||
void giveTwoClickOrders(int x, int y);
|
||||
|
||||
//hotkeys
|
||||
void centerCameraOnSelection();
|
||||
void selectInterestingUnit(InterestingUnitType iut);
|
||||
void clickCommonCommand(CommandClass commandClass);
|
||||
|
||||
//misc
|
||||
int computePosDisplay(int x, int y);
|
||||
void computeDisplay();
|
||||
void resetState();
|
||||
void mouseDownDisplayUnitSkills(int posDisplay);
|
||||
void mouseDownDisplayUnitBuild(int posDisplay);
|
||||
void computeInfoString(int posDisplay);
|
||||
void addOrdersResultToConsole(CommandClass cc, CommandResult rr);
|
||||
bool isSharedCommandClass(CommandClass commandClass);
|
||||
void computeSelected(bool doubleCkick);
|
||||
bool computeTarget(const Vec2i &screenPos, Vec2i &targetPos, const Unit *&targetUnit);
|
||||
};
|
||||
|
||||
}} //end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,270 @@
|
|||
// ==============================================================
|
||||
// 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 "program.h"
|
||||
|
||||
#include "sound.h"
|
||||
#include "renderer.h"
|
||||
#include "config.h"
|
||||
#include "game.h"
|
||||
#include "main_menu.h"
|
||||
#include "intro.h"
|
||||
#include "world.h"
|
||||
#include "main.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "logger.h"
|
||||
#include "profiler.h"
|
||||
#include "core_data.h"
|
||||
#include "metrics.h"
|
||||
#include "network_manager.h"
|
||||
#include "menu_state_custom_game.h"
|
||||
#include "menu_state_join_game.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Util;
|
||||
using namespace Shared::Graphics;
|
||||
using namespace Shared::Graphics::Gl;
|
||||
|
||||
// =====================================================
|
||||
// class Program
|
||||
// =====================================================
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
const int Program::maxTimes= 10;
|
||||
|
||||
// ===================== PUBLIC ========================
|
||||
|
||||
Program::Program(){
|
||||
programState= NULL;
|
||||
}
|
||||
|
||||
void Program::initNormal(WindowGl *window){
|
||||
init(window);
|
||||
setState(new Intro(this));
|
||||
}
|
||||
|
||||
void Program::initServer(WindowGl *window){
|
||||
MainMenu* mainMenu= NULL;
|
||||
|
||||
init(window);
|
||||
mainMenu= new MainMenu(this);
|
||||
setState(mainMenu);
|
||||
mainMenu->setState(new MenuStateCustomGame(this, mainMenu, true));
|
||||
}
|
||||
|
||||
void Program::initClient(WindowGl *window, const Ip &serverIp){
|
||||
MainMenu* mainMenu= NULL;
|
||||
|
||||
init(window);
|
||||
mainMenu= new MainMenu(this);
|
||||
setState(mainMenu);
|
||||
mainMenu->setState(new MenuStateJoinGame(this, mainMenu, true, serverIp));
|
||||
}
|
||||
|
||||
Program::~Program(){
|
||||
delete programState;
|
||||
|
||||
Renderer::getInstance().end();
|
||||
|
||||
//restore video mode
|
||||
restoreDisplaySettings();
|
||||
}
|
||||
|
||||
void Program::mouseDownLeft(int x, int y){
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
programState->mouseDownLeft(metrics.toVirtualX(x), metrics.toVirtualY(y));
|
||||
}
|
||||
|
||||
void Program::mouseUpLeft(int x, int y){
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
programState->mouseUpLeft(metrics.toVirtualX(x), metrics.toVirtualY(y));
|
||||
}
|
||||
|
||||
void Program::mouseDownRight(int x, int y){
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
programState->mouseDownRight(metrics.toVirtualX(x), metrics.toVirtualY(y));
|
||||
}
|
||||
|
||||
void Program::mouseDoubleClickLeft(int x, int y){
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
programState->mouseDoubleClickLeft(metrics.toVirtualX(x), metrics.toVirtualY(y));
|
||||
}
|
||||
|
||||
void Program::mouseMove(int x, int y, const MouseState *ms){
|
||||
const Metrics &metrics= Metrics::getInstance();
|
||||
programState->mouseMove(metrics.toVirtualX(x), metrics.toVirtualY(y), ms);
|
||||
}
|
||||
|
||||
void Program::keyDown(char key){
|
||||
//delegate event
|
||||
programState->keyDown(key);
|
||||
}
|
||||
|
||||
void Program::keyUp(char key){
|
||||
programState->keyUp(key);
|
||||
}
|
||||
|
||||
void Program::keyPress(char c){
|
||||
programState->keyPress(c);
|
||||
}
|
||||
|
||||
void Program::loop(){
|
||||
|
||||
//render
|
||||
programState->render();
|
||||
|
||||
//update camera
|
||||
while(updateCameraTimer.isTime()){
|
||||
programState->updateCamera();
|
||||
}
|
||||
|
||||
//update world
|
||||
while(updateTimer.isTime()){
|
||||
GraphicComponent::update();
|
||||
programState->update();
|
||||
SoundRenderer::getInstance().update();
|
||||
NetworkManager::getInstance().update();
|
||||
}
|
||||
|
||||
//fps timer
|
||||
while(fpsTimer.isTime()){
|
||||
programState->tick();
|
||||
}
|
||||
}
|
||||
|
||||
void Program::resize(SizeState sizeState){
|
||||
|
||||
switch(sizeState){
|
||||
case ssMinimized:
|
||||
//restoreVideoMode();
|
||||
break;
|
||||
case ssMaximized:
|
||||
case ssRestored:
|
||||
//setDisplaySettings();
|
||||
//renderer.reloadResources();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== misc ====================
|
||||
|
||||
void Program::setState(ProgramState *programState)
|
||||
{
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
|
||||
delete this->programState;
|
||||
|
||||
if(Socket::enableDebugText) printf("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__);
|
||||
|
||||
programState->init();
|
||||
|
||||
if(Socket::enableDebugText) printf("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__);
|
||||
}
|
||||
|
||||
void Program::exit(){
|
||||
window->destroy();
|
||||
}
|
||||
|
||||
// ==================== PRIVATE ====================
|
||||
|
||||
void Program::init(WindowGl *window){
|
||||
|
||||
this->window= window;
|
||||
Config &config= Config::getInstance();
|
||||
|
||||
//set video mode
|
||||
setDisplaySettings();
|
||||
|
||||
//window
|
||||
window->setText("Glest");
|
||||
window->setStyle(config.getBool("Windowed")? wsWindowedFixed: wsFullscreen);
|
||||
window->setPos(0, 0);
|
||||
window->setSize(config.getInt("ScreenWidth"), config.getInt("ScreenHeight"));
|
||||
window->create();
|
||||
|
||||
//timers
|
||||
fpsTimer.init(1, maxTimes);
|
||||
updateTimer.init(GameConstants::updateFps, maxTimes);
|
||||
updateCameraTimer.init(GameConstants::cameraFps, maxTimes);
|
||||
|
||||
//log start
|
||||
Logger &logger= Logger::getInstance();
|
||||
logger.setFile("glest.log");
|
||||
logger.clear();
|
||||
|
||||
//lang
|
||||
Lang &lang= Lang::getInstance();
|
||||
lang.loadStrings(config.getString("Lang"));
|
||||
|
||||
//render
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
window->initGl(config.getInt("ColorBits"), config.getInt("DepthBits"), config.getInt("StencilBits"));
|
||||
window->makeCurrentGl();
|
||||
|
||||
//coreData, needs renderer, but must load before renderer init
|
||||
CoreData &coreData= CoreData::getInstance();
|
||||
coreData.load();
|
||||
|
||||
//init renderer (load global textures)
|
||||
renderer.init();
|
||||
|
||||
//sound
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
soundRenderer.init(window);
|
||||
|
||||
NetworkInterface::setAllowGameDataSynchCheck(Config::getInstance().getBool("AllowGameDataSynchCheck","0"));
|
||||
NetworkInterface::setAllowDownloadDataSynch(Config::getInstance().getBool("AllowDownloadDataSynch","0"));
|
||||
}
|
||||
|
||||
void Program::setDisplaySettings(){
|
||||
|
||||
Config &config= Config::getInstance();
|
||||
|
||||
if(!config.getBool("Windowed")){
|
||||
|
||||
int freq= config.getInt("RefreshFrequency");
|
||||
int colorBits= config.getInt("ColorBits");
|
||||
int screenWidth= config.getInt("ScreenWidth");
|
||||
int screenHeight= config.getInt("ScreenHeight");
|
||||
|
||||
if(!(changeVideoMode(screenWidth, screenHeight, colorBits, freq) ||
|
||||
changeVideoMode(screenWidth, screenHeight, colorBits, 0)))
|
||||
{
|
||||
throw runtime_error(
|
||||
"Error setting video mode: " +
|
||||
intToStr(screenWidth) + "x" + intToStr(screenHeight) + "x" + intToStr(colorBits));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Program::restoreDisplaySettings(){
|
||||
Config &config= Config::getInstance();
|
||||
|
||||
if(!config.getBool("Windowed")){
|
||||
restoreVideoMode();
|
||||
}
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,211 @@
|
|||
// ==============================================================
|
||||
// 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_NETWORKINTERFACE_H_
|
||||
#define _GLEST_GAME_NETWORKINTERFACE_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "checksum.h"
|
||||
#include "network_message.h"
|
||||
#include "network_types.h"
|
||||
|
||||
#include "game_settings.h"
|
||||
|
||||
#include "thread.h"
|
||||
#include "types.h"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using Shared::Util::Checksum;
|
||||
using namespace Shared::Util;
|
||||
using namespace Shared::Platform;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
//class GameSettings;
|
||||
|
||||
// =====================================================
|
||||
// class NetworkInterface
|
||||
// =====================================================
|
||||
|
||||
class NetworkInterface {
|
||||
|
||||
protected:
|
||||
static bool allowGameDataSynchCheck;
|
||||
static bool allowDownloadDataSynch;
|
||||
bool networkGameDataSynchCheckOkMap;
|
||||
bool networkGameDataSynchCheckOkTile;
|
||||
bool networkGameDataSynchCheckOkTech;
|
||||
bool networkGameDataSynchCheckOkFogOfWar;
|
||||
|
||||
string chatText;
|
||||
string chatSender;
|
||||
int chatTeamIndex;
|
||||
|
||||
public:
|
||||
static const int readyWaitTimeout;
|
||||
GameSettings gameSettings;
|
||||
|
||||
public:
|
||||
virtual ~NetworkInterface(){}
|
||||
|
||||
virtual Socket* getSocket()= 0;
|
||||
virtual const Socket* getSocket() const= 0;
|
||||
virtual void close()= 0;
|
||||
|
||||
string getIp() const {return getSocket()->getIp();}
|
||||
string getHostName() const {return getSocket()->getHostName();}
|
||||
|
||||
void sendMessage(const NetworkMessage* networkMessage);
|
||||
NetworkMessageType getNextMessageType(bool checkHasDataFirst = false);
|
||||
bool receiveMessage(NetworkMessage* networkMessage);
|
||||
|
||||
bool isConnected();
|
||||
|
||||
//virtual void setGameSettings(GameSettings *serverGameSettings) { gameSettings = *serverGameSettings; }
|
||||
const virtual GameSettings * getGameSettings() { return &gameSettings; }
|
||||
|
||||
static void setAllowDownloadDataSynch(bool value) { allowDownloadDataSynch = value; }
|
||||
static bool getAllowDownloadDataSynch() { return allowDownloadDataSynch; }
|
||||
|
||||
static void setAllowGameDataSynchCheck(bool value) { allowGameDataSynchCheck = value; }
|
||||
static bool getAllowGameDataSynchCheck() { return allowGameDataSynchCheck; }
|
||||
|
||||
virtual bool getNetworkGameDataSynchCheckOk() { return (networkGameDataSynchCheckOkMap && networkGameDataSynchCheckOkTile && networkGameDataSynchCheckOkTech && networkGameDataSynchCheckOkFogOfWar); }
|
||||
virtual void setNetworkGameDataSynchCheckOkMap(bool value) { networkGameDataSynchCheckOkMap = value; }
|
||||
virtual void setNetworkGameDataSynchCheckOkTile(bool value) { networkGameDataSynchCheckOkTile = value; }
|
||||
virtual void setNetworkGameDataSynchCheckOkTech(bool value) { networkGameDataSynchCheckOkTech = value; }
|
||||
virtual bool getNetworkGameDataSynchCheckOkMap() { return networkGameDataSynchCheckOkMap; }
|
||||
virtual bool getNetworkGameDataSynchCheckOkTile() { return networkGameDataSynchCheckOkTile; }
|
||||
virtual bool getNetworkGameDataSynchCheckOkTech() { return networkGameDataSynchCheckOkTech; }
|
||||
virtual bool getFogOfWar()=0;
|
||||
virtual bool getNetworkGameDataSynchCheckOkFogOfWar() { return networkGameDataSynchCheckOkFogOfWar; }
|
||||
virtual void setNetworkGameDataSynchCheckOkFogOfWar(bool value) { networkGameDataSynchCheckOkFogOfWar = value; }
|
||||
|
||||
const string getChatText() const {return chatText;}
|
||||
const string getChatSender() const {return chatSender;}
|
||||
int getChatTeamIndex() const {return chatTeamIndex;}
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class GameNetworkInterface
|
||||
//
|
||||
// Adds functions common to servers and clients
|
||||
// but not connection slots
|
||||
// =====================================================
|
||||
|
||||
class GameNetworkInterface: public NetworkInterface{
|
||||
private:
|
||||
typedef vector<NetworkCommand> Commands;
|
||||
|
||||
protected:
|
||||
Commands requestedCommands; //commands requested by the user
|
||||
Commands pendingCommands; //commands ready to be given
|
||||
bool quit;
|
||||
|
||||
public:
|
||||
GameNetworkInterface();
|
||||
|
||||
//message processimg
|
||||
virtual void update()= 0;
|
||||
virtual void updateLobby()= 0;
|
||||
virtual void updateKeyframe(int frameCount)= 0;
|
||||
virtual void waitUntilReady(Checksum* checksum)= 0;
|
||||
|
||||
//message sending
|
||||
virtual void sendTextMessage(const string &text, int teamIndex)= 0;
|
||||
virtual void quitGame(bool userManuallyQuit)=0;
|
||||
|
||||
//misc
|
||||
virtual string getNetworkStatus() const= 0;
|
||||
|
||||
//access functions
|
||||
void requestCommand(const NetworkCommand *networkCommand) {requestedCommands.push_back(*networkCommand);}
|
||||
int getPendingCommandCount() const {return pendingCommands.size();}
|
||||
const NetworkCommand* getPendingCommand(int i) const {return &pendingCommands[i];}
|
||||
void clearPendingCommands() {pendingCommands.clear();}
|
||||
bool getQuit() const {return quit;}
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class FileTransferSocketThread
|
||||
// =====================================================
|
||||
|
||||
enum FileTransferHostType
|
||||
{
|
||||
eClient,
|
||||
eServer
|
||||
};
|
||||
|
||||
enum FileTransferOperationType
|
||||
{
|
||||
eSend,
|
||||
eReceive
|
||||
};
|
||||
|
||||
class FileTransferInfo
|
||||
{
|
||||
private:
|
||||
|
||||
void CopyAll(const FileTransferInfo &obj)
|
||||
{
|
||||
hostType = obj.hostType;
|
||||
serverIP = obj.serverIP;
|
||||
serverPort = obj.serverPort;
|
||||
opType = obj.opType;
|
||||
fileName = obj.fileName;
|
||||
}
|
||||
|
||||
public:
|
||||
FileTransferInfo()
|
||||
{
|
||||
}
|
||||
FileTransferInfo(const FileTransferInfo &obj)
|
||||
{
|
||||
CopyAll(obj);
|
||||
}
|
||||
FileTransferInfo &operator=(const FileTransferInfo &obj)
|
||||
{
|
||||
CopyAll(obj);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FileTransferHostType hostType;
|
||||
string serverIP;
|
||||
int32 serverPort;
|
||||
FileTransferOperationType opType;
|
||||
string fileName;
|
||||
};
|
||||
|
||||
class FileInfo
|
||||
{
|
||||
public:
|
||||
string fileName;
|
||||
int64 filesize;
|
||||
int32 filecrc;
|
||||
};
|
||||
|
||||
class FileTransferSocketThread : public Thread
|
||||
{
|
||||
private:
|
||||
FileTransferInfo info;
|
||||
|
||||
public:
|
||||
FileTransferSocketThread(FileTransferInfo fileInfo);
|
||||
virtual void execute();
|
||||
};
|
||||
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -107,6 +107,7 @@ const int Unit::invalidId= -1;
|
|||
Unit::Unit(int id, const Vec2i &pos, const UnitType *type, Faction *faction, Map *map, float unitPlacementRotation) {
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
|
||||
allowRotateUnits = Config::getInstance().getBool("AllowRotateUnits","0");
|
||||
|
||||
Random random;
|
||||
|
||||
|
@ -1108,17 +1109,21 @@ void Unit::startDamageParticles(){
|
|||
|
||||
bool Unit::getCellMapCell(int x, int y) const {
|
||||
const UnitType *ut= getType();
|
||||
if(ut != NULL && rotateAmount > 0) {
|
||||
|
||||
if(allowRotateUnits == true && ut != NULL && rotateAmount > 0) {
|
||||
return cellMap[ut->getSize() * y + x];
|
||||
}
|
||||
else {
|
||||
else if(ut != NULL) {
|
||||
return ut->getCellMapCell(x,y);
|
||||
}
|
||||
else {
|
||||
throw runtime_error("ut == NULL in Unit::getCellMapCell()!");
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::setRotateAmount(float value) {
|
||||
if(allowRotateUnits == true) {
|
||||
rotateAmount = value;
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] unit id = %d [%s] rotate amount = %f\n",__FILE__,__FUNCTION__,getId(), getFullName().c_str(),rotateAmount);
|
||||
|
||||
const UnitType *ut= getType();
|
||||
|
@ -1165,13 +1170,16 @@ void Unit::setRotateAmount(float value) {
|
|||
}
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] Transformed matrix below:\n",__FILE__,__FUNCTION__);
|
||||
/*
|
||||
for(int iRow = 0; iRow < matrixSize; ++iRow) {
|
||||
for(int iCol = 0; iCol < matrixSize; ++iCol) {
|
||||
bool getCellResult = ut->getCellMapCell(iCol, iRow);
|
||||
bool getCellResultRotated = getCellMapCell(iRow, iCol);
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] matrix [%d,%d] = %d, rotated = %d\n",__FILE__,__FUNCTION__,iRow,iCol,getCellResult,getCellResultRotated);
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] matrix [%d,%d] = %d, rotated = %d\n",__FILE__,__FUNCTION__,iRow,iCol,getCellResult,getCellResultRotated);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,316 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<74>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_UNIT_H_
|
||||
#define _GLEST_GAME_UNIT_H_
|
||||
|
||||
#include "model.h"
|
||||
#include "upgrade_type.h"
|
||||
#include "particle.h"
|
||||
#include "skill_type.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
using Shared::Graphics::ParticleSystem;
|
||||
using Shared::Graphics::UnitParticleSystem;
|
||||
using Shared::Graphics::Vec4f;
|
||||
using Shared::Graphics::Vec2f;
|
||||
using Shared::Graphics::Vec3f;
|
||||
using Shared::Graphics::Vec2i;
|
||||
using Shared::Graphics::Model;
|
||||
|
||||
class Map;
|
||||
class Faction;
|
||||
class Unit;
|
||||
class Command;
|
||||
class SkillType;
|
||||
class ResourceType;
|
||||
class CommandType;
|
||||
class SkillType;
|
||||
class UnitType;
|
||||
class TotalUpgrade;
|
||||
class UpgradeType;
|
||||
class Level;
|
||||
class MorphCommandType;
|
||||
|
||||
enum CommandResult{
|
||||
crSuccess,
|
||||
crFailRes,
|
||||
crFailReqs,
|
||||
crFailUndefined,
|
||||
crSomeFailed
|
||||
};
|
||||
|
||||
enum InterestingUnitType{
|
||||
iutIdleHarvester,
|
||||
iutBuiltBuilding,
|
||||
iutProducer,
|
||||
iutDamaged,
|
||||
iutStore
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class UnitObserver
|
||||
// =====================================================
|
||||
|
||||
class UnitObserver{
|
||||
public:
|
||||
enum Event{
|
||||
eKill
|
||||
};
|
||||
|
||||
public:
|
||||
virtual ~UnitObserver() {}
|
||||
virtual void unitEvent(Event event, const Unit *unit)=0;
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class UnitReference
|
||||
// =====================================================
|
||||
|
||||
class UnitReference{
|
||||
private:
|
||||
int id;
|
||||
Faction *faction;
|
||||
|
||||
public:
|
||||
UnitReference();
|
||||
|
||||
void operator=(const Unit *unit);
|
||||
Unit *getUnit() const;
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class UnitPath
|
||||
//
|
||||
/// Holds the next cells of a Unit movement
|
||||
// =====================================================
|
||||
|
||||
class UnitPath{
|
||||
private:
|
||||
static const int maxBlockCount;
|
||||
|
||||
private:
|
||||
int blockCount;
|
||||
vector<Vec2i> pathQueue;
|
||||
|
||||
public:
|
||||
bool isBlocked();
|
||||
bool isEmpty();
|
||||
|
||||
void clear();
|
||||
void incBlockCount();
|
||||
void push(const Vec2i &path);
|
||||
Vec2i pop();
|
||||
};
|
||||
|
||||
// ===============================
|
||||
// class Unit
|
||||
//
|
||||
/// A game unit or building
|
||||
// ===============================
|
||||
|
||||
class Unit{
|
||||
private:
|
||||
typedef list<Command*> Commands;
|
||||
typedef list<UnitObserver*> Observers;
|
||||
typedef list<UnitParticleSystem*> UnitParticleSystems;
|
||||
|
||||
public:
|
||||
static const float speedDivider;
|
||||
static const int maxDeadCount;
|
||||
static const float highlightTime;
|
||||
static const int invalidId;
|
||||
|
||||
|
||||
private:
|
||||
int id;
|
||||
int hp;
|
||||
int ep;
|
||||
int loadCount;
|
||||
int deadCount;
|
||||
float progress; //between 0 and 1
|
||||
float lastAnimProgress; //between 0 and 1
|
||||
float animProgress; //between 0 and 1
|
||||
float highlight;
|
||||
int progress2;
|
||||
int kills;
|
||||
|
||||
UnitReference targetRef;
|
||||
|
||||
Field currField;
|
||||
Field targetField;
|
||||
const Level *level;
|
||||
|
||||
Vec2i pos;
|
||||
Vec2i lastPos;
|
||||
Vec2i targetPos; //absolute target pos
|
||||
Vec3f targetVec;
|
||||
Vec2i meetingPos;
|
||||
|
||||
float lastRotation; //in degrees
|
||||
float targetRotation;
|
||||
float rotation;
|
||||
|
||||
const UnitType *type;
|
||||
const ResourceType *loadType;
|
||||
const SkillType *currSkill;
|
||||
|
||||
bool toBeUndertaken;
|
||||
bool alive;
|
||||
bool showUnitParticles;
|
||||
|
||||
Faction *faction;
|
||||
ParticleSystem *fire;
|
||||
TotalUpgrade totalUpgrade;
|
||||
Map *map;
|
||||
|
||||
UnitPath unitPath;
|
||||
|
||||
Commands commands;
|
||||
Observers observers;
|
||||
UnitParticleSystems unitParticleSystems;
|
||||
UnitParticleSystems damageParticleSystems;
|
||||
|
||||
bool allowRotateUnits;
|
||||
float rotateAmount;
|
||||
bool *cellMap;
|
||||
|
||||
public:
|
||||
Unit(int id, const Vec2i &pos, const UnitType *type, Faction *faction, Map *map, float unitPlacementRotation);
|
||||
~Unit();
|
||||
|
||||
//queries
|
||||
int getId() const {return id;}
|
||||
Field getCurrField() const {return currField;}
|
||||
int getLoadCount() const {return loadCount;}
|
||||
float getLastAnimProgress() const {return lastAnimProgress;}
|
||||
float getProgress() const {return progress;}
|
||||
float getAnimProgress() const {return animProgress;}
|
||||
float getHightlight() const {return highlight;}
|
||||
int getProgress2() const {return progress2;}
|
||||
int getFactionIndex() const;
|
||||
int getTeam() const;
|
||||
int getHp() const {return hp;}
|
||||
int getEp() const {return ep;}
|
||||
int getProductionPercent() const;
|
||||
float getHpRatio() const;
|
||||
float getEpRatio() const;
|
||||
bool getToBeUndertaken() const {return toBeUndertaken;}
|
||||
Vec2i getTargetPos() const {return targetPos;}
|
||||
Vec3f getTargetVec() const {return targetVec;}
|
||||
Field getTargetField() const {return targetField;}
|
||||
Vec2i getMeetingPos() const {return meetingPos;}
|
||||
Faction *getFaction() const {return faction;}
|
||||
const ResourceType *getLoadType() const {return loadType;}
|
||||
const UnitType *getType() const {return type;}
|
||||
const SkillType *getCurrSkill() const {return currSkill;}
|
||||
const TotalUpgrade *getTotalUpgrade() const {return &totalUpgrade;}
|
||||
float getRotation() const {return rotation;}
|
||||
float getVerticalRotation() const;
|
||||
ParticleSystem *getFire() const {return fire;}
|
||||
int getKills() {return kills;}
|
||||
const Level *getLevel() const {return level;}
|
||||
const Level *getNextLevel() const;
|
||||
string getFullName() const;
|
||||
const UnitPath *getPath() const {return &unitPath;}
|
||||
UnitPath *getPath() {return &unitPath;}
|
||||
|
||||
//pos
|
||||
Vec2i getPos() const {return pos;}
|
||||
Vec2i getLastPos() const {return lastPos;}
|
||||
Vec2i getCenteredPos() const;
|
||||
Vec2f getFloatCenteredPos() const;
|
||||
Vec2i getCellPos() const;
|
||||
|
||||
//is
|
||||
bool isHighlighted() const {return highlight>0.f;}
|
||||
bool isDead() const {return !alive;}
|
||||
bool isAlive() const {return alive;}
|
||||
bool isOperative() const;
|
||||
bool isBeingBuilt() const;
|
||||
bool isBuilt() const;
|
||||
bool isPutrefacting() const;
|
||||
bool isAlly(const Unit *unit) const;
|
||||
bool isDamaged() const;
|
||||
bool isInteresting(InterestingUnitType iut) const;
|
||||
|
||||
//set
|
||||
void setCurrField(Field currField) {this->currField= currField;}
|
||||
void setCurrSkill(const SkillType *currSkill);
|
||||
void setCurrSkill(SkillClass sc);
|
||||
void setLoadCount(int loadCount) {this->loadCount= loadCount;}
|
||||
void setLoadType(const ResourceType *loadType) {this->loadType= loadType;}
|
||||
void setProgress2(int progress2) {this->progress2= progress2;}
|
||||
void setPos(const Vec2i &pos);
|
||||
void setTargetPos(const Vec2i &targetPos);
|
||||
void setTarget(const Unit *unit);
|
||||
void setTargetVec(const Vec3f &targetVec) {this->targetVec= targetVec;}
|
||||
void setMeetingPos(const Vec2i &meetingPos) {this->meetingPos= meetingPos;}
|
||||
void setVisible(const bool visible);
|
||||
|
||||
//render related
|
||||
const Model *getCurrentModel() const;
|
||||
Vec3f getCurrVector() const;
|
||||
Vec3f getCurrVectorFlat() const;
|
||||
|
||||
//command related
|
||||
bool anyCommand() const;
|
||||
Command *getCurrCommand() const;
|
||||
unsigned int getCommandSize() const;
|
||||
CommandResult giveCommand(Command *command); //give a command
|
||||
CommandResult finishCommand(); //command finished
|
||||
CommandResult cancelCommand(); //cancel canceled
|
||||
|
||||
//lifecycle
|
||||
void create(bool startingUnit= false);
|
||||
void born();
|
||||
void kill();
|
||||
void undertake();
|
||||
|
||||
//observers
|
||||
void addObserver(UnitObserver *unitObserver) ;
|
||||
void removeObserver(UnitObserver *unitObserver);
|
||||
void notifyObservers(UnitObserver::Event event);
|
||||
|
||||
//other
|
||||
void resetHighlight();
|
||||
const CommandType *computeCommandType(const Vec2i &pos, const Unit *targetUnit= NULL) const;
|
||||
string getDesc() const;
|
||||
bool computeEp();
|
||||
bool repair();
|
||||
bool decHp(int i);
|
||||
int update2();
|
||||
bool update();
|
||||
void tick();
|
||||
void applyUpgrade(const UpgradeType *upgradeType);
|
||||
void computeTotalUpgrade();
|
||||
void incKills();
|
||||
bool morph(const MorphCommandType *mct);
|
||||
CommandResult checkCommand(Command *command) const;
|
||||
void applyCommand(Command *command);
|
||||
|
||||
void setRotateAmount(float value);
|
||||
float getRotateAmount() { return rotateAmount; }
|
||||
bool getCellMapCell(int x, int y) const;
|
||||
|
||||
private:
|
||||
float computeHeight(const Vec2i &pos) const;
|
||||
void updateTarget();
|
||||
void clearCommands();
|
||||
CommandResult undoCommand(Command *command);
|
||||
void stopDamageParticles();
|
||||
void startDamageParticles();
|
||||
};
|
||||
|
||||
}}// end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,898 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<74>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 "unit_updater.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#include "sound.h"
|
||||
#include "upgrade.h"
|
||||
#include "unit.h"
|
||||
#include "particle_type.h"
|
||||
#include "core_data.h"
|
||||
#include "config.h"
|
||||
#include "renderer.h"
|
||||
#include "sound_renderer.h"
|
||||
#include "game.h"
|
||||
#include "path_finder.h"
|
||||
#include "object.h"
|
||||
#include "faction.h"
|
||||
#include "network_manager.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Graphics;
|
||||
using namespace Shared::Util;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
// =====================================================
|
||||
// class UnitUpdater
|
||||
// =====================================================
|
||||
|
||||
// ===================== PUBLIC ========================
|
||||
|
||||
void UnitUpdater::init(Game *game){
|
||||
|
||||
this->gui= game->getGui();
|
||||
this->gameCamera= game->getGameCamera();
|
||||
this->world= game->getWorld();
|
||||
this->map= world->getMap();
|
||||
this->console= game->getConsole();
|
||||
this->scriptManager= game->getScriptManager();
|
||||
pathFinder.init(map);
|
||||
|
||||
allowRotateUnits = Config::getInstance().getBool(reinterpret_cast<const char *>("AllowRotateUnits"),"0");
|
||||
}
|
||||
|
||||
|
||||
// ==================== progress skills ====================
|
||||
|
||||
//skill dependent actions
|
||||
void UnitUpdater::updateUnit(Unit *unit){
|
||||
|
||||
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
|
||||
|
||||
//play skill sound
|
||||
const SkillType *currSkill= unit->getCurrSkill();
|
||||
if(currSkill->getSound()!=NULL){
|
||||
float soundStartTime= currSkill->getSoundStartTime();
|
||||
if(soundStartTime>=unit->getLastAnimProgress() && soundStartTime<unit->getAnimProgress()){
|
||||
if(map->getSurfaceCell(Map::toSurfCoords(unit->getPos()))->isVisible(world->getThisTeamIndex())){
|
||||
soundRenderer.playFx(currSkill->getSound(), unit->getCurrVector(), gameCamera->getPos());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//start attack particle system
|
||||
if(unit->getCurrSkill()->getClass()==scAttack){
|
||||
const AttackSkillType *ast= static_cast<const AttackSkillType*>(unit->getCurrSkill());
|
||||
float attackStartTime= ast->getAttackStartTime();
|
||||
if(attackStartTime>=unit->getLastAnimProgress() && attackStartTime<unit->getAnimProgress()){
|
||||
startAttackParticleSystem(unit);
|
||||
}
|
||||
}
|
||||
|
||||
//update unit
|
||||
if(unit->update()){
|
||||
|
||||
updateUnitCommand(unit);
|
||||
|
||||
//if unit is out of EP, it stops
|
||||
if(unit->computeEp()){
|
||||
unit->setCurrSkill(scStop);
|
||||
unit->cancelCommand();
|
||||
}
|
||||
|
||||
//move unit in cells
|
||||
if(unit->getCurrSkill()->getClass()==scMove){
|
||||
world->moveUnitCells(unit);
|
||||
|
||||
//play water sound
|
||||
if(map->getCell(unit->getPos())->getHeight()<map->getWaterLevel() && unit->getCurrField()==fLand){
|
||||
soundRenderer.playFx(CoreData::getInstance().getWaterSound());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//unit death
|
||||
if(unit->isDead() && unit->getCurrSkill()->getClass()!=scDie){
|
||||
unit->kill();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ==================== progress commands ====================
|
||||
|
||||
//VERY IMPORTANT: compute next state depending on the first order of the list
|
||||
void UnitUpdater::updateUnitCommand(Unit *unit){
|
||||
|
||||
//if unis has command process it
|
||||
if(unit->anyCommand()) {
|
||||
unit->getCurrCommand()->getCommandType()->update(this, unit);
|
||||
}
|
||||
|
||||
//if no commands stop and add stop command
|
||||
if(!unit->anyCommand() && unit->isOperative()){
|
||||
unit->setCurrSkill(scStop);
|
||||
if(unit->getType()->hasCommandClass(ccStop)){
|
||||
unit->giveCommand(new Command(unit->getType()->getFirstCtOfClass(ccStop)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== updateStop ====================
|
||||
|
||||
void UnitUpdater::updateStop(Unit *unit){
|
||||
|
||||
Command *command= unit->getCurrCommand();
|
||||
const StopCommandType *sct = static_cast<const StopCommandType*>(command->getCommandType());
|
||||
Unit *sighted;
|
||||
|
||||
unit->setCurrSkill(sct->getStopSkillType());
|
||||
|
||||
//we can attack any unit => attack it
|
||||
if(unit->getType()->hasSkillClass(scAttack)){
|
||||
for(int i=0; i<unit->getType()->getCommandTypeCount(); ++i){
|
||||
const CommandType *ct= unit->getType()->getCommandType(i);
|
||||
|
||||
//look for an attack skill
|
||||
const AttackSkillType *ast= NULL;
|
||||
if(ct->getClass()==ccAttack){
|
||||
ast= static_cast<const AttackCommandType*>(ct)->getAttackSkillType();
|
||||
}
|
||||
else if(ct->getClass()==ccAttackStopped){
|
||||
ast= static_cast<const AttackStoppedCommandType*>(ct)->getAttackSkillType();
|
||||
}
|
||||
|
||||
//use it to attack
|
||||
if(ast!=NULL){
|
||||
if(attackableOnSight(unit, &sighted, ast)){
|
||||
unit->giveCommand(new Command(ct, sighted->getPos()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//see any unit and cant attack it => run
|
||||
else if(unit->getType()->hasCommandClass(ccMove)){
|
||||
if(attackerOnSight(unit, &sighted)){
|
||||
Vec2i escapePos= unit->getPos()*2-sighted->getPos();
|
||||
unit->giveCommand(new Command(unit->getType()->getFirstCtOfClass(ccMove), escapePos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ==================== updateMove ====================
|
||||
|
||||
void UnitUpdater::updateMove(Unit *unit){
|
||||
|
||||
Command *command= unit->getCurrCommand();
|
||||
const MoveCommandType *mct= static_cast<const MoveCommandType*>(command->getCommandType());
|
||||
|
||||
Vec2i pos= command->getUnit()!=NULL? command->getUnit()->getCenteredPos(): command->getPos();
|
||||
|
||||
switch(pathFinder.findPath(unit, pos)){
|
||||
case PathFinder::tsOnTheWay:
|
||||
unit->setCurrSkill(mct->getMoveSkillType());
|
||||
break;
|
||||
|
||||
case PathFinder::tsBlocked:
|
||||
if(unit->getPath()->isBlocked()){
|
||||
unit->finishCommand();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
unit->finishCommand();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ==================== updateAttack ====================
|
||||
|
||||
void UnitUpdater::updateAttack(Unit *unit){
|
||||
|
||||
Command *command= unit->getCurrCommand();
|
||||
const AttackCommandType *act= static_cast<const AttackCommandType*>(command->getCommandType());
|
||||
Unit *target= NULL;
|
||||
|
||||
//if found
|
||||
if(attackableOnRange(unit, &target, act->getAttackSkillType())){
|
||||
if(unit->getEp()>=act->getAttackSkillType()->getEpCost()){
|
||||
unit->setCurrSkill(act->getAttackSkillType());
|
||||
unit->setTarget(target);
|
||||
}
|
||||
else{
|
||||
unit->setCurrSkill(scStop);
|
||||
}
|
||||
}
|
||||
else{
|
||||
//compute target pos
|
||||
Vec2i pos;
|
||||
if(command->getUnit()!=NULL){
|
||||
pos= command->getUnit()->getCenteredPos();
|
||||
}
|
||||
else if(attackableOnSight(unit, &target, act->getAttackSkillType())){
|
||||
pos= target->getPos();
|
||||
}
|
||||
else{
|
||||
pos= command->getPos();
|
||||
}
|
||||
|
||||
//if unit arrives destPos order has ended
|
||||
switch (pathFinder.findPath(unit, pos)){
|
||||
case PathFinder::tsOnTheWay:
|
||||
unit->setCurrSkill(act->getMoveSkillType());
|
||||
break;
|
||||
case PathFinder::tsBlocked:
|
||||
if(unit->getPath()->isBlocked()){
|
||||
unit->finishCommand();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
unit->finishCommand();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ==================== updateAttackStopped ====================
|
||||
|
||||
void UnitUpdater::updateAttackStopped(Unit *unit){
|
||||
|
||||
Command *command= unit->getCurrCommand();
|
||||
const AttackStoppedCommandType *asct= static_cast<const AttackStoppedCommandType*>(command->getCommandType());
|
||||
Unit *enemy;
|
||||
|
||||
if(attackableOnRange(unit, &enemy, asct->getAttackSkillType())){
|
||||
unit->setCurrSkill(asct->getAttackSkillType());
|
||||
unit->setTarget(enemy);
|
||||
}
|
||||
else{
|
||||
unit->setCurrSkill(asct->getStopSkillType());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ==================== updateBuild ====================
|
||||
|
||||
void UnitUpdater::updateBuild(Unit *unit){
|
||||
|
||||
Command *command= unit->getCurrCommand();
|
||||
const BuildCommandType *bct= static_cast<const BuildCommandType*>(command->getCommandType());
|
||||
|
||||
if(unit->getCurrSkill()->getClass() != scBuild) {
|
||||
//if not building
|
||||
const UnitType *ut= command->getUnitType();
|
||||
|
||||
switch (pathFinder.findPath(unit, command->getPos()-Vec2i(1))){
|
||||
case PathFinder::tsOnTheWay:
|
||||
unit->setCurrSkill(bct->getMoveSkillType());
|
||||
break;
|
||||
|
||||
case PathFinder::tsArrived:
|
||||
//if arrived destination
|
||||
assert(command->getUnitType()!=NULL);
|
||||
if(map->isFreeCells(command->getPos(), ut->getSize(), fLand)){
|
||||
const UnitType *builtUnitType= command->getUnitType();
|
||||
|
||||
//!!!
|
||||
float unitRotation = -1;
|
||||
if(allowRotateUnits == true) {
|
||||
char unitKey[50]="";
|
||||
sprintf(unitKey,"%d_%d",builtUnitType->getId(),unit->getFaction()->getIndex());
|
||||
unitRotation = gui->getUnitTypeBuildRotation(unitKey);
|
||||
}
|
||||
Unit *builtUnit= new Unit(world->getNextUnitId(), command->getPos(), builtUnitType, unit->getFaction(), world->getMap(),unitRotation);
|
||||
builtUnit->create();
|
||||
|
||||
if(!builtUnitType->hasSkillClass(scBeBuilt)){
|
||||
throw runtime_error("Unit " + builtUnitType->getName() + "has no be_built skill");
|
||||
}
|
||||
|
||||
builtUnit->setCurrSkill(scBeBuilt);
|
||||
unit->setCurrSkill(bct->getBuildSkillType());
|
||||
unit->setTarget(builtUnit);
|
||||
map->prepareTerrain(builtUnit);
|
||||
command->setUnit(builtUnit);
|
||||
|
||||
//play start sound
|
||||
if(unit->getFactionIndex()==world->getThisFactionIndex()){
|
||||
SoundRenderer::getInstance().playFx(
|
||||
bct->getStartSound(),
|
||||
unit->getCurrVector(),
|
||||
gameCamera->getPos());
|
||||
}
|
||||
|
||||
//!!!
|
||||
/*
|
||||
if(unitRotation > 0) {
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] before sending ccRotateUnit...\n",__FILE__,__FUNCTION__);
|
||||
|
||||
RotateUnitCommandType *rotateCmdType = new RotateUnitCommandType();
|
||||
rotateCmdType->setRotateAmount(unitRotation);
|
||||
|
||||
Command *rotateUnitCmd = new Command(rotateCmdType);
|
||||
rotateUnitCmd->setUnit(builtUnit);
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] in sending ccRotateUnit...\n",__FILE__,__FUNCTION__);
|
||||
|
||||
builtUnit->giveCommand(rotateUnitCmd);
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] after sending ccRotateUnit...\n",__FILE__,__FUNCTION__);
|
||||
}
|
||||
*/
|
||||
}
|
||||
else{
|
||||
//if there are no free cells
|
||||
unit->cancelCommand();
|
||||
unit->setCurrSkill(scStop);
|
||||
if(unit->getFactionIndex()==world->getThisFactionIndex()){
|
||||
console->addStdMessage("BuildingNoPlace");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PathFinder::tsBlocked:
|
||||
if(unit->getPath()->isBlocked()){
|
||||
unit->cancelCommand();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
//if building
|
||||
Unit *builtUnit= map->getCell(unit->getTargetPos())->getUnit(fLand);
|
||||
|
||||
//if u is killed while building then u==NULL;
|
||||
if(builtUnit!=NULL && builtUnit!=command->getUnit()){
|
||||
unit->setCurrSkill(scStop);
|
||||
}
|
||||
else if(builtUnit==NULL || builtUnit->isBuilt()){
|
||||
unit->finishCommand();
|
||||
unit->setCurrSkill(scStop);
|
||||
}
|
||||
else if(builtUnit->repair()){
|
||||
//building finished
|
||||
unit->finishCommand();
|
||||
unit->setCurrSkill(scStop);
|
||||
builtUnit->born();
|
||||
scriptManager->onUnitCreated(builtUnit);
|
||||
if(unit->getFactionIndex()==world->getThisFactionIndex()){
|
||||
SoundRenderer::getInstance().playFx(
|
||||
bct->getBuiltSound(),
|
||||
unit->getCurrVector(),
|
||||
gameCamera->getPos());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ==================== updateHarvest ====================
|
||||
|
||||
void UnitUpdater::updateHarvest(Unit *unit){
|
||||
|
||||
Command *command= unit->getCurrCommand();
|
||||
const HarvestCommandType *hct= static_cast<const HarvestCommandType*>(command->getCommandType());
|
||||
Vec2i targetPos;
|
||||
|
||||
if(unit->getCurrSkill()->getClass() != scHarvest) {
|
||||
//if not working
|
||||
if(unit->getLoadCount()==0){
|
||||
//if not loaded go for resources
|
||||
Resource *r= map->getSurfaceCell(Map::toSurfCoords(command->getPos()))->getResource();
|
||||
if(r!=NULL && hct->canHarvest(r->getType())){
|
||||
//if can harvest dest. pos
|
||||
if(unit->getPos().dist(command->getPos())<harvestDistance &&
|
||||
map->isResourceNear(unit->getPos(), r->getType(), targetPos)) {
|
||||
//if it finds resources it starts harvesting
|
||||
unit->setCurrSkill(hct->getHarvestSkillType());
|
||||
unit->setTargetPos(targetPos);
|
||||
unit->setLoadCount(0);
|
||||
unit->setLoadType(map->getSurfaceCell(Map::toSurfCoords(unit->getTargetPos()))->getResource()->getType());
|
||||
}
|
||||
else{
|
||||
//if not continue walking
|
||||
switch(pathFinder.findPath(unit, command->getPos())){
|
||||
case PathFinder::tsOnTheWay:
|
||||
unit->setCurrSkill(hct->getMoveSkillType());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
//if can't harvest, search for another resource
|
||||
unit->setCurrSkill(scStop);
|
||||
if(!searchForResource(unit, hct)){
|
||||
unit->finishCommand();
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
//if loaded, return to store
|
||||
Unit *store= world->nearestStore(unit->getPos(), unit->getFaction()->getIndex(), unit->getLoadType());
|
||||
if(store!=NULL){
|
||||
switch(pathFinder.findPath(unit, store->getCenteredPos())){
|
||||
case PathFinder::tsOnTheWay:
|
||||
unit->setCurrSkill(hct->getMoveLoadedSkillType());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//world->changePosCells(unit,unit->getPos()+unit->getDest());
|
||||
if(map->isNextTo(unit->getPos(), store)){
|
||||
|
||||
//update resources
|
||||
int resourceAmount= unit->getLoadCount();
|
||||
if(unit->getFaction()->getCpuUltraControl()){
|
||||
resourceAmount*= ultraResourceFactor;
|
||||
}
|
||||
if(unit->getFaction()->getCpuMegaControl()){
|
||||
resourceAmount*= megaResourceFactor;
|
||||
}
|
||||
unit->getFaction()->incResourceAmount(unit->getLoadType(), resourceAmount);
|
||||
world->getStats()->harvest(unit->getFactionIndex(), resourceAmount);
|
||||
scriptManager->onResourceHarvested();
|
||||
|
||||
//if next to a store unload resources
|
||||
unit->getPath()->clear();
|
||||
unit->setCurrSkill(scStop);
|
||||
unit->setLoadCount(0);
|
||||
}
|
||||
}
|
||||
else{
|
||||
unit->finishCommand();
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
//if working
|
||||
SurfaceCell *sc= map->getSurfaceCell(Map::toSurfCoords(unit->getTargetPos()));
|
||||
Resource *r= sc->getResource();
|
||||
if(r!=NULL){
|
||||
//if there is a resource, continue working, until loaded
|
||||
unit->update2();
|
||||
if(unit->getProgress2()>=hct->getHitsPerUnit()){
|
||||
unit->setProgress2(0);
|
||||
unit->setLoadCount(unit->getLoadCount()+1);
|
||||
|
||||
//if resource exausted, then delete it and stop
|
||||
if(r->decAmount(1)){
|
||||
sc->deleteResource();
|
||||
unit->setCurrSkill(hct->getStopLoadedSkillType());
|
||||
}
|
||||
|
||||
if(unit->getLoadCount()==hct->getMaxLoad()){
|
||||
unit->setCurrSkill(hct->getStopLoadedSkillType());
|
||||
unit->getPath()->clear();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else{
|
||||
//if there is no resource, just stop
|
||||
unit->setCurrSkill(hct->getStopLoadedSkillType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ==================== updateRepair ====================
|
||||
|
||||
void UnitUpdater::updateRepair(Unit *unit){
|
||||
|
||||
Command *command= unit->getCurrCommand();
|
||||
const RepairCommandType *rct= static_cast<const RepairCommandType*>(command->getCommandType());
|
||||
|
||||
Unit *repaired= map->getCell(command->getPos())->getUnit(fLand);
|
||||
bool nextToRepaired= repaired!=NULL && map->isNextTo(unit->getPos(), repaired);
|
||||
|
||||
if(unit->getCurrSkill()->getClass()!=scRepair || !nextToRepaired){
|
||||
//if not repairing
|
||||
if(repaired!=NULL && rct->isRepairableUnitType(repaired->getType()) && repaired->isDamaged()){
|
||||
|
||||
if(nextToRepaired){
|
||||
unit->setTarget(repaired);
|
||||
unit->setCurrSkill(rct->getRepairSkillType());
|
||||
}
|
||||
else{
|
||||
switch(pathFinder.findPath(unit, command->getPos())){
|
||||
case PathFinder::tsOnTheWay:
|
||||
unit->setCurrSkill(rct->getMoveSkillType());
|
||||
break;
|
||||
case PathFinder::tsBlocked:
|
||||
if(unit->getPath()->isBlocked()){
|
||||
unit->finishCommand();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
unit->setCurrSkill(scStop);
|
||||
unit->finishCommand();
|
||||
}
|
||||
}
|
||||
else{
|
||||
//if repairing
|
||||
if(repaired!=NULL){
|
||||
unit->setTarget(repaired);
|
||||
}
|
||||
if(repaired==NULL || repaired->repair()){
|
||||
unit->setCurrSkill(scStop);
|
||||
unit->finishCommand();
|
||||
if(repaired!=NULL && !repaired->isBuilt()){
|
||||
repaired->born();
|
||||
scriptManager->onUnitCreated(repaired);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ==================== updateProduce ====================
|
||||
|
||||
void UnitUpdater::updateProduce(Unit *unit){
|
||||
|
||||
Command *command= unit->getCurrCommand();
|
||||
const ProduceCommandType *pct= static_cast<const ProduceCommandType*>(command->getCommandType());
|
||||
Unit *produced;
|
||||
|
||||
if(unit->getCurrSkill()->getClass()!=scProduce){
|
||||
//if not producing
|
||||
unit->setCurrSkill(pct->getProduceSkillType());
|
||||
}
|
||||
else{
|
||||
unit->update2();
|
||||
if(unit->getProgress2()>pct->getProduced()->getProductionTime()){
|
||||
unit->finishCommand();
|
||||
unit->setCurrSkill(scStop);
|
||||
|
||||
//!!!
|
||||
float unitRotation = -1;
|
||||
if(allowRotateUnits == true) {
|
||||
char unitKey[50]="";
|
||||
sprintf(unitKey,"%d_%d",pct->getId(),unit->getFaction()->getIndex());
|
||||
unitRotation = gui->getUnitTypeBuildRotation(unitKey);
|
||||
}
|
||||
|
||||
produced= new Unit(world->getNextUnitId(), Vec2i(0), pct->getProducedUnit(), unit->getFaction(), world->getMap(),unitRotation);
|
||||
|
||||
//place unit creates the unit
|
||||
if(!world->placeUnit(unit->getCenteredPos(), 10, produced)){
|
||||
delete produced;
|
||||
}
|
||||
else{
|
||||
produced->create();
|
||||
produced->born();
|
||||
world->getStats()->produce(unit->getFactionIndex());
|
||||
const CommandType *ct= produced->computeCommandType(unit->getMeetingPos());
|
||||
if(ct!=NULL){
|
||||
produced->giveCommand(new Command(ct, unit->getMeetingPos()));
|
||||
}
|
||||
scriptManager->onUnitCreated(produced);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ==================== updateUpgrade ====================
|
||||
|
||||
void UnitUpdater::updateUpgrade(Unit *unit){
|
||||
|
||||
Command *command= unit->getCurrCommand();
|
||||
const UpgradeCommandType *uct= static_cast<const UpgradeCommandType*>(command->getCommandType());
|
||||
|
||||
if(unit->getCurrSkill()->getClass()!=scUpgrade){
|
||||
//if not producing
|
||||
unit->setCurrSkill(uct->getUpgradeSkillType());
|
||||
}
|
||||
else{
|
||||
//if producing
|
||||
unit->update2();
|
||||
if(unit->getProgress2()>uct->getProduced()->getProductionTime()){
|
||||
unit->finishCommand();
|
||||
unit->setCurrSkill(scStop);
|
||||
unit->getFaction()->finishUpgrade(uct->getProducedUpgrade());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== updateMorph ====================
|
||||
|
||||
void UnitUpdater::updateMorph(Unit *unit){
|
||||
|
||||
Command *command= unit->getCurrCommand();
|
||||
const MorphCommandType *mct= static_cast<const MorphCommandType*>(command->getCommandType());
|
||||
|
||||
if(unit->getCurrSkill()->getClass()!=scMorph){
|
||||
//if not morphing, check space
|
||||
if(map->isFreeCellsOrHasUnit(unit->getPos(), mct->getMorphUnit()->getSize(), unit->getCurrField(), unit)){
|
||||
unit->setCurrSkill(mct->getMorphSkillType());
|
||||
}
|
||||
else{
|
||||
if(unit->getFactionIndex()==world->getThisFactionIndex()){
|
||||
console->addStdMessage("InvalidPosition");
|
||||
}
|
||||
unit->cancelCommand();
|
||||
}
|
||||
}
|
||||
else{
|
||||
unit->update2();
|
||||
if(unit->getProgress2()>mct->getProduced()->getProductionTime()){
|
||||
|
||||
//finish the command
|
||||
if(unit->morph(mct)){
|
||||
unit->finishCommand();
|
||||
if(gui->isSelected(unit)){
|
||||
gui->onSelectionChanged();
|
||||
}
|
||||
scriptManager->onUnitCreated(unit);
|
||||
}
|
||||
else{
|
||||
unit->cancelCommand();
|
||||
if(unit->getFactionIndex()==world->getThisFactionIndex()){
|
||||
console->addStdMessage("InvalidPosition");
|
||||
}
|
||||
}
|
||||
unit->setCurrSkill(scStop);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== PRIVATE ====================
|
||||
|
||||
// ==================== attack ====================
|
||||
|
||||
void UnitUpdater::hit(Unit *attacker){
|
||||
hit(attacker, static_cast<const AttackSkillType*>(attacker->getCurrSkill()), attacker->getTargetPos(), attacker->getTargetField());
|
||||
}
|
||||
|
||||
void UnitUpdater::hit(Unit *attacker, const AttackSkillType* ast, const Vec2i &targetPos, Field targetField){
|
||||
|
||||
//hit attack positions
|
||||
if(ast->getSplash()){
|
||||
PosCircularIterator pci(map, targetPos, ast->getSplashRadius());
|
||||
while(pci.next()){
|
||||
Unit *attacked= map->getCell(pci.getPos())->getUnit(targetField);
|
||||
if(attacked!=NULL){
|
||||
if(ast->getSplashDamageAll()
|
||||
|| !attacker->isAlly(attacked)
|
||||
|| ( targetPos.x==pci.getPos().x && targetPos.y==pci.getPos().y )){
|
||||
damage(attacker, ast, attacked, pci.getPos().dist(attacker->getTargetPos()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
Unit *attacked= map->getCell(targetPos)->getUnit(targetField);
|
||||
if(attacked!=NULL){
|
||||
damage(attacker, ast, attacked, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void UnitUpdater::damage(Unit *attacker, const AttackSkillType* ast, Unit *attacked, float distance){
|
||||
|
||||
//get vars
|
||||
float damage= ast->getTotalAttackStrength(attacker->getTotalUpgrade());
|
||||
int var= ast->getAttackVar();
|
||||
int armor= attacked->getType()->getTotalArmor(attacked->getTotalUpgrade());
|
||||
float damageMultiplier= world->getTechTree()->getDamageMultiplier(ast->getAttackType(), attacked->getType()->getArmorType());
|
||||
|
||||
//compute damage
|
||||
damage+= random.randRange(-var, var);
|
||||
damage/= distance+1;
|
||||
damage-= armor;
|
||||
damage*= damageMultiplier;
|
||||
if(damage<1){
|
||||
damage= 1;
|
||||
}
|
||||
|
||||
//damage the unit
|
||||
if(attacked->decHp(static_cast<int>(damage))){
|
||||
world->getStats()->kill(attacker->getFactionIndex(), attacked->getFactionIndex());
|
||||
attacker->incKills();
|
||||
scriptManager->onUnitDied(attacked);
|
||||
}
|
||||
}
|
||||
|
||||
void UnitUpdater::startAttackParticleSystem(Unit *unit){
|
||||
Renderer &renderer= Renderer::getInstance();
|
||||
|
||||
ProjectileParticleSystem *psProj = 0;
|
||||
SplashParticleSystem *psSplash;
|
||||
|
||||
const AttackSkillType *ast= static_cast<const AttackSkillType*>(unit->getCurrSkill());
|
||||
ParticleSystemTypeProjectile *pstProj= ast->getProjParticleType();
|
||||
ParticleSystemTypeSplash *pstSplash= ast->getSplashParticleType();
|
||||
|
||||
Vec3f startPos= unit->getCurrVector();
|
||||
Vec3f endPos= unit->getTargetVec();
|
||||
|
||||
//make particle system
|
||||
const SurfaceCell *sc= map->getSurfaceCell(Map::toSurfCoords(unit->getPos()));
|
||||
const SurfaceCell *tsc= map->getSurfaceCell(Map::toSurfCoords(unit->getTargetPos()));
|
||||
bool visible= sc->isVisible(world->getThisTeamIndex()) || tsc->isVisible(world->getThisTeamIndex());
|
||||
|
||||
//projectile
|
||||
if(pstProj!=NULL){
|
||||
psProj= pstProj->create();
|
||||
psProj->setPath(startPos, endPos);
|
||||
psProj->setObserver(new ParticleDamager(unit, this, gameCamera));
|
||||
psProj->setVisible(visible);
|
||||
psProj->setFactionColor(unit->getFaction()->getTexture()->getPixmap()->getPixel3f(0,0));
|
||||
renderer.manageParticleSystem(psProj, rsGame);
|
||||
}
|
||||
else{
|
||||
hit(unit);
|
||||
}
|
||||
|
||||
//splash
|
||||
if(pstSplash!=NULL){
|
||||
psSplash= pstSplash->create();
|
||||
psSplash->setPos(endPos);
|
||||
psSplash->setVisible(visible);
|
||||
psSplash->setFactionColor(unit->getFaction()->getTexture()->getPixmap()->getPixel3f(0,0));
|
||||
renderer.manageParticleSystem(psSplash, rsGame);
|
||||
if(pstProj!=NULL){
|
||||
psProj->link(psSplash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== misc ====================
|
||||
|
||||
//looks for a resource of type rt, if rt==NULL looks for any
|
||||
//resource the unit can harvest
|
||||
bool UnitUpdater::searchForResource(Unit *unit, const HarvestCommandType *hct){
|
||||
|
||||
Vec2i pos= unit->getCurrCommand()->getPos();
|
||||
|
||||
for(int radius= 0; radius<maxResSearchRadius; radius++){
|
||||
for(int i=pos.x-radius; i<=pos.x+radius; ++i){
|
||||
for(int j=pos.y-radius; j<=pos.y+radius; ++j){
|
||||
if(map->isInside(i, j)){
|
||||
Resource *r= map->getSurfaceCell(Map::toSurfCoords(Vec2i(i, j)))->getResource();
|
||||
if(r!=NULL){
|
||||
if(hct->canHarvest(r->getType())){
|
||||
unit->getCurrCommand()->setPos(Vec2i(i, j));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnitUpdater::attackerOnSight(const Unit *unit, Unit **rangedPtr){
|
||||
int range= unit->getType()->getSight();
|
||||
return unitOnRange(unit, range, rangedPtr, NULL);
|
||||
}
|
||||
|
||||
bool UnitUpdater::attackableOnSight(const Unit *unit, Unit **rangedPtr, const AttackSkillType *ast){
|
||||
int range= unit->getType()->getSight();
|
||||
return unitOnRange(unit, range, rangedPtr, ast);
|
||||
}
|
||||
|
||||
bool UnitUpdater::attackableOnRange(const Unit *unit, Unit **rangedPtr, const AttackSkillType *ast){
|
||||
int range= ast->getTotalAttackRange(unit->getTotalUpgrade());
|
||||
return unitOnRange(unit, range, rangedPtr, ast);
|
||||
}
|
||||
|
||||
//if the unit has any enemy on range
|
||||
bool UnitUpdater::unitOnRange(const Unit *unit, int range, Unit **rangedPtr, const AttackSkillType *ast){
|
||||
|
||||
vector<Unit*> enemies;
|
||||
|
||||
//we check command target
|
||||
const Unit *commandTarget= NULL;
|
||||
if(unit->anyCommand()){
|
||||
commandTarget= static_cast<const Unit*>(unit->getCurrCommand()->getUnit());
|
||||
}
|
||||
if(commandTarget!=NULL && commandTarget->isDead()){
|
||||
commandTarget= NULL;
|
||||
}
|
||||
|
||||
//aux vars
|
||||
int size= unit->getType()->getSize();
|
||||
Vec2i center= unit->getPos();
|
||||
Vec2f floatCenter= unit->getFloatCenteredPos();
|
||||
|
||||
//nearby cells
|
||||
for(int i=center.x-range; i<center.x+range+size; ++i){
|
||||
for(int j=center.y-range; j<center.y+range+size; ++j){
|
||||
|
||||
//cells insede map and in range
|
||||
if(map->isInside(i, j) && floor(floatCenter.dist(Vec2f(i, j))) <= (range+1)){
|
||||
|
||||
//all fields
|
||||
for(int k=0; k<fieldCount; k++){
|
||||
Field f= static_cast<Field>(k);
|
||||
|
||||
//check field
|
||||
if((ast==NULL || ast->getAttackField(f))){
|
||||
Unit *possibleEnemy= map->getCell(i, j)->getUnit(f);
|
||||
|
||||
//check enemy
|
||||
if(possibleEnemy!=NULL && possibleEnemy->isAlive()){
|
||||
if((!unit->isAlly(possibleEnemy) && commandTarget==NULL) || commandTarget==possibleEnemy){
|
||||
enemies.push_back(possibleEnemy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//attack enemies that can attack first
|
||||
for(int i=0; i<enemies.size(); ++i){
|
||||
if(enemies[i]->getType()->hasSkillClass(scAttack)){
|
||||
*rangedPtr= enemies[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//any enemy
|
||||
if(enemies.size()>0){
|
||||
*rangedPtr= enemies.front();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class ParticleDamager
|
||||
// =====================================================
|
||||
|
||||
ParticleDamager::ParticleDamager(Unit *attacker, UnitUpdater *unitUpdater, const GameCamera *gameCamera){
|
||||
this->gameCamera= gameCamera;
|
||||
this->attackerRef= attacker;
|
||||
this->ast= static_cast<const AttackSkillType*>(attacker->getCurrSkill());
|
||||
this->targetPos= attacker->getTargetPos();
|
||||
this->targetField= attacker->getTargetField();
|
||||
this->unitUpdater= unitUpdater;
|
||||
}
|
||||
|
||||
void ParticleDamager::update(ParticleSystem *particleSystem){
|
||||
Unit *attacker= attackerRef.getUnit();
|
||||
|
||||
if(attacker!=NULL){
|
||||
|
||||
unitUpdater->hit(attacker, ast, targetPos, targetField);
|
||||
|
||||
//play sound
|
||||
StaticSound *projSound= ast->getProjSound();
|
||||
if(particleSystem->getVisible() && projSound!=NULL){
|
||||
SoundRenderer::getInstance().playFx(projSound, attacker->getCurrVector(), gameCamera->getPos());
|
||||
}
|
||||
}
|
||||
particleSystem->setObserver(NULL);
|
||||
delete this;
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,115 @@
|
|||
// ==============================================================
|
||||
// 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_UNITUPDATER_H_
|
||||
#define _GLEST_GAME_UNITUPDATER_H_
|
||||
|
||||
#include "gui.h"
|
||||
#include "path_finder.h"
|
||||
#include "particle.h"
|
||||
#include "random.h"
|
||||
|
||||
using Shared::Graphics::ParticleObserver;
|
||||
using Shared::Util::Random;
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
class Unit;
|
||||
class Map;
|
||||
class ScriptManager;
|
||||
|
||||
// =====================================================
|
||||
// class UnitUpdater
|
||||
//
|
||||
/// Updates all units in the game, even the player
|
||||
/// controlled units, performs basic actions only
|
||||
/// such as responding to an attack
|
||||
// =====================================================
|
||||
|
||||
class ParticleDamager;
|
||||
|
||||
class UnitUpdater{
|
||||
private:
|
||||
friend class ParticleDamager;
|
||||
|
||||
private:
|
||||
static const int maxResSearchRadius= 10;
|
||||
static const int harvestDistance= 5;
|
||||
static const int ultraResourceFactor= 3;
|
||||
static const int megaResourceFactor= 4;
|
||||
|
||||
private:
|
||||
const GameCamera *gameCamera;
|
||||
Gui *gui;
|
||||
Map *map;
|
||||
World *world;
|
||||
Console *console;
|
||||
ScriptManager *scriptManager;
|
||||
PathFinder pathFinder;
|
||||
Random random;
|
||||
bool allowRotateUnits;
|
||||
|
||||
public:
|
||||
void init(Game *game);
|
||||
|
||||
//update skills
|
||||
void updateUnit(Unit *unit);
|
||||
|
||||
//update commands
|
||||
void updateUnitCommand(Unit *unit);
|
||||
void updateStop(Unit *unit);
|
||||
void updateMove(Unit *unit);
|
||||
void updateAttack(Unit *unit);
|
||||
void updateAttackStopped(Unit *unit);
|
||||
void updateBuild(Unit *unit);
|
||||
void updateHarvest(Unit *unit);
|
||||
void updateRepair(Unit *unit);
|
||||
void updateProduce(Unit *unit);
|
||||
void updateUpgrade(Unit *unit);
|
||||
void updateMorph(Unit *unit);
|
||||
|
||||
private:
|
||||
//attack
|
||||
void hit(Unit *attacker);
|
||||
void hit(Unit *attacker, const AttackSkillType* ast, const Vec2i &targetPos, Field targetField);
|
||||
void damage(Unit *attacker, const AttackSkillType* ast, Unit *attacked, float distance);
|
||||
void startAttackParticleSystem(Unit *unit);
|
||||
|
||||
//misc
|
||||
bool searchForResource(Unit *unit, const HarvestCommandType *hct);
|
||||
bool attackerOnSight(const Unit *unit, Unit **enemyPtr);
|
||||
bool attackableOnSight(const Unit *unit, Unit **enemyPtr, const AttackSkillType *ast);
|
||||
bool attackableOnRange(const Unit *unit, Unit **enemyPtr, const AttackSkillType *ast);
|
||||
bool unitOnRange(const Unit *unit, int range, Unit **enemyPtr, const AttackSkillType *ast);
|
||||
void enemiesAtDistance(const Unit *unit, const Unit *priorityUnit, int distance, vector<Unit*> &enemies);
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class ParticleDamager
|
||||
// =====================================================
|
||||
|
||||
class ParticleDamager: public ParticleObserver{
|
||||
public:
|
||||
UnitReference attackerRef;
|
||||
const AttackSkillType* ast;
|
||||
UnitUpdater *unitUpdater;
|
||||
const GameCamera *gameCamera;
|
||||
Vec2i targetPos;
|
||||
Field targetField;
|
||||
|
||||
public:
|
||||
ParticleDamager(Unit *attacker, UnitUpdater *unitUpdater, const GameCamera *gameCamera);
|
||||
virtual void update(ParticleSystem *particleSystem);
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -48,6 +48,8 @@ World::World(){
|
|||
|
||||
scriptManager= NULL;
|
||||
this->game = NULL;
|
||||
|
||||
allowRotateUnits = Config::getInstance().getBool("AllowRotateUnits","0");
|
||||
}
|
||||
|
||||
void World::end(){
|
||||
|
@ -312,9 +314,12 @@ void World::createUnit(const string &unitName, int factionIndex, const Vec2i &po
|
|||
const UnitType* ut= ft->getUnitType(unitName);
|
||||
|
||||
//!!!
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] A\n",__FILE__,__FUNCTION__);
|
||||
float unitRotation = game->getGui()->getUnitTypeBuildRotation(ut->getId());
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] B\n",__FILE__,__FUNCTION__);
|
||||
float unitRotation = -1;
|
||||
if(allowRotateUnits == true) {
|
||||
char unitKey[50]="";
|
||||
sprintf(unitKey,"%d_%d",ut->getId(),faction->getIndex());
|
||||
unitRotation = game->getGui()->getUnitTypeBuildRotation(unitKey);
|
||||
}
|
||||
|
||||
Unit* unit= new Unit(getNextUnitId(), pos, ut, faction, &map, unitRotation);
|
||||
|
||||
|
@ -575,9 +580,12 @@ void World::initUnits(){
|
|||
for(int l=0; l<initNumber; l++){
|
||||
|
||||
//!!!
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] A\n",__FILE__,__FUNCTION__);
|
||||
float unitRotation = game->getGui()->getUnitTypeBuildRotation(ut->getId());
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] B\n",__FILE__,__FUNCTION__);
|
||||
float unitRotation = -1;
|
||||
if(allowRotateUnits == true) {
|
||||
char unitKey[50]="";
|
||||
sprintf(unitKey,"%d_%d",ut->getId(),f->getIndex());
|
||||
unitRotation = game->getGui()->getUnitTypeBuildRotation(unitKey);
|
||||
}
|
||||
|
||||
Unit *unit= new Unit(getNextUnitId(), Vec2i(0), ut, f, &map, unitRotation);
|
||||
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
// ==============================================================
|
||||
// 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_WORLD_H_
|
||||
#define _GLEST_GAME_WORLD_H_
|
||||
|
||||
#include "vec.h"
|
||||
#include "math_util.h"
|
||||
#include "resource.h"
|
||||
#include "tech_tree.h"
|
||||
#include "tileset.h"
|
||||
#include "console.h"
|
||||
#include "map.h"
|
||||
#include "scenario.h"
|
||||
#include "minimap.h"
|
||||
#include "logger.h"
|
||||
#include "stats.h"
|
||||
#include "time_flow.h"
|
||||
#include "upgrade.h"
|
||||
#include "water_effects.h"
|
||||
#include "faction.h"
|
||||
#include "unit_updater.h"
|
||||
#include "random.h"
|
||||
#include "game_constants.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
using Shared::Graphics::Quad2i;
|
||||
using Shared::Graphics::Rect2i;
|
||||
using Shared::Util::Random;
|
||||
|
||||
class Faction;
|
||||
class Unit;
|
||||
class Config;
|
||||
class Game;
|
||||
class GameSettings;
|
||||
class ScriptManager;
|
||||
|
||||
// =====================================================
|
||||
// class World
|
||||
//
|
||||
/// The game world: Map + Tileset + TechTree
|
||||
// =====================================================
|
||||
|
||||
class World{
|
||||
private:
|
||||
typedef vector<Faction> Factions;
|
||||
|
||||
public:
|
||||
static const int generationArea= 100;
|
||||
static const float airHeight;
|
||||
static const int indirectSightRange= 5;
|
||||
|
||||
private:
|
||||
|
||||
Map map;
|
||||
Tileset tileset;
|
||||
TechTree techTree;
|
||||
TimeFlow timeFlow;
|
||||
Scenario scenario;
|
||||
|
||||
UnitUpdater unitUpdater;
|
||||
WaterEffects waterEffects;
|
||||
Minimap minimap;
|
||||
Stats stats; //BattleEnd will delete this object
|
||||
|
||||
Factions factions;
|
||||
|
||||
Random random;
|
||||
|
||||
ScriptManager* scriptManager;
|
||||
|
||||
int thisFactionIndex;
|
||||
int thisTeamIndex;
|
||||
int frameCount;
|
||||
int nextUnitId;
|
||||
|
||||
//config
|
||||
bool fogOfWar;
|
||||
int fogOfWarSmoothingFrameSkip;
|
||||
bool fogOfWarSmoothing;
|
||||
Game *game;
|
||||
bool allowRotateUnits;
|
||||
|
||||
public:
|
||||
World();
|
||||
void end(); //to die before selection does
|
||||
|
||||
//get
|
||||
int getMaxPlayers() const {return map.getMaxPlayers();}
|
||||
int getThisFactionIndex() const {return thisFactionIndex;}
|
||||
int getThisTeamIndex() const {return thisTeamIndex;}
|
||||
const Faction *getThisFaction() const {return &factions[thisFactionIndex];}
|
||||
int getFactionCount() const {return factions.size();}
|
||||
const Map *getMap() const {return ↦}
|
||||
const Tileset *getTileset() const {return &tileset;}
|
||||
const TechTree *getTechTree() const {return &techTree;}
|
||||
const Scenario *getScenario() const {return &scenario;}
|
||||
const TimeFlow *getTimeFlow() const {return &timeFlow;}
|
||||
Tileset *getTileset() {return &tileset;}
|
||||
Map *getMap() {return ↦}
|
||||
const Faction *getFaction(int i) const {return &factions[i];}
|
||||
Faction *getFaction(int i) {return &factions[i];}
|
||||
const Minimap *getMinimap() const {return &minimap;}
|
||||
const Stats *getStats() const {return &stats;};
|
||||
Stats *getStats() {return &stats;};
|
||||
const WaterEffects *getWaterEffects() const {return &waterEffects;}
|
||||
int getNextUnitId() {return nextUnitId++;}
|
||||
int getFrameCount() const {return frameCount;}
|
||||
|
||||
//init & load
|
||||
void init(Game *game, bool createUnits);
|
||||
void loadTileset(const string &dir, Checksum* checksum);
|
||||
void loadTech(const string &dir, set<string> &factions, Checksum* checksum);
|
||||
void loadMap(const string &path, Checksum* checksum);
|
||||
void loadScenario(const string &path, Checksum* checksum);
|
||||
|
||||
//misc
|
||||
void update();
|
||||
Unit* findUnitById(int id);
|
||||
const UnitType* findUnitTypeById(const FactionType* factionType, int id);
|
||||
bool placeUnit(const Vec2i &startLoc, int radius, Unit *unit, bool spaciated= false);
|
||||
void moveUnitCells(Unit *unit);
|
||||
bool toRenderUnit(const Unit *unit, const Quad2i &visibleQuad) const;
|
||||
bool toRenderUnit(const Unit *unit) const;
|
||||
Unit *nearestStore(const Vec2i &pos, int factionIndex, const ResourceType *rt);
|
||||
|
||||
//scripting interface
|
||||
void createUnit(const string &unitName, int factionIndex, const Vec2i &pos);
|
||||
void givePositionCommand(int unitId, const string &commandName, const Vec2i &pos);
|
||||
void giveProductionCommand(int unitId, const string &producedName);
|
||||
void giveUpgradeCommand(int unitId, const string &upgradeName);
|
||||
void giveResource(const string &resourceName, int factionIndex, int amount);
|
||||
int getResourceAmount(const string &resourceName, int factionIndex);
|
||||
Vec2i getStartLocation(int factionIndex);
|
||||
Vec2i getUnitPosition(int unitId);
|
||||
int getUnitFactionIndex(int unitId);
|
||||
int getUnitCount(int factionIndex);
|
||||
int getUnitCountOfType(int factionIndex, const string &typeName);
|
||||
|
||||
private:
|
||||
|
||||
void initCells();
|
||||
void initSplattedTextures();
|
||||
void initFactionTypes(GameSettings *gs);
|
||||
void initMinimap();
|
||||
void initUnits();
|
||||
void initMap();
|
||||
void initExplorationState();
|
||||
|
||||
//misc
|
||||
void tick();
|
||||
void computeFow();
|
||||
void exploreCells(const Vec2i &newPos, int sightRange, int teamIndex);
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,886 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<74>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 "main.h"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include "conversion.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace Shared::Util;
|
||||
using namespace std;
|
||||
|
||||
namespace MapEditor {
|
||||
|
||||
const string MainWindow::versionString = "v1.5.0-beta3";
|
||||
const string MainWindow::winHeader = "Glest Map Editor " + versionString + " - Built: " + __DATE__;
|
||||
|
||||
// ===============================================
|
||||
// class Global functions
|
||||
// ===============================================
|
||||
|
||||
wxString ToUnicode(const char* str) {
|
||||
return wxString(str, wxConvUTF8);
|
||||
}
|
||||
|
||||
wxString ToUnicode(const string& str) {
|
||||
return wxString(str.c_str(), wxConvUTF8);
|
||||
}
|
||||
|
||||
// ===============================================
|
||||
// class MainWindow
|
||||
// ===============================================
|
||||
|
||||
MainWindow::MainWindow()
|
||||
: wxFrame(NULL, -1, ToUnicode(winHeader), wxDefaultPosition, wxSize(800, 600)) {
|
||||
|
||||
fileModified=false;
|
||||
lastX=0;
|
||||
lastY=0;
|
||||
radius=1;
|
||||
height=0;
|
||||
surface=1;
|
||||
object=0;
|
||||
resource=0;
|
||||
startLocation=1;
|
||||
enabledGroup=ctHeight;
|
||||
currentBrush=btHeight;
|
||||
resourceUnderMouse=0;
|
||||
objectUnderMouse=0;
|
||||
|
||||
//gl canvas
|
||||
int args[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER };
|
||||
glCanvas = new GlCanvas(this, args);
|
||||
|
||||
//menus
|
||||
menuBar = new wxMenuBar();
|
||||
|
||||
//file
|
||||
menuFile = new wxMenu();
|
||||
menuFile->Append(wxID_OPEN);
|
||||
menuFile->AppendSeparator();
|
||||
menuFile->Append(wxID_SAVE);
|
||||
menuFile->Append(wxID_SAVEAS);
|
||||
menuFile->AppendSeparator();
|
||||
menuFile->Append(wxID_EXIT);
|
||||
menuBar->Append(menuFile, wxT("&File"));
|
||||
|
||||
//edit
|
||||
menuEdit = new wxMenu();
|
||||
menuEdit->Append(miEditUndo, wxT("&Undo\tCTRL+z"));
|
||||
menuEdit->Append(miEditRedo, wxT("&Redo\tCTRL+y"));
|
||||
menuEdit->Append(miEditReset, wxT("Rese&t"));
|
||||
menuEdit->Append(miEditResetPlayers, wxT("Reset &Players"));
|
||||
menuEdit->Append(miEditResize, wxT("Re&size"));
|
||||
menuEdit->Append(miEditFlipX, wxT("Flip &X"));
|
||||
menuEdit->Append(miEditFlipY, wxT("Flip &Y"));
|
||||
menuEdit->Append(miEditRandomizeHeights, wxT("Randomize &Heights"));
|
||||
menuEdit->Append(miEditRandomize, wxT("Randomi&ze"));
|
||||
menuEdit->Append(miEditSwitchSurfaces, wxT("Switch Su&rfaces"));
|
||||
menuEdit->Append(miEditInfo, wxT("&Info"));
|
||||
menuEdit->Append(miEditAdvanced, wxT("&Advanced"));
|
||||
menuBar->Append(menuEdit, wxT("&Edit"));
|
||||
|
||||
//misc
|
||||
menuMisc = new wxMenu();
|
||||
menuMisc->Append(miMiscResetZoomAndPos, wxT("&Reset zoom and pos"));
|
||||
menuMisc->Append(miMiscAbout, wxT("&About"));
|
||||
menuMisc->Append(miMiscHelp, wxT("&Help"));
|
||||
menuBar->Append(menuMisc, wxT("&Misc"));
|
||||
|
||||
//brush
|
||||
menuBrush = new wxMenu();
|
||||
|
||||
// Glest height brush
|
||||
menuBrushHeight = new wxMenu();
|
||||
for (int i = 0; i < heightCount; ++i) {
|
||||
menuBrushHeight->AppendCheckItem(miBrushHeight + i + 1, ToUnicode(intToStr(i - heightCount / 2)));
|
||||
}
|
||||
menuBrushHeight->Check(miBrushHeight + (heightCount + 1) / 2, true);
|
||||
menuBrush->Append(miBrushHeight, wxT("&Height"), menuBrushHeight);
|
||||
|
||||
enabledGroup = ctHeight;
|
||||
|
||||
// ZombiePirate height brush
|
||||
menuBrushGradient = new wxMenu();
|
||||
for (int i = 0; i < heightCount; ++i) {
|
||||
menuBrushGradient->AppendCheckItem(miBrushGradient + i + 1, ToUnicode(intToStr(i - heightCount / 2)));
|
||||
}
|
||||
menuBrush->Append(miBrushGradient, wxT("&Gradient"), menuBrushGradient);
|
||||
|
||||
//surface
|
||||
menuBrushSurface = new wxMenu();
|
||||
menuBrushSurface->AppendCheckItem(miBrushSurface + 1, wxT("&1 - Grass"));
|
||||
menuBrushSurface->AppendCheckItem(miBrushSurface + 2, wxT("&2 - Secondary Grass"));
|
||||
menuBrushSurface->AppendCheckItem(miBrushSurface + 3, wxT("&3 - Road"));
|
||||
menuBrushSurface->AppendCheckItem(miBrushSurface + 4, wxT("&4 - Stone"));
|
||||
menuBrushSurface->AppendCheckItem(miBrushSurface + 5, wxT("&5 - Ground"));
|
||||
menuBrush->Append(miBrushSurface, wxT("&Surface"), menuBrushSurface);
|
||||
|
||||
//objects
|
||||
menuBrushObject = new wxMenu();
|
||||
menuBrushObject->AppendCheckItem(miBrushObject + 1, wxT("&0 - None (erase)"));
|
||||
menuBrushObject->AppendCheckItem(miBrushObject+2, wxT("&1 - Tree (unwalkable/harvestable)"));
|
||||
menuBrushObject->AppendCheckItem(miBrushObject+3, wxT("&2 - DeadTree/Cactuses/Thornbush (unwalkable)"));
|
||||
menuBrushObject->AppendCheckItem(miBrushObject+4, wxT("&3 - Stone (unwalkable)"));
|
||||
menuBrushObject->AppendCheckItem(miBrushObject+5, wxT("&4 - Bush/Grass/Fern (walkable)"));
|
||||
menuBrushObject->AppendCheckItem(miBrushObject+6, wxT("&5 - Water Object/Reed/Papyrus (walkable)"));
|
||||
menuBrushObject->AppendCheckItem(miBrushObject+7, wxT("&6 - C1 BigTree/DeadTree/OldPalm (unwalkable/not harvestable)"));
|
||||
menuBrushObject->AppendCheckItem(miBrushObject+8, wxT("&7 - C2 Hanged/Impaled (unwalkable)"));
|
||||
menuBrushObject->AppendCheckItem(miBrushObject+9, wxT("&8 - C3 Statues (unwalkable)"));
|
||||
menuBrushObject->AppendCheckItem(miBrushObject+10, wxT("&9 - C4 Big Rock (Mountain) (unwalkable)"));
|
||||
menuBrushObject->AppendCheckItem(miBrushObject+11, wxT("10 &- C5 Invisible Blocking Object (unwalkable)"));
|
||||
menuBrush->Append(miBrushObject, wxT("&Object"), menuBrushObject);
|
||||
|
||||
//resources
|
||||
menuBrushResource = new wxMenu();
|
||||
menuBrushResource->AppendCheckItem(miBrushResource + 1, wxT("&0 - None"));
|
||||
menuBrushResource->AppendCheckItem(miBrushResource+2, wxT("&1 - gold (unwalkable)"));
|
||||
menuBrushResource->AppendCheckItem(miBrushResource+3, wxT("&2 - stone (unwalkable)"));
|
||||
menuBrushResource->AppendCheckItem(miBrushResource+4, wxT("&3 - custom"));
|
||||
menuBrushResource->AppendCheckItem(miBrushResource+5, wxT("&4 - custom"));
|
||||
menuBrushResource->AppendCheckItem(miBrushResource+6, wxT("&5 - custom"));
|
||||
menuBrush->Append(miBrushResource, wxT("&Resource"), menuBrushResource);
|
||||
|
||||
//players
|
||||
menuBrushStartLocation = new wxMenu();
|
||||
menuBrushStartLocation->AppendCheckItem(miBrushStartLocation + 1, wxT("&1 - Player 1"));
|
||||
menuBrushStartLocation->AppendCheckItem(miBrushStartLocation + 2, wxT("&2 - Player 2"));
|
||||
menuBrushStartLocation->AppendCheckItem(miBrushStartLocation + 3, wxT("&3 - Player 3"));
|
||||
menuBrushStartLocation->AppendCheckItem(miBrushStartLocation + 4, wxT("&4 - Player 4"));
|
||||
menuBrushStartLocation->AppendCheckItem(miBrushStartLocation + 5, wxT("&5 - Player 5 "));
|
||||
menuBrushStartLocation->AppendCheckItem(miBrushStartLocation + 6, wxT("&6 - Player 6 "));
|
||||
menuBrushStartLocation->AppendCheckItem(miBrushStartLocation + 7, wxT("&7 - Player 7 "));
|
||||
menuBrushStartLocation->AppendCheckItem(miBrushStartLocation + 8, wxT("&8 - Player 8 "));
|
||||
menuBrush->Append(miBrushStartLocation, wxT("&Player"), menuBrushStartLocation);
|
||||
menuBar->Append(menuBrush, wxT("&Brush"));
|
||||
|
||||
//radius
|
||||
menuRadius = new wxMenu();
|
||||
for (int i = 1; i <= radiusCount; ++i) {
|
||||
menuRadius->AppendCheckItem(miRadius + i, ToUnicode("&" + intToStr(i) + "\tALT+" + intToStr(i)));
|
||||
}
|
||||
menuRadius->Check(miRadius + 1, true);
|
||||
menuBar->Append(menuRadius, wxT("&Radius"));
|
||||
|
||||
SetMenuBar(menuBar);
|
||||
|
||||
fileName = "New (unsaved) map";
|
||||
int status_widths[siCOUNT] = {
|
||||
10, // empty
|
||||
-2, // File name
|
||||
-1, // File type
|
||||
-2, // Current Object
|
||||
-2, // Brush Type
|
||||
-2, // Brush 'Value'
|
||||
-1, // Brush Radius
|
||||
};
|
||||
CreateStatusBar(siCOUNT);
|
||||
GetStatusBar()->SetStatusWidths(siCOUNT, status_widths);
|
||||
|
||||
SetStatusText(wxT("File: ") + ToUnicode(fileName), siFILE_NAME);
|
||||
SetStatusText(wxT(".gbm"), siFILE_TYPE);
|
||||
SetStatusText(wxT("Object: None (Erase)"), siCURR_OBJECT);
|
||||
SetStatusText(wxT("Brush: Height"), siBRUSH_TYPE);
|
||||
SetStatusText(wxT("Value: 0"), siBRUSH_VALUE);
|
||||
SetStatusText(wxT("Radius: 1"), siBRUSH_RADIUS);
|
||||
|
||||
#ifndef WIN32
|
||||
timer = new wxTimer(this);
|
||||
timer->Start(100);
|
||||
#endif
|
||||
glCanvas->SetFocus();
|
||||
}
|
||||
|
||||
void MainWindow::init(string fname) {
|
||||
glCanvas->SetCurrent();
|
||||
program = new Program(GetClientSize().x, GetClientSize().y);
|
||||
|
||||
fileName = "New (unsaved) Map";
|
||||
if (!fname.empty() && fileExists(fname)) {
|
||||
program->loadMap(fname);
|
||||
currentFile = fname;
|
||||
fileName = cutLastExt(lastFile(fname));
|
||||
}
|
||||
SetTitle(ToUnicode(winHeader + "; " + currentFile));
|
||||
setDirty(false);
|
||||
setExtension();
|
||||
}
|
||||
|
||||
void MainWindow::onClose(wxCloseEvent &event) {
|
||||
delete this;
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
delete program;
|
||||
delete glCanvas;
|
||||
}
|
||||
|
||||
void MainWindow::setDirty(bool val) {
|
||||
if (fileModified && val) {
|
||||
return;
|
||||
}
|
||||
fileModified = val;
|
||||
if (fileModified) {
|
||||
SetStatusText(wxT("File: ") + ToUnicode(fileName) + wxT("*"), siFILE_NAME);
|
||||
} else {
|
||||
SetStatusText(wxT("File: ") + ToUnicode(fileName), siFILE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::setExtension() {
|
||||
if (currentFile.empty()) {
|
||||
return;
|
||||
}
|
||||
string extnsn = ext(currentFile);
|
||||
if (extnsn == "gbm" || extnsn == "mgm") {
|
||||
currentFile = cutLastExt(currentFile);
|
||||
}
|
||||
if (Program::getMap()->getMaxFactions() <= 4) {
|
||||
SetStatusText(wxT(".gbm"), siFILE_TYPE);
|
||||
currentFile += ".gbm";
|
||||
} else {
|
||||
SetStatusText(wxT(".mgm"), siFILE_TYPE);
|
||||
currentFile += ".mgm";
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onTimer(wxTimerEvent &event) {
|
||||
wxPaintEvent paintEvent;
|
||||
onPaint(paintEvent);
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::onMouseDown(wxMouseEvent &event) {
|
||||
if (event.LeftIsDown()) {
|
||||
program->setUndoPoint(enabledGroup);
|
||||
program->setRefAlt(event.GetX(), event.GetY());
|
||||
change(event.GetX(), event.GetY());
|
||||
if (!isDirty()) {
|
||||
setDirty(true);
|
||||
}
|
||||
wxPaintEvent ev;
|
||||
onPaint(ev);
|
||||
}
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void MainWindow::onMouseMove(wxMouseEvent &event) {
|
||||
int dif;
|
||||
|
||||
int x = event.GetX();
|
||||
int y = event.GetY();
|
||||
|
||||
bool doPaint = true;
|
||||
if (event.LeftIsDown()) {
|
||||
change(x, y);
|
||||
} else if (event.MiddleIsDown()) {
|
||||
dif = (y - lastY);
|
||||
if (dif != 0) {
|
||||
program->incCellSize(dif / abs(dif));
|
||||
}
|
||||
} else if (event.RightIsDown()) {
|
||||
program->setOfset(x - lastX, y - lastY);
|
||||
} else {
|
||||
doPaint = false;
|
||||
}
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
if (doPaint) {
|
||||
wxPaintEvent ev;
|
||||
onPaint(ev);
|
||||
}
|
||||
else {
|
||||
int currResource = program->getResource(x,y);
|
||||
if(currResource>0){
|
||||
SetStatusText(wxT("Resource: ") + ToUnicode(resource_descs[currResource]), siCURR_OBJECT);
|
||||
resourceUnderMouse = currResource;
|
||||
objectUnderMouse = 0;
|
||||
}
|
||||
else {
|
||||
int currObject = program->getObject(x,y);
|
||||
SetStatusText(wxT("Object: ") + ToUnicode(object_descs[currObject]), siCURR_OBJECT);
|
||||
resourceUnderMouse = 0;
|
||||
objectUnderMouse = currObject;
|
||||
}
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void MainWindow::onPaint(wxPaintEvent &event) {
|
||||
program->renderMap(GetClientSize().x, GetClientSize().y);
|
||||
glCanvas->SwapBuffers();
|
||||
}
|
||||
|
||||
void MainWindow::onMenuFileLoad(wxCommandEvent &event) {
|
||||
wxFileDialog fileDialog(this);
|
||||
fileDialog.SetWildcard(wxT("Glest Map (*.gbm)|*.gbm|Mega Map (*.mgm)|*.mgm"));
|
||||
if (fileDialog.ShowModal() == wxID_OK) {
|
||||
currentFile = fileDialog.GetPath().ToAscii();
|
||||
program->loadMap(currentFile);
|
||||
fileName = cutLastExt(lastFile(currentFile));
|
||||
setDirty(false);
|
||||
setExtension();
|
||||
SetTitle(ToUnicode(winHeader + "; " + currentFile));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onMenuFileSave(wxCommandEvent &event) {
|
||||
if (currentFile.empty()) {
|
||||
wxCommandEvent ev;
|
||||
onMenuFileSaveAs(ev);
|
||||
} else {
|
||||
setExtension();
|
||||
program->saveMap(currentFile);
|
||||
setDirty(false);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onMenuFileSaveAs(wxCommandEvent &event) {
|
||||
wxFileDialog fileDialog(this, wxT("Select file"), wxT(""), wxT(""), wxT("*.gbm|*.mgm"), wxSAVE);
|
||||
fileDialog.SetWildcard(wxT("Glest Map (*.gbm)|*.gbm|Mega Map (*.mgm)|*.mgm"));
|
||||
if (fileDialog.ShowModal() == wxID_OK) {
|
||||
currentFile = fileDialog.GetPath().ToAscii();
|
||||
setExtension();
|
||||
program->saveMap(currentFile);
|
||||
fileName = cutLastExt(lastFile(currentFile));
|
||||
setDirty(false);
|
||||
}
|
||||
SetTitle(ToUnicode(winHeader + "; " + currentFile));
|
||||
}
|
||||
|
||||
void MainWindow::onMenuFileExit(wxCommandEvent &event) {
|
||||
Close();
|
||||
}
|
||||
|
||||
void MainWindow::onMenuEditUndo(wxCommandEvent &event) {
|
||||
std::cout << "Undo Pressed" << std::endl;
|
||||
if (program->undo()) {
|
||||
Refresh();
|
||||
setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onMenuEditRedo(wxCommandEvent &event) {
|
||||
std::cout << "Redo Pressed" << std::endl;
|
||||
if (program->redo()) {
|
||||
Refresh();
|
||||
setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onMenuEditReset(wxCommandEvent &event) {
|
||||
program->setUndoPoint(ctAll);
|
||||
SimpleDialog simpleDialog;
|
||||
simpleDialog.addValue("Altitude", "10");
|
||||
simpleDialog.addValue("Surface", "1");
|
||||
simpleDialog.addValue("Width", "64");
|
||||
simpleDialog.addValue("Height", "64");
|
||||
simpleDialog.show();
|
||||
|
||||
try {
|
||||
program->reset(
|
||||
strToInt(simpleDialog.getValue("Width")),
|
||||
strToInt(simpleDialog.getValue("Height")),
|
||||
strToInt(simpleDialog.getValue("Altitude")),
|
||||
strToInt(simpleDialog.getValue("Surface")));
|
||||
} catch (const exception &e) {
|
||||
wxMessageDialog(NULL, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
|
||||
}
|
||||
currentFile = "";
|
||||
fileName = "New (unsaved) map";
|
||||
}
|
||||
|
||||
void MainWindow::onMenuEditResetPlayers(wxCommandEvent &event) {
|
||||
SimpleDialog simpleDialog;
|
||||
simpleDialog.addValue("Factions", intToStr(program->getMap()->getMaxFactions()));
|
||||
simpleDialog.show();
|
||||
|
||||
try {
|
||||
program->resetFactions(strToInt(simpleDialog.getValue("Factions")));
|
||||
} catch (const exception &e) {
|
||||
wxMessageDialog(NULL, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
|
||||
}
|
||||
setDirty();
|
||||
setExtension();
|
||||
}
|
||||
|
||||
void MainWindow::onMenuEditResize(wxCommandEvent &event) {
|
||||
SimpleDialog simpleDialog;
|
||||
simpleDialog.addValue("Altitude", "10");
|
||||
simpleDialog.addValue("Surface", "1");
|
||||
simpleDialog.addValue("Height", "64");
|
||||
simpleDialog.addValue("Width", "64");
|
||||
simpleDialog.show();
|
||||
|
||||
try {
|
||||
program->resize(
|
||||
strToInt(simpleDialog.getValue("Height")),
|
||||
strToInt(simpleDialog.getValue("Width")),
|
||||
strToInt(simpleDialog.getValue("Altitude")),
|
||||
strToInt(simpleDialog.getValue("Surface")));
|
||||
} catch (const exception &e) {
|
||||
wxMessageDialog(NULL, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
|
||||
}
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void MainWindow::onMenuEditFlipX(wxCommandEvent &event) {
|
||||
program->flipX();
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void MainWindow::onMenuEditFlipY(wxCommandEvent &event) {
|
||||
program->flipY();
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void MainWindow::onMenuEditRandomizeHeights(wxCommandEvent &event) {
|
||||
program->randomizeMapHeights();
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void MainWindow::onMenuEditRandomize(wxCommandEvent &event) {
|
||||
program->randomizeMap();
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void MainWindow::onMenuEditSwitchSurfaces(wxCommandEvent &event) {
|
||||
SimpleDialog simpleDialog;
|
||||
simpleDialog.addValue("Surface1", "1");
|
||||
simpleDialog.addValue("Surface2", "2");
|
||||
simpleDialog.show();
|
||||
|
||||
try {
|
||||
program->switchMapSurfaces(
|
||||
strToInt(simpleDialog.getValue("Surface1")),
|
||||
strToInt(simpleDialog.getValue("Surface2")));
|
||||
} catch (const exception &e) {
|
||||
wxMessageDialog(NULL, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
|
||||
}
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void MainWindow::onMenuEditInfo(wxCommandEvent &event) {
|
||||
SimpleDialog simpleDialog;
|
||||
simpleDialog.addValue("Title", program->getMap()->getTitle());
|
||||
simpleDialog.addValue("Desc", program->getMap()->getDesc());
|
||||
simpleDialog.addValue("Author", program->getMap()->getAuthor());
|
||||
|
||||
simpleDialog.show();
|
||||
|
||||
if (program->setMapTitle(simpleDialog.getValue("Title"))
|
||||
|| program->setMapDesc(simpleDialog.getValue("Desc"))
|
||||
|| program->setMapAuthor(simpleDialog.getValue("Author"))) {
|
||||
if (!isDirty()) {
|
||||
setDirty(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onMenuEditAdvanced(wxCommandEvent &event) {
|
||||
SimpleDialog simpleDialog;
|
||||
simpleDialog.addValue("Height Factor", intToStr(program->getMap()->getHeightFactor()));
|
||||
simpleDialog.addValue("Water Level", intToStr(program->getMap()->getWaterLevel()));
|
||||
|
||||
simpleDialog.show();
|
||||
|
||||
try {
|
||||
program->setMapAdvanced(
|
||||
strToInt(simpleDialog.getValue("Height Factor")),
|
||||
strToInt(simpleDialog.getValue("Water Level")));
|
||||
} catch (const exception &e) {
|
||||
wxMessageDialog(NULL, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
|
||||
}
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void MainWindow::onMenuMiscResetZoomAndPos(wxCommandEvent &event) {
|
||||
program->resetOfset();
|
||||
}
|
||||
|
||||
void MainWindow::onMenuMiscAbout(wxCommandEvent &event) {
|
||||
wxMessageDialog(
|
||||
NULL,
|
||||
wxT("Glest Map Editor - Copyright 2004 The Glest Team\n(with improvements by others, 2010)."),
|
||||
wxT("About")).ShowModal();
|
||||
}
|
||||
|
||||
void MainWindow::onMenuMiscHelp(wxCommandEvent &event) {
|
||||
wxMessageDialog(
|
||||
NULL,
|
||||
wxT("Left mouse click: draw\nRight mouse drag: move\nCenter mouse drag: zoom"),
|
||||
wxT("Help")).ShowModal();
|
||||
}
|
||||
|
||||
void MainWindow::onMenuBrushHeight(wxCommandEvent &e) {
|
||||
uncheckBrush();
|
||||
menuBrushHeight->Check(e.GetId(), true);
|
||||
height = e.GetId() - miBrushHeight - heightCount / 2 - 1;
|
||||
enabledGroup = ctHeight;
|
||||
currentBrush = btHeight;
|
||||
SetStatusText(wxT("Brush: Height"), siBRUSH_TYPE);
|
||||
SetStatusText(wxT("Value: ") + ToUnicode(intToStr(height)), siBRUSH_VALUE);
|
||||
}
|
||||
|
||||
void MainWindow::onMenuBrushGradient(wxCommandEvent &e) {
|
||||
uncheckBrush();
|
||||
menuBrushGradient->Check(e.GetId(), true);
|
||||
height = e.GetId() - miBrushGradient - heightCount / 2 - 1;
|
||||
enabledGroup = ctGradient;
|
||||
currentBrush = btGradient;
|
||||
SetStatusText(wxT("Brush: Gradient"), siBRUSH_TYPE);
|
||||
SetStatusText(wxT("Value: ") + ToUnicode(intToStr(height)), siBRUSH_VALUE);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::onMenuBrushSurface(wxCommandEvent &e) {
|
||||
uncheckBrush();
|
||||
menuBrushSurface->Check(e.GetId(), true);
|
||||
surface = e.GetId() - miBrushSurface;
|
||||
enabledGroup = ctSurface;
|
||||
currentBrush = btSurface;
|
||||
SetStatusText(wxT("Brush: Surface"), siBRUSH_TYPE);
|
||||
SetStatusText(
|
||||
wxT("Value: ") + ToUnicode(intToStr(surface)) + wxT(" ")
|
||||
+ ToUnicode(surface_descs[surface - 1]), siBRUSH_VALUE);
|
||||
}
|
||||
|
||||
void MainWindow::onMenuBrushObject(wxCommandEvent &e) {
|
||||
uncheckBrush();
|
||||
menuBrushObject->Check(e.GetId(), true);
|
||||
object = e.GetId() - miBrushObject - 1;
|
||||
enabledGroup = ctObject;
|
||||
currentBrush = btObject;
|
||||
SetStatusText(wxT("Brush: Object"), siBRUSH_TYPE);
|
||||
SetStatusText(
|
||||
wxT("Value: ") + ToUnicode(intToStr(object)) + wxT(" ")
|
||||
+ ToUnicode(object_descs[object]), siBRUSH_VALUE);
|
||||
}
|
||||
|
||||
void MainWindow::onMenuBrushResource(wxCommandEvent &e) {
|
||||
uncheckBrush();
|
||||
menuBrushResource->Check(e.GetId(), true);
|
||||
resource = e.GetId() - miBrushResource - 1;
|
||||
enabledGroup = ctResource;
|
||||
currentBrush = btResource;
|
||||
SetStatusText(wxT("Brush: Resource"), siBRUSH_TYPE);
|
||||
SetStatusText(
|
||||
wxT("Value: ") + ToUnicode(intToStr(resource)) + wxT(" ")
|
||||
+ ToUnicode(resource_descs[resource]), siBRUSH_VALUE);
|
||||
}
|
||||
|
||||
void MainWindow::onMenuBrushStartLocation(wxCommandEvent &e) {
|
||||
uncheckBrush();
|
||||
menuBrushStartLocation->Check(e.GetId(), true);
|
||||
startLocation = e.GetId() - miBrushStartLocation;
|
||||
enabledGroup = ctLocation;
|
||||
currentBrush = btStartLocation;
|
||||
SetStatusText(wxT("Brush: Start Locations"), siBRUSH_TYPE);
|
||||
SetStatusText(wxT("Value: ") + ToUnicode(intToStr(startLocation)), siBRUSH_VALUE);
|
||||
}
|
||||
|
||||
void MainWindow::onMenuRadius(wxCommandEvent &e) {
|
||||
uncheckRadius();
|
||||
menuRadius->Check(e.GetId(), true);
|
||||
radius = e.GetId() - miRadius;
|
||||
SetStatusText(wxT("Radius: ") + ToUnicode(intToStr(radius)), siBRUSH_RADIUS);
|
||||
}
|
||||
|
||||
void MainWindow::change(int x, int y) {
|
||||
switch (enabledGroup) {
|
||||
case ctHeight:
|
||||
program->glestChangeMapHeight(x, y, height, radius);
|
||||
break;
|
||||
case ctSurface:
|
||||
program->changeMapSurface(x, y, surface, radius);
|
||||
break;
|
||||
case ctObject:
|
||||
program->changeMapObject(x, y, object, radius);
|
||||
break;
|
||||
case ctResource:
|
||||
program->changeMapResource(x, y, resource, radius);
|
||||
break;
|
||||
case ctLocation:
|
||||
program->changeStartLocation(x, y, startLocation - 1);
|
||||
break;
|
||||
case ctGradient:
|
||||
program->pirateChangeMapHeight(x, y, height, radius);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::uncheckBrush() {
|
||||
for (int i = 0; i < heightCount; ++i) {
|
||||
menuBrushHeight->Check(miBrushHeight + i + 1, false);
|
||||
}
|
||||
for (int i = 0; i < heightCount; ++i) {
|
||||
menuBrushGradient->Check(miBrushGradient + i + 1, false);
|
||||
}
|
||||
for (int i = 0; i < surfaceCount; ++i) {
|
||||
menuBrushSurface->Check(miBrushSurface + i + 1, false);
|
||||
}
|
||||
for (int i = 0; i < objectCount; ++i) {
|
||||
menuBrushObject->Check(miBrushObject + i + 1, false);
|
||||
}
|
||||
for (int i = 0; i < resourceCount; ++i) {
|
||||
menuBrushResource->Check(miBrushResource + i + 1, false);
|
||||
}
|
||||
for (int i = 0; i < startLocationCount; ++i) {
|
||||
menuBrushStartLocation->Check(miBrushStartLocation + i + 1, false);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::uncheckRadius() {
|
||||
for (int i = 1; i <= radiusCount; ++i) {
|
||||
menuRadius->Check(miRadius + i, false);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onKeyDown(wxKeyEvent &e) {
|
||||
if (currentBrush == btHeight || currentBrush == btGradient) { // 'height' brush
|
||||
if (e.GetKeyCode() >= '0' && e.GetKeyCode() <= '5') {
|
||||
height = e.GetKeyCode() - 48; // '0'-'5' == 0-5
|
||||
if (e.GetModifiers() == wxMOD_CONTROL) { // Ctrl means negative
|
||||
height = -height ;
|
||||
}
|
||||
int id_offset = heightCount / 2 + height + 1;
|
||||
if (currentBrush == btHeight) {
|
||||
wxCommandEvent evt(wxEVT_NULL, miBrushHeight + id_offset);
|
||||
onMenuBrushHeight(evt);
|
||||
} else {
|
||||
wxCommandEvent evt(wxEVT_NULL, miBrushGradient + id_offset);
|
||||
onMenuBrushGradient(evt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (currentBrush == btSurface) { // surface texture
|
||||
if (e.GetKeyCode() >= '1' && e.GetKeyCode() <= '5') {
|
||||
surface = e.GetKeyCode() - 48; // '1'-'5' == 1-5
|
||||
wxCommandEvent evt(wxEVT_NULL, miBrushSurface + surface);
|
||||
onMenuBrushSurface(evt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (currentBrush == btObject) {
|
||||
bool valid = true;
|
||||
if (e.GetKeyCode() >= '1' && e.GetKeyCode() <= '9') {
|
||||
object = e.GetKeyCode() - 48; // '1'-'9' == 1-9
|
||||
} else if (e.GetKeyCode() == '0') { // '0' == 10
|
||||
object = 10;
|
||||
} else if (e.GetKeyCode() == '-') { // '-' == 0
|
||||
object = 0;
|
||||
} else {
|
||||
valid = false;
|
||||
}
|
||||
if (valid) {
|
||||
wxCommandEvent evt(wxEVT_NULL, miBrushObject + object + 1);
|
||||
onMenuBrushObject(evt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (currentBrush == btResource) {
|
||||
if (e.GetKeyCode() >= '0' && e.GetKeyCode() <= '5') {
|
||||
resource = e.GetKeyCode() - 48; // '0'-'5' == 0-5
|
||||
wxCommandEvent evt(wxEVT_NULL, miBrushResource + resource + 1);
|
||||
onMenuBrushResource(evt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (currentBrush == btStartLocation) {
|
||||
if (e.GetKeyCode() >= '1' && e.GetKeyCode() <= '8') {
|
||||
startLocation = e.GetKeyCode() - 48; // '1'-'8' == 0-7
|
||||
wxCommandEvent evt(wxEVT_NULL, miBrushStartLocation + startLocation);
|
||||
onMenuBrushStartLocation(evt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (e.GetKeyCode() == 'H') {
|
||||
wxCommandEvent evt(wxEVT_NULL, miBrushHeight + height + heightCount / 2 + 1);
|
||||
onMenuBrushHeight(evt);
|
||||
} else if (e.GetKeyCode() == ' ') {
|
||||
if( resourceUnderMouse != 0 )
|
||||
{
|
||||
wxCommandEvent evt(wxEVT_NULL, miBrushResource + resourceUnderMouse + 1);
|
||||
onMenuBrushResource(evt);
|
||||
}
|
||||
else
|
||||
{
|
||||
wxCommandEvent evt(wxEVT_NULL, miBrushObject + objectUnderMouse + 1);
|
||||
onMenuBrushObject(evt);
|
||||
}
|
||||
} else if (e.GetKeyCode() == 'G') {
|
||||
wxCommandEvent evt(wxEVT_NULL, miBrushGradient + height + heightCount / 2 + 1);
|
||||
onMenuBrushGradient(evt);
|
||||
} else if (e.GetKeyCode() == 'S') {
|
||||
wxCommandEvent evt(wxEVT_NULL, miBrushSurface + surface);
|
||||
onMenuBrushSurface(evt);
|
||||
} else if (e.GetKeyCode() == 'O') {
|
||||
wxCommandEvent evt(wxEVT_NULL, miBrushObject + object + 1);
|
||||
onMenuBrushObject(evt);
|
||||
} else if (e.GetKeyCode() == 'R') {
|
||||
wxCommandEvent evt(wxEVT_NULL, miBrushResource + resource + 1);
|
||||
onMenuBrushResource(evt);
|
||||
} else if (e.GetKeyCode() == 'L') {
|
||||
wxCommandEvent evt(wxEVT_NULL, miBrushStartLocation + startLocation + 1);
|
||||
onMenuBrushStartLocation(evt);
|
||||
} else {
|
||||
e.Skip();
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(MainWindow, wxFrame)
|
||||
|
||||
EVT_TIMER(-1, MainWindow::onTimer)
|
||||
|
||||
EVT_CLOSE(MainWindow::onClose)
|
||||
|
||||
// these are 'handled' by GlCanvas and funneled to these handlers
|
||||
//EVT_LEFT_DOWN(MainWindow::onMouseDown)
|
||||
//EVT_MOTION(MainWindow::onMouseMove)
|
||||
//EVT_KEY_DOWN(MainWindow::onKeyDown)
|
||||
|
||||
EVT_MENU(wxID_OPEN, MainWindow::onMenuFileLoad)
|
||||
EVT_MENU(wxID_SAVE, MainWindow::onMenuFileSave)
|
||||
EVT_MENU(wxID_SAVEAS, MainWindow::onMenuFileSaveAs)
|
||||
EVT_MENU(wxID_EXIT, MainWindow::onMenuFileExit)
|
||||
|
||||
EVT_MENU(miEditUndo, MainWindow::onMenuEditUndo)
|
||||
EVT_MENU(miEditRedo, MainWindow::onMenuEditRedo)
|
||||
EVT_MENU(miEditReset, MainWindow::onMenuEditReset)
|
||||
EVT_MENU(miEditResetPlayers, MainWindow::onMenuEditResetPlayers)
|
||||
EVT_MENU(miEditResize, MainWindow::onMenuEditResize)
|
||||
EVT_MENU(miEditFlipX, MainWindow::onMenuEditFlipX)
|
||||
EVT_MENU(miEditFlipY, MainWindow::onMenuEditFlipY)
|
||||
EVT_MENU(miEditRandomizeHeights, MainWindow::onMenuEditRandomizeHeights)
|
||||
EVT_MENU(miEditRandomize, MainWindow::onMenuEditRandomize)
|
||||
EVT_MENU(miEditSwitchSurfaces, MainWindow::onMenuEditSwitchSurfaces)
|
||||
EVT_MENU(miEditInfo, MainWindow::onMenuEditInfo)
|
||||
EVT_MENU(miEditAdvanced, MainWindow::onMenuEditAdvanced)
|
||||
|
||||
EVT_MENU(miMiscResetZoomAndPos, MainWindow::onMenuMiscResetZoomAndPos)
|
||||
EVT_MENU(miMiscAbout, MainWindow::onMenuMiscAbout)
|
||||
EVT_MENU(miMiscHelp, MainWindow::onMenuMiscHelp)
|
||||
|
||||
EVT_MENU_RANGE(miBrushHeight + 1, miBrushHeight + heightCount, MainWindow::onMenuBrushHeight)
|
||||
EVT_MENU_RANGE(miBrushGradient + 1, miBrushGradient + heightCount, MainWindow::onMenuBrushGradient)
|
||||
EVT_MENU_RANGE(miBrushSurface + 1, miBrushSurface + surfaceCount, MainWindow::onMenuBrushSurface)
|
||||
EVT_MENU_RANGE(miBrushObject + 1, miBrushObject + objectCount, MainWindow::onMenuBrushObject)
|
||||
EVT_MENU_RANGE(miBrushResource + 1, miBrushResource + resourceCount, MainWindow::onMenuBrushResource)
|
||||
EVT_MENU_RANGE(miBrushStartLocation + 1, miBrushStartLocation + startLocationCount, MainWindow::onMenuBrushStartLocation)
|
||||
EVT_MENU_RANGE(miRadius, miRadius + radiusCount, MainWindow::onMenuRadius)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// =====================================================
|
||||
// class GlCanvas
|
||||
// =====================================================
|
||||
|
||||
GlCanvas::GlCanvas(MainWindow * mainWindow, int* args)
|
||||
: wxGLCanvas(mainWindow, -1, wxDefaultPosition, wxDefaultSize, 0, wxT("GLCanvas"), args) {
|
||||
this->mainWindow = mainWindow;
|
||||
}
|
||||
|
||||
void GlCanvas::onMouseDown(wxMouseEvent &event) {
|
||||
mainWindow->onMouseDown(event);
|
||||
}
|
||||
|
||||
void GlCanvas::onMouseMove(wxMouseEvent &event) {
|
||||
mainWindow->onMouseMove(event);
|
||||
}
|
||||
|
||||
void GlCanvas::onKeyDown(wxKeyEvent &event) {
|
||||
mainWindow->onKeyDown(event);
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(GlCanvas, wxGLCanvas)
|
||||
EVT_KEY_DOWN(GlCanvas::onKeyDown)
|
||||
|
||||
EVT_LEFT_DOWN(GlCanvas::onMouseDown)
|
||||
EVT_MOTION(GlCanvas::onMouseMove)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// ===============================================
|
||||
// class SimpleDialog
|
||||
// ===============================================
|
||||
|
||||
void SimpleDialog::addValue(const string &key, const string &value) {
|
||||
values.push_back(pair<string, string>(key, value));
|
||||
}
|
||||
|
||||
string SimpleDialog::getValue(const string &key) {
|
||||
for (int i = 0; i < values.size(); ++i) {
|
||||
if (values[i].first == key) {
|
||||
return values[i].second;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void SimpleDialog::show() {
|
||||
|
||||
Create(NULL, -1, wxT("Edit Values"));
|
||||
|
||||
wxSizer *sizer = new wxFlexGridSizer(2);
|
||||
|
||||
vector<wxTextCtrl*> texts;
|
||||
|
||||
for (Values::iterator it = values.begin(); it != values.end(); ++it) {
|
||||
sizer->Add(new wxStaticText(this, -1, ToUnicode(it->first)), 0, wxALL, 5);
|
||||
wxTextCtrl *text = new wxTextCtrl(this, -1, ToUnicode(it->second));
|
||||
sizer->Add(text, 0, wxALL, 5);
|
||||
texts.push_back(text);
|
||||
}
|
||||
SetSizerAndFit(sizer);
|
||||
|
||||
ShowModal();
|
||||
|
||||
for (int i = 0; i < texts.size(); ++i) {
|
||||
values[i].second = texts[i]->GetValue().ToAscii();
|
||||
}
|
||||
}
|
||||
|
||||
// ===============================================
|
||||
// class App
|
||||
// ===============================================
|
||||
|
||||
bool App::OnInit() {
|
||||
string fileparam;
|
||||
if(argc==2){
|
||||
fileparam = wxFNCONV(argv[1]);
|
||||
}
|
||||
|
||||
mainWindow = new MainWindow();
|
||||
mainWindow->Show();
|
||||
mainWindow->init(fileparam);
|
||||
return true;
|
||||
}
|
||||
|
||||
int App::MainLoop() {
|
||||
try {
|
||||
return wxApp::MainLoop();
|
||||
} catch (const exception &e) {
|
||||
wxMessageDialog(NULL, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int App::OnExit() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}// end namespace
|
||||
|
||||
IMPLEMENT_APP(MapEditor::App)
|
|
@ -0,0 +1,172 @@
|
|||
// ==============================================================
|
||||
// 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_GRAPHICS_MODEL_H_
|
||||
#define _SHARED_GRAPHICS_MODEL_H_
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "types.h"
|
||||
#include "pixmap.h"
|
||||
#include "texture_manager.h"
|
||||
#include "texture.h"
|
||||
#include "model_header.h"
|
||||
|
||||
using std::string;
|
||||
using std::map;
|
||||
using std::pair;
|
||||
|
||||
namespace Shared{ namespace Graphics{
|
||||
|
||||
class Model;
|
||||
class Mesh;
|
||||
class ShadowVolumeData;
|
||||
class InterpolationData;
|
||||
class TextureManager;
|
||||
|
||||
// =====================================================
|
||||
// class Mesh
|
||||
//
|
||||
// Part of a 3D model
|
||||
// =====================================================
|
||||
|
||||
class Mesh{
|
||||
private:
|
||||
//mesh data
|
||||
Texture2D *textures[meshTextureCount];
|
||||
string texturePaths[meshTextureCount];
|
||||
|
||||
//vertex data counts
|
||||
uint32 frameCount;
|
||||
uint32 vertexCount;
|
||||
uint32 indexCount;
|
||||
|
||||
//vertex data
|
||||
Vec3f *vertices;
|
||||
Vec3f *normals;
|
||||
Vec2f *texCoords;
|
||||
Vec3f *tangents;
|
||||
uint32 *indices;
|
||||
|
||||
//material data
|
||||
Vec3f diffuseColor;
|
||||
Vec3f specularColor;
|
||||
float specularPower;
|
||||
float opacity;
|
||||
|
||||
//properties
|
||||
bool twoSided;
|
||||
bool customColor;
|
||||
|
||||
InterpolationData *interpolationData;
|
||||
|
||||
public:
|
||||
//init & end
|
||||
Mesh();
|
||||
~Mesh();
|
||||
void init();
|
||||
void end();
|
||||
|
||||
//maps
|
||||
const Texture2D *getTexture(int i) const {return textures[i];}
|
||||
|
||||
//counts
|
||||
uint32 getFrameCount() const {return frameCount;}
|
||||
uint32 getVertexCount() const {return vertexCount;}
|
||||
uint32 getIndexCount() const {return indexCount;}
|
||||
uint32 getTriangleCount() const;
|
||||
|
||||
//data
|
||||
const Vec3f *getVertices() const {return vertices;}
|
||||
const Vec3f *getNormals() const {return normals;}
|
||||
const Vec2f *getTexCoords() const {return texCoords;}
|
||||
const Vec3f *getTangents() const {return tangents;}
|
||||
const uint32 *getIndices() const {return indices;}
|
||||
|
||||
//material
|
||||
const Vec3f &getDiffuseColor() const {return diffuseColor;}
|
||||
const Vec3f &getSpecularColor() const {return specularColor;}
|
||||
float getSpecularPower() const {return specularPower;}
|
||||
float getOpacity() const {return opacity;}
|
||||
|
||||
//properties
|
||||
bool getTwoSided() const {return twoSided;}
|
||||
bool getCustomTexture() const {return customColor;}
|
||||
|
||||
//external data
|
||||
const InterpolationData *getInterpolationData() const {return interpolationData;}
|
||||
|
||||
//interpolation
|
||||
void buildInterpolationData();
|
||||
void updateInterpolationData(float t, bool cycle) const;
|
||||
void updateInterpolationVertices(float t, bool cycle) const;
|
||||
|
||||
//load
|
||||
void loadV2(const string &dir, FILE *f, TextureManager *textureManager);
|
||||
void loadV3(const string &dir, FILE *f, TextureManager *textureManager);
|
||||
void load(const string &dir, FILE *f, TextureManager *textureManager);
|
||||
void save(const string &dir, FILE *f);
|
||||
|
||||
private:
|
||||
void computeTangents();
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
// class Model
|
||||
//
|
||||
// 3D Model, than can be loaded from a g3d file
|
||||
// =====================================================
|
||||
|
||||
class Model{
|
||||
private:
|
||||
TextureManager *textureManager;
|
||||
|
||||
private:
|
||||
uint8 fileVersion;
|
||||
uint32 meshCount;
|
||||
Mesh *meshes;
|
||||
|
||||
public:
|
||||
//constructor & destructor
|
||||
Model();
|
||||
virtual ~Model();
|
||||
virtual void init()= 0;
|
||||
virtual void end()= 0;
|
||||
|
||||
//data
|
||||
void updateInterpolationData(float t, bool cycle) const;
|
||||
void updateInterpolationVertices(float t, bool cycle) const;
|
||||
void buildShadowVolumeData() const;
|
||||
|
||||
//get
|
||||
uint8 getFileVersion() const {return fileVersion;}
|
||||
uint32 getMeshCount() const {return meshCount;}
|
||||
const Mesh *getMesh(int i) const {return &meshes[i];}
|
||||
|
||||
uint32 getTriangleCount() const;
|
||||
uint32 getVertexCount() const;
|
||||
|
||||
//io
|
||||
void load(const string &path);
|
||||
void save(const string &path);
|
||||
void loadG3d(const string &path);
|
||||
void saveS3d(const string &path);
|
||||
|
||||
void setTextureManager(TextureManager *textureManager) {this->textureManager= textureManager;}
|
||||
|
||||
private:
|
||||
void buildInterpolationData() const;
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,80 @@
|
|||
// ==============================================================
|
||||
// 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_UTIL_PROPERTIES_H_
|
||||
#define _SHARED_UTIL_PROPERTIES_H_
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
using std::map;
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::pair;
|
||||
|
||||
namespace Shared{ namespace Util{
|
||||
|
||||
// =====================================================
|
||||
// class Properties
|
||||
//
|
||||
/// ini-like file loader
|
||||
// =====================================================
|
||||
|
||||
class Properties{
|
||||
private:
|
||||
static const int maxLine= 1024;
|
||||
|
||||
public:
|
||||
typedef pair<string, string> PropertyPair;
|
||||
typedef map<string, string> PropertyMap;
|
||||
typedef vector<PropertyPair> PropertyVector;
|
||||
|
||||
private:
|
||||
PropertyVector propertyVector;
|
||||
PropertyMap propertyMap;
|
||||
string path;
|
||||
|
||||
public:
|
||||
void clear();
|
||||
void load(const string &path);
|
||||
void save(const string &path);
|
||||
|
||||
int getPropertyCount() {return propertyVector.size();}
|
||||
string getKey(int i) {return propertyVector[i].first;}
|
||||
string getString(int i) {return propertyVector[i].second;}
|
||||
|
||||
bool getBool(const string &key, const char *defaultValueIfNotFound=NULL) const;
|
||||
int getInt(const string &key, const char *defaultValueIfNotFound=NULL) const;
|
||||
int getInt(const string &key, int min, int max, const char *defaultValueIfNotFound=NULL) const;
|
||||
float getFloat(const string &key, const char *defaultValueIfNotFound=NULL) const;
|
||||
float getFloat(const string &key, float min, float max, const char *defaultValueIfNotFound=NULL) const;
|
||||
|
||||
const string getString(const string &key, const char *defaultValueIfNotFound=NULL) const;
|
||||
|
||||
int getInt(const char *key,const char *defaultValueIfNotFound=NULL) const;
|
||||
bool getBool(const char *key,const char *defaultValueIfNotFound=NULL) const;
|
||||
float getFloat(const char *key,const char *defaultValueIfNotFound=NULL) const;
|
||||
const string getString(const char *key,const char *defaultValueIfNotFound=NULL) const;
|
||||
|
||||
void setInt(const string &key, int value);
|
||||
void setBool(const string &key, bool value);
|
||||
void setFloat(const string &key, float value);
|
||||
void setString(const string &key, const string &value);
|
||||
|
||||
string toString();
|
||||
|
||||
|
||||
};
|
||||
|
||||
}}//end namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,151 @@
|
|||
// ==============================================================
|
||||
// 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
|
||||
// ==============================================================
|
||||
|
||||
#include "opengl.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "graphics_interface.h"
|
||||
#include "context_gl.h"
|
||||
#include "gl_wrap.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Platform;
|
||||
using namespace std;
|
||||
|
||||
namespace Shared{ namespace Graphics{ namespace Gl{
|
||||
|
||||
// =====================================================
|
||||
// class Globals
|
||||
// =====================================================
|
||||
|
||||
bool isGlExtensionSupported(const char *extensionName){
|
||||
const char *s;
|
||||
GLint len;
|
||||
const GLubyte *extensionStr= glGetString(GL_EXTENSIONS);
|
||||
|
||||
s= reinterpret_cast<const char *>(extensionStr);
|
||||
len= strlen(extensionName);
|
||||
|
||||
if(s != NULL) {
|
||||
while ((s = strstr (s, extensionName)) != NULL) {
|
||||
s+= len;
|
||||
if((*s == ' ') || (*s == '\0')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isGlVersionSupported(int major, int minor, int release){
|
||||
|
||||
const char *strVersion= getGlVersion();
|
||||
|
||||
//major
|
||||
const char *majorTok= strVersion;
|
||||
int majorSupported= atoi(majorTok);
|
||||
|
||||
if(majorSupported<major){
|
||||
return false;
|
||||
}
|
||||
else if(majorSupported>major){
|
||||
return true;
|
||||
}
|
||||
|
||||
//minor
|
||||
int i=0;
|
||||
while(strVersion[i]!='.'){
|
||||
++i;
|
||||
}
|
||||
const char *minorTok= &strVersion[i]+1;
|
||||
int minorSupported= atoi(minorTok);
|
||||
|
||||
if(minorSupported<minor){
|
||||
return false;
|
||||
}
|
||||
else if(minorSupported>minor){
|
||||
return true;
|
||||
}
|
||||
|
||||
//release
|
||||
++i;
|
||||
while(strVersion[i]!='.'){
|
||||
++i;
|
||||
}
|
||||
const char *releaseTok= &strVersion[i]+1;
|
||||
|
||||
if(atoi(releaseTok)<release){
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *getGlVersion(){
|
||||
return reinterpret_cast<const char *>(glGetString(GL_VERSION));
|
||||
}
|
||||
|
||||
const char *getGlRenderer(){
|
||||
return reinterpret_cast<const char *>(glGetString(GL_RENDERER));
|
||||
}
|
||||
|
||||
const char *getGlVendor(){
|
||||
return reinterpret_cast<const char *>(glGetString(GL_VENDOR));
|
||||
}
|
||||
|
||||
const char *getGlExtensions(){
|
||||
return reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
|
||||
}
|
||||
|
||||
const char *getGlPlatformExtensions(){
|
||||
Context *c= GraphicsInterface::getInstance().getCurrentContext();
|
||||
return getPlatformExtensions(static_cast<ContextGl*>(c)->getPlatformContextGl());
|
||||
}
|
||||
|
||||
int getGlMaxLights(){
|
||||
int i;
|
||||
glGetIntegerv(GL_MAX_LIGHTS, &i);
|
||||
return i;
|
||||
}
|
||||
|
||||
int getGlMaxTextureSize(){
|
||||
int i;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &i);
|
||||
return i;
|
||||
}
|
||||
|
||||
int getGlMaxTextureUnits(){
|
||||
int i;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &i);
|
||||
return i;
|
||||
}
|
||||
|
||||
int getGlModelviewMatrixStackDepth(){
|
||||
int i;
|
||||
glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, &i);
|
||||
return i;
|
||||
}
|
||||
|
||||
int getGlProjectionMatrixStackDepth(){
|
||||
int i;
|
||||
glGetIntegerv(GL_MAX_PROJECTION_STACK_DEPTH, &i);
|
||||
return i;
|
||||
}
|
||||
|
||||
void checkGlExtension(const char *extensionName){
|
||||
if(!isGlExtensionSupported(extensionName)){
|
||||
throw runtime_error("OpenGL extension not supported: " + string(extensionName));
|
||||
}
|
||||
}
|
||||
|
||||
}}}// end namespace
|
|
@ -0,0 +1,373 @@
|
|||
// ==============================================================
|
||||
// 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
|
||||
// ==============================================================
|
||||
|
||||
#include "texture_gl.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "opengl.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Shared{ namespace Graphics{ namespace Gl{
|
||||
|
||||
using namespace Platform;
|
||||
|
||||
GLint toWrapModeGl(Texture::WrapMode wrapMode){
|
||||
switch(wrapMode){
|
||||
case Texture::wmClamp:
|
||||
return GL_CLAMP;
|
||||
case Texture::wmRepeat:
|
||||
return GL_REPEAT;
|
||||
case Texture::wmClampToEdge:
|
||||
return GL_CLAMP_TO_EDGE;
|
||||
default:
|
||||
assert(false);
|
||||
return GL_CLAMP;
|
||||
}
|
||||
}
|
||||
|
||||
GLint toFormatGl(Texture::Format format, int components){
|
||||
switch(format){
|
||||
case Texture::fAuto:
|
||||
switch(components){
|
||||
case 1:
|
||||
return GL_LUMINANCE;
|
||||
case 3:
|
||||
return GL_RGB;
|
||||
case 4:
|
||||
return GL_RGBA;
|
||||
default:
|
||||
assert(false);
|
||||
return GL_RGBA;
|
||||
}
|
||||
break;
|
||||
case Texture::fLuminance:
|
||||
return GL_LUMINANCE;
|
||||
case Texture::fAlpha:
|
||||
return GL_ALPHA;
|
||||
case Texture::fRgb:
|
||||
return GL_RGB;
|
||||
case Texture::fRgba:
|
||||
return GL_RGBA;
|
||||
default:
|
||||
assert(false);
|
||||
return GL_RGB;
|
||||
}
|
||||
}
|
||||
|
||||
GLint toInternalFormatGl(Texture::Format format, int components){
|
||||
switch(format){
|
||||
case Texture::fAuto:
|
||||
switch(components){
|
||||
case 1:
|
||||
return GL_LUMINANCE8;
|
||||
case 3:
|
||||
return GL_RGB8;
|
||||
case 4:
|
||||
return GL_RGBA8;
|
||||
default:
|
||||
assert(false);
|
||||
return GL_RGBA8;
|
||||
}
|
||||
break;
|
||||
case Texture::fLuminance:
|
||||
return GL_LUMINANCE8;
|
||||
case Texture::fAlpha:
|
||||
return GL_ALPHA8;
|
||||
case Texture::fRgb:
|
||||
return GL_RGB8;
|
||||
case Texture::fRgba:
|
||||
return GL_RGBA8;
|
||||
default:
|
||||
assert(false);
|
||||
return GL_RGB8;
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class Texture1DGl
|
||||
// =====================================================
|
||||
|
||||
void Texture1DGl::init(Filter filter, int maxAnisotropy){
|
||||
assertGl();
|
||||
|
||||
if(!inited){
|
||||
|
||||
//params
|
||||
GLint wrap= toWrapModeGl(wrapMode);
|
||||
GLint glFormat= toFormatGl(format, pixmap.getComponents());
|
||||
GLint glInternalFormat= toInternalFormatGl(format, pixmap.getComponents());
|
||||
|
||||
//pixel init var
|
||||
const uint8* pixels= pixmapInit? pixmap.getPixels(): NULL;
|
||||
|
||||
//gen texture
|
||||
glGenTextures(1, &handle);
|
||||
glBindTexture(GL_TEXTURE_1D, handle);
|
||||
|
||||
//wrap params
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, wrap);
|
||||
|
||||
//maxAnisotropy
|
||||
if(isGlExtensionSupported("GL_EXT_texture_filter_anisotropic")){
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
|
||||
}
|
||||
|
||||
if(mipmap){
|
||||
GLuint glFilter= filter==fTrilinear? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST;
|
||||
|
||||
//build mipmaps
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, glFilter);
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
int error= gluBuild1DMipmaps(
|
||||
GL_TEXTURE_1D, glInternalFormat, pixmap.getW(),
|
||||
glFormat, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
if(error!=0){
|
||||
throw runtime_error("Error building texture 1D mipmaps");
|
||||
}
|
||||
}
|
||||
else{
|
||||
//build single texture
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glTexImage1D(
|
||||
GL_TEXTURE_1D, 0, glInternalFormat, pixmap.getW(),
|
||||
0, glFormat, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
GLint error= glGetError();
|
||||
if(error!=GL_NO_ERROR){
|
||||
throw runtime_error("Error creating texture 1D");
|
||||
}
|
||||
}
|
||||
inited= true;
|
||||
}
|
||||
|
||||
assertGl();
|
||||
}
|
||||
|
||||
void Texture1DGl::end(){
|
||||
if(inited){
|
||||
assertGl();
|
||||
glDeleteTextures(1, &handle);
|
||||
assertGl();
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class Texture2DGl
|
||||
// =====================================================
|
||||
|
||||
void Texture2DGl::init(Filter filter, int maxAnisotropy){
|
||||
assertGl();
|
||||
|
||||
if(!inited){
|
||||
|
||||
//params
|
||||
GLint wrap= toWrapModeGl(wrapMode);
|
||||
GLint glFormat= toFormatGl(format, pixmap.getComponents());
|
||||
GLint glInternalFormat= toInternalFormatGl(format, pixmap.getComponents());
|
||||
|
||||
//pixel init var
|
||||
const uint8* pixels= pixmapInit? pixmap.getPixels(): NULL;
|
||||
|
||||
//gen texture
|
||||
glGenTextures(1, &handle);
|
||||
glBindTexture(GL_TEXTURE_2D, handle);
|
||||
|
||||
//wrap params
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
|
||||
|
||||
//maxAnisotropy
|
||||
if(isGlExtensionSupported("GL_EXT_texture_filter_anisotropic")){
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
|
||||
}
|
||||
|
||||
if(mipmap){
|
||||
GLuint glFilter= filter==fTrilinear? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST;
|
||||
|
||||
//build mipmaps
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glFilter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
int error= gluBuild2DMipmaps(
|
||||
GL_TEXTURE_2D, glInternalFormat,
|
||||
pixmap.getW(), pixmap.getH(),
|
||||
glFormat, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
if(error!=0){
|
||||
throw runtime_error("Error building texture 2D mipmaps");
|
||||
}
|
||||
}
|
||||
else{
|
||||
//build single texture
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, glInternalFormat,
|
||||
pixmap.getW(), pixmap.getH(),
|
||||
0, glFormat, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
GLint error= glGetError();
|
||||
if(error!=GL_NO_ERROR){
|
||||
throw runtime_error("Error creating texture 2D");
|
||||
}
|
||||
}
|
||||
inited= true;
|
||||
}
|
||||
|
||||
assertGl();
|
||||
}
|
||||
|
||||
void Texture2DGl::end(){
|
||||
if(inited){
|
||||
assertGl();
|
||||
glDeleteTextures(1, &handle);
|
||||
assertGl();
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class Texture3DGl
|
||||
// =====================================================
|
||||
|
||||
void Texture3DGl::init(Filter filter, int maxAnisotropy){
|
||||
assertGl();
|
||||
|
||||
if(!inited){
|
||||
|
||||
//params
|
||||
GLint wrap= toWrapModeGl(wrapMode);
|
||||
GLint glFormat= toFormatGl(format, pixmap.getComponents());
|
||||
GLint glInternalFormat= toInternalFormatGl(format, pixmap.getComponents());
|
||||
|
||||
//pixel init var
|
||||
const uint8* pixels= pixmapInit? pixmap.getPixels(): NULL;
|
||||
|
||||
//gen texture
|
||||
glGenTextures(1, &handle);
|
||||
glBindTexture(GL_TEXTURE_3D, handle);
|
||||
|
||||
//wrap params
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, wrap);
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, wrap);
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, wrap);
|
||||
|
||||
//build single texture
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glTexImage3D(
|
||||
GL_TEXTURE_3D, 0, glInternalFormat,
|
||||
pixmap.getW(), pixmap.getH(), pixmap.getD(),
|
||||
0, glFormat, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
GLint error= glGetError();
|
||||
if(error!=GL_NO_ERROR){
|
||||
throw runtime_error("Error creating texture 3D");
|
||||
}
|
||||
inited= true;
|
||||
}
|
||||
|
||||
assertGl();
|
||||
}
|
||||
|
||||
void Texture3DGl::end(){
|
||||
if(inited){
|
||||
assertGl();
|
||||
glDeleteTextures(1, &handle);
|
||||
assertGl();
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class TextureCubeGl
|
||||
// =====================================================
|
||||
|
||||
void TextureCubeGl::init(Filter filter, int maxAnisotropy){
|
||||
assertGl();
|
||||
|
||||
if(!inited){
|
||||
|
||||
//gen texture
|
||||
glGenTextures(1, &handle);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, handle);
|
||||
|
||||
//wrap
|
||||
GLint wrap= toWrapModeGl(wrapMode);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrap);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrap);
|
||||
|
||||
//filter
|
||||
if(mipmap){
|
||||
GLuint glFilter= filter==fTrilinear? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST;
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, glFilter);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
else{
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
|
||||
for(int i=0; i<6; ++i){
|
||||
//params
|
||||
const Pixmap2D *currentPixmap= pixmap.getFace(i);
|
||||
|
||||
GLint glFormat= toFormatGl(format, currentPixmap->getComponents());
|
||||
GLint glInternalFormat= toInternalFormatGl(format, currentPixmap->getComponents());
|
||||
|
||||
//pixel init var
|
||||
const uint8* pixels= pixmapInit? currentPixmap->getPixels(): NULL;
|
||||
GLenum target= GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
|
||||
|
||||
if(mipmap){
|
||||
int error= gluBuild2DMipmaps(
|
||||
target, glInternalFormat,
|
||||
currentPixmap->getW(), currentPixmap->getH(),
|
||||
glFormat, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
if(error!=0){
|
||||
throw runtime_error("Error building texture cube mipmaps");
|
||||
}
|
||||
}
|
||||
else{
|
||||
glTexImage2D(
|
||||
target, 0, glInternalFormat,
|
||||
currentPixmap->getW(), currentPixmap->getH(),
|
||||
0, glFormat, GL_UNSIGNED_BYTE, pixels);
|
||||
}
|
||||
|
||||
if(glGetError()!=GL_NO_ERROR){
|
||||
throw runtime_error("Error creating texture cube");
|
||||
}
|
||||
}
|
||||
inited= true;
|
||||
|
||||
}
|
||||
|
||||
assertGl();
|
||||
}
|
||||
|
||||
void TextureCubeGl::end(){
|
||||
if(inited){
|
||||
assertGl();
|
||||
glDeleteTextures(1, &handle);
|
||||
assertGl();
|
||||
}
|
||||
}
|
||||
|
||||
}}}//end namespace
|
|
@ -0,0 +1,525 @@
|
|||
// ==============================================================
|
||||
// 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
|
||||
// ==============================================================
|
||||
|
||||
#include "model.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "interpolation.h"
|
||||
#include "conversion.h"
|
||||
#include "util.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Platform;
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Shared{ namespace Graphics{
|
||||
|
||||
using namespace Util;
|
||||
|
||||
// =====================================================
|
||||
// class Mesh
|
||||
// =====================================================
|
||||
|
||||
// ==================== constructor & destructor ====================
|
||||
|
||||
Mesh::Mesh(){
|
||||
frameCount= 0;
|
||||
vertexCount= 0;
|
||||
indexCount= 0;
|
||||
|
||||
vertices= NULL;
|
||||
normals= NULL;
|
||||
texCoords= NULL;
|
||||
tangents= NULL;
|
||||
indices= NULL;
|
||||
interpolationData= NULL;
|
||||
|
||||
for(int i=0; i<meshTextureCount; ++i){
|
||||
textures[i]= NULL;
|
||||
}
|
||||
|
||||
twoSided= false;
|
||||
customColor= false;
|
||||
}
|
||||
|
||||
Mesh::~Mesh(){
|
||||
end();
|
||||
}
|
||||
|
||||
void Mesh::init(){
|
||||
vertices= new Vec3f[frameCount*vertexCount];
|
||||
normals= new Vec3f[frameCount*vertexCount];
|
||||
texCoords= new Vec2f[vertexCount];
|
||||
indices= new uint32[indexCount];
|
||||
}
|
||||
|
||||
void Mesh::end(){
|
||||
delete [] vertices;
|
||||
delete [] normals;
|
||||
delete [] texCoords;
|
||||
delete [] tangents;
|
||||
delete [] indices;
|
||||
|
||||
delete interpolationData;
|
||||
}
|
||||
|
||||
// ========================== shadows & interpolation =========================
|
||||
|
||||
void Mesh::buildInterpolationData(){
|
||||
interpolationData= new InterpolationData(this);
|
||||
}
|
||||
|
||||
void Mesh::updateInterpolationData(float t, bool cycle) const{
|
||||
interpolationData->update(t, cycle);
|
||||
}
|
||||
|
||||
void Mesh::updateInterpolationVertices(float t, bool cycle) const{
|
||||
interpolationData->updateVertices(t, cycle);
|
||||
}
|
||||
|
||||
// ==================== load ====================
|
||||
|
||||
void Mesh::loadV2(const string &dir, FILE *f, TextureManager *textureManager){
|
||||
//read header
|
||||
MeshHeaderV2 meshHeader;
|
||||
fread(&meshHeader, sizeof(MeshHeaderV2), 1, f);
|
||||
|
||||
|
||||
if(meshHeader.normalFrameCount!=meshHeader.vertexFrameCount){
|
||||
throw runtime_error("Old model: vertex frame count different from normal frame count");
|
||||
}
|
||||
|
||||
if(meshHeader.texCoordFrameCount!=1){
|
||||
throw runtime_error("Old model: texture coord frame count is not 1");
|
||||
}
|
||||
|
||||
//init
|
||||
frameCount= meshHeader.vertexFrameCount;
|
||||
vertexCount= meshHeader.pointCount;
|
||||
indexCount= meshHeader.indexCount;
|
||||
|
||||
init();
|
||||
|
||||
//misc
|
||||
twoSided= false;
|
||||
customColor= false;
|
||||
|
||||
//texture
|
||||
if(meshHeader.hasTexture && textureManager!=NULL){
|
||||
texturePaths[mtDiffuse]= toLower(reinterpret_cast<char*>(meshHeader.texName));
|
||||
string texPath= dir+"/"+texturePaths[mtDiffuse];
|
||||
|
||||
textures[mtDiffuse]= static_cast<Texture2D*>(textureManager->getTexture(texPath));
|
||||
if(textures[mtDiffuse]==NULL){
|
||||
textures[mtDiffuse]= textureManager->newTexture2D();
|
||||
textures[mtDiffuse]->load(texPath);
|
||||
}
|
||||
}
|
||||
|
||||
//read data
|
||||
fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
||||
fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
||||
if(textures[mtDiffuse]!=NULL){
|
||||
fread(texCoords, sizeof(Vec2f)*vertexCount, 1, f);
|
||||
}
|
||||
fread(&diffuseColor, sizeof(Vec3f), 1, f);
|
||||
fread(&opacity, sizeof(float32), 1, f);
|
||||
fseek(f, sizeof(Vec4f)*(meshHeader.colorFrameCount-1), SEEK_CUR);
|
||||
fread(indices, sizeof(uint32)*indexCount, 1, f);
|
||||
}
|
||||
|
||||
void Mesh::loadV3(const string &dir, FILE *f, TextureManager *textureManager){
|
||||
//read header
|
||||
MeshHeaderV3 meshHeader;
|
||||
fread(&meshHeader, sizeof(MeshHeaderV3), 1, f);
|
||||
|
||||
|
||||
if(meshHeader.normalFrameCount!=meshHeader.vertexFrameCount){
|
||||
throw runtime_error("Old model: vertex frame count different from normal frame count");
|
||||
}
|
||||
|
||||
//init
|
||||
frameCount= meshHeader.vertexFrameCount;
|
||||
vertexCount= meshHeader.pointCount;
|
||||
indexCount= meshHeader.indexCount;
|
||||
|
||||
init();
|
||||
|
||||
//misc
|
||||
twoSided= (meshHeader.properties & mp3TwoSided) != 0;
|
||||
customColor= (meshHeader.properties & mp3CustomColor) != 0;
|
||||
|
||||
//texture
|
||||
if(!(meshHeader.properties & mp3NoTexture) && textureManager!=NULL){
|
||||
texturePaths[mtDiffuse]= toLower(reinterpret_cast<char*>(meshHeader.texName));
|
||||
string texPath= dir+"/"+texturePaths[mtDiffuse];
|
||||
|
||||
textures[mtDiffuse]= static_cast<Texture2D*>(textureManager->getTexture(texPath));
|
||||
if(textures[mtDiffuse]==NULL){
|
||||
textures[mtDiffuse]= textureManager->newTexture2D();
|
||||
textures[mtDiffuse]->load(texPath);
|
||||
}
|
||||
}
|
||||
|
||||
//read data
|
||||
fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
||||
fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
||||
if(textures[mtDiffuse]!=NULL){
|
||||
for(int i=0; i<meshHeader.texCoordFrameCount; ++i){
|
||||
fread(texCoords, sizeof(Vec2f)*vertexCount, 1, f);
|
||||
}
|
||||
}
|
||||
fread(&diffuseColor, sizeof(Vec3f), 1, f);
|
||||
fread(&opacity, sizeof(float32), 1, f);
|
||||
fseek(f, sizeof(Vec4f)*(meshHeader.colorFrameCount-1), SEEK_CUR);
|
||||
fread(indices, sizeof(uint32)*indexCount, 1, f);
|
||||
}
|
||||
|
||||
void Mesh::load(const string &dir, FILE *f, TextureManager *textureManager){
|
||||
//read header
|
||||
MeshHeader meshHeader;
|
||||
fread(&meshHeader, sizeof(MeshHeader), 1, f);
|
||||
|
||||
//init
|
||||
frameCount= meshHeader.frameCount;
|
||||
vertexCount= meshHeader.vertexCount;
|
||||
indexCount= meshHeader.indexCount;
|
||||
|
||||
init();
|
||||
|
||||
//properties
|
||||
customColor= (meshHeader.properties & mpfCustomColor) != 0;
|
||||
twoSided= (meshHeader.properties & mpfTwoSided) != 0;
|
||||
|
||||
//material
|
||||
diffuseColor= Vec3f(meshHeader.diffuseColor);
|
||||
specularColor= Vec3f(meshHeader.specularColor);
|
||||
specularPower= meshHeader.specularPower;
|
||||
opacity= meshHeader.opacity;
|
||||
|
||||
//maps
|
||||
uint32 flag= 1;
|
||||
for(int i=0; i<meshTextureCount; ++i){
|
||||
if((meshHeader.textures & flag) && textureManager!=NULL){
|
||||
uint8 cMapPath[mapPathSize];
|
||||
fread(cMapPath, mapPathSize, 1, f);
|
||||
string mapPath= toLower(reinterpret_cast<char*>(cMapPath));
|
||||
|
||||
string mapFullPath= dir + "/" + mapPath;
|
||||
|
||||
textures[i]= static_cast<Texture2D*>(textureManager->getTexture(mapFullPath));
|
||||
if(textures[i]==NULL){
|
||||
textures[i]= textureManager->newTexture2D();
|
||||
if(meshTextureChannelCount[i]!=-1){
|
||||
textures[i]->getPixmap()->init(meshTextureChannelCount[i]);
|
||||
}
|
||||
textures[i]->load(mapFullPath);
|
||||
}
|
||||
}
|
||||
flag*= 2;
|
||||
}
|
||||
|
||||
//read data
|
||||
fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
||||
fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
||||
if(meshHeader.textures!=0){
|
||||
fread(texCoords, sizeof(Vec2f)*vertexCount, 1, f);
|
||||
}
|
||||
fread(indices, sizeof(uint32)*indexCount, 1, f);
|
||||
|
||||
//tangents
|
||||
if(textures[mtNormal]!=NULL){
|
||||
computeTangents();
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::save(const string &dir, FILE *f){
|
||||
/*MeshHeader meshHeader;
|
||||
meshHeader.vertexFrameCount= vertexFrameCount;
|
||||
meshHeader.normalFrameCount= normalFrameCount;
|
||||
meshHeader.texCoordFrameCount= texCoordFrameCount;
|
||||
meshHeader.colorFrameCount= colorFrameCount;
|
||||
meshHeader.pointCount= pointCount;
|
||||
meshHeader.indexCount= indexCount;
|
||||
meshHeader.properties= 0;
|
||||
|
||||
if(twoSided) meshHeader.properties|= mpTwoSided;
|
||||
if(customTexture) meshHeader.properties|= mpCustomTexture;
|
||||
|
||||
if(texture==NULL){
|
||||
meshHeader.properties|= mpNoTexture;
|
||||
meshHeader.texName[0]= '\0';
|
||||
}
|
||||
else{
|
||||
strcpy(reinterpret_cast<char*>(meshHeader.texName), texName.c_str());
|
||||
texture->getPixmap()->saveTga(dir+"/"+texName);
|
||||
}
|
||||
|
||||
fwrite(&meshHeader, sizeof(MeshHeader), 1, f);
|
||||
fwrite(vertices, sizeof(Vec3f)*vertexFrameCount*pointCount, 1, f);
|
||||
fwrite(normals, sizeof(Vec3f)*normalFrameCount*pointCount, 1, f);
|
||||
fwrite(texCoords, sizeof(Vec2f)*texCoordFrameCount*pointCount, 1, f);
|
||||
fwrite(colors, sizeof(Vec4f)*colorFrameCount, 1, f);
|
||||
fwrite(indices, sizeof(uint32)*indexCount, 1, f);*/
|
||||
}
|
||||
|
||||
void Mesh::computeTangents(){
|
||||
delete [] tangents;
|
||||
tangents= new Vec3f[vertexCount];
|
||||
for(int i=0; i<vertexCount; ++i){
|
||||
tangents[i]= Vec3f(0.f);
|
||||
}
|
||||
|
||||
for(int i=0; i<indexCount; i+=3){
|
||||
for(int j=0; j<3; ++j){
|
||||
uint32 i0= indices[i+j];
|
||||
uint32 i1= indices[i+(j+1)%3];
|
||||
uint32 i2= indices[i+(j+2)%3];
|
||||
|
||||
Vec3f p0= vertices[i0];
|
||||
Vec3f p1= vertices[i1];
|
||||
Vec3f p2= vertices[i2];
|
||||
|
||||
float u0= texCoords[i0].x;
|
||||
float u1= texCoords[i1].x;
|
||||
float u2= texCoords[i2].x;
|
||||
|
||||
float v0= texCoords[i0].y;
|
||||
float v1= texCoords[i1].y;
|
||||
float v2= texCoords[i2].y;
|
||||
|
||||
tangents[i0]+=
|
||||
((p2-p0)*(v1-v0)-(p1-p0)*(v2-v0))/
|
||||
((u2-u0)*(v1-v0)-(u1-u0)*(v2-v0));
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<vertexCount; ++i){
|
||||
/*Vec3f binormal= normals[i].cross(tangents[i]);
|
||||
tangents[i]+= binormal.cross(normals[i]);*/
|
||||
tangents[i].normalize();
|
||||
}
|
||||
}
|
||||
|
||||
// ===============================================
|
||||
// class Model
|
||||
// ===============================================
|
||||
|
||||
// ==================== constructor & destructor ====================
|
||||
|
||||
Model::Model(){
|
||||
meshCount= 0;
|
||||
meshes= NULL;
|
||||
textureManager= NULL;
|
||||
}
|
||||
|
||||
Model::~Model(){
|
||||
delete [] meshes;
|
||||
}
|
||||
|
||||
// ==================== data ====================
|
||||
|
||||
void Model::buildInterpolationData() const{
|
||||
for(int i=0; i<meshCount; ++i){
|
||||
meshes[i].buildInterpolationData();
|
||||
}
|
||||
}
|
||||
|
||||
void Model::updateInterpolationData(float t, bool cycle) const{
|
||||
for(int i=0; i<meshCount; ++i){
|
||||
meshes[i].updateInterpolationData(t, cycle);
|
||||
}
|
||||
}
|
||||
|
||||
void Model::updateInterpolationVertices(float t, bool cycle) const{
|
||||
for(int i=0; i<meshCount; ++i){
|
||||
meshes[i].updateInterpolationVertices(t, cycle);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== get ====================
|
||||
|
||||
uint32 Model::getTriangleCount() const{
|
||||
uint32 triangleCount= 0;
|
||||
for(uint32 i=0; i<meshCount; ++i){
|
||||
triangleCount+= meshes[i].getIndexCount()/3;
|
||||
}
|
||||
return triangleCount;
|
||||
}
|
||||
|
||||
uint32 Model::getVertexCount() const{
|
||||
uint32 vertexCount= 0;
|
||||
for(uint32 i=0; i<meshCount; ++i){
|
||||
vertexCount+= meshes[i].getVertexCount();
|
||||
}
|
||||
return vertexCount;
|
||||
}
|
||||
|
||||
// ==================== io ====================
|
||||
|
||||
void Model::load(const string &path){
|
||||
string extension= path.substr(path.find_last_of('.')+1);
|
||||
if(extension=="g3d" || extension=="G3D"){
|
||||
loadG3d(path);
|
||||
}
|
||||
else{
|
||||
throw runtime_error("Unknown model format: " + extension);
|
||||
}
|
||||
}
|
||||
|
||||
void Model::save(const string &path){
|
||||
string extension= path.substr(path.find_last_of('.')+1);
|
||||
if(extension=="g3d" ||extension=="G3D" || extension=="s3d" || extension=="S3D"){
|
||||
saveS3d(path);
|
||||
}
|
||||
else{
|
||||
throw runtime_error("Unknown model format: " + extension);
|
||||
}
|
||||
}
|
||||
|
||||
/*void Model::loadG3dOld(const string &path){
|
||||
try{
|
||||
FILE *f=fopen(path.c_str(),"rb");
|
||||
if (f==NULL){
|
||||
throw runtime_error("Error opening 3d model file");
|
||||
}
|
||||
|
||||
string dir= cutLastFile(path);
|
||||
|
||||
//read header
|
||||
ModelHeaderOld modelHeader;
|
||||
fread(&modelHeader, sizeof(ModelHeader), 1, f);
|
||||
meshCount= modelHeader.meshCount;
|
||||
|
||||
if(modelHeader.id[0]!='G' || modelHeader.id[1]!='3' || modelHeader.id[2]!='D'){
|
||||
throw runtime_error("Model: "+path+": is not a valid G3D model");
|
||||
}
|
||||
|
||||
switch(modelHeader.version){
|
||||
case 3:{
|
||||
meshes= new Mesh[meshCount];
|
||||
for(uint32 i=0; i<meshCount; ++i){
|
||||
meshes[i].load(dir, f, textureManager);
|
||||
meshes[i].buildInterpolationData();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw runtime_error("Unknown model version");
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
catch(exception &e){
|
||||
throw runtime_error("Exception caught loading 3d file: " + path +"\n"+ e.what());
|
||||
}
|
||||
}*/
|
||||
|
||||
//load a model from a g3d file
|
||||
void Model::loadG3d(const string &path){
|
||||
|
||||
try{
|
||||
FILE *f=fopen(path.c_str(),"rb");
|
||||
if (f==NULL){
|
||||
throw runtime_error("Error opening 3d model file");
|
||||
}
|
||||
|
||||
string dir= cutLastFile(path);
|
||||
|
||||
//file header
|
||||
FileHeader fileHeader;
|
||||
fread(&fileHeader, sizeof(FileHeader), 1, f);
|
||||
if(strncmp(reinterpret_cast<char*>(fileHeader.id), "G3D", 3)!=0){
|
||||
|
||||
printf("In [%s::%s] file = [%s] fileheader.id = [%s][%c]\n",__FILE__,__FUNCTION__,path.c_str(),reinterpret_cast<char*>(fileHeader.id),fileHeader.id[0]);
|
||||
throw runtime_error("Not a valid S3D model");
|
||||
}
|
||||
fileVersion= fileHeader.version;
|
||||
|
||||
//version 4
|
||||
if(fileHeader.version==4){
|
||||
|
||||
//model header
|
||||
ModelHeader modelHeader;
|
||||
fread(&modelHeader, sizeof(ModelHeader), 1, f);
|
||||
meshCount= modelHeader.meshCount;
|
||||
if(modelHeader.type!=mtMorphMesh){
|
||||
throw runtime_error("Invalid model type");
|
||||
}
|
||||
|
||||
//load meshes
|
||||
meshes= new Mesh[meshCount];
|
||||
for(uint32 i=0; i<meshCount; ++i){
|
||||
meshes[i].load(dir, f, textureManager);
|
||||
meshes[i].buildInterpolationData();
|
||||
}
|
||||
}
|
||||
//version 3
|
||||
else if(fileHeader.version==3){
|
||||
|
||||
fread(&meshCount, sizeof(meshCount), 1, f);
|
||||
meshes= new Mesh[meshCount];
|
||||
for(uint32 i=0; i<meshCount; ++i){
|
||||
meshes[i].loadV3(dir, f, textureManager);
|
||||
meshes[i].buildInterpolationData();
|
||||
}
|
||||
}
|
||||
//version 2
|
||||
else if(fileHeader.version==2){
|
||||
|
||||
fread(&meshCount, sizeof(meshCount), 1, f);
|
||||
meshes= new Mesh[meshCount];
|
||||
for(uint32 i=0; i<meshCount; ++i){
|
||||
meshes[i].loadV2(dir, f, textureManager);
|
||||
meshes[i].buildInterpolationData();
|
||||
}
|
||||
}
|
||||
else{
|
||||
throw runtime_error("Invalid model version: "+ intToStr(fileHeader.version));
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
catch(exception &e){
|
||||
throw runtime_error("Exception caught loading 3d file: " + path +"\n"+ e.what());
|
||||
}
|
||||
}
|
||||
|
||||
//save a model to a g3d file
|
||||
void Model::saveS3d(const string &path){
|
||||
|
||||
/*FILE *f= fopen(path.c_str(), "wb");
|
||||
if(f==NULL){
|
||||
throw runtime_error("Cant open file for writting: "+path);
|
||||
}
|
||||
|
||||
ModelHeader modelHeader;
|
||||
modelHeader.id[0]= 'G';
|
||||
modelHeader.id[1]= '3';
|
||||
modelHeader.id[2]= 'D';
|
||||
modelHeader.version= 3;
|
||||
modelHeader.meshCount= meshCount;
|
||||
|
||||
string dir= cutLastFile(path);
|
||||
|
||||
fwrite(&modelHeader, sizeof(ModelHeader), 1, f);
|
||||
for(int i=0; i<meshCount; ++i){
|
||||
meshes[i].save(dir, f);
|
||||
}
|
||||
|
||||
fclose(f);*/
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,96 @@
|
|||
// ==============================================================
|
||||
// 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
|
||||
// ==============================================================
|
||||
|
||||
#include "texture_manager.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "graphics_interface.h"
|
||||
#include "graphics_factory.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
namespace Shared{ namespace Graphics{
|
||||
|
||||
// =====================================================
|
||||
// class TextureManager
|
||||
// =====================================================
|
||||
|
||||
TextureManager::TextureManager(){
|
||||
textureFilter= Texture::fBilinear;
|
||||
maxAnisotropy= 1;
|
||||
}
|
||||
|
||||
TextureManager::~TextureManager(){
|
||||
end();
|
||||
}
|
||||
|
||||
void TextureManager::init(){
|
||||
for(int i=0; i<textures.size(); ++i){
|
||||
textures[i]->init(textureFilter, maxAnisotropy);
|
||||
}
|
||||
}
|
||||
|
||||
void TextureManager::end(){
|
||||
for(int i=0; i<textures.size(); ++i){
|
||||
textures[i]->end();
|
||||
delete textures[i];
|
||||
}
|
||||
textures.clear();
|
||||
}
|
||||
|
||||
void TextureManager::setFilter(Texture::Filter textureFilter){
|
||||
this->textureFilter= textureFilter;
|
||||
}
|
||||
|
||||
void TextureManager::setMaxAnisotropy(int maxAnisotropy){
|
||||
this->maxAnisotropy= maxAnisotropy;
|
||||
}
|
||||
|
||||
Texture *TextureManager::getTexture(const string &path){
|
||||
for(int i=0; i<textures.size(); ++i){
|
||||
if(textures[i]->getPath()==path){
|
||||
return textures[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Texture1D *TextureManager::newTexture1D(){
|
||||
Texture1D *texture1D= GraphicsInterface::getInstance().getFactory()->newTexture1D();
|
||||
textures.push_back(texture1D);
|
||||
|
||||
return texture1D;
|
||||
}
|
||||
|
||||
Texture2D *TextureManager::newTexture2D(){
|
||||
Texture2D *texture2D= GraphicsInterface::getInstance().getFactory()->newTexture2D();
|
||||
textures.push_back(texture2D);
|
||||
|
||||
return texture2D;
|
||||
}
|
||||
|
||||
Texture3D *TextureManager::newTexture3D(){
|
||||
Texture3D *texture3D= GraphicsInterface::getInstance().getFactory()->newTexture3D();
|
||||
textures.push_back(texture3D);
|
||||
|
||||
return texture3D;
|
||||
}
|
||||
|
||||
|
||||
TextureCube *TextureManager::newTextureCube(){
|
||||
TextureCube *textureCube= GraphicsInterface::getInstance().getFactory()->newTextureCube();
|
||||
textures.push_back(textureCube);
|
||||
|
||||
return textureCube;
|
||||
}
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,126 @@
|
|||
// ==============================================================
|
||||
// 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
|
||||
// ==============================================================
|
||||
|
||||
#include "conversion.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Shared{ namespace Util{
|
||||
|
||||
const int strSize = 256;
|
||||
|
||||
bool strToBool(const string &s){
|
||||
if (s=="0" || s=="false"){
|
||||
return false;
|
||||
}
|
||||
if (s=="1" || s=="true"){
|
||||
return true;
|
||||
}
|
||||
throw runtime_error("Error converting string to bool, expected 0 or 1, found: [" + s + "]");
|
||||
}
|
||||
|
||||
int strToInt(const string &s){
|
||||
char *endChar;
|
||||
int intValue= strtol(s.c_str(), &endChar, 10);
|
||||
|
||||
if(*endChar!='\0'){
|
||||
throw runtime_error("Error converting from string to int, found: [" + s + "]");
|
||||
}
|
||||
|
||||
return intValue;
|
||||
}
|
||||
|
||||
|
||||
float strToFloat(const string &s){
|
||||
char *endChar;
|
||||
float floatValue= static_cast<float>(strtod(s.c_str(), &endChar));
|
||||
|
||||
if(*endChar!='\0'){
|
||||
throw runtime_error("Error converting from string to float, found: [" + s + "]");
|
||||
}
|
||||
|
||||
return floatValue;
|
||||
}
|
||||
|
||||
bool strToBool(const string &s, bool *b){
|
||||
if (s=="0" || s=="false"){
|
||||
*b= false;
|
||||
return true;
|
||||
}
|
||||
if (s=="1" || s=="true"){
|
||||
*b= true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool strToInt(const string &s, int *i){
|
||||
char *endChar;
|
||||
*i= strtol(s.c_str(), &endChar, 10);
|
||||
|
||||
if(*endChar!='\0'){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool strToFloat(const string &s, float *f){
|
||||
char *endChar;
|
||||
*f= static_cast<float>(strtod(s.c_str(), &endChar));
|
||||
|
||||
if(*endChar!='\0'){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
string boolToStr(bool b){
|
||||
if(b){
|
||||
return "1";
|
||||
}
|
||||
else{
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
|
||||
string intToStr(int i){
|
||||
char str[strSize];
|
||||
sprintf(str, "%d", i);
|
||||
return str;
|
||||
}
|
||||
|
||||
string intToHex(int i){
|
||||
char str[strSize];
|
||||
sprintf(str, "%x", i);
|
||||
return str;
|
||||
}
|
||||
|
||||
string floatToStr(float f){
|
||||
char str[strSize];
|
||||
sprintf(str, "%.2f", f);
|
||||
return str;
|
||||
}
|
||||
|
||||
string doubleToStr(double d){
|
||||
char str[strSize];
|
||||
sprintf(str, "%.2f", d);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
}}//end namespace
|
|
@ -0,0 +1,224 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest Shared Library (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2007 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 "properties.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
|
||||
#include "conversion.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Shared{ namespace Util{
|
||||
|
||||
// =====================================================
|
||||
// class Properties
|
||||
// =====================================================
|
||||
|
||||
void Properties::load(const string &path){
|
||||
|
||||
ifstream fileStream;
|
||||
char lineBuffer[maxLine];
|
||||
string line, key, value;
|
||||
int pos;
|
||||
|
||||
this->path= path;
|
||||
|
||||
fileStream.open(path.c_str(), ios_base::in);
|
||||
if(fileStream.fail()){
|
||||
throw runtime_error("Can't open propertyMap file: " + path);
|
||||
}
|
||||
|
||||
propertyMap.clear();
|
||||
while(!fileStream.eof()){
|
||||
fileStream.getline(lineBuffer, maxLine);
|
||||
lineBuffer[maxLine-1]='\0';
|
||||
|
||||
//process line if it it not a comment
|
||||
if(lineBuffer[0]!=';'){
|
||||
|
||||
// gracefully handle win32 \r\n line endings
|
||||
size_t len= strlen(lineBuffer);
|
||||
if(len > 0 && lineBuffer[len-1] == '\r'){
|
||||
lineBuffer[len-1]= 0;
|
||||
}
|
||||
|
||||
line= lineBuffer;
|
||||
pos= line.find('=');
|
||||
|
||||
if(pos != string::npos){
|
||||
key= line.substr(0, pos);
|
||||
value= line.substr(pos+1);
|
||||
propertyMap.insert(PropertyPair(key, value));
|
||||
propertyVector.push_back(PropertyPair(key, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileStream.close();
|
||||
}
|
||||
|
||||
void Properties::save(const string &path){
|
||||
ofstream fileStream;
|
||||
|
||||
fileStream.open(path.c_str(), ios_base::out | ios_base::trunc);
|
||||
|
||||
fileStream << "; === propertyMap File === \n";
|
||||
fileStream << '\n';
|
||||
|
||||
for(PropertyMap::iterator pi= propertyMap.begin(); pi!=propertyMap.end(); ++pi){
|
||||
fileStream << pi->first << '=' << pi->second << '\n';
|
||||
}
|
||||
|
||||
fileStream.close();
|
||||
}
|
||||
|
||||
void Properties::clear(){
|
||||
propertyMap.clear();
|
||||
propertyVector.clear();
|
||||
}
|
||||
|
||||
bool Properties::getBool(const string &key, const char *defaultValueIfNotFound) const{
|
||||
try{
|
||||
return strToBool(getString(key,defaultValueIfNotFound));
|
||||
}
|
||||
catch(exception &e){
|
||||
throw runtime_error("Error accessing value: " + key + " in: " + path+"\n[" + e.what() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
int Properties::getInt(const string &key,const char *defaultValueIfNotFound) const{
|
||||
try{
|
||||
return strToInt(getString(key,defaultValueIfNotFound));
|
||||
}
|
||||
catch(exception &e){
|
||||
throw runtime_error("Error accessing value: " + key + " in: " + path + "\n[" + e.what() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
int Properties::getInt(const string &key, int min, int max,const char *defaultValueIfNotFound) const{
|
||||
int i= getInt(key,defaultValueIfNotFound);
|
||||
if(i<min || i>max){
|
||||
throw runtime_error("Value out of range: " + key + ", min: " + intToStr(min) + ", max: " + intToStr(max));
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
float Properties::getFloat(const string &key, const char *defaultValueIfNotFound) const{
|
||||
try{
|
||||
return strToFloat(getString(key,defaultValueIfNotFound));
|
||||
}
|
||||
catch(exception &e){
|
||||
throw runtime_error("Error accessing value: " + key + " in: " + path + "\n[" + e.what() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
float Properties::getFloat(const string &key, float min, float max, const char *defaultValueIfNotFound) const{
|
||||
float f= getFloat(key,defaultValueIfNotFound);
|
||||
if(f<min || f>max){
|
||||
throw runtime_error("Value out of range: " + key + ", min: " + floatToStr(min) + ", max: " + floatToStr(max));
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
const string Properties::getString(const string &key, const char *defaultValueIfNotFound) const{
|
||||
PropertyMap::const_iterator it;
|
||||
it= propertyMap.find(key);
|
||||
if(it==propertyMap.end()){
|
||||
if(defaultValueIfNotFound != NULL) {
|
||||
return string(defaultValueIfNotFound);
|
||||
}
|
||||
else {
|
||||
throw runtime_error("Value not found in propertyMap: " + key + ", loaded from: " + path);
|
||||
}
|
||||
}
|
||||
else{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
void Properties::setInt(const string &key, int value){
|
||||
setString(key, intToStr(value));
|
||||
}
|
||||
|
||||
void Properties::setBool(const string &key, bool value){
|
||||
setString(key, boolToStr(value));
|
||||
}
|
||||
|
||||
void Properties::setFloat(const string &key, float value){
|
||||
setString(key, floatToStr(value));
|
||||
}
|
||||
|
||||
void Properties::setString(const string &key, const string &value){
|
||||
propertyMap.erase(key);
|
||||
propertyMap.insert(PropertyPair(key, value));
|
||||
}
|
||||
|
||||
string Properties::toString(){
|
||||
string rStr;
|
||||
|
||||
for(PropertyMap::iterator pi= propertyMap.begin(); pi!=propertyMap.end(); pi++)
|
||||
rStr+= pi->first + "=" + pi->second + "\n";
|
||||
|
||||
return rStr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool Properties::getBool(const char *key, const char *defaultValueIfNotFound) const{
|
||||
try{
|
||||
return strToBool(getString(key,defaultValueIfNotFound));
|
||||
}
|
||||
catch(exception &e){
|
||||
throw runtime_error("Error accessing value: " + string(key) + " in: " + path+"\n[" + e.what() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
int Properties::getInt(const char *key,const char *defaultValueIfNotFound) const{
|
||||
try{
|
||||
return strToInt(getString(key,defaultValueIfNotFound));
|
||||
}
|
||||
catch(exception &e){
|
||||
throw runtime_error("Error accessing value: " + string(key) + " in: " + path + "\n[" + e.what() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
float Properties::getFloat(const char *key, const char *defaultValueIfNotFound) const{
|
||||
try{
|
||||
return strToFloat(getString(key,defaultValueIfNotFound));
|
||||
}
|
||||
catch(exception &e){
|
||||
throw runtime_error("Error accessing value: " + string(key) + " in: " + path + "\n[" + e.what() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
const string Properties::getString(const char *key, const char *defaultValueIfNotFound) const{
|
||||
PropertyMap::const_iterator it;
|
||||
it= propertyMap.find(key);
|
||||
if(it==propertyMap.end()){
|
||||
if(defaultValueIfNotFound != NULL) {
|
||||
return string(defaultValueIfNotFound);
|
||||
}
|
||||
else {
|
||||
throw runtime_error("Value not found in propertyMap: " + string(key) + ", loaded from: " + path);
|
||||
}
|
||||
}
|
||||
else{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}}//end namepsace
|
Loading…
Reference in New Issue