From 87f8777a6324d3d79d38826ba3a79b248a1bd38c Mon Sep 17 00:00:00 2001 From: i-nod Date: Sat, 6 Mar 2010 23:03:29 +0000 Subject: [PATCH 1/9] TCMask support infrastructure: mask loading and colour retrieval routines. Part of #851. git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@10178 4a71c877-e1ca-e34f-864e-861f7616d084 --- data/base/palette.txt | 8 ++++++ lib/ivis_common/bitimage.c | 2 +- lib/ivis_common/imd.h | 3 +++ lib/ivis_common/imdload.c | 25 +++++++++++++++++- lib/ivis_common/ivisdef.h | 2 ++ lib/ivis_common/piepalette.h | 22 ++++++++++++++-- lib/ivis_common/tex.h | 7 +++-- lib/ivis_opengl/piepalette.c | 40 +++++++++++++++++++++++++++++ lib/ivis_opengl/tex.c | 41 ++++++++++++++++++++++++----- src/data.c | 50 ++++++++++++++++++++++++++++++++---- 10 files changed, 183 insertions(+), 17 deletions(-) diff --git a/data/base/palette.txt b/data/base/palette.txt index 53a5afa4b..c3e7cc522 100644 --- a/data/base/palette.txt +++ b/data/base/palette.txt @@ -49,3 +49,11 @@ ff,50,50,ff // blueprint invalid a0,a0,0,ff // health medium shadow a0,0,0,ff // health low shadow 80,c0,ff,ff // health resistance +00,60,00,ff // team1 - green +A0,70,00,ff // team2 - orange +80,80,80,ff // team3 - gray +20,20,20,ff // team4 - black +80,00,00,ff // team5 - red +20,30,60,ff // team6 - blue +90,00,70,ff // team7 - purple +00,80,80,ff // team8 - teal diff --git a/lib/ivis_common/bitimage.c b/lib/ivis_common/bitimage.c index f52e1c15c..02a7ff219 100644 --- a/lib/ivis_common/bitimage.c +++ b/lib/ivis_common/bitimage.c @@ -48,7 +48,7 @@ static unsigned short LoadTextureFile(const char *FileName) } debug(LOG_TEXTURE, "LoadTextureFile: had to upload texture!"); - return pie_AddTexPage(pSprite, FileName, 0, 0); + return pie_AddTexPage(pSprite, FileName, 0, 0, true); } IMAGEFILE *iV_LoadImageFile(const char *fileName) diff --git a/lib/ivis_common/imd.h b/lib/ivis_common/imd.h index 02088f4b3..5a7f4fc3a 100644 --- a/lib/ivis_common/imd.h +++ b/lib/ivis_common/imd.h @@ -35,6 +35,9 @@ //************************************************************************* +// PIE model flags +#define iV_IMD_TCMASK 0x00010000 + // polygon flags b0..b7: col, b24..b31: anim index diff --git a/lib/ivis_common/imdload.c b/lib/ivis_common/imdload.c index fa440b03e..4c02123a2 100644 --- a/lib/ivis_common/imdload.c +++ b/lib/ivis_common/imdload.c @@ -515,6 +515,7 @@ static iIMDShape *_imd_load_level(const char **ppFileData, const char *FileDataE return NULL; } + s->flags = 0; s->nconnectors = 0; // Default number of connectors must be 0 s->npoints = 0; s->npolys = 0; @@ -527,6 +528,7 @@ static iIMDShape *_imd_load_level(const char **ppFileData, const char *FileDataE s->shadowEdgeList = NULL; s->nShadowEdges = 0; s->texpage = iV_TEX_INVALID; + s->tcmaskpage = iV_TEX_INVALID; if (sscanf(pFileData, "%s %d%n", buffer, &s->npoints, &cnt) != 2) @@ -620,7 +622,7 @@ iIMDShape *iV_ProcessIMD( const char **ppFileData, const char *FileDataEnd ) iIMDShape *shape, *psShape; UDWORD level; int32_t imd_version; - uint32_t imd_flags; // FIXME UNUSED + uint32_t imd_flags; BOOL bTextured = false; if (sscanf(pFileData, "%s %d%n", buffer, &imd_version, &cnt) != 2) @@ -753,6 +755,27 @@ iIMDShape *iV_ProcessIMD( const char **ppFileData, const char *FileDataEnd ) { psShape->texpage = texpage; } + + // check if model should use team colour mask + if (imd_flags & iV_IMD_TCMASK) + { + pie_MakeTexPageTCMaskName(texfile); + texpage = iV_GetTexture(texfile); + + if (texpage < 0) + { + ASSERT(false, "iV_ProcessIMD %s could not load tcmask %s", pFileName, texfile); + debug(LOG_ERROR, "iV_ProcessIMD %s could not load tcmask %s", pFileName, texfile); + } + else + { + shape->flags |= iV_IMD_TCMASK; + for (psShape = shape; psShape != NULL; psShape = psShape->next) + { + psShape->tcmaskpage = texpage; + } + } + } } *ppFileData = pFileData; diff --git a/lib/ivis_common/ivisdef.h b/lib/ivis_common/ivisdef.h index 63693807a..60175f4d6 100644 --- a/lib/ivis_common/ivisdef.h +++ b/lib/ivis_common/ivisdef.h @@ -84,7 +84,9 @@ typedef struct { } iIMDPoly; typedef struct _iIMDShape { + unsigned int flags; int texpage; + int tcmaskpage; int sradius, radius; Vector3f min, max; diff --git a/lib/ivis_common/piepalette.h b/lib/ivis_common/piepalette.h index b70122979..0221db4a7 100644 --- a/lib/ivis_common/piepalette.h +++ b/lib/ivis_common/piepalette.h @@ -63,7 +63,7 @@ #define WZCOL_CONS_TEXT_DEBUG psPalette[38] #define WZCOL_GREY psPalette[39] #define WZCOL_MAP_PREVIEW_AIPLAYER psPalette[40] -#define WZCOL_MENU_SHADOW psPalette[41] +#define WZCOL_MENU_SHADOW psPalette[41] #define WZCOL_DBLUE psPalette[42] #define WZCOL_LBLUE psPalette[43] #define WZCOL_BLUEPRINT_VALID psPalette[44] @@ -73,8 +73,16 @@ #define WZCOL_HEALTH_MEDIUM_SHADOW psPalette[48] #define WZCOL_HEALTH_LOW_SHADOW psPalette[49] #define WZCOL_HEALTH_RESISTANCE psPalette[50] +#define WZCOL_TEAM1 psPalette[51] +#define WZCOL_TEAM2 psPalette[52] +#define WZCOL_TEAM3 psPalette[53] +#define WZCOL_TEAM4 psPalette[54] +#define WZCOL_TEAM5 psPalette[55] +#define WZCOL_TEAM6 psPalette[56] +#define WZCOL_TEAM7 psPalette[57] +#define WZCOL_TEAM8 psPalette[58] -#define WZCOL_MAX 51 +#define WZCOL_MAX 59 //************************************************************************* @@ -84,6 +92,7 @@ extern PIELIGHT psPalette[]; extern void pal_Init(void); extern void pal_ShutDown(void); +extern PIELIGHT pal_GetTeamColour(int team); static inline PIELIGHT pal_Colour(UBYTE r, UBYTE g, UBYTE b) { @@ -122,4 +131,13 @@ static inline PIELIGHT pal_RGBA(UBYTE r, UBYTE g, UBYTE b, UBYTE a) return c; } + +static inline void pal_PIELIGHTtoRGBA4f(float *rgba4f, PIELIGHT rgba) +{ + rgba4f[0] = rgba.byte.r / 255.0; + rgba4f[1] = rgba.byte.g / 255.0; + rgba4f[2] = rgba.byte.b / 255.0; + rgba4f[3] = rgba.byte.a / 255.0; +} + #endif diff --git a/lib/ivis_common/tex.h b/lib/ivis_common/tex.h index 00754e159..9ed1bcf26 100644 --- a/lib/ivis_common/tex.h +++ b/lib/ivis_common/tex.h @@ -33,6 +33,8 @@ #define iV_TEX_INVALID -1 #define iV_TEXNAME_MAX 64 +#define iV_TEXNAME_TCSUFFIX "_tcmask" + //************************************************************************* #define iV_TEXNAME(i) ((char *) (&_TEX_PAGE[(i)].name)) @@ -56,13 +58,14 @@ extern int iV_GetTexture(const char *filename); extern void iV_unloadImage(iV_Image *image); extern unsigned int iV_getPixelFormat(const iV_Image *image); -extern int pie_ReplaceTexPage(iV_Image *s, const char *texPage, int maxTextureSize); -extern int pie_AddTexPage(iV_Image *s, const char *filename, int slot, int maxTextureSize); +extern int pie_ReplaceTexPage(iV_Image *s, const char *texPage, int maxTextureSize, bool useMipmaping); +extern int pie_AddTexPage(iV_Image *s, const char *filename, int slot, int maxTextureSize, bool useMipmaping); extern void pie_TexInit(void); extern void pie_InitSkybox(SDWORD pageNum); extern void pie_MakeTexPageName(char * filename); +extern void pie_MakeTexPageTCMaskName(char * filename); //************************************************************************* diff --git a/lib/ivis_opengl/piepalette.c b/lib/ivis_opengl/piepalette.c index 242de32d3..07e853723 100644 --- a/lib/ivis_opengl/piepalette.c +++ b/lib/ivis_opengl/piepalette.c @@ -58,3 +58,43 @@ void pal_ShutDown(void) { // placeholder } + +PIELIGHT pal_GetTeamColour(int team) +{ + PIELIGHT tcolour; + + // set correct team colour based on team + switch (team) + { + case 0: + tcolour = WZCOL_TEAM1; //green + break; + case 1: + tcolour = WZCOL_TEAM2; //orange + break; + case 2: + tcolour = WZCOL_TEAM3; //gray + break; + case 3: + tcolour = WZCOL_TEAM4; //black + break; + case 4: + tcolour = WZCOL_TEAM5; //red + break; + case 5: + tcolour = WZCOL_TEAM6; //blue + break; + case 6: + tcolour = WZCOL_TEAM7; //purple + break; + case 7: + tcolour = WZCOL_TEAM8; //teal + break; + default: + ASSERT(false, "Attempting to get colour for non-existing team %u", (unsigned int)team); + tcolour = WZCOL_WHITE; //default is white + break; + } + + return tcolour; +} \ No newline at end of file diff --git a/lib/ivis_opengl/tex.c b/lib/ivis_opengl/tex.c index 7a8f617ea..391611133 100644 --- a/lib/ivis_opengl/tex.c +++ b/lib/ivis_opengl/tex.c @@ -57,12 +57,13 @@ static void pie_PrintLoadedTextures(void); Returns the texture number of the image. **************************************************************************/ -int pie_AddTexPage(iV_Image *s, const char* filename, int slot, int maxTextureSize) +int pie_AddTexPage(iV_Image *s, const char* filename, int slot, int maxTextureSize, bool useMipmaping) { unsigned int i = 0; int width, height; void *bmp; bool scaleDown = false; + GLint minfilter; /* Have we already loaded this one? Should not happen here. */ while (i < _TEX_INDEX) @@ -130,14 +131,28 @@ int pie_AddTexPage(iV_Image *s, const char* filename, int slot, int maxTextureSi // this is an interface texture, do not use compression gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, width, height, iV_getPixelFormat(s), GL_UNSIGNED_BYTE, bmp); } - } else { + } + else + { debug(LOG_ERROR, "pie_AddTexPage: non POT texture %s", filename); } - free(bmp); // it is uploaded, we do not need it anymore + + // it is uploaded, we do not need it anymore + free(bmp); s->bmp = NULL; + if (useMipmaping) + { + minfilter = GL_LINEAR_MIPMAP_LINEAR; + } + else + { + minfilter = GL_LINEAR; + } + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Use anisotropic filtering, if available, but only max 4.0 to reduce processor burden @@ -181,6 +196,20 @@ void pie_MakeTexPageName(char * filename) } } +/*! + * Turns page filename into a pagename + tc mask if possible + * \param[in,out] filename Filename to pagify + */ +void pie_MakeTexPageTCMaskName(char * filename) +{ + if (strncmp(filename, "page-", 5) == 0) + { + int i; + for( i = 5; i < iV_TEXNAME_MAX-1 && isdigit(filename[i]); i++); + filename[i] = '\0'; + strcat(filename, iV_TEXNAME_TCSUFFIX); + } +} /*! * Print the names of all loaded textures to LOG_ERROR @@ -236,7 +265,7 @@ int iV_GetTexture(const char *filename) replaceing the texture page with the same name if another file with this prefix is loaded. **************************************************************************/ -int pie_ReplaceTexPage(iV_Image *s, const char *texPage, int maxTextureSize) +int pie_ReplaceTexPage(iV_Image *s, const char *texPage, int maxTextureSize, bool useMipmaping) { int i = iV_GetTexture(texPage); @@ -249,7 +278,7 @@ int pie_ReplaceTexPage(iV_Image *s, const char *texPage, int maxTextureSize) glDeleteTextures(1, &_TEX_PAGE[i].id); debug(LOG_TEXTURE, "Reloading texture %s from index %d", texPage, i); _TEX_PAGE[i].name[0] = '\0'; - pie_AddTexPage(s, texPage, i, maxTextureSize); + pie_AddTexPage(s, texPage, i, maxTextureSize, useMipmaping); return i; } diff --git a/src/data.c b/src/data.c index c7aac7f15..e662693b0 100644 --- a/src/data.c +++ b/src/data.c @@ -42,6 +42,9 @@ #include "text.h" #include "texture.h" +#define DT_TEXPAGE "TEXPAGE" +#define DT_TCMASK "TCMASK" + // whether a save game is currently being loaded static bool saveFlag = false; @@ -822,17 +825,53 @@ static bool dataTexPageLoad(const char *fileName, void **ppData) } // see if this texture page has already been loaded - if (resPresent("TEXPAGE", texpage)) + if (resPresent(DT_TEXPAGE, texpage)) { // replace the old texture page with the new one debug(LOG_TEXTURE, "replacing %s with new texture %s", texpage, fileName); - (void) pie_ReplaceTexPage(*ppData, texpage, getTextureSize()); + (void) pie_ReplaceTexPage(*ppData, texpage, getTextureSize(), true); } else { debug(LOG_TEXTURE, "adding page %s with texture %s", texpage, fileName); SetLastResourceFilename(texpage); - (void) pie_AddTexPage(*ppData, texpage, 0, getTextureSize()); + (void) pie_AddTexPage(*ppData, texpage, 0, getTextureSize(), true); + } + + return true; +} + +/* Load a team colour mask texturepage into memory */ +static BOOL dataTexPageTCMaskLoad(const char *fileName, void **ppData) +{ + char texpage[PATH_MAX] = {'\0'}; + + // This hackery is needed, because fileName will include the directory name, whilst the LastResourceFilename will not, and we need a short name to identify the texpage + sstrcpy(texpage, GetLastResourceFilename()); + + // Check if a corresponding texpage exists, exit if no + pie_MakeTexPageName(texpage); + ASSERT_OR_RETURN(false, resPresent(DT_TEXPAGE, texpage), "Corresponding texpage %s doesn't exists!", texpage); + + pie_MakeTexPageTCMaskName(texpage); + + if (!dataImageLoad(fileName, ppData)) + { + return false; + } + + // see if this texture page has already been loaded + if (resPresent(DT_TCMASK, texpage)) + { + // replace the old texture page with the new one + debug(LOG_TEXTURE, "replacing %s with new tcmask %s", texpage, fileName); + (void) pie_ReplaceTexPage(*ppData, texpage, getTextureSize(), false); + } + else + { + debug(LOG_TEXTURE, "adding page %s with tcmask %s", texpage, fileName); + SetLastResourceFilename(texpage); + (void) pie_AddTexPage(*ppData, texpage, 0, getTextureSize(), false); } return true; @@ -1149,11 +1188,12 @@ static const RES_TYPE_MIN_FILE FileResourceTypes[] = {"IMGPAGE", dataImageLoad, dataImageRelease}, {"TERTILES", dataTERTILESLoad, dataTERTILESRelease}, {"IMG", dataIMGLoad, dataIMGRelease}, - {"TEXPAGE", dataTexPageLoad, dataImageRelease}, + {DT_TEXPAGE, dataTexPageLoad, dataImageRelease}, + {DT_TCMASK, dataTexPageTCMaskLoad, dataImageRelease}, {"SCRIPT", dataScriptLoad, dataScriptRelease}, {"SCRIPTVAL", dataScriptLoadVals, NULL}, {"STR_RES", dataStrResLoad, dataStrResRelease}, - { "RESEARCHMSG", dataResearchMsgLoad, dataSMSGRelease }, + {"RESEARCHMSG", dataResearchMsgLoad, dataSMSGRelease }, }; /* Pass all the data loading functions to the framework library */ From 4ad78bf9b2ef7d2c58bc38954f1d6dbd98c3d092 Mon Sep 17 00:00:00 2001 From: i-nod Date: Sat, 6 Mar 2010 23:06:35 +0000 Subject: [PATCH 2/9] TCMask feature: shaders infrastructure and TCMask shader, FF fallback is supported for TCMask. Part of #851. git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@10179 4a71c877-e1ca-e34f-864e-861f7616d084 --- data/Makefile.am | 1 + data/base/shaders/tcmask.frag | 25 ++++ data/base/shaders/tcmask.vert | 20 ++++ data/makefile.win32 | 1 + lib/ivis_common/piedef.h | 7 +- lib/ivis_common/piestate.h | 24 ++++ lib/ivis_opengl/piedraw.c | 142 ++++++++++++++++++++-- lib/ivis_opengl/piestate.c | 220 ++++++++++++++++++++++++++++++++++ lib/ivis_opengl/screen.c | 106 +++++++++------- src/display3d.c | 20 +++- src/hci.c | 108 ++++++++++++++++- 11 files changed, 607 insertions(+), 67 deletions(-) create mode 100644 data/base/shaders/tcmask.frag create mode 100644 data/base/shaders/tcmask.vert diff --git a/data/Makefile.am b/data/Makefile.am index a65e30ab7..ecff6ebb1 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -23,6 +23,7 @@ BASELIST = \ multiplay \ script \ sequenceaudio \ + shaders\ stats \ structs \ tagdefinitions \ diff --git a/data/base/shaders/tcmask.frag b/data/base/shaders/tcmask.frag new file mode 100644 index 000000000..24af3d101 --- /dev/null +++ b/data/base/shaders/tcmask.frag @@ -0,0 +1,25 @@ +#pragma debug(on) + +varying float vertexDistance; +uniform sampler2D Texture0; +uniform sampler2D Texture1; +uniform vec4 teamcolour; + +void main(void) +{ + vec4 colour, mask; + + // Get color and tcmask information from TIUs 0-1 + colour = texture2D(Texture0, gl_TexCoord[0].st); + mask = texture2D(Texture1, gl_TexCoord[0].st); + + // Apply color using "Merge grain" within tcmask + colour = (colour + (teamcolour - 0.5) * mask.a) * gl_Color; + + // Calculate linear fog + float fogFactor = (gl_Fog.end - vertexDistance) / (gl_Fog.end - gl_Fog.start); + fogFactor = clamp(fogFactor, 0.0, 1.0); + + // Return fragment color + gl_FragColor = mix(gl_Fog.color, colour, fogFactor); +} \ No newline at end of file diff --git a/data/base/shaders/tcmask.vert b/data/base/shaders/tcmask.vert new file mode 100644 index 000000000..eaec3ecd6 --- /dev/null +++ b/data/base/shaders/tcmask.vert @@ -0,0 +1,20 @@ +#pragma debug(on) + +varying float vertexDistance; + +void main(void) +{ + // Pass vertex color information to fragment shader + gl_FrontColor = gl_Color; + + // Pass texture coordinates to fragment shader + gl_TexCoord[0] = gl_TextureMatrix [0] * gl_MultiTexCoord0; + + // Translate every vertex according to the Model View and Projection Matrix + //gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; + // Use "magic" fixed routine while using GLSL < 1.30 + gl_Position = ftransform(); + + // Remember vertex distance + vertexDistance = gl_Position.z; +} \ No newline at end of file diff --git a/data/makefile.win32 b/data/makefile.win32 index 5b02950dd..62336bd30 100644 --- a/data/makefile.win32 +++ b/data/makefile.win32 @@ -20,6 +20,7 @@ BASELIST= \ palette.txt \ script \ sequenceaudio \ + shaders\ stats \ structs \ tagdefinitions \ diff --git a/lib/ivis_common/piedef.h b/lib/ivis_common/piedef.h index a9b97fb5b..b8a969af4 100644 --- a/lib/ivis_common/piedef.h +++ b/lib/ivis_common/piedef.h @@ -93,19 +93,20 @@ typedef struct {SDWORD texPage; SWORD tu, tv, tw, th;} PIEIMAGE; /**< An area of * Global ProtoTypes */ /***************************************************************************/ -extern void pie_Draw3DShape(iIMDShape *shape, int frame, int team, PIELIGHT colour, PIELIGHT specular, int pieFlag, int pieData); +extern void pie_Draw3DShape(iIMDShape *shape, int frame, int team, PIELIGHT colour, PIELIGHT specular, int pieFlag, int pieFlagData); extern void pie_DrawImage(const PIEIMAGE *image, const PIERECT *dest); extern void pie_GetResetCounts(unsigned int* pPieCount, unsigned int* pTileCount, unsigned int* pPolyCount, unsigned int* pStateCount); /** Setup stencil shadows and OpenGL lighting. */ -void pie_BeginLighting(const Vector3f * light); +void pie_BeginLighting(const Vector3f * light, bool drawshadows); /* Stop using stencil shadows and OpenGL lighting (if enabled). */ void pie_EndLighting(void); void pie_RemainingPasses(void); -void pie_CleanUp( void ); +void pie_SetUp(void); +void pie_CleanUp(void); #endif // _piedef_h diff --git a/lib/ivis_common/piestate.h b/lib/ivis_common/piestate.h index 954fe1fe8..9ffa982dc 100644 --- a/lib/ivis_common/piestate.h +++ b/lib/ivis_common/piestate.h @@ -87,6 +87,13 @@ typedef enum TEXPAGE_FONT = -2 } TEXPAGE_TYPE; +typedef enum +{ + SHADER_NONE, + SHADER_TCMASK, + SHADER_MAX +} SHADER_MODE; + /***************************************************************************/ /* * Global Variables @@ -125,6 +132,23 @@ extern void pie_ShowMouse(bool visible); extern void pie_SetTranslucencyMode(TRANSLUCENCY_MODE transMode); +/* Actually in piestate.c */ + +// Shaders control center +extern bool pie_GetShadersStatus(void); +extern void pie_SetShadersStatus(bool); +bool pie_LoadShaders(void); +// Actual shaders (we do not want to export these calls) +void pie_DeactivateShader(void); +void pie_ActivateShader_TCMask(PIELIGHT teamcolour, SDWORD maskpage); + +/* Actually in piedraw.c */ + +// Lighting cotrols +extern void pie_SetLightingState(bool); +extern bool pie_GetLightingState(void); + +/* Errors control routine */ #define glErrors() \ _glerrors(__FUNCTION__, __FILE__, __LINE__) diff --git a/lib/ivis_opengl/piedraw.c b/lib/ivis_opengl/piedraw.c index cfe56bc15..a1197b9c0 100644 --- a/lib/ivis_opengl/piedraw.c +++ b/lib/ivis_opengl/piedraw.c @@ -32,6 +32,7 @@ #include "lib/ivis_common/tex.h" #include "lib/ivis_common/piedef.h" #include "lib/ivis_common/piestate.h" +#include "lib/ivis_common/piepalette.h" #include "lib/ivis_common/pieclip.h" #include "piematrix.h" #include "screen.h" @@ -54,14 +55,15 @@ extern BOOL drawing_interface; static unsigned int pieCount = 0; static unsigned int tileCount = 0; static unsigned int polyCount = 0; -static BOOL lighting = false; -static BOOL shadows = false; +static bool lighting = false; +static bool lightingstate = false; +static bool shadows = false; /* * Source */ -void pie_BeginLighting(const Vector3f * light) +void pie_BeginLighting(const Vector3f * light, bool drawshadows) { const float pos[4] = {light->x, light->y, light->z, 0.0f}; const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; @@ -77,8 +79,21 @@ void pie_BeginLighting(const Vector3f * light) glLightfv(GL_LIGHT0, GL_SPECULAR, specular); glEnable(GL_LIGHT0); -// lighting = true; - shadows = true; + lighting = lightingstate; + if (drawshadows) + { + shadows = true; + } +} + +bool pie_GetLightingState(void) +{ + return lightingstate; +} + +void pie_SetLightingState(bool val) +{ + lightingstate = val; } void pie_EndLighting(void) @@ -120,10 +135,10 @@ static transluscent_shape_t* tshapes = NULL; static unsigned int tshapes_size = 0; static unsigned int nb_tshapes = 0; -static void pie_Draw3DShape2(iIMDShape *shape, int frame, PIELIGHT colour, WZ_DECL_UNUSED PIELIGHT specular, int pieFlag, int pieFlagData) +static void pie_Draw3DShape2(iIMDShape *shape, int frame, PIELIGHT colour, PIELIGHT teamcolour, WZ_DECL_UNUSED PIELIGHT specular, int pieFlag, int pieFlagData) { iIMDPoly *pPolys; - BOOL light = lighting; + bool light = lighting; pie_SetAlphaTest(true); @@ -172,8 +187,6 @@ static void pie_Draw3DShape2(iIMDShape *shape, int frame, PIELIGHT colour, WZ_DE glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess); } - pie_SetTexturePage(shape->texpage); - if (pieFlag & pie_HEIGHT_SCALED) // construct { glScalef(1.0f, (float)pieFlagData / (float)pie_RAISE_SCALE, 1.0f); @@ -184,6 +197,72 @@ static void pie_Draw3DShape2(iIMDShape *shape, int frame, PIELIGHT colour, WZ_DE } glColor4ubv(colour.vector); // Only need to set once for entire model + pie_SetTexturePage(shape->texpage); + + // Activate TCMask if needed + if (shape->flags & iV_IMD_TCMASK && rendStates.rendMode == REND_OPAQUE) + { +#ifdef _DEBUG + glErrors(); +#endif + if (pie_GetShadersStatus()) + { + pie_ActivateShader_TCMask(teamcolour, shape->tcmaskpage); + } + else + { + //Set the environment colour with tcmask + GLfloat tc_env_colour[4]; + pal_PIELIGHTtoRGBA4f(&tc_env_colour[0], teamcolour); + + // TU0 + glActiveTexture(GL_TEXTURE0); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, tc_env_colour); + + // TU0 RGB + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD_SIGNED); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + + // TU0 Alpha + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + + // TU1 + glActiveTexture(GL_TEXTURE1); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, _TEX_PAGE[shape->tcmaskpage].id); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + + // TU1 RGB + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE0); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); + + // TU1 Alpha + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + + + // This is why we are doing in opaque mode. + glEnable(GL_BLEND); + glBlendFunc(GL_CONSTANT_COLOR, GL_ZERO); + glBlendColor(colour.byte.r / 255.0, colour.byte.g / 255.0, + colour.byte.b / 255.0, colour.byte.a / 255.0); + } +#ifdef _DEBUG + glErrors(); +#endif + } for (pPolys = shape->polys; pPolys < shape->polys + shape->npolys; pPolys++) { @@ -205,7 +284,8 @@ static void pie_Draw3DShape2(iIMDShape *shape, int frame, PIELIGHT colour, WZ_DE polyCount++; - if (frame != 0 && pPolys->flags & iV_IMD_TEXANIM) + // Run TextureAnimation (exluding the new teamcoloured models) + if (frame && pPolys->flags & iV_IMD_TEXANIM && !(shape->flags & iV_IMD_TCMASK)) { frame %= shape->numFrames; @@ -233,12 +313,37 @@ static void pie_Draw3DShape2(iIMDShape *shape, int frame, PIELIGHT colour, WZ_DE for (n = 0; n < pPolys->npnts; n++) { glTexCoord2fv((GLfloat*)&texCoords[n]); + if (shape->flags & iV_IMD_TCMASK && rendStates.rendMode == REND_OPAQUE && + !pie_GetShadersStatus()) + { + glMultiTexCoord2fv(GL_TEXTURE1, (GLfloat*)&texCoords[n]); + } glVertex3fv((GLfloat*)&vertexCoords[n]); } glEnd(); } + // Deactivate TCMask if it was previously enabled + if (shape->flags & iV_IMD_TCMASK && rendStates.rendMode == REND_OPAQUE) + { + if (pie_GetShadersStatus()) + { + pie_DeactivateShader(); + } + else + { + glDisable(GL_BLEND); + + glActiveTexture(GL_TEXTURE1); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glDisable(GL_TEXTURE_2D); + + glActiveTexture(GL_TEXTURE0); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } + } + if (pieFlag & pie_BUTTON) { pie_SetDepthBufferStatus(DEPTH_CMP_ALWAYS_WRT_ON); @@ -463,6 +568,11 @@ static void inverse_matrix(const float * src, float * dst) dst[8] = invdet * (src[0]*src[5] - src[4]*src[1]); } +void pie_SetUp(void) +{ + // initialise pie engine (just a placeholder for now) +} + void pie_CleanUp( void ) { free( tshapes ); @@ -473,7 +583,12 @@ void pie_CleanUp( void ) void pie_Draw3DShape(iIMDShape *shape, int frame, int team, PIELIGHT colour, PIELIGHT specular, int pieFlag, int pieFlagData) { + PIELIGHT teamcolour; + ASSERT_OR_RETURN(, shape, "Attempting to draw null sprite"); + + teamcolour = pal_GetTeamColour(team); + pieCount++; if (frame == 0) @@ -483,7 +598,7 @@ void pie_Draw3DShape(iIMDShape *shape, int frame, int team, PIELIGHT colour, PIE if (drawing_interface || !shadows) { - pie_Draw3DShape2(shape, frame, colour, specular, pieFlag, pieFlagData); + pie_Draw3DShape2(shape, frame, colour, teamcolour, specular, pieFlag, pieFlagData); } else { @@ -563,7 +678,8 @@ void pie_Draw3DShape(iIMDShape *shape, int frame, int team, PIELIGHT colour, PIE nb_scshapes++; } } - pie_Draw3DShape2(shape, frame, colour, specular, pieFlag, pieFlagData); + + pie_Draw3DShape2(shape, frame, colour, teamcolour, specular, pieFlag, pieFlagData); } } } @@ -688,7 +804,7 @@ static void pie_DrawRemainingTransShapes(void) for (i = 0; i < nb_tshapes; ++i) { glLoadMatrixf(tshapes[i].matrix); - pie_Draw3DShape2(tshapes[i].shape, tshapes[i].frame, tshapes[i].colour, + pie_Draw3DShape2(tshapes[i].shape, tshapes[i].frame, tshapes[i].colour, tshapes[i].colour, tshapes[i].specular, tshapes[i].flag, tshapes[i].flag_data); } glPopMatrix(); diff --git a/lib/ivis_opengl/piestate.c b/lib/ivis_opengl/piestate.c index be36e4884..786f55b07 100644 --- a/lib/ivis_opengl/piestate.c +++ b/lib/ivis_opengl/piestate.c @@ -26,12 +26,14 @@ #include #include +#include #include "lib/ivis_common/piestate.h" #include "lib/ivis_common/piedef.h" #include "lib/ivis_common/tex.h" #include "lib/ivis_common/piepalette.h" #include "lib/ivis_common/rendmode.h" +#include "screen.h" /* * Global Variables @@ -43,11 +45,229 @@ static bool ColouredMouse = false; static IMAGEFILE* MouseCursors = NULL; static uint16_t MouseCursorIDs[CURSOR_MAX]; static bool MouseVisible = true; +static GLuint shaderProgram[SHADER_MAX]; +static bool shadersAvailable = false; // Can we use shaders? +static bool shadersActivate = true; // If we can, should we use them? /* * Source */ +// Read shader into text buffer +static char *readShaderBuf(const char *name) +{ + PHYSFS_file *fp; + int filesize; + char *buffer; + + fp = PHYSFS_openRead(name); + debug(LOG_3D, "Reading...[directory: %s] %s", PHYSFS_getRealDir(name), name); + ASSERT_OR_RETURN(0, fp != NULL, "Could not open %s", name); + filesize = PHYSFS_fileLength(fp); + buffer = malloc(filesize + 1); + if (buffer) + { + PHYSFS_read(fp, buffer, 1, filesize); + buffer[filesize] = '\0'; + } + PHYSFS_close(fp); + + return buffer; +} + +// Retrieve shader compilation errors +static void printShaderInfoLog(GLuint shader) +{ + int infologLen = 0; + + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLen); + if (infologLen > 0) + { + int charsWritten = 0; + GLchar *infoLog = (GLchar *)malloc(infologLen); + + glGetShaderInfoLog(shader, infologLen, &charsWritten, infoLog); + debug(LOG_ERROR, "Shader info log: %s", infoLog); + free(infoLog); + } +} + +// Retrieve shader linkage errors +static void printProgramInfoLog(GLuint program) +{ + int infologLen = 0; + + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLen); + if (infologLen > 0) + { + int charsWritten = 0; + GLchar *infoLog = (GLchar *)malloc(infologLen); + + glGetProgramInfoLog(program, infologLen, &charsWritten, infoLog); + debug(LOG_ERROR, "Program info log: %s", infoLog); + free(infoLog); + } +} + +// Read/compile/link shaders +static bool loadShaders(GLuint *program, const char *vertexPath, const char *fragmentPath) +{ + GLint status; + bool success = true; // Assume overall success + char *buffer; + *program = glCreateProgram(); + + ASSERT_OR_RETURN(false, *program != 0, "Could not create shader program"); + + if (vertexPath) + { + success = false; // Assume failure before reading shader file + + if ((buffer = readShaderBuf(vertexPath))) + { + GLuint shader = glCreateShader(GL_VERTEX_SHADER); + + glShaderSource(shader, 1, (const char **)&buffer, NULL); + glCompileShader(shader); + + // Check for compilation errors + glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + if (!status) + { + debug(LOG_ERROR, "Vertex shader compilation has failed [%s]", vertexPath); + printShaderInfoLog(shader); + } + else + { + glAttachShader(*program, shader); + success = true; + } + + free(buffer); + } + } + + if (success && fragmentPath) + { + success = false; // Assume failure before reading shader file + + if ((buffer = readShaderBuf(fragmentPath))) + { + GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); + + glShaderSource(shader, 1, (const char **)&buffer, NULL); + glCompileShader(shader); + + // Check for compilation errors + glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + if (!status) + { + debug(LOG_ERROR, "Fragment shader compilation has failed [%s]", fragmentPath); + printShaderInfoLog(shader); + } + else + { + glAttachShader(*program, shader); + success = true; + } + + free(buffer); + } + } + + if (success) + { + glLinkProgram(*program); + + // Check for linkage errors + glGetProgramiv(*program, GL_LINK_STATUS, &status); + if (!status) + { + debug(LOG_ERROR, "Shader program linkage has failed [%s, %s]", vertexPath, fragmentPath); + printProgramInfoLog(*program); + success = false; + } + } + + return success; +} + +// Run from screen.c on init. FIXME: do some kind of FreeShaders on failure. +bool pie_LoadShaders() +{ + GLuint program; + + // Reset shaders status + shadersAvailable = false; + + // Try and load some shaders + shaderProgram[SHADER_NONE] = 0; + + // TCMask shader + debug(LOG_3D, "Loading shaders: SHADER_TCMASK"); + if (!loadShaders(&program, "shaders/tcmask.vert", "shaders/tcmask.frag")) + return false; + shaderProgram[SHADER_TCMASK] = program; + + // Good to go + shadersAvailable = true; + return true; +} + +static inline GLuint pie_SetShader(SHADER_MODE shaderMode) +{ + if (!shadersAvailable || shaderMode >= SHADER_MAX) + return shaderProgram[SHADER_NONE]; + + glUseProgram(shaderProgram[shaderMode]); + return shaderProgram[shaderMode]; +} + +void pie_DeactivateShader(void) +{ + pie_SetShader(SHADER_NONE); +} + +bool pie_GetShadersStatus(void) +{ + return shadersAvailable && shadersActivate; +} + +void pie_SetShadersStatus(bool status) +{ + shadersActivate = status; +} + +void pie_ActivateShader_TCMask(PIELIGHT teamcolour, SDWORD maskpage) +{ + GLint loc; + GLuint shaderProgram; + GLfloat colour4f[4]; + + if (!shadersAvailable) + return; + + shaderProgram = pie_SetShader(SHADER_TCMASK); + + loc = glGetUniformLocation(shaderProgram, "Texture0"); + glUniform1i(loc, 0); + + loc = glGetUniformLocation(shaderProgram, "Texture1"); + glUniform1i(loc, 1); + + loc = glGetUniformLocation(shaderProgram, "teamcolour"); + pal_PIELIGHTtoRGBA4f(&colour4f[0], teamcolour); + glUniform4fv(loc, 1, &colour4f[0]); + + glActiveTexture(GL_TEXTURE1); + pie_SetTexturePage(maskpage); + glActiveTexture(GL_TEXTURE0); + +#ifdef _DEBUG + glErrors(); +#endif +} + void pie_SetDepthBufferStatus(DEPTH_MODE depthMode) { switch(depthMode) diff --git a/lib/ivis_opengl/screen.c b/lib/ivis_opengl/screen.c index 9e7c3831e..b0dd797fd 100644 --- a/lib/ivis_opengl/screen.c +++ b/lib/ivis_opengl/screen.c @@ -78,6 +78,8 @@ bool screenInitialise( { static int video_flags = 0; int bpp = 0, value; + char buf[512]; + GLint glMaxTUs; /* Store the screen information */ screenWidth = width; @@ -162,51 +164,49 @@ bool screenInitialise( exit(1); } - { - char buf[256]; + /* Dump general information about OpenGL implementation to the console and the dump file */ + ssprintf(buf, "OpenGL Vendor : %s", glGetString(GL_VENDOR)); + addDumpInfo(buf); + debug(LOG_3D, buf); + ssprintf(buf, "OpenGL Renderer : %s", glGetString(GL_RENDERER)); + addDumpInfo(buf); + debug(LOG_3D, buf); + ssprintf(buf, "OpenGL Version : %s", glGetString(GL_VERSION)); + addDumpInfo(buf); + debug(LOG_3D, buf); + ssprintf(buf, "Video Mode %d x %d (%d bpp) (%s)", width, height, bpp, fullScreen ? "fullscreen" : "window"); + addDumpInfo(buf); + debug(LOG_3D, buf); - // Copy this info to be used by the crash handler for the dump file - ssprintf(buf, "OpenGL Vendor : %s", glGetString(GL_VENDOR)); - addDumpInfo(buf); - ssprintf(buf, "OpenGL Renderer : %s", glGetString(GL_RENDERER)); - addDumpInfo(buf); - ssprintf(buf, "OpenGL Version : %s", glGetString(GL_VERSION)); - addDumpInfo(buf); - if (GLEE_VERSION_2_0) - { - ssprintf(buf, "OpenGL GLSL Version : %s", glGetString(GL_SHADING_LANGUAGE_VERSION)); - addDumpInfo(buf); - } - ssprintf(buf, "Video Mode %d x %d (%d bpp) (%s)", width, height, bpp, fullScreen ? "fullscreen" : "window"); - addDumpInfo(buf); - /* Dump information about OpenGL implementation to the console */ - debug(LOG_3D, "OpenGL Vendor : %s", glGetString(GL_VENDOR)); - debug(LOG_3D, "OpenGL Renderer : %s", glGetString(GL_RENDERER)); - debug(LOG_3D, "OpenGL Version : %s", glGetString(GL_VERSION)); - debug(LOG_3D, "OpenGL Extensions : %s", glGetString(GL_EXTENSIONS)); // FIXME This is too much for MAX_LEN_LOG_LINE - debug(LOG_3D, "Supported OpenGL extensions:"); - debug(LOG_3D, " * OpenGL 1.2 %s supported!", GLEE_VERSION_1_2 ? "is" : "is NOT"); - debug(LOG_3D, " * OpenGL 1.3 %s supported!", GLEE_VERSION_1_3 ? "is" : "is NOT"); - debug(LOG_3D, " * OpenGL 1.4 %s supported!", GLEE_VERSION_1_4 ? "is" : "is NOT"); - debug(LOG_3D, " * OpenGL 1.5 %s supported!", GLEE_VERSION_1_5 ? "is" : "is NOT"); - debug(LOG_3D, " * OpenGL 2.0 %s supported!", GLEE_VERSION_2_0 ? "is" : "is NOT"); - debug(LOG_3D, " * OpenGL 2.1 %s supported!", GLEE_VERSION_2_1 ? "is" : "is NOT"); - debug(LOG_3D, " * OpenGL 3.0 %s supported!", GLEE_VERSION_3_0 ? "is" : "is NOT"); - debug(LOG_3D, " * Texture compression %s supported.", GLEE_ARB_texture_compression ? "is" : "is NOT"); - debug(LOG_3D, " * Two side stencil %s supported.", GLEE_EXT_stencil_two_side ? "is" : "is NOT"); - debug(LOG_3D, " * ATI separate stencil is%s supported.", GLEE_ATI_separate_stencil ? "" : " NOT"); - debug(LOG_3D, " * Stencil wrap %s supported.", GLEE_EXT_stencil_wrap ? "is" : "is NOT"); - debug(LOG_3D, " * Anisotropic filtering %s supported.", GLEE_EXT_texture_filter_anisotropic ? "is" : "is NOT"); - debug(LOG_3D, " * Rectangular texture %s supported.", GLEE_ARB_texture_rectangle ? "is" : "is NOT"); - debug(LOG_3D, " * FrameBuffer Object (FBO) %s supported.", GLEE_EXT_framebuffer_object ? "is" : "is NOT"); - debug(LOG_3D, " * Shader Objects %s supported.", GL_ARB_shader_objects ? "is" : "is NOT"); - debug(LOG_3D, " * Vertex Buffer Object (VBO) %s supported.", GL_ARB_vertex_buffer_object ? "is" : "is NOT"); - if (GLEE_VERSION_2_0) - { - debug(LOG_3D, " * OpenGL GLSL Version : %s", glGetString(GL_SHADING_LANGUAGE_VERSION)); - } - } + /* Dump extended information about OpenGL implementation to the console */ + debug(LOG_3D, "OpenGL Extensions : %s", glGetString(GL_EXTENSIONS)); // FIXME This is too much for MAX_LEN_LOG_LINE + debug(LOG_3D, "Supported OpenGL extensions:"); + debug(LOG_3D, " * OpenGL 1.2 %s supported!", GLEE_VERSION_1_2 ? "is" : "is NOT"); + debug(LOG_3D, " * OpenGL 1.3 %s supported!", GLEE_VERSION_1_3 ? "is" : "is NOT"); + debug(LOG_3D, " * OpenGL 1.4 %s supported!", GLEE_VERSION_1_4 ? "is" : "is NOT"); + debug(LOG_3D, " * OpenGL 1.5 %s supported!", GLEE_VERSION_1_5 ? "is" : "is NOT"); + debug(LOG_3D, " * OpenGL 2.0 %s supported!", GLEE_VERSION_2_0 ? "is" : "is NOT"); + debug(LOG_3D, " * OpenGL 2.1 %s supported!", GLEE_VERSION_2_1 ? "is" : "is NOT"); + debug(LOG_3D, " * OpenGL 3.0 %s supported!", GLEE_VERSION_3_0 ? "is" : "is NOT"); + debug(LOG_3D, " * Texture compression %s supported.", GLEE_ARB_texture_compression ? "is" : "is NOT"); + debug(LOG_3D, " * Two side stencil %s supported.", GLEE_EXT_stencil_two_side ? "is" : "is NOT"); + debug(LOG_3D, " * ATI separate stencil is%s supported.", GLEE_ATI_separate_stencil ? "" : " NOT"); + debug(LOG_3D, " * Stencil wrap %s supported.", GLEE_EXT_stencil_wrap ? "is" : "is NOT"); + debug(LOG_3D, " * Anisotropic filtering %s supported.", GLEE_EXT_texture_filter_anisotropic ? "is" : "is NOT"); + debug(LOG_3D, " * Rectangular texture %s supported.", GLEE_ARB_texture_rectangle ? "is" : "is NOT"); + debug(LOG_3D, " * FrameBuffer Object (FBO) %s supported.", GLEE_EXT_framebuffer_object ? "is" : "is NOT"); + debug(LOG_3D, " * Shader Objects %s supported.", GL_ARB_shader_objects ? "is" : "is NOT"); + debug(LOG_3D, " * Vertex Buffer Object (VBO) %s supported.", GL_ARB_vertex_buffer_object ? "is" : "is NOT"); + glGetIntegerv(GL_MAX_TEXTURE_UNITS, &glMaxTUs); + debug(LOG_3D, " * Total number of Texture Units (TUs) supported is %d.", glMaxTUs); + + if (!GLEE_VERSION_1_4) + { + debug(LOG_FATAL, "OpenGL 1.4+ is required for this game!"); + exit(1); + } + #ifndef WZ_OS_MAC // Make OpenGL's VBO functions available under the core names for // implementations that have them only as extensions, namely Mesa. @@ -230,6 +230,26 @@ bool screenInitialise( } #endif + /* Dump information about OpenGL 2.0+ implementation to the console and the dump file */ + if (GLEE_VERSION_2_0) + { + GLint glMaxTIUs; + + debug(LOG_3D, " * OpenGL GLSL Version : %s", glGetString(GL_SHADING_LANGUAGE_VERSION)); + ssprintf(buf, "OpenGL GLSL Version : %s", glGetString(GL_SHADING_LANGUAGE_VERSION)); + addDumpInfo(buf); + + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &glMaxTIUs); + debug(LOG_3D, " * Total number of Texture Image Units (TIUs) supported is %d.", glMaxTIUs); + + if (!pie_LoadShaders()) + debug(LOG_WARNING, "Can't use shaders! Switching back to fixed pipeline...");; + } + else + { + debug(LOG_WARNING, "OpenGL 2.0 is not supported by your system! Using fixed pipeline..."); + } + glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glPushMatrix(); diff --git a/src/display3d.c b/src/display3d.c index 25622a1c7..ee571fc44 100644 --- a/src/display3d.c +++ b/src/display3d.c @@ -740,6 +740,7 @@ static void drawTiles(iView *player) { UDWORD i, j; SDWORD rx, rz; + Vector3f theSun; /* ---------------------------------------------------------------- */ /* Do boundary and extent checking */ @@ -778,12 +779,9 @@ static void drawTiles(iView *player) /* Translate */ pie_TRANSLATE(-rx, -player->p.y, rz); - if (getDrawShadows()) - { - Vector3f theSun = getTheSun(); - // this also detemines the length of the shadows - pie_BeginLighting(&theSun); - } + // this also detemines the length of the shadows + theSun = getTheSun(); + pie_BeginLighting(&theSun, getDrawShadows()); // update the fog of war for (i = 0; i < visibleTiles.y+1; i++) @@ -842,7 +840,12 @@ static void drawTiles(iView *player) drawTerrain(); // go back to the warzone [0,255] range + glActiveTexture(GL_TEXTURE1); pie_TranslateTextureEnd(); + // go back to the warzone [0,255] range + glActiveTexture(GL_TEXTURE0); + pie_TranslateTextureEnd(); + // and to the warzone modelview transform glPopMatrix(); @@ -895,7 +898,12 @@ static void drawTiles(iView *player) drawWater(); // go back to the warzone [0,255] range + glActiveTexture(GL_TEXTURE1); pie_TranslateTextureEnd(); + // go back to the warzone [0,255] range + glActiveTexture(GL_TEXTURE0); + pie_TranslateTextureEnd(); + // and to the warzone modelview transform glPopMatrix(); diff --git a/src/hci.c b/src/hci.c index 7740f79ae..5bb1ee8c5 100644 --- a/src/hci.c +++ b/src/hci.c @@ -35,6 +35,7 @@ #include "lib/gamelib/gtime.h" #include "lib/ivis_common/rendmode.h" #include "lib/ivis_common/piepalette.h" +#include "lib/ivis_common/piestate.h" // FIXME Direct iVis implementation include! #include "lib/ivis_opengl/screen.h" #include "lib/script/script.h" @@ -177,9 +178,13 @@ BOOL Refreshing = false; #define IDOPT_DROID 1037 // The place droid button #define IDOPT_STRUCT 1038 // The place struct button #define IDOPT_FEATURE 1039 // The place feature button -#define IDOPT_TILE 1040 // The place tile button -#define IDOPT_PAUSE 1041 // The edit pause button +#define IDOPT_TILE 1040 // The place tile button +#define IDOPT_PAUSE 1041 // The edit pause button #define IDOPT_ZALIGN 1042 // The z-align button +#define IDOPT_IVISFORM 1043 // iViS engine form +#define IDOPT_IVISLABEL 1044 // iViS form label +#define IDOPT_IVISSHADERS 1045 // iViS shaders button +#define IDOPT_IVISLIGHTING 1046 // iViS lighting button /* Edit screen IDs */ #define IDED_FORM 2000 // The edit form @@ -1456,6 +1461,39 @@ static void intProcessOptions(UDWORD id) intMode = INT_NORMAL; // widgSetButtonState(psWScreen, IDRET_OPTIONS, 0); break; + case IDOPT_IVISSHADERS: + { + bool status = pie_GetShadersStatus(); + pie_SetShadersStatus(!status); + if (status != pie_GetShadersStatus()) + { + if (!status) + { + widgSetButtonState(psWScreen, IDOPT_IVISSHADERS, WBUT_CLICKLOCK); + } + else + { + widgSetButtonState(psWScreen, IDOPT_IVISSHADERS, 0); + } + } + else + { + widgSetButtonState(psWScreen, IDOPT_IVISSHADERS, WBUT_DISABLE); + } + } + break; + case IDOPT_IVISLIGHTING: + if (pie_GetLightingState()) + { + pie_SetLightingState(false); + widgSetButtonState(psWScreen, IDOPT_IVISLIGHTING, 0); + } + else + { + pie_SetLightingState(true); + widgSetButtonState(psWScreen, IDOPT_IVISLIGHTING, WBUT_CLICKLOCK); + } + break; /* Ignore these */ case IDOPT_FORM: case IDOPT_LABEL: @@ -1463,6 +1501,8 @@ static void intProcessOptions(UDWORD id) case IDOPT_MAPLABEL: case IDOPT_PLAYERFORM: case IDOPT_PLAYERLABEL: + case IDOPT_IVISFORM: + case IDOPT_IVISLABEL: break; default: ASSERT( false, "intProcessOptions: Unknown return code" ); @@ -4172,6 +4212,70 @@ BOOL intAddOptions(void) } } + /* Add iViS form */ + sFormInit.formID = IDOPT_FORM; + sFormInit.id = IDOPT_IVISFORM; + sFormInit.style = WFORM_PLAIN; + sFormInit.x = OPT_GAP; + sFormInit.y = OPT_PLAYERY + OPT_BUTHEIGHT * 3 + OPT_GAP * 5; + sFormInit.width = OPT_WIDTH - OPT_GAP * 2; + sFormInit.height = OPT_BUTHEIGHT * 3 + OPT_GAP * 4; + if (!widgAddForm(psWScreen, &sFormInit)) + { + return false; + } + + /* Add iViS label */ + sLabInit.formID = IDOPT_IVISFORM; + sLabInit.id = IDOPT_IVISLABEL; + sLabInit.style = WLAB_PLAIN; + sLabInit.x = OPT_GAP; + sLabInit.y = OPT_GAP; + sLabInit.pText = "iViS:"; + sLabInit.FontID = font_regular; + if (!widgAddLabel(psWScreen, &sLabInit)) + { + return false; + } + + /* Add iViS shaders button */ + sButInit.formID = IDOPT_IVISFORM; + sButInit.id = IDOPT_IVISSHADERS; + sButInit.x = OPT_BUTWIDTH + OPT_GAP * 2; + sButInit.y = OPT_GAP; + sButInit.width = OPT_BUTWIDTH; + sButInit.height = OPT_BUTHEIGHT; + sButInit.FontID = font_regular; + sButInit.pText = "Shaders"; + sButInit.pTip = "Toggles Shaders/FF mode."; + if (!widgAddButton(psWScreen, &sButInit)) + { + return false; + } + if (pie_GetShadersStatus()) + { + widgSetButtonState(psWScreen, IDOPT_IVISSHADERS, WBUT_CLICKLOCK); + } + + /* Add iViS lighting button */ + sButInit.formID = IDOPT_IVISFORM; + sButInit.id = IDOPT_IVISLIGHTING; + sButInit.x += OPT_BUTWIDTH + OPT_GAP; + sButInit.y = OPT_GAP; + sButInit.width = OPT_BUTWIDTH; + sButInit.height = OPT_BUTHEIGHT; + sButInit.FontID = font_regular; + sButInit.pText = "Lighting"; + sButInit.pTip = "Toggles lighting On/Off."; + if (!widgAddButton(psWScreen, &sButInit)) + { + return false; + } + if (pie_GetLightingState()) + { + widgSetButtonState(psWScreen, IDOPT_IVISLIGHTING, WBUT_CLICKLOCK); + } + // widgStartScreen(psWScreen); widgSetButtonState(psWScreen, IDOPT_PLAYERSTART + selectedPlayer, WBUT_LOCK); From 6cd520e4a04b7792989cadb7e2fc92ef59ef4752 Mon Sep 17 00:00:00 2001 From: Christian Ohm Date: Sat, 6 Mar 2010 23:21:08 +0000 Subject: [PATCH 3/9] Include/declaration cleanup for src/keyedit.c/h. git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@10180 4a71c877-e1ca-e34f-864e-861f7616d084 --- src/keyedit.c | 46 ++++++++++------------------------------------ src/keyedit.h | 8 ++++---- src/main.h | 1 + src/multiint.h | 1 + 4 files changed, 16 insertions(+), 40 deletions(-) diff --git a/src/keyedit.c b/src/keyedit.c index 707c0a2c4..c57b7c01e 100644 --- a/src/keyedit.c +++ b/src/keyedit.c @@ -23,32 +23,21 @@ * alexl. */ -// //////////////////////////////////////////////////////////////////////////// -// includes -#include -#include -#include - #include "lib/framework/frame.h" -#include "lib/framework/strres.h" -#include "lib/framework/input.h" +#include "lib/ivis_common/bitimage.h" +#include "lib/ivis_common/pieblitfunc.h" #include "lib/sound/audio.h" +#include "lib/sound/audio_id.h" -#include "lib/widget/widget.h" -#include "frontend.h" #include "frend.h" -#include "lib/ivis_common/textdraw.h" -#include "lib/ivis_common/piepalette.h" +#include "frontend.h" #include "hci.h" #include "init.h" -#include "loadsave.h" -#include "keymap.h" -#include "intimage.h" -#include "lib/ivis_common/bitimage.h" #include "intdisplay.h" -#include "lib/sound/audio_id.h" -#include "lib/ivis_common/pieblitfunc.h" -#include "lib/netplay/netplay.h" +#include "keyedit.h" +#include "keymap.h" +#include "loadsave.h" +#include "main.h" #include "multiint.h" // //////////////////////////////////////////////////////////////////////////// @@ -67,9 +56,6 @@ #define KM_X 30 #define KM_Y 20 -#define KM_RETURNX (KM_W-90) -#define KM_RETURNY (KM_H-42) - #define BUTTONSPERKEYMAPPAGE 20 #define KM_ENTRYW 480 @@ -80,19 +66,7 @@ // variables static KEY_MAPPING *selectedKeyMap; -// //////////////////////////////////////////////////////////////////////////// -// protos - -BOOL runKeyMapEditor (void); -static BOOL keyMapToString (char *pStr, KEY_MAPPING *psMapping); -static void displayKeyMap(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours); -BOOL startKeyMapEditor (BOOL first); -BOOL saveKeyMap (void); -BOOL loadKeyMap (void); -static BOOL pushedKeyMap (UDWORD key); - -char keymapVersion[8] = "KM_0002"; -extern char KeyMapPath[]; +static char keymapVersion[8] = "KM_0002"; // //////////////////////////////////////////////////////////////////////////// // funcs @@ -318,7 +292,7 @@ static BOOL keyMapToString(char *pStr, KEY_MAPPING *psMapping) // //////////////////////////////////////////////////////////////////////////// // display a keymap on the interface. -void displayKeyMap(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, WZ_DECL_UNUSED PIELIGHT *pColours) +static void displayKeyMap(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, WZ_DECL_UNUSED PIELIGHT *pColours) { UDWORD x = xOffset+psWidget->x; UDWORD y = yOffset+psWidget->y; diff --git a/src/keyedit.h b/src/keyedit.h index b8b28bd69..9a36edfa0 100644 --- a/src/keyedit.h +++ b/src/keyedit.h @@ -26,10 +26,10 @@ extern "C" { #endif //__cplusplus -extern BOOL runKeyMapEditor (void); -extern BOOL startKeyMapEditor (BOOL first); -extern BOOL saveKeyMap (void); -extern BOOL loadKeyMap (void); +BOOL runKeyMapEditor(void); +BOOL startKeyMapEditor(BOOL first); +BOOL saveKeyMap(void); +BOOL loadKeyMap(void); #ifdef __cplusplus } diff --git a/src/main.h b/src/main.h index d178ba932..02d078c15 100644 --- a/src/main.h +++ b/src/main.h @@ -42,6 +42,7 @@ extern void SetGameMode(GS_GAMEMODE status); extern char SaveGamePath[PATH_MAX]; extern char datadir[PATH_MAX]; extern char configdir[PATH_MAX]; +extern char KeyMapPath[PATH_MAX]; #define MAX_MODS 100 diff --git a/src/multiint.h b/src/multiint.h index 983e0ea4b..94b50a0c8 100644 --- a/src/multiint.h +++ b/src/multiint.h @@ -24,6 +24,7 @@ #ifndef __INCLUDED_SRC_MULTIINT_H__ #define __INCLUDED_SRC_MULTIINT_H__ +#include "lib/netplay/netplay.h" #include "lib/widget/widgbase.h" #ifdef __cplusplus From 9e3cde7a7ad1a182e706ade5c40e12664d9f135d Mon Sep 17 00:00:00 2001 From: Christian Ohm Date: Sat, 6 Mar 2010 23:21:45 +0000 Subject: [PATCH 4/9] Fix compilation on Linux. git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@10181 4a71c877-e1ca-e34f-864e-861f7616d084 --- src/data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data.c b/src/data.c index e662693b0..616ceb243 100644 --- a/src/data.c +++ b/src/data.c @@ -842,7 +842,7 @@ static bool dataTexPageLoad(const char *fileName, void **ppData) } /* Load a team colour mask texturepage into memory */ -static BOOL dataTexPageTCMaskLoad(const char *fileName, void **ppData) +static bool dataTexPageTCMaskLoad(const char *fileName, void **ppData) { char texpage[PATH_MAX] = {'\0'}; From 5c64a642a4658156cac079e25532a188611961ee Mon Sep 17 00:00:00 2001 From: i-nod Date: Sat, 6 Mar 2010 23:54:11 +0000 Subject: [PATCH 5/9] Fix warnings on MacOS builds that were caused by [10179]. git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@10183 4a71c877-e1ca-e34f-864e-861f7616d084 --- lib/ivis_opengl/piestate.c | 4 ++-- lib/ivis_opengl/screen.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ivis_opengl/piestate.c b/lib/ivis_opengl/piestate.c index 786f55b07..1a4796c70 100644 --- a/lib/ivis_opengl/piestate.c +++ b/lib/ivis_opengl/piestate.c @@ -78,7 +78,7 @@ static char *readShaderBuf(const char *name) // Retrieve shader compilation errors static void printShaderInfoLog(GLuint shader) { - int infologLen = 0; + GLint infologLen = 0; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLen); if (infologLen > 0) @@ -95,7 +95,7 @@ static void printShaderInfoLog(GLuint shader) // Retrieve shader linkage errors static void printProgramInfoLog(GLuint program) { - int infologLen = 0; + GLint infologLen = 0; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLen); if (infologLen > 0) diff --git a/lib/ivis_opengl/screen.c b/lib/ivis_opengl/screen.c index b0dd797fd..45fb2a27b 100644 --- a/lib/ivis_opengl/screen.c +++ b/lib/ivis_opengl/screen.c @@ -199,7 +199,7 @@ bool screenInitialise( debug(LOG_3D, " * Vertex Buffer Object (VBO) %s supported.", GL_ARB_vertex_buffer_object ? "is" : "is NOT"); glGetIntegerv(GL_MAX_TEXTURE_UNITS, &glMaxTUs); - debug(LOG_3D, " * Total number of Texture Units (TUs) supported is %d.", glMaxTUs); + debug(LOG_3D, " * Total number of Texture Units (TUs) supported is %d.", (int) glMaxTUs); if (!GLEE_VERSION_1_4) { @@ -240,7 +240,7 @@ bool screenInitialise( addDumpInfo(buf); glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &glMaxTIUs); - debug(LOG_3D, " * Total number of Texture Image Units (TIUs) supported is %d.", glMaxTIUs); + debug(LOG_3D, " * Total number of Texture Image Units (TIUs) supported is %d.", (int) glMaxTIUs); if (!pie_LoadShaders()) debug(LOG_WARNING, "Can't use shaders! Switching back to fixed pipeline...");; From 1756afb3a184d2de7bf6d92c2fe910eb9edd0ef3 Mon Sep 17 00:00:00 2001 From: i-nod Date: Sun, 7 Mar 2010 01:44:28 +0000 Subject: [PATCH 6/9] Fix another 2 warnings on MacOS builds that were caused by [10179]. git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@10184 4a71c877-e1ca-e34f-864e-861f7616d084 --- lib/ivis_opengl/piestate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ivis_opengl/piestate.c b/lib/ivis_opengl/piestate.c index 1a4796c70..b1dd3f4f0 100644 --- a/lib/ivis_opengl/piestate.c +++ b/lib/ivis_opengl/piestate.c @@ -83,7 +83,7 @@ static void printShaderInfoLog(GLuint shader) glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLen); if (infologLen > 0) { - int charsWritten = 0; + GLint charsWritten = 0; GLchar *infoLog = (GLchar *)malloc(infologLen); glGetShaderInfoLog(shader, infologLen, &charsWritten, infoLog); @@ -100,7 +100,7 @@ static void printProgramInfoLog(GLuint program) glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLen); if (infologLen > 0) { - int charsWritten = 0; + GLint charsWritten = 0; GLchar *infoLog = (GLchar *)malloc(infologLen); glGetProgramInfoLog(program, infologLen, &charsWritten, infoLog); From 058044b2b5847e56b7b9deea291430ccf234304f Mon Sep 17 00:00:00 2001 From: dak180 Date: Sun, 7 Mar 2010 04:19:06 +0000 Subject: [PATCH 7/9] Minor housekeeping and set a few lib headers to public. git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@10185 4a71c877-e1ca-e34f-864e-861f7616d084 --- macosx/Warzone.xcodeproj/project.pbxproj | 4 ++-- macosx/configs/Warzone-All.xcconfig | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/macosx/Warzone.xcodeproj/project.pbxproj b/macosx/Warzone.xcodeproj/project.pbxproj index 60cfa5781..4d84a63cc 100644 --- a/macosx/Warzone.xcodeproj/project.pbxproj +++ b/macosx/Warzone.xcodeproj/project.pbxproj @@ -140,7 +140,7 @@ 022B2FA80BD55B50002E64E3 /* vasnwprintf.h in Headers */ = {isa = PBXBuildFile; fileRef = 022B2F950BD55B50002E64E3 /* vasnwprintf.h */; }; 022B2FA90BD55B50002E64E3 /* wprintf-parse.h in Headers */ = {isa = PBXBuildFile; fileRef = 022B2F960BD55B50002E64E3 /* wprintf-parse.h */; }; 022B2FAA0BD55B50002E64E3 /* xsize.h in Headers */ = {isa = PBXBuildFile; fileRef = 022B2F970BD55B50002E64E3 /* xsize.h */; }; - 022B2FE20BD55E45002E64E3 /* libgnuintl.h in Headers */ = {isa = PBXBuildFile; fileRef = 022B2FE00BD55E45002E64E3 /* libgnuintl.h */; }; + 022B2FE20BD55E45002E64E3 /* libgnuintl.h in Headers */ = {isa = PBXBuildFile; fileRef = 022B2FE00BD55E45002E64E3 /* libgnuintl.h */; settings = {ATTRIBUTES = (Public, ); }; }; 022B2FE30BD55E45002E64E3 /* libintl.h in Headers */ = {isa = PBXBuildFile; fileRef = 022B2FE10BD55E45002E64E3 /* libintl.h */; settings = {ATTRIBUTES = (Public, ); }; }; 022B30AB0BD564FC002E64E3 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 022B30AA0BD564FC002E64E3 /* config.h */; }; 022B30E00BD56618002E64E3 /* plural.c in Sources */ = {isa = PBXBuildFile; fileRef = 022B30DF0BD56618002E64E3 /* plural.c */; }; @@ -170,7 +170,7 @@ 02356DB50BD3BB6F00E9A019 /* zutil.h in Headers */ = {isa = PBXBuildFile; fileRef = 02356D9F0BD3BB6F00E9A019 /* zutil.h */; settings = {ATTRIBUTES = (); }; }; 02356DDB0BD3BC9900E9A019 /* png.c in Sources */ = {isa = PBXBuildFile; fileRef = 02356DC90BD3BC9900E9A019 /* png.c */; }; 02356DDC0BD3BC9900E9A019 /* png.h in Headers */ = {isa = PBXBuildFile; fileRef = 02356DCA0BD3BC9900E9A019 /* png.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 02356DDD0BD3BC9900E9A019 /* pngconf.h in Headers */ = {isa = PBXBuildFile; fileRef = 02356DCB0BD3BC9900E9A019 /* pngconf.h */; settings = {ATTRIBUTES = (); }; }; + 02356DDD0BD3BC9900E9A019 /* pngconf.h in Headers */ = {isa = PBXBuildFile; fileRef = 02356DCB0BD3BC9900E9A019 /* pngconf.h */; settings = {ATTRIBUTES = (Public, ); }; }; 02356DDE0BD3BC9900E9A019 /* pngerror.c in Sources */ = {isa = PBXBuildFile; fileRef = 02356DCC0BD3BC9900E9A019 /* pngerror.c */; }; 02356DE00BD3BC9900E9A019 /* pngget.c in Sources */ = {isa = PBXBuildFile; fileRef = 02356DCE0BD3BC9900E9A019 /* pngget.c */; }; 02356DE10BD3BC9900E9A019 /* pngmem.c in Sources */ = {isa = PBXBuildFile; fileRef = 02356DCF0BD3BC9900E9A019 /* pngmem.c */; }; diff --git a/macosx/configs/Warzone-All.xcconfig b/macosx/configs/Warzone-All.xcconfig index 0f059f69b..6aeed7635 100644 --- a/macosx/configs/Warzone-All.xcconfig +++ b/macosx/configs/Warzone-All.xcconfig @@ -3,7 +3,7 @@ INSTALL_PATH = $(HOME)/Applications COPY_PHASE_STRIP = NO -OTHER_LDFLAGS[arch=ppc] = -w +OTHER_LDFLAGS[arch=ppc] = -w // This turns off 2 warnings that are actually in apple's sdk. PREBINDING = NO INFOPLIST_FILE = Resources/Warzone-Info.plist INFOPLIST_OTHER_PREPROCESSOR_FLAGS = -traditional From 240bb9189125a5560535956d253c755ec0890d04 Mon Sep 17 00:00:00 2001 From: Per Inge Mathisen Date: Sun, 7 Mar 2010 08:29:13 +0000 Subject: [PATCH 8/9] Remove our dependency on popt by writing a custom popt-like parser. Patch by me and i-NoD. Closes ticket:1659 git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@10186 4a71c877-e1ca-e34f-864e-861f7616d084 --- configure.ac | 7 +- src/Makefile.am | 4 +- src/clparse.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 169 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index d166a6770..1ec904efe 100644 --- a/configure.ac +++ b/configure.ac @@ -313,8 +313,7 @@ fi # check for nearbyint() AC_CHECK_LIB(m, nearbyint, [MATH_LIB=""], AC_MSG_ERROR([nearbyint not found.])) -# When (cross-)compiling for Windows (MinGW) we need to link in iberty for Popt -# and the Dr. MinGW derived exception handler. +# When (cross-)compiling for Windows (MinGW) we need to link in iberty for the Dr. MinGW derived exception handler. if test "x$host_os_mingw32" = "xyes" ; then AC_CHECK_LIB(iberty, main, AC_SUBST([IBERTY_LIBS], [-liberty]), AC_MSG_ERROR([libiberty not found.])) @@ -333,10 +332,6 @@ AC_TRY_COMPILE(, [ AC_MSG_ERROR([X11 library not found])) ]) -# Look for Popt -AC_CHECK_HEADER(popt.h, , AC_MSG_ERROR([Popt header not found.])) -AC_CHECK_LIB(popt, poptGetContext, AC_SUBST([POPT_LIBS], [-lpopt]), AC_MSG_ERROR([Popt not found.]), [${WIN32_LIBS}]) - # Look for PhysicsFS AC_CHECK_HEADER(physfs.h, , AC_MSG_ERROR([PhysicsFS header not found.])) AC_CHECK_LIB(physfs, PHYSFS_init, AC_SUBST([PHYSFS_LIBS], [-lphysfs]), AC_MSG_ERROR([PhysicsFS not found.]), [${WIN32_LIBS}]) diff --git a/src/Makefile.am b/src/Makefile.am index 2940b329b..9bab9fa16 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,7 +8,7 @@ force-linker.cpp: touch $@ -AM_CPPFLAGS = -DYY_NO_INPUT $(SDL_CFLAGS) $(PHYSFS_CFLAGS) $(PNG_CFLAGS) $(OGGVORBIS_CFLAGS) $(OPENAL_CFLAGS) $(OPENGLC_CFLAGS) $(OPENGL_CFLAGS) $(POPT_CFLAGS) $(WZ_CPPFLAGS) $(GLee_CFLAGS) +AM_CPPFLAGS = -DYY_NO_INPUT $(SDL_CFLAGS) $(PHYSFS_CFLAGS) $(PNG_CFLAGS) $(OGGVORBIS_CFLAGS) $(OPENAL_CFLAGS) $(OPENGLC_CFLAGS) $(OPENGL_CFLAGS) $(WZ_CPPFLAGS) $(GLee_CFLAGS) AM_CFLAGS = $(WZ_CFLAGS) AM_LFLAGS = $(FLEX_FLAGS) AM_YFLAGS = -d @@ -301,7 +301,7 @@ warzone2100_LDADD = \ $(top_builddir)/lib/iniparser/libiniparser.a \ $(top_builddir)/lib/exceptionhandler/libexceptionhandler.a -warzone2100_LDADD += $(LTLIBINTL) $(SDL_LIBS) $(PHYSFS_LIBS) $(PNG_LIBS) $(OGGVORBIS_LIBS) $(THEORA_LIBS) $(OPENAL_LIBS) $(OPENGLC_LIBS) $(OPENGL_LIBS) $(POPT_LIBS) $(X11_LIBS) $(GLee_LIBS) +warzone2100_LDADD += $(LTLIBINTL) $(SDL_LIBS) $(PHYSFS_LIBS) $(PNG_LIBS) $(OGGVORBIS_LIBS) $(THEORA_LIBS) $(OPENAL_LIBS) $(OPENGLC_LIBS) $(OPENGL_LIBS) $(X11_LIBS) $(GLee_LIBS) if MINGW32 warzone2100_LDADD += $(top_builddir)/win32/warzone2100.o $(WIN32_LIBS) diff --git a/src/clparse.c b/src/clparse.c index 590977d85..7cdc6ac29 100644 --- a/src/clparse.c +++ b/src/clparse.c @@ -24,8 +24,6 @@ * */ -#include - #include "lib/framework/frame.h" #include "lib/netplay/netplay.h" @@ -43,6 +41,171 @@ //! Let the end user into debug mode.... BOOL bAllowDebugMode = false; +////// +// Our fine replacement for the popt abomination follows + +#define POPT_ARG_STRING true +#define POPT_ARG_NONE false +#define POPT_ERROR_BADOPT -1 +#define POPT_ARGFLAG_DOC_HIDDEN 0 + +struct poptOption +{ + const char *string; + char short_form; + bool argument; + void *nullptr; // unused + int enumeration; + const char *descrip; + const char *argDescrip; +}; + +typedef struct _poptContext +{ + int argc, current, size; + const char **argv; + const char *parameter; + const char *bad; + const struct poptOption *table; +} *poptContext; + +static void poptPrintUsage(poptContext ctx, FILE *output, WZ_DECL_UNUSED int unused) +{ + // TODO ? +} + +static void poptPrintHelp(poptContext ctx, FILE *output, WZ_DECL_UNUSED int unused) +{ + int i; + + fprintf(output, "Usage: %s [OPTION...]\n", ctx->argv[0]); + for (i = 0; i < ctx->size; i++) + { + char txt[128]; + + if (ctx->table[i].short_form != '\0') + { + ssprintf(txt, " -%c, --%s", ctx->table[i].short_form, ctx->table[i].string); + } + else + { + ssprintf(txt, " --%s", ctx->table[i].string); + } + + if (ctx->table[i].argument) + { + sstrcat(txt, "="); + sstrcat(txt, ctx->table[i].argDescrip); + } + + fprintf(output, "%-40s", txt); + if (ctx->table[i].descrip) + { + fprintf(output, "%s", ctx->table[i].descrip); + } + fprintf(output, "\n"); + } +} + +static void poptFreeContext(WZ_DECL_UNUSED poptContext ctx) +{ + // Nothing! +} + +static const char *poptBadOption(poptContext ctx, WZ_DECL_UNUSED int unused) +{ + return ctx->bad; +} + +static const char *poptGetOptArg(poptContext ctx) +{ + return ctx->parameter; +} + +static int poptGetNextOpt(poptContext ctx) +{ + static char match[PATH_MAX]; // static for bad function + static char parameter[PATH_MAX]; // static for arg function + char *pparam; + int i; + + ctx->bad = NULL; + ctx->parameter = NULL; + parameter[0] = '\0'; + match[0] = '\0'; + + if (ctx->current >= ctx->argc) // counts from 1 + { + return 0; + } + + sstrcpy(match, ctx->argv[ctx->current]); + ctx->current++; + pparam = strrchr(match, '='); + if (pparam) // option's got a parameter + { + *pparam++ = '\0'; // split option from parameter and increment past '=' + if (pparam[0] == '"') // found scary quotes + { + pparam++; // skip start quote + sstrcpy(parameter, pparam); // copy first parameter + if (!strrchr(pparam, '"')) // if no end quote, then find it + { + while (!strrchr(parameter, '"') && ctx->current < ctx->argc) + { + sstrcat(parameter, " "); // insert space + sstrcat(parameter, ctx->argv[ctx->current]); + ctx->current++; // next part, please! + } + } + if (strrchr(parameter, '"')) // its not an else for above! + { + *strrchr(parameter, '"') = '\0'; // remove end qoute + } + } + else + { + sstrcpy(parameter, pparam); // copy parameter + } + } + + for (i = 0; i < ctx->size; i++) + { + char sshort[3]; + char slong[64]; + + ssprintf(sshort, "-%c", ctx->table[i].short_form); + ssprintf(slong, "--%s", ctx->table[i].string); + if ((strcmp(sshort, match) == 0 && ctx->table[i].short_form != '\0') || strcmp(slong, match) == 0) + { + if (ctx->table[i].argument && pparam) + { + ctx->parameter = parameter; + } + return ctx->table[i].enumeration; + } + } + ctx->bad = match; + ctx->current++; + return POPT_ERROR_BADOPT; +} + +static poptContext poptGetContext(WZ_DECL_UNUSED void *unused, int argc, const char **argv, const struct poptOption *table, WZ_DECL_UNUSED int none) +{ + static struct _poptContext ctx; + + ctx.argc = argc; + ctx.argv = argv; + ctx.table = table; + ctx.current = 1; + ctx.parameter = NULL; + + for (ctx.size = 0; table[ctx.size].string; ctx.size++) ; // count table size + + return &ctx; +} + + typedef enum { // We don't want to use zero, so start at one (1) @@ -79,8 +242,8 @@ static const struct poptOption* getOptionsTable(void) static const struct poptOption optionsTable[] = { { "cheat", '\0', POPT_ARG_NONE, NULL, CLI_CHEAT, N_("Run in cheat mode"), NULL }, - { "datadir", '\0', POPT_ARG_STRING, NULL, CLI_DATADIR, N_("Set default data directory"), N_("data directory") }, { "configdir", '\0', POPT_ARG_STRING, NULL, CLI_CONFIGDIR, N_("Set configuration directory"), N_("configuration directory") }, + { "datadir", '\0', POPT_ARG_STRING, NULL, CLI_DATADIR, N_("Set default data directory"), N_("data directory") }, { "debug", '\0', POPT_ARG_STRING, NULL, CLI_DEBUG, N_("Show debug for given level"), N_("debug level") }, { "debugfile", '\0', POPT_ARG_STRING, NULL, CLI_DEBUGFILE, N_("Log debug output to file"), N_("file") }, { "flush-debug-stderr", '\0', POPT_ARG_NONE, NULL, CLI_FLUSHDEBUGSTDERR, N_("Flush all debug output written to stderr"), NULL }, From bcb70cb5d7882a524ef28dbb67b86dcb6daaa08e Mon Sep 17 00:00:00 2001 From: Per Inge Mathisen Date: Sun, 7 Mar 2010 08:31:41 +0000 Subject: [PATCH 9/9] Remove popt API calls that are no longer necessary. git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@10187 4a71c877-e1ca-e34f-864e-861f7616d084 --- src/clparse.c | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/src/clparse.c b/src/clparse.c index 7cdc6ac29..45f29ceee 100644 --- a/src/clparse.c +++ b/src/clparse.c @@ -47,7 +47,6 @@ BOOL bAllowDebugMode = false; #define POPT_ARG_STRING true #define POPT_ARG_NONE false #define POPT_ERROR_BADOPT -1 -#define POPT_ARGFLAG_DOC_HIDDEN 0 struct poptOption { @@ -69,11 +68,6 @@ typedef struct _poptContext const struct poptOption *table; } *poptContext; -static void poptPrintUsage(poptContext ctx, FILE *output, WZ_DECL_UNUSED int unused) -{ - // TODO ? -} - static void poptPrintHelp(poptContext ctx, FILE *output, WZ_DECL_UNUSED int unused) { int i; @@ -107,11 +101,6 @@ static void poptPrintHelp(poptContext ctx, FILE *output, WZ_DECL_UNUSED int unus } } -static void poptFreeContext(WZ_DECL_UNUSED poptContext ctx) -{ - // Nothing! -} - static const char *poptBadOption(poptContext ctx, WZ_DECL_UNUSED int unused) { return ctx->bad; @@ -222,7 +211,6 @@ typedef enum CLI_MOD_CA, CLI_MOD_MP, CLI_SAVEGAME, - CLI_USAGE, CLI_WINDOW, CLI_VERSION, CLI_RESOLUTION, @@ -256,8 +244,6 @@ static const struct poptOption* getOptionsTable(void) { "noassert", '\0', POPT_ARG_NONE, NULL, CLI_NOASSERT, N_("Disable asserts"), NULL }, { "crash", '\0', POPT_ARG_NONE, NULL, CLI_CRASH, N_("Causes a crash to test the crash handler"), NULL }, { "savegame", '\0', POPT_ARG_STRING, NULL, CLI_SAVEGAME, N_("Load a saved game"), N_("savegame") }, - { "usage", '\0', POPT_ARG_NONE - | POPT_ARGFLAG_DOC_HIDDEN, NULL, CLI_USAGE, NULL, NULL, }, { "window", '\0', POPT_ARG_NONE, NULL, CLI_WINDOW, N_("Play in windowed mode"), NULL }, { "version", '\0', POPT_ARG_NONE, NULL, CLI_VERSION, N_("Show version information and exit"), NULL }, { "resolution", '\0', POPT_ARG_STRING, NULL, CLI_RESOLUTION, N_("Set the resolution to use"), N_("WIDTHxHEIGHT") }, @@ -336,7 +322,6 @@ bool ParseCommandLineEarly(int argc, const char** argv) if (token == NULL) { debug(LOG_ERROR, "Usage: --debug "); - poptFreeContext(poptCon); return false; } @@ -344,7 +329,6 @@ bool ParseCommandLineEarly(int argc, const char** argv) if (!debug_enable_switch(token)) { debug(LOG_ERROR, "Debug flag \"%s\" not found!", token); - poptFreeContext(poptCon); return false; } break; @@ -355,7 +339,6 @@ bool ParseCommandLineEarly(int argc, const char** argv) if (token == NULL) { debug(LOG_ERROR, "Missing debugfile filename?"); - poptFreeContext(poptCon); return false; } debug_register_callback( debug_callback_file, debug_callback_file_init, debug_callback_file_exit, (void*)token ); @@ -372,7 +355,6 @@ bool ParseCommandLineEarly(int argc, const char** argv) if (token == NULL) { debug(LOG_ERROR, "Unrecognised configuration directory"); - poptFreeContext(poptCon); return false; } sstrcpy(configdir, token); @@ -380,17 +362,10 @@ bool ParseCommandLineEarly(int argc, const char** argv) case CLI_HELP: poptPrintHelp(poptCon, stdout, 0); - poptFreeContext(poptCon); - return false; - - case CLI_USAGE: - poptPrintUsage(poptCon, stdout, 0); - poptFreeContext(poptCon); return false; case CLI_VERSION: printf("Warzone 2100 - %s\n", version_getFormattedVersionString()); - poptFreeContext(poptCon); return false; default: @@ -398,8 +373,6 @@ bool ParseCommandLineEarly(int argc, const char** argv) }; } - poptFreeContext(poptCon); - return true; } @@ -428,7 +401,6 @@ bool ParseCommandLine(int argc, const char** argv) case CLI_FLUSHDEBUGSTDERR: case CLI_CONFIGDIR: case CLI_HELP: - case CLI_USAGE: case CLI_VERSION: // These options are parsed in ParseCommandLineEarly() already, so ignore them break; @@ -456,7 +428,6 @@ bool ParseCommandLine(int argc, const char** argv) if (token == NULL) { debug(LOG_ERROR, "Unrecognised datadir"); - poptFreeContext(poptCon); return false; } sstrcpy(datadir, token); @@ -471,7 +442,6 @@ bool ParseCommandLine(int argc, const char** argv) if (token == NULL) { debug(LOG_ERROR, "No IP/hostname given"); - poptFreeContext(poptCon); return false; } sstrcpy(iptoconnect, token); @@ -486,7 +456,6 @@ bool ParseCommandLine(int argc, const char** argv) if (token == NULL) { debug(LOG_ERROR, "No game name"); - poptFreeContext(poptCon); return false; } if (strcmp(token, "CAM_1A") && strcmp(token, "CAM_2A") && strcmp(token, "CAM_3A") @@ -521,7 +490,6 @@ bool ParseCommandLine(int argc, const char** argv) if (token == NULL) { debug(LOG_ERROR, "Missing mod name?"); - poptFreeContext(poptCon); return false; } @@ -530,7 +498,6 @@ bool ParseCommandLine(int argc, const char** argv) if (i >= 100 || global_mods[i] != NULL) { debug(LOG_ERROR, "Too many mods registered! Aborting!"); - poptFreeContext(poptCon); return false; } global_mods[i] = strdup(token); @@ -545,7 +512,6 @@ bool ParseCommandLine(int argc, const char** argv) if (token == NULL) { debug(LOG_ERROR, "Missing mod name?"); - poptFreeContext(poptCon); return false; } @@ -554,7 +520,6 @@ bool ParseCommandLine(int argc, const char** argv) if (i >= 100 || campaign_mods[i] != NULL) { debug(LOG_ERROR, "Too many mods registered! Aborting!"); - poptFreeContext(poptCon); return false; } campaign_mods[i] = strdup(token); @@ -569,7 +534,6 @@ bool ParseCommandLine(int argc, const char** argv) if (token == NULL) { debug(LOG_ERROR, "Missing mod name?"); - poptFreeContext(poptCon); return false; } @@ -577,7 +541,6 @@ bool ParseCommandLine(int argc, const char** argv) if (i >= 100 || multiplay_mods[i] != NULL) { debug(LOG_ERROR, "Too many mods registered! Aborting!"); - poptFreeContext(poptCon); return false; } multiplay_mods[i] = strdup(token); @@ -615,7 +578,6 @@ bool ParseCommandLine(int argc, const char** argv) if (token == NULL) { debug(LOG_ERROR, "Unrecognised savegame name"); - poptFreeContext(poptCon); return false; } snprintf(saveGameName, sizeof(saveGameName), "%s/%s", SaveGamePath, token); @@ -648,7 +610,5 @@ bool ParseCommandLine(int argc, const char** argv) }; } - poptFreeContext(poptCon); - return true; }