From d4ef639e9bfd130578de5ba1deb36b2477e26844 Mon Sep 17 00:00:00 2001 From: Tom Reynolds Date: Fri, 17 Jan 2014 10:45:22 +0100 Subject: [PATCH 01/17] Change default MySQL database server to 'localhost' to prevent issues with Unix socket connections --- source/masterserver/config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/masterserver/config.php b/source/masterserver/config.php index 8dc7be29..a05a7ced 100644 --- a/source/masterserver/config.php +++ b/source/masterserver/config.php @@ -8,7 +8,7 @@ define( 'PRODUCT_NAME', 'MegaGlest' ); define( 'PRODUCT_URL', 'http://megaglest.org' ); - define( 'MYSQL_HOST', '127.0.0.1' ); + define( 'MYSQL_HOST', 'localhost' ); define( 'MYSQL_DATABASE', 'megaglest_master' ); define( 'MYSQL_USER', 'not_root' ); define( 'MYSQL_PASSWORD', 'your_pwd' ); From 728dd3aea7ca9be23811010cf2f318ff037e5f55 Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Fri, 17 Jan 2014 07:56:14 -0800 Subject: [PATCH 02/17] - added mutex guards in client connected menu to try to fix thread race bugs --- .../menu/menu_state_connected_game.cpp | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/source/glest_game/menu/menu_state_connected_game.cpp b/source/glest_game/menu/menu_state_connected_game.cpp index 184afab9..0d470b07 100644 --- a/source/glest_game/menu/menu_state_connected_game.cpp +++ b/source/glest_game/menu/menu_state_connected_game.cpp @@ -1033,8 +1033,11 @@ void MenuStateConnectedGame::simpleTask(BaseThread *callingThread,void *userdata } if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); + + MutexSafeWrapper safeMutex(callingThread->getMutexThreadObjectAccessor(),string(__FILE__) + "_" + intToStr(__LINE__)); tilesetListRemote.clear(); Tokenize(tilesetsMetaData,tilesetListRemote,"\n"); + safeMutex.ReleaseLock(true); for(unsigned int i=0; i < tilesetListRemote.size(); i++) { @@ -1043,7 +1046,9 @@ void MenuStateConnectedGame::simpleTask(BaseThread *callingThread,void *userdata return; } + safeMutex.Lock(); string result=refreshTilesetModInfo(tilesetListRemote[i]); + safeMutex.ReleaseLock(true); } if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) { @@ -1060,8 +1065,10 @@ void MenuStateConnectedGame::simpleTask(BaseThread *callingThread,void *userdata if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); + safeMutex.Lock(); techListRemote.clear(); Tokenize(techsMetaData,techListRemote,"\n"); + safeMutex.ReleaseLock(true); if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) { if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -1075,7 +1082,9 @@ void MenuStateConnectedGame::simpleTask(BaseThread *callingThread,void *userdata return; } + safeMutex.Lock(); string result=refreshTechModInfo(techListRemote[i]); + safeMutex.ReleaseLock(true); } if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) { @@ -1092,8 +1101,10 @@ void MenuStateConnectedGame::simpleTask(BaseThread *callingThread,void *userdata if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); + safeMutex.Lock(); mapListRemote.clear(); Tokenize(mapsMetaData,mapListRemote,"\n"); + safeMutex.ReleaseLock(true); for(unsigned int i=0; i < mapListRemote.size(); i++) { @@ -1102,7 +1113,9 @@ void MenuStateConnectedGame::simpleTask(BaseThread *callingThread,void *userdata return; } + safeMutex.Lock(); string result=refreshMapModInfo(mapListRemote[i]); + safeMutex.ReleaseLock(true); } if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) { @@ -1218,7 +1231,10 @@ void MenuStateConnectedGame::mouseClick(int x, int y, MouseButton mouseButton){ if(ftpClientThread != NULL) { if(button == 0 && ftpMessageBox.getButtonCount() == 3) { string mapName = getMissingMapFromFTPServer; + + MutexSafeWrapper safeMutexThread((modHttpServerThread != NULL ? modHttpServerThread->getMutexThreadObjectAccessor() : NULL),string(__FILE__) + "_" + intToStr(__LINE__)); string mapURL = mapCacheList[mapName].url; + safeMutexThread.ReleaseLock(); if(ftpClientThread != NULL) ftpClientThread->addMapToRequests(mapName,mapURL); MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),string(__FILE__) + "_" + intToStr(__LINE__)); @@ -1253,7 +1269,10 @@ void MenuStateConnectedGame::mouseClick(int x, int y, MouseButton mouseButton){ if(ftpClientThread != NULL) { if(button == 0 && ftpMessageBox.getButtonCount() == 3) { string tilesetName = getMissingTilesetFromFTPServer; + + MutexSafeWrapper safeMutexThread((modHttpServerThread != NULL ? modHttpServerThread->getMutexThreadObjectAccessor() : NULL),string(__FILE__) + "_" + intToStr(__LINE__)); string tilesetURL = tilesetCacheList[tilesetName].url; + safeMutexThread.ReleaseLock(); if(ftpClientThread != NULL) ftpClientThread->addTilesetToRequests(tilesetName,tilesetURL); MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),string(__FILE__) + "_" + intToStr(__LINE__)); @@ -1288,7 +1307,10 @@ void MenuStateConnectedGame::mouseClick(int x, int y, MouseButton mouseButton){ if(ftpClientThread != NULL) { if(button == 0 && ftpMessageBox.getButtonCount() == 3) { string techName = getMissingTechtreeFromFTPServer; + + MutexSafeWrapper safeMutexThread((modHttpServerThread != NULL ? modHttpServerThread->getMutexThreadObjectAccessor() : NULL),string(__FILE__) + "_" + intToStr(__LINE__)); string techURL = techCacheList[techName].url; + safeMutexThread.ReleaseLock(); if(ftpClientThread != NULL) ftpClientThread->addTechtreeToRequests(techName,techURL); MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),string(__FILE__) + "_" + intToStr(__LINE__)); @@ -4372,6 +4394,7 @@ void MenuStateConnectedGame::setupUIFromGameSettings(GameSettings *gameSettings, snprintf(szBuf,8096,"%s %s ?",lang.getString("DownloadMissingTilesetQuestion").c_str(),gameSettings->getTileset().c_str()); // Is the item in the mod center? + MutexSafeWrapper safeMutexThread((modHttpServerThread != NULL ? modHttpServerThread->getMutexThreadObjectAccessor() : NULL),string(__FILE__) + "_" + intToStr(__LINE__)); if(tilesetCacheList.find(getMissingMapFromFTPServer) == tilesetCacheList.end()) { ftpMessageBox.init(lang.getString("Yes"),lang.getString("NoDownload")); } @@ -4379,6 +4402,7 @@ void MenuStateConnectedGame::setupUIFromGameSettings(GameSettings *gameSettings, ftpMessageBox.init(lang.getString("ModCenter"),lang.getString("GameHost")); ftpMessageBox.addButton(lang.getString("NoDownload")); } + safeMutexThread.ReleaseLock(); ftpMissingDataType = ftpmsg_MissingTileset; showFTPMessageBox(szBuf, lang.getString("Question"), false); @@ -4443,6 +4467,7 @@ void MenuStateConnectedGame::setupUIFromGameSettings(GameSettings *gameSettings, snprintf(szBuf,8096,"%s %s ?",lang.getString("DownloadMissingTechtreeQuestion").c_str(),gameSettings->getTech().c_str()); // Is the item in the mod center? + MutexSafeWrapper safeMutexThread((modHttpServerThread != NULL ? modHttpServerThread->getMutexThreadObjectAccessor() : NULL),string(__FILE__) + "_" + intToStr(__LINE__)); if(techCacheList.find(getMissingTechtreeFromFTPServer) == techCacheList.end()) { ftpMessageBox.init(lang.getString("Yes"),lang.getString("NoDownload")); } @@ -4450,6 +4475,7 @@ void MenuStateConnectedGame::setupUIFromGameSettings(GameSettings *gameSettings, ftpMessageBox.init(lang.getString("ModCenter"),lang.getString("GameHost")); ftpMessageBox.addButton(lang.getString("NoDownload")); } + safeMutexThread.ReleaseLock(); ftpMissingDataType = ftpmsg_MissingTechtree; showFTPMessageBox(szBuf, lang.getString("Question"), false); @@ -4534,6 +4560,7 @@ void MenuStateConnectedGame::setupUIFromGameSettings(GameSettings *gameSettings, snprintf(szBuf,8096,"%s %s ?",lang.getString("DownloadMissingMapQuestion").c_str(),currentMap.c_str()); // Is the item in the mod center? + MutexSafeWrapper safeMutexThread((modHttpServerThread != NULL ? modHttpServerThread->getMutexThreadObjectAccessor() : NULL),string(__FILE__) + "_" + intToStr(__LINE__)); if(mapCacheList.find(getMissingTechtreeFromFTPServer) == mapCacheList.end()) { ftpMessageBox.init(lang.getString("Yes"),lang.getString("NoDownload")); } @@ -4541,6 +4568,7 @@ void MenuStateConnectedGame::setupUIFromGameSettings(GameSettings *gameSettings, ftpMessageBox.init(lang.getString("ModCenter"),lang.getString("GameHost")); ftpMessageBox.addButton(lang.getString("NoDownload")); } + safeMutexThread.ReleaseLock(); ftpMissingDataType = ftpmsg_MissingMap; showFTPMessageBox(szBuf, lang.getString("Question"), false); From 0de4f339238d57b4d1f3f4c14552c6c83c47ef6b Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Fri, 17 Jan 2014 09:46:31 -0800 Subject: [PATCH 03/17] - error output now shows system time --- source/shared_lib/sources/util/util.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/shared_lib/sources/util/util.cpp b/source/shared_lib/sources/util/util.cpp index f5a31cd9..ecc3ca28 100644 --- a/source/shared_lib/sources/util/util.cpp +++ b/source/shared_lib/sources/util/util.cpp @@ -449,7 +449,8 @@ void SystemFlags::logDebugEntry(DebugType type, string debugEntry, time_t debugT } char szBuf2[100]=""; - if (type != debugPathFinder && type != debugError && type != debugWorldSynch) { + //if (type != debugPathFinder && type != debugError && type != debugWorldSynch) { + if (type != debugPathFinder && type != debugWorldSynch) { // Get the current time. // time_t curtime = time (NULL); // Convert it to local time representation. @@ -581,7 +582,7 @@ void SystemFlags::logDebugEntry(DebugType type, string debugEntry, time_t debugT (*currentDebugLog.fileStream) << "[" << szBuf2 << "] " << debugEntry.c_str(); } else if (type == debugError) { - (*currentDebugLog.fileStream) << " *ERROR* " << debugEntry.c_str(); + (*currentDebugLog.fileStream) << "[" << szBuf2 << "] *ERROR* " << debugEntry.c_str(); } else { (*currentDebugLog.fileStream) << debugEntry.c_str(); From b0fc9597e34d10d1dbcfc2b139a2e2c4c618b273 Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Fri, 17 Jan 2014 09:53:19 -0800 Subject: [PATCH 04/17] - fixed some bugs reported by coverity --- source/glest_game/main/main.cpp | 2 +- source/glest_game/types/unit_type.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/source/glest_game/main/main.cpp b/source/glest_game/main/main.cpp index a3d2aca1..a540037f 100644 --- a/source/glest_game/main/main.cpp +++ b/source/glest_game/main/main.cpp @@ -4638,7 +4638,7 @@ int glestMain(int argc, char** argv) { if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LUA_DEBUG]) == true) { printf("Forcing LUA debugging enabled!\n"); - config.setBool("DebugLUA","true", true); + config.setBool("DebugLUA",true, true); } // Setup debug logging etc diff --git a/source/glest_game/types/unit_type.cpp b/source/glest_game/types/unit_type.cpp index f9aa117e..846a4a9e 100644 --- a/source/glest_game/types/unit_type.cpp +++ b/source/glest_game/types/unit_type.cpp @@ -129,6 +129,7 @@ UnitType::UnitType() : ProducibleType() { armor=0; sight=0; size=0; + renderSize=0; height=0; addItemToVault(&(this->maxHp),this->maxHp); From 6439d98146131bf1825f2e9d3a40ec0f017a4549 Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Fri, 17 Jan 2014 11:32:21 -0800 Subject: [PATCH 05/17] - do NOT pause for lagging clients if game network setting set to false --- source/glest_game/network/server_interface.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/source/glest_game/network/server_interface.cpp b/source/glest_game/network/server_interface.cpp index 9acdb80f..c6600dfc 100644 --- a/source/glest_game/network/server_interface.cpp +++ b/source/glest_game/network/server_interface.cpp @@ -1069,9 +1069,10 @@ void ServerInterface::checkForCompletedClients(std::map & mapSlotSigna void ServerInterface::checkForAutoPauseForLaggingClient(int index,ConnectionSlot* connectionSlot) { - if (this->clientsAutoPausedDueToLag == false) { + if (gameSettings.getNetworkPauseGameForLaggedClients() == true && + this->clientsAutoPausedDueToLag == false) { if (connectionSlot != NULL && connectionSlot->isConnected() == true) { - if (connectionSlot->getAutoPauseGameCountForLag()< MAX_CLIENT_PAUSE_FOR_LAG_COUNT) { + if (connectionSlot->getAutoPauseGameCountForLag() < MAX_CLIENT_PAUSE_FOR_LAG_COUNT) { if (this->clientLagCallbackInterface != NULL) { if (this->clientsAutoPausedDueToLagTimer.isStarted() == false || @@ -1438,7 +1439,8 @@ void ServerInterface::dispatchPendingUnMarkCellMessages(std::vector &er } void ServerInterface::checkForAutoResumeForLaggingClients() { - if (this->clientsAutoPausedDueToLag == true && + if (gameSettings.getNetworkPauseGameForLaggedClients() == true && + this->clientsAutoPausedDueToLag == true && this->clientsAutoPausedDueToLagTimer.getMillis() >= MAX_CLIENT_WAIT_SECONDS_FOR_PAUSE_MILLISECONDS) { //printf("this->clientsAutoPausedDueToLag: %d [%lld]\n",this->clientsAutoPausedDueToLag,(long long)this->clientsAutoPausedDueToLagTimer.getMillis()); From 27316e89125eb94c89b4e8ac0eb44514eee171eb Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Fri, 17 Jan 2014 13:32:42 -0800 Subject: [PATCH 06/17] - added time to error console output log items --- source/shared_lib/sources/util/util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/shared_lib/sources/util/util.cpp b/source/shared_lib/sources/util/util.cpp index ecc3ca28..e749937f 100644 --- a/source/shared_lib/sources/util/util.cpp +++ b/source/shared_lib/sources/util/util.cpp @@ -603,7 +603,7 @@ void SystemFlags::logDebugEntry(DebugType type, string debugEntry, time_t debugT printf("[%s] %s", szBuf2, debugEntry.c_str()); } else if (type == debugError) { - printf("*ERROR* %s", debugEntry.c_str()); + printf("*ERROR* [%s] %s", szBuf2,debugEntry.c_str()); } else { printf("%s", debugEntry.c_str()); From 6d15d66795980dcf842e20d2f520f4916e4e103b Mon Sep 17 00:00:00 2001 From: titiger Date: Fri, 17 Jan 2014 23:14:40 +0100 Subject: [PATCH 07/17] newest blender exporter from Yggdrasil (thanks!!) . Works with blender 2.69 and later and fixes a serious bug with normals and too many exported vertices. --- source/tools/glexemel/g3d_support_b269.py | 920 ++++++++++++++++++++++ 1 file changed, 920 insertions(+) create mode 100644 source/tools/glexemel/g3d_support_b269.py diff --git a/source/tools/glexemel/g3d_support_b269.py b/source/tools/glexemel/g3d_support_b269.py new file mode 100644 index 00000000..ffa52d1c --- /dev/null +++ b/source/tools/glexemel/g3d_support_b269.py @@ -0,0 +1,920 @@ +# -*- coding: utf-8 -*- + +########################################################################### +# Glest Model / Texture / UV / Animation Importer and Exporter +# for the Game Glest that u can find http://www.glest.org +# copyright 2005 By Andreas Becker (seltsamuel@yahoo.de) +# +# 2011/05/25: v0.1 alpha1 +# modified by William Zheng for Blender 2.57(loveheaven_zhengwei@hotmail.com) +# +# corrected by MrPostiga for Blender 2.58 +# +# extended by Yggdrasil +# +# Started Date: 07 June 2005 Put Public 20 June 2005 +# Distributed under the GNU PUBLIC LICENSE +#""" +#Here an explanation of the V4 Format found at www.glest.org +#================================ +#1. DATA TYPES +#================================ +#G3D files use the following data types: +#uint8: 8 bit unsigned integer +#uint16: 16 bit unsigned integer +#uint32: 32 bit unsigned integer +#float32: 32 bit floating point +#================================ +#2. OVERALL STRUCTURE +#================================ +#- File header +#- Model header +#- Mesh header +#- Texture names +#- Mesh data +#================================ +#2. FILE HEADER +#================================ +#Code: +#struct FileHeader{ +# uint8 id[3]; +# uint8 version; +#}; +#This header is shared among all the versions of G3D, it identifies this file as a G3D model and provides information of the version. +#id: must be "G3D" +#version: must be 4, in binary (not '4') +#================================ +#3. MODEL HEADER +#================================ +#Code: +#struct ModelHeader{ +# uint16 meshCount; +# uint8 type; +#}; +#meshCount: number of meshes in this model +#type: must be 0 +#================================ +#4. MESH HEADER +#================================ +#There is a mesh header for each mesh, there must be "meshCount" headers in a file but they are not consecutive, texture names and mesh data are stored in between. +#Code: +#struct MeshHeader{ +# uint8 name[64]; +# uint32 frameCount; +# uint32 vertexCount; +# uint32 indexCount; +# float32 diffuseColor[3]; +# float32 specularColor[3]; +# float32 specularPower; +# float32 opacity; +# uint32 properties; +# uint32 textures; +#}; +#name: name of the mesh +#frameCount: number of keyframes in this mesh +#vertexCount: number of vertices in each frame +#indexCount: number of indices in this mesh (the number of triangles is indexCount/3) +#diffuseColor: RGB diffuse color +#specularColor: RGB specular color (currently unused) +#specularPower: specular power (currently unused) +##properties: property flags +#Code: +#enum MeshPropertyFlag{ +# mpfCustomColor= 1, +# mpfTwoSided= 2, +# mpfNoSelect= 4 +#}; +#mpfTwoSided: meshes in this mesh are rendered by both sides, if this flag is not present only "counter clockwise" faces are rendered +#mpfCustomColor: alpha in this model is replaced by a custom color, usually the player color +#textures: texture flags +#Code: +#enum MeshTexture{ +# diffuse = 1, +# specular = 2, +# normal = 4 +#}; +#================================ +#4. TEXTURE NAMES +#================================ +#A list of uint8[64] texture name values. One for each texture in the mesh. If there are no textures in the mesh no texture names are present. +#================================ +#5. MESH DATA +#================================ +#After each mesh header and texture names the mesh data is placed. +#vertices: frameCount * vertexCount * 3, float32 values representing the x, y, z vertex coords for all frames +#normals: frameCount * vertexCount * 3, float32 values representing the x, y, z normal coords for all frames +#texture coords: vertexCount * 2, float32 values representing the s, t tex coords for all frames (only present if the mesh has 1 texture at least) +#indices: indexCount, uint32 values representing the indices +########################################################################### + +bl_info = { + "name": "G3D Mesh Import/Export", + "description": "Import/Export .g3d file (Glest 3D)", + "author": "various, see head of script", + "version": (0, 11, 1), + "blender": (2, 65, 0), + "location": "File > Import-Export", + "warning": "always keep .blend files", + "wiki_url": "http://glest.wikia.com/wiki/G3D_support", + "tracker_url": "https://forum.megaglest.org/index.php?topic=6596", + "category": "Import-Export"} +########################################################################### +# Importing Structures needed (must later verify if i need them really all) +########################################################################### +import bpy +from bpy.props import StringProperty +from bpy_extras.image_utils import load_image +from bpy_extras.io_utils import ImportHelper, ExportHelper +import bmesh + +import sys, struct, string, types +from types import * +import os +from os import path +from os.path import dirname, abspath + +import subprocess +from mathutils import Matrix +from math import radians +########################################################################### +# Variables that are better Global to handle +########################################################################### +imported = [] #List of all imported Objects +toexport = [] #List of Objects to export (actually only meshes) +sceneID = None #Points to the active Blender Scene +def unpack_list(list_of_tuples): + l = [] + for t in list_of_tuples: + l.extend(t) + return l +########################################################################### +# Declaring Structures of G3D Format +########################################################################### +class G3DHeader: #Read first 4 Bytes of file should be G3D + Versionnumber + binary_format = "<3cB" + def __init__(self, fileID): + temp = fileID.read(struct.calcsize(self.binary_format)) + data = struct.unpack(self.binary_format,temp) + self.id = str(data[0]+data[1]+data[2], "utf-8") + self.version = data[3] + +class G3DModelHeaderv3: #Read Modelheader in V3 there is only the number of Meshes in file + binary_format = "> 3 + while tex: + tex &= tex - 1 # set rightmost 1-bit to 0 + # discard texture name, as we don't know what to do with it + fileID.seek(struct.calcsize(self.texname_format)) + print("warning: ignored texture in undefined texture slot") + +class G3DMeshdataV3: #Calculate and read the Mesh Datapack + def __init__(self,fileID,header): + #Calculation of the Meshdatasize to load because its variable + #Animationframes * Vertices per Animation * 3 (Each Point are 3 Float X Y Z Coordinates) + vertex_format = "<%if" % int(header.framecount * header.vertexcount * 3) + #The same for Normals + normals_format = "<%if" % int(header.normalframecount * header.vertexcount * 3) + #Same here but Textures are 2D so only 2 Floats needed for Position inside Texture Bitmap + texturecoords_format = "<%if" % int(header.texturecoordframecount * header.vertexcount * 2) + #Colors in format RGBA + colors_format = "<%if" % int(header.colorframecount * 4) + #Indices + indices_format = "<%iI" % int(header.indexcount) + #Load the Meshdata as calculated above + self.vertices = struct.unpack(vertex_format,fileID.read(struct.calcsize(vertex_format))) + self.normals = struct.unpack(normals_format,fileID.read(struct.calcsize(normals_format))) + self.texturecoords = struct.unpack(texturecoords_format,fileID.read(struct.calcsize(texturecoords_format))) + self.colors = struct.unpack(colors_format,fileID.read(struct.calcsize(colors_format))) + self.indices = struct.unpack(indices_format ,fileID.read(struct.calcsize(indices_format))) + +class G3DMeshdataV4: #Calculate and read the Mesh Datapack + def __init__(self,fileID,header): + #Calculation of the Meshdatasize to load because its variable + #Animationframes * Points (Vertex) per Animation * 3 (Each Point are 3 Float X Y Z Coordinates) + vertex_format = "<%if" % int(header.framecount * header.vertexcount * 3) + #The same for Normals + normals_format = "<%if" % int(header.framecount * header.vertexcount * 3) + #Same here but Textures are 2D so only 2 Floats needed for Position inside Texture Bitmap + texturecoords_format = "<%if" % int(header.vertexcount * 2) + #Indices + indices_format = "<%iI" % int(header.indexcount) + #Load the Meshdata as calculated above + self.vertices = struct.unpack(vertex_format,fileID.read(struct.calcsize(vertex_format))) + self.normals = struct.unpack(normals_format,fileID.read(struct.calcsize(normals_format))) + if header.hastexture: + self.texturecoords = struct.unpack(texturecoords_format,fileID.read(struct.calcsize(texturecoords_format))) + self.indices = struct.unpack(indices_format ,fileID.read(struct.calcsize(indices_format))) + +#Create a Mesh inside Blender +def createMesh(filename, header, data, toblender, operator): + mesh = bpy.data.meshes.new(header.meshname) #New Mesh + meshobj = bpy.data.objects.new(header.meshname+'Object', mesh) #New Object for the new Mesh + scene = bpy.context.scene + scene.objects.link(meshobj) + scene.update() + uvcoords = [] + img_diffuse = None + img_specular = None + img_normal = None + if header.hastexture: #Load Texture when assigned + try: + texturefile = dirname(abspath(filename)) + os.sep + header.diffusetexture + img_diffuse = bpy.data.images.load(texturefile) + for x in range(0,len(data.texturecoords),2): #Prepare the UV + uvcoords.append([data.texturecoords[x],data.texturecoords[x+1]]) + + if header.isv4: + if header.speculartexture: + texturefile = dirname(abspath(filename)) + os.sep + header.speculartexture + img_specular = bpy.data.images.load(texturefile) + if header.normaltexture: + texturefile = dirname(abspath(filename)) + os.sep + header.normaltexture + img_normal = bpy.data.images.load(texturefile) + except: + import traceback + traceback.print_exc() + + header.hastexture = False + operator.report({'WARNING'}, "Couldn't load texture. See console for details.") + + vertsCO = [] + vertsNormal = [] + for x in range(0,header.vertexcount*3,3): #Get the Vertices and Normals into empty Mesh + vertsCO.extend([(data.vertices[x],data.vertices[x+1],data.vertices[x+2])]) + vertsNormal.extend([(data.normals[x],data.normals[x+1],data.normals[x+2])]) + #vertsCO.extend([(data.vertices[x+(header.framecount-1)*header.vertexcount*3],data.vertices[x+(header.framecount-1)*header.vertexcount*3+1],data.vertices[x+(header.framecount-1)*header.vertexcount*3+2])]) + #vertsNormal.extend([(data.normals[x+(header.framecount-1)*header.vertexcount*3],data.normals[x+(header.framecount-1)*header.vertexcount*3+1],data.normals[x+(header.framecount-1)*header.vertexcount*3+2])]) + mesh.vertices.add(len(vertsCO)) + mesh.vertices.foreach_set("co", unpack_list(vertsCO)) + mesh.vertices.foreach_set("normal", unpack_list(vertsNormal)) + + faces = [] + faceuv = [] + for i in range(0,len(data.indices),3): #Build Faces into Mesh + faces.extend([data.indices[i], data.indices[i+1], data.indices[i+2], 0]) + if header.hastexture: + uv = [] + u0 = uvcoords[data.indices[i]][0] + v0 = uvcoords[data.indices[i]][1] + uv.append([u0,v0]) + u1 = uvcoords[data.indices[i+1]][0] + v1 = uvcoords[data.indices[i+1]][1] + uv.append([u1,v1]) + u2 = uvcoords[data.indices[i+2]][0] + v2 = uvcoords[data.indices[i+2]][1] + uv.append([u2,v2]) + faceuv.append([uv,0,0,0]) + else: + uv = [] + uv.append([0,0]) + uv.append([0,0]) + uv.append([0,0]) + faceuv.append([uv,0,0,0]) + mesh.tessfaces.add(len(faces)//4) + mesh.tessfaces.foreach_set("vertices_raw", faces) + mesh.tessfaces.foreach_set("use_smooth", [True] * len(mesh.tessfaces)) + mesh.g3d_customColor = header.customalpha + mesh.show_double_sided = header.istwosided + if header.isv4: + mesh.g3d_noSelect = header.noselect + else: + mesh.g3d_noSelect = False + mesh.g3d_fullyOpaque = False + #=================================================================================================== + #Material Setup + #=================================================================================================== + def addtexslot(matdata,index,name,img): + texture = bpy.data.textures.new(name=name,type='IMAGE') + texture.image = img + slot = matdata.texture_slots.create(index) + slot.texture = texture + slot.texture_coords = 'UV' + + if header.hastexture: + materialname = "pskmat" + materials = [] + matdata = bpy.data.materials.new(materialname + '1') + + addtexslot(matdata, 0, 'diffusetexture', img_diffuse) + if img_specular: + addtexslot(matdata, 1, 'speculartexture', img_specular) + if img_normal: + addtexslot(matdata, 2, 'normaltexture', img_normal) + + if header.isv4: + matdata.diffuse_color = (header.diffusecolor[0], header.diffusecolor[1],header.diffusecolor[2]) + matdata.alpha = header.opacity + matdata.specular_color = (header.specularcolor[0], header.specularcolor[1],header.specularcolor[2]) + materials.append(matdata) + + for material in materials: + #add material to the mesh list of materials + mesh.materials.append(material) + + countm = 0 + psktexname="psk" + str(countm) + mesh.tessface_uv_textures.new(name=psktexname) + if (len(faceuv) > 0): + for countm in range(len(mesh.tessface_uv_textures)): + uvtex = mesh.tessface_uv_textures[countm] #add one uv texture + for i, face in enumerate(mesh.tessfaces): + blender_tface = uvtex.data[i] #face + mfaceuv = faceuv[i] + if countm == faceuv[i][1]: + face.material_index = faceuv[i][1] + blender_tface.uv1 = mfaceuv[0][0] #uv = (0,0) + blender_tface.uv2 = mfaceuv[0][1] #uv = (0,0) + blender_tface.uv3 = mfaceuv[0][2] #uv = (0,0) + blender_tface.image = img_diffuse + else: + blender_tface.uv1 = [0,0] + blender_tface.uv2 = [0,0] + blender_tface.uv3 = [0,0] + imported.append(meshobj) #Add to Imported Objects + sk = meshobj.shape_key_add() + for x in range(1,header.framecount): #Put in Vertex Positions for Keyanimation + sk = meshobj.shape_key_add() + for i in range(0,header.vertexcount*3,3): + sk.data[i//3].co[0]= data.vertices[x*header.vertexcount*3 + i] + sk.data[i//3].co[1]= data.vertices[x*header.vertexcount*3 + i +1] + sk.data[i//3].co[2]= data.vertices[x*header.vertexcount*3 + i +2] + + # activate one shapekey per frame + for i in range(1,header.framecount): + shape = mesh.shape_keys.key_blocks[i] + shape.value = 0.0 + shape.keyframe_insert("value", frame=i) + shape.value = 1.0 + shape.keyframe_insert("value", frame=(i+1)) + shape.value = 0.0 + shape.keyframe_insert("value", frame=(i+2)) + + meshobj.active_shape_key_index = 0 + + if toblender: + # rotate from glest to blender orientation + #mesh.transform( Matrix( ((1,0,0,0),(0,0,-1,0),(0,1,0,0),(0,0,0,1)) ) ) + # doesn't work, maybe because of shape keys + # use object transformation instead + meshobj.rotation_euler = (radians(90), 0, 0) + + # update polygon structures from tessfaces + mesh.update() + mesh.update_tag() + + # remove duplicates + bm = bmesh.new() + bm.from_mesh(mesh) + bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.0001) + bm.to_mesh(mesh) + bm.free() + + return +########################################################################### +# Import +########################################################################### +def G3DLoader(filepath, toblender, operator): #Main Import Routine + global imported, sceneID + print ("\nNow Importing File: " + filepath) + fileID = open(filepath,"rb") + header = G3DHeader(fileID) + print ("\nHeader ID : " + header.id) + print ("Version : " + str(header.version)) + if header.id != "G3D": + print ("ERROR: This is Not a G3D Model File") + operator.report({'ERROR'}, "This is Not a G3D Model File") + fileID.close + return + if header.version not in (3, 4): + print ("ERROR: The Version of this G3D File is not Supported") + operator.report({'ERROR'}, "The Version of this G3D File is not Supported") + fileID.close + return + #in_editmode = Blender.Window.EditMode() #Must leave Editmode when active + #if in_editmode: Blender.Window.EditMode(0) + sceneID = bpy.context.scene #Get active Scene + #scenecontext=sceneID.getRenderingContext() #To Access the Start/Endframe its so hidden i searched till i got angry :-) + basename=os.path.basename(filepath).split('.')[0] #Generate the Base Filename without Path + extension + imported = [] + maxframe=0 + if header.version == 3: + modelheader = G3DModelHeaderv3(fileID) + print ("Number of Meshes : " + str(modelheader.meshcount)) + for x in range(modelheader.meshcount): + meshheader = G3DMeshHeaderv3(fileID) + meshheader.isv4 = False + print ("\nMesh Number : " + str(x+1)) + print ("framecount : " + str(meshheader.framecount)) + print ("normalframecount : " + str(meshheader.normalframecount)) + print ("texturecoordframecount: " + str(meshheader.texturecoordframecount)) + print ("colorframecount : " + str(meshheader.colorframecount)) + print ("pointcount : " + str(meshheader.vertexcount)) + print ("indexcount : " + str(meshheader.indexcount)) + print ("texturename : " + str(meshheader.diffusetexture)) + print ("hastexture : " + str(meshheader.hastexture)) + print ("istwosided : " + str(meshheader.istwosided)) + print ("customalpha : " + str(meshheader.customalpha)) + meshheader.meshname = basename+str(x+1) #Generate Meshname because V3 has none + if meshheader.framecount > maxframe: maxframe = meshheader.framecount #Evaluate the maximal animationsteps + meshdata = G3DMeshdataV3(fileID,meshheader) + createMesh(filepath, meshheader, meshdata, toblender, operator) + fileID.close + bpy.context.scene.frame_start=1 + bpy.context.scene.frame_end=maxframe + bpy.context.scene.frame_current=1 + anchor = bpy.data.objects.new('Empty', None) + anchor.select = True + bpy.context.scene.objects.link(anchor) + for ob in imported: + ob.parent = anchor + bpy.context.scene.update() + return + if header.version == 4: + modelheader = G3DModelHeaderv4(fileID) + print ("Number of Meshes : " + str(modelheader.meshcount)) + for x in range(modelheader.meshcount): + meshheader = G3DMeshHeaderv4(fileID) + meshheader.isv4 = True + print ("\nMesh Number : " + str(x+1)) + print ("meshname : " + str(meshheader.meshname)) + print ("framecount : " + str(meshheader.framecount)) + print ("vertexcount : " + str(meshheader.vertexcount)) + print ("indexcount : " + str(meshheader.indexcount)) + print ("diffusecolor : %1.6f %1.6f %1.6f" %meshheader.diffusecolor) + print ("specularcolor : %1.6f %1.6f %1.6f" %meshheader.specularcolor) + print ("specularpower : %1.6f" %meshheader.specularpower) + print ("opacity : %1.6f" %meshheader.opacity) + print ("properties : " + str(meshheader.properties)) + print ("textures : " + str(meshheader.textures)) + print ("texturename : " + str(meshheader.diffusetexture)) + if len(meshheader.meshname) ==0: #When no Meshname in File Generate one + meshheader.meshname = basename+str(x+1) + if meshheader.framecount > maxframe: maxframe = meshheader.framecount #Evaluate the maximal animationsteps + meshdata = G3DMeshdataV4(fileID,meshheader) + createMesh(filepath, meshheader, meshdata, toblender, operator) + fileID.close + + bpy.context.scene.frame_start=1 + bpy.context.scene.frame_end=maxframe + bpy.context.scene.frame_current=1 + anchor = bpy.data.objects.new('Empty', None) + anchor.select = True + bpy.context.scene.objects.link(anchor) + for ob in imported: + ob.parent = anchor + bpy.context.scene.update() + print ("Created a empty Object as 'Grip' where all imported Objects are parented to") + print ("To move the complete Meshes only select this empty Object and move it") + print ("All Done, have a good Day :-)\n\n") + return + +def G3DSaver(filepath, context, toglest, operator): + print ("\nNow Exporting File: " + filepath) + + objs = context.selected_objects + if len(objs) == 0: + objs = bpy.data.objects + + #get real meshcount as len(bpy.data.meshes) holds also old meshes + meshCount = 0 + for obj in objs: + if obj.type == 'MESH': + meshCount += 1 + if obj.mode != 'OBJECT': # we want to be in object mode + print("ERROR: mesh not in object mode") + operator.report({'ERROR'}, "mesh not in object mode") + return -1 + + if meshCount == 0: + print("ERROR: no meshes found") + operator.report({'ERROR'}, "no meshes found") + return -1 + + fileID = open(filepath,"wb") + # G3DHeader v4 + fileID.write(struct.pack("<3cB", b'G', b'3', b'D', 4)) + # G3DModelHeaderv4 + fileID.write(struct.pack(" 0: + # we have a texture, hopefully + material = mesh.materials[0] + slot = material.texture_slots[0] + # only look for other textures when we have diffuse + if slot and slot.texture.type=='IMAGE' and len(mesh.uv_textures)>0: + diffuseColor = material.diffuse_color + specularColor = material.specular_color + opacity = material.alpha + textures = 1 + texnames = [] + texnames.append(bpy.path.basename(slot.texture.image.filepath)) + # specular and normal + for i in range(1, 3): + slot = material.texture_slots[i] + if slot and slot.texture.type=='IMAGE': + texnames.append(bpy.path.basename(slot.texture.image.filepath)) + textures |= 1 << i + + else: + print("WARNING: first texture slot in first material isn't of type IMAGE or it's not unwrapped, texture ignored") + operator.report({'WARNING'}, "first texture slot in first material isn't of type IMAGE or it's not unwrapped, texture ignored") + #continue without texture + + meshname = mesh.name + frameCount = context.scene.frame_end - context.scene.frame_start +1 + realFaceCount = 0 # real face count (triangles) + indices=[] # list of indices + newverts=[] # list of vertex indices which need to be duplicated + uvlist = [] # list of texcoords + mesh.update(calc_tessface=True) # tesselate n-polygons to triangles & quads + if textures: + uvtex = mesh.tessface_uv_textures[0] + uvlist[:] = [[0]*2 for i in range(len(mesh.vertices))] + # blender allows to have multiple texcoords per vertex, + # in g3d format every vertex can only have one texcoord + # -> duplicate vertex + # the dictionary/map vdict collects all the stuff + # index to "unique" vertices from blender + # -> tuple( list of texcoords, list of indices to the duplicated vertex ) + vdict = dict() + nextIndex = len(mesh.vertices) + for face in mesh.tessfaces: + # when a vertex is duplicated it gets a new index, so the + # triple of indices describing the face is different too + faceindices = [] + realFaceCount += 1 + uvdata = uvtex.data[face.index] + for i in range(3): + #closure, got rid of copy&paste, still looking weird + def getTexCoords(): + nonlocal nextIndex, vdict, uvlist, newverts + vindex = face.vertices[i] + if vindex not in vdict: # new vertex -> add it + vdict[vindex] = [uvdata.uv[i]], [vindex] + uvlist[vindex] = uvdata.uv[i] # that's a (s,t)-pair + else: + found = False + idx = 0 + for ele in vdict[vindex][0]: + if uvdata.uv[i][0] == ele[0] and uvdata.uv[i][1] == ele[1]: + found = True + break + idx += 1 + if found: # same vertex and texcoord before + # it could be a different index now, the index of a new + # duplicated vertex + #vindex = vdict[vindex][1][ vdict[vindex][0].index(uvdata.uv[i]) ] + vindex = vdict[vindex][1][idx] + else: # same vertex as before but with different texcoord -> duplicate + vdict[vindex][0].append(uvdata.uv[i]) + vdict[vindex][1].append(nextIndex) + + # duplicate vertex because it takes part in different faces + # with different texcoords + newverts.append(vindex) + uvlist.append(uvdata.uv[i]) + # new index for the duplicated vertex + vindex = nextIndex + nextIndex += 1 + + faceindices.append(vindex) + getTexCoords() + indices.extend(faceindices) + + if len(face.vertices) == 4: + faceindices = [] + realFaceCount += 1 + for i in [0,2,3]: + getTexCoords() + indices.extend(faceindices) + else: + for face in mesh.tessfaces: + realFaceCount += 1 + indices.extend(face.vertices[0:3]) + if len(face.vertices) == 4: + realFaceCount += 1 + # new face because quad got split + indices.append(face.vertices[0]) + indices.append(face.vertices[2]) + indices.append(face.vertices[3]) + + + # abort when no triangles as it crashs g3dviewer + if realFaceCount == 0: + print("ERROR: no triangles found") + operator.report({'ERROR'}, "no triangles found") + fileID.close() + return -1 + indexCount = realFaceCount * 3 + vertexCount = len(mesh.vertices) + len(newverts) + specularPower = 9.999999 # unused, same as old exporter + properties = 0 + if mesh.g3d_customColor: + properties |= 1 + if mesh.show_double_sided: + properties |= 2 + if mesh.g3d_noSelect: + properties |= 4 + + #MeshData + vertices = [] + normals = [] + fcurrent = context.scene.frame_current + for i in range(context.scene.frame_start, context.scene.frame_end+1): + context.scene.frame_set(i) + #FIXME: not sure what's better: PREVIEW or RENDER settings + m = obj.to_mesh(context.scene, True, 'RENDER') + m.transform(obj.matrix_world) # apply object-mode transformations + + if toglest: + # rotate from blender to glest orientation + m.transform( Matrix( ((1,0,0,0),(0,0,1,0),(0,-1,0,0),(0,0,0,1)) ) ) + # transform normals too + m.calc_normals() + + for vertex in m.vertices: + vertices.extend(vertex.co) + normals.extend(vertex.normal) + + # duplicate vertices and corresponding normals, for every frame + for nv in newverts: + vertices.extend(m.vertices[nv].co) + normals.extend(m.vertices[nv].normal) + + context.scene.frame_set(fcurrent) + + if mesh.g3d_fullyOpaque: + opacity = 1.0 + + # MeshHeader + fileID.write(struct.pack("<64s3I8f2I", + bytes(meshname, "ascii"), + frameCount, vertexCount, indexCount, + diffuseColor[0], diffuseColor[1], diffuseColor[2], + specularColor[0], specularColor[1], specularColor[2], + specularPower, opacity, + properties, textures + )) + #Texture names + if textures: # only when we have textures + for i in range(len(texnames)): + fileID.write(struct.pack("<64s", bytes(texnames[i], "ascii"))) + + # see G3DMeshdataV4 + vertex_format = "<%if" % int(frameCount * vertexCount * 3) + normals_format = "<%if" % int(frameCount * vertexCount * 3) + texturecoords_format = "<%if" % int(vertexCount * 2) + indices_format = "<%iI" % int(indexCount) + + fileID.write(struct.pack(vertex_format, *vertices)) + fileID.write(struct.pack(normals_format, *normals)) + + # texcoords + if textures: # only when we have textures + texcoords = [] + for uv in uvlist: + texcoords.extend(uv) + fileID.write(struct.pack(texturecoords_format, *texcoords)) + + fileID.write(struct.pack(indices_format, *indices)) + + fileID.close() + return 0 + + +#---=== Register === +class G3DPanel(bpy.types.Panel): + #bl_idname = "OBJECT_PT_G3DPanel" + bl_label = "G3D properties" + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "data" + + @classmethod + def poll(cls, context): + return (context.object is not None and context.object.type == 'MESH') + + def draw(self, context): + self.layout.prop(context.object.data, "g3d_customColor") + self.layout.prop(context.object.data, "show_double_sided", text="double sided") + self.layout.prop(context.object.data, "g3d_noSelect") + self.layout.prop(context.object.data, "g3d_fullyOpaque") + +class ImportG3D(bpy.types.Operator, ImportHelper): + '''Load a G3D file''' + bl_idname = "importg3d.g3d" + bl_label = "Import G3D" + + filename_ext = ".g3d" + filter_glob = StringProperty(default="*.g3d", options={'HIDDEN'}) + + toblender = bpy.props.BoolProperty( + name="rotate to Blender orientation", + description="Rotate meshes from Glest to Blender orientation", + default=True) + + def execute(self, context): + try: + G3DLoader(self.filepath, self.toblender, self) + except: + import traceback + traceback.print_exc() + + return {'CANCELLED'} + + return {'FINISHED'} + +class ExportG3D(bpy.types.Operator, ExportHelper): + '''Save a G3D file''' + bl_idname = "exportg3d.g3d" + bl_label = "Export G3D" + + filename_ext = ".g3d" + filter_glob = StringProperty(default="*.g3d", options={'HIDDEN'}) + + #export options + showg3d = bpy.props.BoolProperty( + name="show G3D afterwards", + description=("Run g3dviewer to show G3D after export. " + "g3dviewer needs to be in the scripts directory, " + "otherwise the associated program of .g3d is run."), + default=False) + toglest = bpy.props.BoolProperty( + name="rotate to glest orientation", + description="Rotate meshes from Blender to Glest orientation", + default=True) + + def execute(self, context): + try: + res = G3DSaver(self.filepath, context, self.toglest, self) + if res==0 and self.showg3d: + print("opening g3dviewer with " + self.filepath) + scriptsdir = bpy.utils.script_path_user() + dname = os.path.dirname(self.filepath) + found = False + for f in os.listdir(scriptsdir): + if "g3dviewer" in f: + f = os.path.join(scriptsdir, f) + if os.path.isfile(f) and os.access(f, os.X_OK): + cmd = [f, self.filepath] + print(cmd) + subprocess.Popen(cmd, cwd=dname) + found = True + + # try default associated program + if not found: + if os.name == 'posix': + # xdg-open is only a shell script which delegates the job to a + # desktop specific program, e.g. if DE=kde than kde-open + # needs DE environment variable set, otherwise it just throws it + # at the browser, which is not very helpful + print("running xdg-open "+self.filepath) + subprocess.Popen(['xdg-open', self.filepath], cwd=dname) + elif os.name == 'mac': + subprocess.Popen(['open', self.filepath], cwd=dname) + elif os.name == 'nt': + #os.startfile(self.filepath) # no way to change dir + subprocess.Popen(['cmd', '/C', 'start', self.filepath], cwd=dname) + + except: + import traceback + traceback.print_exc() + + return {'CANCELLED'} + + return {'FINISHED'} + +def menu_func_import(self, context): + self.layout.operator(ImportG3D.bl_idname, text="Glest 3D File (.g3d)") + +def menu_func_export(self, context): + self.layout.operator(ExportG3D.bl_idname, text="Glest 3D File (.g3d)") + +def register(): + # custom mesh properties + bpy.types.Mesh.g3d_customColor = bpy.props.BoolProperty( + name="team color", + description="replace alpha channel of texture with team color") + bpy.types.Mesh.g3d_noSelect = bpy.props.BoolProperty( + name="non-selectable", + description="click on mesh doesn't select unit") + bpy.types.Mesh.g3d_fullyOpaque = bpy.props.BoolProperty( + name="fully opaque", + description="sets opacity to 1.0, ignoring what's set in materials") + + bpy.utils.register_module(__name__) + + bpy.types.INFO_MT_file_import.append(menu_func_import) + bpy.types.INFO_MT_file_export.append(menu_func_export) + + +def unregister(): + bpy.utils.unregister_module(__name__) + + bpy.types.INFO_MT_file_import.remove(menu_func_import) + bpy.types.INFO_MT_file_export.remove(menu_func_export) + +if __name__ == '__main__': + register() +# main() + + #for obj in bpy.data.objects: + # if obj.type == 'MESH': + # obj.select = True + # bpy.ops.object.delete() + #G3DLoader("import.g3d", True, None) + + #for obj in bpy.context.selected_objects: + # obj.select = False # deselect everything, so we get it all + #G3DSaver("test.g3d", bpy.context) + From 0078909bc144a456e7beba57a935041bd9ab2855 Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Fri, 17 Jan 2014 18:10:58 -0800 Subject: [PATCH 08/17] - added shortcut to megaglest menu folder to point to installation folder --- mk/windoze/Installer/MegaGlestInstaller.nsi | 1 + 1 file changed, 1 insertion(+) diff --git a/mk/windoze/Installer/MegaGlestInstaller.nsi b/mk/windoze/Installer/MegaGlestInstaller.nsi index 0d23cb06..f35aec3c 100644 --- a/mk/windoze/Installer/MegaGlestInstaller.nsi +++ b/mk/windoze/Installer/MegaGlestInstaller.nsi @@ -285,6 +285,7 @@ Section "Start Menu Shortcuts" CreateShortCut "$SMPROGRAMS\${APNAME}\${APNAME} Map Editor.lnk" "$INSTDIR\megaglest_editor.exe" "" "$INSTDIR\megaglest_editor.exe" 0 "" "" "${APNAME} MegaGlest Map Editor" CreateShortCut "$SMPROGRAMS\${APNAME}\${APNAME} G3D Viewer.lnk" "$INSTDIR\megaglest_g3dviewer.exe" "" "$INSTDIR\megaglest_g3dviewer.exe" 0 "" "" "${APNAME} MegaGlest G3D Viewer" + CreateShortCut "$SMPROGRAMS\${APNAME}\${APNAME} Main.lnk" "$INSTDIR" "" "" 0 "" "" "This folder is the ${APNAME} installation folder" CreateShortCut "$SMPROGRAMS\${APNAME}\${APNAME} User Data.lnk" "$APPDATA\megaglest" "" "" 0 "" "" "This folder contains downloaded data (such as mods) and your personal ${APNAME} configuration" SectionEnd From a690867bcd5da4527a904c9e49a4d5977d337043 Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Fri, 17 Jan 2014 18:57:18 -0800 Subject: [PATCH 09/17] - small update to release data source build script (different assumed path) --- mk/linux/makedata-source.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mk/linux/makedata-source.sh b/mk/linux/makedata-source.sh index 52a43032..d201ba09 100755 --- a/mk/linux/makedata-source.sh +++ b/mk/linux/makedata-source.sh @@ -14,6 +14,7 @@ PACKAGE="$RELEASENAME-$VERSION.tar.xz" CURRENTDIR="$(dirname $(readlink -f $0))" RELEASEDIR="$CURRENTDIR/release/$RELEASENAME-$VERSION/megaglest-$VERSION" SOURCEDIR="$CURRENTDIR/../../source/" +# Below we assume you have the data source contents root in a folder called: git-data-source/ REPODIR="$CURRENTDIR/../../../git-data-source/" echo "Creating data package in $RELEASEDIR" @@ -36,7 +37,7 @@ fi mkdir -p "$RELEASEDIR/data-source" cd "$RELEASEDIR/data-source" #svn export --force "$CURRENTDIR/../../../git-data-source" "$RELEASEDIR/data-source/" -git archive --remote ${REPODIR}/megaglest-data-source/ HEAD: | tar x +git archive --remote ${REPODIR}/ HEAD: | tar x cd "$CURRENTDIR" echo "creating $PACKAGE" From d6e7deb26ef5ff91767c8af2a7ffa385b8e2eb15 Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Fri, 17 Jan 2014 19:23:33 -0800 Subject: [PATCH 10/17] - bugfix for linux installer build script finding vlc folder --- mk/linux/mojosetup/megaglest-installer/make.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mk/linux/mojosetup/megaglest-installer/make.sh b/mk/linux/mojosetup/megaglest-installer/make.sh index b4ca9246..2fdb78c8 100755 --- a/mk/linux/mojosetup/megaglest-installer/make.sh +++ b/mk/linux/mojosetup/megaglest-installer/make.sh @@ -270,9 +270,11 @@ if [ $REPACKONLY -eq 0 ]; then copyGlestDeptsCmd="${INSTALL_ROOTDIR}makedeps_folder.sh megaglest" $copyGlestDeptsCmd + cd "$CURRENTDIR" + cd data LIBVLC_DIR_CHECK=$( ldd megaglest | grep "libvlc\." | sort -u | awk '{print $3}' ) if [ "$LIBVLC_DIR_CHECK" != '' ]; then - LIBVLC_DIR=$( $LIBVLC_DIR_CHECK | xargs dirname ) + LIBVLC_DIR=$( dirname $LIBVLC_DIR_CHECK ) fi echo LibVLC installed in [$LIBVLC_DIR] copying to lib/ From 4bada8fc5acb42d97e21ae8d246f91640ac0307e Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Fri, 17 Jan 2014 19:37:25 -0800 Subject: [PATCH 11/17] - updating game version to 3.9.1 in preparation for release --- mk/linux/mg-version.sh | 2 +- mk/linux/mojosetup/megaglest-installer/scripts/config.lua | 2 +- mk/windoze/Installer/MegaGlestInstaller.nsi | 4 ++-- mk/windoze/Installer/MegaGlestUpdater.nsi | 6 +++--- source/glest_game/facilities/game_util.cpp | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mk/linux/mg-version.sh b/mk/linux/mg-version.sh index 021829d4..6aded2e5 100755 --- a/mk/linux/mg-version.sh +++ b/mk/linux/mg-version.sh @@ -6,7 +6,7 @@ OLD_MG_VERSION=3.9.0 OLD_MG_VERSION_BINARY=3.9.0 -MG_VERSION=3.9.1-dev +MG_VERSION=3.9.1 if [ "$1" = "--oldversion" ]; then echo "$OLD_MG_VERSION" diff --git a/mk/linux/mojosetup/megaglest-installer/scripts/config.lua b/mk/linux/mojosetup/megaglest-installer/scripts/config.lua index dc2ef7c3..74fda0ec 100644 --- a/mk/linux/mojosetup/megaglest-installer/scripts/config.lua +++ b/mk/linux/mojosetup/megaglest-installer/scripts/config.lua @@ -1,5 +1,5 @@ local GAME_INSTALL_SIZE = 700000000; -local GAME_VERSION = "3.9.0"; +local GAME_VERSION = "3.9.1"; local _ = MojoSetup.translate diff --git a/mk/windoze/Installer/MegaGlestInstaller.nsi b/mk/windoze/Installer/MegaGlestInstaller.nsi index f35aec3c..2982812e 100644 --- a/mk/windoze/Installer/MegaGlestInstaller.nsi +++ b/mk/windoze/Installer/MegaGlestInstaller.nsi @@ -3,8 +3,8 @@ !define APNAME MegaGlest !define APNAME_OLD Mega-Glest -!define APVER_OLD 3.7.1 -!define APVER 3.9.0 +!define APVER_OLD 3.9.0 +!define APVER 3.9.1 Name "${APNAME} ${APVER}" SetCompressor /FINAL /SOLID lzma diff --git a/mk/windoze/Installer/MegaGlestUpdater.nsi b/mk/windoze/Installer/MegaGlestUpdater.nsi index 9e03d948..312029d0 100644 --- a/mk/windoze/Installer/MegaGlestUpdater.nsi +++ b/mk/windoze/Installer/MegaGlestUpdater.nsi @@ -2,10 +2,10 @@ ; General Attributes !define APNAME MegaGlest -!define APVER 3.9.0 +!define APVER 3.9.1 !define APNAME_OLD Mega-Glest -!define APVER_OLD 3.7.1 -!define APVER_UPDATE 3.9.0 +!define APVER_OLD 3.9.0 +!define APVER_UPDATE 3.9.1 Name "${APNAME} ${APVER_UPDATE}" SetCompressor /FINAL /SOLID lzma diff --git a/source/glest_game/facilities/game_util.cpp b/source/glest_game/facilities/game_util.cpp index b2d94bc6..df05dad9 100644 --- a/source/glest_game/facilities/game_util.cpp +++ b/source/glest_game/facilities/game_util.cpp @@ -27,7 +27,7 @@ using namespace Shared::Platform; namespace Glest { namespace Game { const char *mailString = " http://bugs.megaglest.org"; -const string glestVersionString = "v3.9.1-dev"; +const string glestVersionString = "v3.9.1"; #if defined(GITVERSION) const string GIT_RawRev = string(GITVERSION); const string GIT_Rev = string("Rev: ") + string(GITVERSION); From 4583b8d4bca890e7ceaee6a417964d083f29ce08 Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Fri, 17 Jan 2014 20:10:18 -0800 Subject: [PATCH 12/17] - bugfix for windows compile error for new particle feature from titi --- source/shared_lib/sources/graphics/particle.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/shared_lib/sources/graphics/particle.cpp b/source/shared_lib/sources/graphics/particle.cpp index 15503957..8b3a42cf 100644 --- a/source/shared_lib/sources/graphics/particle.cpp +++ b/source/shared_lib/sources/graphics/particle.cpp @@ -1163,7 +1163,7 @@ void UnitParticleSystem::initParticle(Particle *p, int particleIndex){ if(meshName!="" && unitModel!=NULL){ //printf("meshName set unitModel given\n"); bool foundMesh=false; - for(uint i=0; igetMeshCount() ; i++){ + for(unsigned int i=0; igetMeshCount() ; i++){ //printf("meshName=%s\n",unitModel->getMesh(i)->getName().c_str()); if(unitModel->getMesh(i)->getName()==meshName){ const InterpolationData *data=unitModel->getMesh(i)->getInterpolationData(); @@ -1178,7 +1178,7 @@ void UnitParticleSystem::initParticle(Particle *p, int particleIndex){ } if( foundMesh == false ) { string meshesFound=""; - for(uint i=0; igetMeshCount() ; i++){ + for(unsigned i=0; igetMeshCount() ; i++){ meshesFound+= unitModel->getMesh(i)->getName()+", "; } From daf96d2af6f167a50d23f4e2964f7a38cf0c6373 Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Fri, 17 Jan 2014 20:46:46 -0800 Subject: [PATCH 13/17] - added tar.exe to windows build process since it may be used for some build script in connection with git --- mk/windoze/build-mg-2010.bat | 1 + mk/windoze/build-mg-2012.bat | 1 + mk/windoze/getTools.vbs | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/mk/windoze/build-mg-2010.bat b/mk/windoze/build-mg-2010.bat index 8fa2e9bb..669df493 100644 --- a/mk/windoze/build-mg-2010.bat +++ b/mk/windoze/build-mg-2010.bat @@ -9,6 +9,7 @@ cd /d "%~dp0" ECHO Checking for windows binary runtime tools... if NOT EXIST ..\..\data\glest_game\7z.exe call cscript getTools.vbs if NOT EXIST ..\..\data\glest_game\7z.dll call cscript getTools.vbs +if NOT EXIST ..\..\data\glest_game\tar.exe call cscript getTools.vbs if NOT EXIST ..\..\data\glest_game\wget.exe call cscript getTools.vbs set depfolder=windows_deps diff --git a/mk/windoze/build-mg-2012.bat b/mk/windoze/build-mg-2012.bat index 7bae91cb..cc613246 100644 --- a/mk/windoze/build-mg-2012.bat +++ b/mk/windoze/build-mg-2012.bat @@ -16,6 +16,7 @@ cd /d "%~dp0" ECHO Checking for windows binary runtime tools... if NOT EXIST ..\..\data\glest_game\7z.exe call cscript getTools.vbs if NOT EXIST ..\..\data\glest_game\7z.dll call cscript getTools.vbs +if NOT EXIST ..\..\data\glest_game\tar.exe call cscript getTools.vbs if NOT EXIST ..\..\data\glest_game\wget.exe call cscript getTools.vbs set depfolder=windows_deps_2012 diff --git a/mk/windoze/getTools.vbs b/mk/windoze/getTools.vbs index 02a3f42a..e7f6fa98 100644 --- a/mk/windoze/getTools.vbs +++ b/mk/windoze/getTools.vbs @@ -106,3 +106,38 @@ If objXMLHTTP.Status = 200 Then End if Set objXMLHTTP = Nothing + +' Set your settings +strFileURL = "http://www.soft-haus.com/glest/tools/tar.exe" +strHDLocation = "..\..\data\glest_game\tar.exe" + +WScript.Echo "----------------------------------------" +WScript.Echo "About to download tar.exe from:" +WScript.Echo strFileURL & ", please wait..." + +' Fetch the file +Set objXMLHTTP = CreateObject("MSXML2.XMLHTTP") +objXMLHTTP.open "GET", strFileURL, false +objXMLHTTP.send() + +If objXMLHTTP.Status = 200 Then + Set objADOStream = CreateObject("ADODB.Stream") + objADOStream.Open + objADOStream.Type = 1 'adTypeBinary + + objADOStream.Write objXMLHTTP.ResponseBody + objADOStream.Position = 0 'Set the stream position to the start + + Set objFSO = Createobject("Scripting.FileSystemObject") + If objFSO.Fileexists(strHDLocation) Then objFSO.DeleteFile strHDLocation + Set objFSO = Nothing + + objADOStream.SaveToFile strHDLocation + objADOStream.Close + Set objADOStream = Nothing + WScript.Echo "tar.exe has been downloaded successfully to: " + WScript.Echo strHDLocation + WScript.Echo "----------------------------------------" +End if + +Set objXMLHTTP = Nothing From ef82c52495a9dee3f11c3d8a2b904337e41ff23e Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Fri, 17 Jan 2014 23:45:44 -0800 Subject: [PATCH 14/17] - update windows data archive script to use git --- mk/windoze/make-data-archive.bat | 78 +++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/mk/windoze/make-data-archive.bat b/mk/windoze/make-data-archive.bat index 6a53e1bd..2c6b9b97 100644 --- a/mk/windoze/make-data-archive.bat +++ b/mk/windoze/make-data-archive.bat @@ -31,37 +31,91 @@ set RELEASENAME=megaglest-standalone-data set PACKAGE=%RELEASENAME%-%mg_version%.7z set RELEASEDIR=release-data\%RELEASENAME%-%mg_version% set PROJDIR=..\..\ - +set REPODIR=%~dp0\..\..\ +set PATH=%path%;%~dp0..\..\data\glest_game rem to debug creating the archive only rem goto make_archive echo Creating data package in [%RELEASEDIR%] +if exist %RELEASEDIR% echo Cleaning previous release folder [%RELEASEDIR%] if exist %RELEASEDIR% rd /s /q %RELEASEDIR% mkdir %RELEASEDIR% rem copy data -echo copying data ... +echo Copying data ... mkdir %RELEASEDIR%\data\ -svn export --force ..\..\data\glest_game\data %RELEASEDIR%\data\ +cd /d %RELEASEDIR%\data\ +rem svn export --force ..\..\data\glest_game\data %RELEASEDIR%\data\ +echo GIT ARCHIVE data ... +git archive --remote %REPODIR%\data\glest_game\ HEAD:data | tar -x +cd /d "%~dp0" +rem pause + mkdir %RELEASEDIR%\docs\ -svn export --force ..\..\data\glest_game\docs %RELEASEDIR%\docs\ -svn export --force ..\..\data\glest_game\docs\CHANGELOG.txt %RELEASEDIR%\docs\CHANGELOG.txt -svn export --force ..\..\data\glest_game\docs\README.txt %RELEASEDIR%\docs\README.txt +cd /d %RELEASEDIR%\docs\ +rem svn export --force ..\..\data\glest_game\docs %RELEASEDIR%\docs\ +echo GIT ARCHIVE docs ... +git archive --remote %REPODIR%/data/glest_game/ HEAD:docs | tar -x +cd /d "%~dp0" + +cd /d %RELEASEDIR%\docs\ +rem svn export --force ..\..\data\glest_game\docs\CHANGELOG.txt %RELEASEDIR%\docs\CHANGELOG.txt +echo GIT ARCHIVE CHANGELOG.txt ... +git archive --remote %REPODIR% HEAD:docs/ CHANGELOG.txt | tar -x +cd /d "%~dp0" +rem pause + +cd /d %RELEASEDIR%\docs\ +rem svn export --force ..\..\data\glest_game\docs\README.txt %RELEASEDIR%\docs\README.txt +echo GIT ARCHIVE README.txt ... +git archive --remote %REPODIR% HEAD:docs/ README.txt | tar -x +cd /d "%~dp0" +rem pause + mkdir %RELEASEDIR%\maps\ -svn export --force ..\..\data\glest_game\maps %RELEASEDIR%\maps\ +cd /d %RELEASEDIR%\maps\ +rem svn export --force ..\..\data\glest_game\maps %RELEASEDIR%\maps\ +echo GIT ARCHIVE maps ... +git archive --remote %REPODIR%/data/glest_game/ HEAD:maps | tar -x +cd /d "%~dp0" + mkdir %RELEASEDIR%\scenarios\ -svn export --force ..\..\data\glest_game\scenarios %RELEASEDIR%\scenarios\ +cd /d %RELEASEDIR%\scenarios\ +rem svn export --force ..\..\data\glest_game\scenarios %RELEASEDIR%\scenarios\ +echo GIT ARCHIVE scenarios ... +git archive --remote %REPODIR%/data/glest_game/ HEAD:scenarios | tar -x +cd /d "%~dp0" + mkdir %RELEASEDIR%\techs\ -svn export --force ..\..\data\glest_game\techs %RELEASEDIR%\techs\ +cd /d %RELEASEDIR%\techs\ +rem svn export --force ..\..\data\glest_game\techs %RELEASEDIR%\techs\ +echo GIT ARCHIVE techs ... +git archive --remote %REPODIR%/data/glest_game/ HEAD:techs | tar -x +cd /d "%~dp0" + mkdir %RELEASEDIR%\tilesets\ -svn export --force ..\..\data\glest_game\tilesets %RELEASEDIR%\tilesets\ +cd /d %RELEASEDIR%\tilesets\ +rem svn export --force ..\..\data\glest_game\tilesets %RELEASEDIR%\tilesets\ +echo GIT ARCHIVE tilesets ... +git archive --remote %REPODIR%/data/glest_game/ HEAD:tilesets | tar -x +cd /d "%~dp0" + mkdir %RELEASEDIR%\tutorials\ -svn export --force ..\..\data\glest_game\tutorials %RELEASEDIR%\tutorials\ +cd /d %RELEASEDIR%\tutorials\ +rem svn export --force ..\..\data\glest_game\tutorials %RELEASEDIR%\tutorials\ +echo GIT ARCHIVE tutorials ... +git archive --remote %REPODIR%/data/glest_game/ HEAD:tutorials | tar -x +cd /d "%~dp0" rem special export for flag images mkdir %RELEASEDIR%\data\core\misc_textures\flags\ -svn export --force ..\..\source\masterserver\flags %RELEASEDIR%\data\core\misc_textures\flags\ +cd /d %RELEASEDIR%\data\core\misc_textures\flags\ +rem svn export --force ..\..\source\masterserver\flags %RELEASEDIR%\data\core\misc_textures\flags\ +echo GIT ARCHIVE flags ... +git archive --remote %REPODIR% HEAD:source/masterserver/flags | tar -x +cd /d "%~dp0" + rem START rem remove embedded data From 2e5d6f8814343b305ecec0d559b0cdaf2c0fb13c Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Sat, 18 Jan 2014 00:54:34 -0800 Subject: [PATCH 15/17] - increase linux installer expanded byte size --- mk/linux/mojosetup/megaglest-installer/scripts/config.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/linux/mojosetup/megaglest-installer/scripts/config.lua b/mk/linux/mojosetup/megaglest-installer/scripts/config.lua index 74fda0ec..f5a63d2e 100644 --- a/mk/linux/mojosetup/megaglest-installer/scripts/config.lua +++ b/mk/linux/mojosetup/megaglest-installer/scripts/config.lua @@ -1,4 +1,4 @@ -local GAME_INSTALL_SIZE = 700000000; +local GAME_INSTALL_SIZE = 730000000; local GAME_VERSION = "3.9.1"; local _ = MojoSetup.translate From 318c700b8fdb8f49b3f61fbb58892982820c8e49 Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Sat, 18 Jan 2014 12:15:00 -0800 Subject: [PATCH 16/17] - more accurate pull of latest code from git --- data/glest_game | 2 +- mk/windoze/build-mg-2010.bat | 1 + mk/windoze/build-mg-2012.bat | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/data/glest_game b/data/glest_game index 4338c735..35d6e480 160000 --- a/data/glest_game +++ b/data/glest_game @@ -1 +1 @@ -Subproject commit 4338c735393e942cefd983b5bdffd92adf6a542d +Subproject commit 35d6e48036cd987fac66de9a2b92c8d5c818483d diff --git a/mk/windoze/build-mg-2010.bat b/mk/windoze/build-mg-2010.bat index 669df493..8895fc47 100644 --- a/mk/windoze/build-mg-2010.bat +++ b/mk/windoze/build-mg-2010.bat @@ -73,6 +73,7 @@ rem Update from GIT to latest rev ECHO -------------------------------- Echo Updating Code from GIT to latest Revision... cd ..\..\ +git submodule update git pull git submodule foreach git pull diff --git a/mk/windoze/build-mg-2012.bat b/mk/windoze/build-mg-2012.bat index cc613246..abe6672e 100644 --- a/mk/windoze/build-mg-2012.bat +++ b/mk/windoze/build-mg-2012.bat @@ -97,6 +97,7 @@ rem Update from GIT to latest rev ECHO -------------------------------- Echo Updating Code from GIT to latest Revision... cd ..\..\ +git submodule update git pull git submodule foreach git pull From 0b41ebca43be7d06734e51ce4551067f23602996 Mon Sep 17 00:00:00 2001 From: Tom Reynolds Date: Sat, 18 Jan 2014 21:24:13 +0100 Subject: [PATCH 17/17] ignore core files when committing --- .gitignore | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index cf9b832c..9901bc2c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,11 @@ *.un~ Session.vim MegaGlest.kdev4 +/mk/linux/mydata +/mk/linux/release +/mk/linux/linux_symbols +/mk/linux/core +/mk/linux/core.bak ## OSX Icon @@ -70,10 +75,6 @@ $RECYCLE.BIN/ /source/windows_deps_2010 /source/windows_deps_2010_old -/mk/linux/mydata -/mk/linux/release -/mk/linux/linux_symbols - # Coverity /cov-int /cov-int/.*