Made changes to properly isolate new unit rotation code so that it is disabled by default

This commit is contained in:
Mark Vejvoda 2010-03-13 21:10:45 +00:00
parent c983eab0af
commit 2012b7e22c
27 changed files with 9174 additions and 58 deletions

View File

@ -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>

View File

@ -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

View File

@ -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(),""));
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

207
source/glest_game/gui/gui.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,69 +1109,76 @@ 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) {
rotateAmount = 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);
//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();
if(ut != NULL && ut->hasCellMap() == true) {
int matrixSize = ut->getSize();
const UnitType *ut= getType();
if(ut != NULL && ut->hasCellMap() == true) {
int matrixSize = ut->getSize();
if(rotateAmount > 0) {
if(rotateAmount > 0) {
delete [] cellMap;
cellMap = new bool[matrixSize * matrixSize];
delete [] cellMap;
cellMap = new bool[matrixSize * matrixSize];
for(int iRow = 0; iRow < matrixSize; ++iRow) {
for(int iCol = 0; iCol < matrixSize; ++iCol) {
bool getCellResult = ut->getCellMapCell(iCol, iRow);
//if(Socket::enableDebugText) printf("In [%s::%s] [%d,%d] = %d\n",__FILE__,__FUNCTION__,iRow,iCol,getCellResult);
for(int iRow = 0; iRow < matrixSize; ++iRow) {
for(int iCol = 0; iCol < matrixSize; ++iCol) {
bool getCellResult = ut->getCellMapCell(iCol, iRow);
//if(Socket::enableDebugText) printf("In [%s::%s] [%d,%d] = %d\n",__FILE__,__FUNCTION__,iRow,iCol,getCellResult);
int newRow = 0;
int newCol = 0;
int newRow = 0;
int newCol = 0;
switch((int)rotateAmount)
{
case 90:
newRow = (matrixSize - iCol - 1);
newCol = iRow;
break;
case 180:
newRow = (matrixSize - iRow - 1);
newCol = (matrixSize - iCol - 1);
break;
case 270:
newRow = iCol;
newCol = (matrixSize - iRow - 1);
break;
switch((int)rotateAmount)
{
case 90:
newRow = (matrixSize - iCol - 1);
newCol = iRow;
break;
case 180:
newRow = (matrixSize - iRow - 1);
newCol = (matrixSize - iCol - 1);
break;
case 270:
newRow = iCol;
newCol = (matrixSize - iRow - 1);
break;
}
//if(Socket::enableDebugText) printf("In [%s::%s] ABOUT TO Transform to [%d,%d] = %d\n",__FILE__,__FUNCTION__,newRow,newCol,getCellResult);
// bool getCellMapCell(int x, int y) const {return cellMap[size*y+x];}
// cellMap[i*size+j]= row[j]=='0'? false: true;
cellMap[matrixSize * newRow + newCol] = getCellResult;
}
//if(Socket::enableDebugText) printf("In [%s::%s] ABOUT TO Transform to [%d,%d] = %d\n",__FILE__,__FUNCTION__,newRow,newCol,getCellResult);
// bool getCellMapCell(int x, int y) const {return cellMap[size*y+x];}
// cellMap[i*size+j]= row[j]=='0'? false: true;
cellMap[matrixSize * newRow + newCol] = getCellResult;
}
}
}
//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] 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);
}
}
*/
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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 &map;}
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 &map;}
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

886
source/glest_map_editor/main.cpp Executable file
View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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