warzone2100/tools/pietoaster/pietoaster.cpp

628 lines
15 KiB
C++

/*
* PieToaster is an OpenGL application to edit 3D models in
* Warzone 2100's (an RTS game) PIE 3D model format, which is heavily
* inspired by PieSlicer created by stratadrake.
* Copyright (C) 2007 Carl Hee
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "SDL.h"
#include "AntTweakBar.h"
#include <SDL_opengl.h>
#include "pie_types.h"
#include "imdloader.h"
#include "resmaster.h"
#include "gui.h"
#include "screen.h"
#include "game_io.h"
int main(int argc, char *argv[])
{
const SDL_VideoInfo* video = NULL;
bool bQuit = false;
if( g_Screen.initialize() < 0 )
{
fprintf(stderr, "Video initialization failed: %s\n", SDL_GetError());
SDL_Quit();
exit(1);
}
video = SDL_GetVideoInfo();
if( !video )
{
fprintf(stderr, "Video query failed: %s\n", SDL_GetError());
SDL_Quit();
exit(1);
}
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
g_Screen.m_bpp = video->vfmt->BitsPerPixel;
fprintf(stderr, "BPP %d\n", video->vfmt->BitsPerPixel);
if (g_Screen.m_bpp == 16)
{
fprintf(stderr, "WARNING:Running at 16bit expecting decreased performance\nChanging Desktop depth to 32bit may correct this problem\n");
}
g_Screen.m_flags = SDL_OPENGL | SDL_HWSURFACE | SDL_RESIZABLE;
g_Screen.m_width = 800;
g_Screen.m_height = 600;
g_Screen.m_useVBO = false;
//flags |= SDL_FULLSCREEN;
if( !g_Screen.setVideoMode() )
{
fprintf(stderr, "Video mode set failed: %s", SDL_GetError());
SDL_Quit();
exit(1);
}
SDL_WM_SetCaption("Pie Toaster powered by AntTweakBar+SDL", "WZ Stats Tools");
// Enable SDL unicode and key-repeat
SDL_EnableUNICODE(1);
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
// Set OpenGL viewport and states
glViewport(0, 0, g_Screen.m_width, g_Screen.m_height);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
//glEnable(GL_LIGHTING);
//glEnable(GL_LIGHT0); // use default light diffuse and position
//glEnable(GL_NORMALIZE);
//glEnable(GL_COLOR_MATERIAL);
glDisable(GL_CULL_FACE);
//glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
glShadeModel(GL_SMOOTH);
// Initialize AntTweakBar
TwInit(TW_OPENGL, NULL);
/// pie vertex type
TwStructMember vertice3fMembers[] =
{
{ "X", TW_TYPE_FLOAT, offsetof(_vertice_list, vertice.x), "step=0.1" },
{ "Y", TW_TYPE_FLOAT, offsetof(_vertice_list, vertice.y), "step=0.1" },
{ "Z", TW_TYPE_FLOAT, offsetof(_vertice_list, vertice.z), "step=0.1" },
{ "Selected", TW_TYPE_BOOLCPP, offsetof(_vertice_list, selected), "" },
};
g_tw_pieVertexType = TwDefineStruct("VerticePie", vertice3fMembers, 4, sizeof(_vertice_list), NULL, NULL);
TwStructMember vector2fMembers[] =
{
{ "X", TW_TYPE_FLOAT, offsetof(Vector2f, x), "min=0 max=4096 step=1" },
{ "Y", TW_TYPE_FLOAT, offsetof(Vector2f, y), "min=0 max=4096 step=1" },
};
g_tw_pieVector2fType = TwDefineStruct("Vector2fPie", vector2fMembers, 2, sizeof(Vector2f), NULL, NULL);
// Tell the window size to AntTweakBar
TwWindowSize(g_Screen.m_width, g_Screen.m_height);
iIMDShape *testIMD = NULL;
//ResMaster = new CResMaster;
ResMaster.getOGLExtensionString();
if (ResMaster.isOGLExtensionAvailable("GL_ARB_vertex_buffer_object"))
{
g_Screen.initializeVBOExtension();
}
ResMaster.cacheGridsVertices();
ResMaster.readTextureList("pages.txt");
ResMaster.loadTexPages();
ResMaster.addGUI();
#ifdef SDL_TTF_TEST
if (!(ResMaster.initFont() && ResMaster.loadFont("FreeMono.ttf", 12)))
{
return 1;
}
#endif
//argc = 2;
//argv[1] = "building1b.pie";
if (argc < 2)
{
fprintf(stderr, "NOTE:no file specified\n");
//ResMaster.addPie(testIMD, "newpie"); //No need to add new pie for now
}
else
{
testIMD = iV_ProcessIMD(argv[1]);
if (testIMD == NULL)
{
fprintf(stderr, "no file specified\n creating new one...\n");
ResMaster.addPie(testIMD, "newpie");
}
else
{
ResMaster.addPie(testIMD, argv[1]);
}
}
//ResMaster.getPieAt(0)->ToFile("test13.pie");
OpenFileDialog.m_Up = false;
while( !bQuit )
{
SDL_Event event;
int handled;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// Set OpenGL camera
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30, (double)g_Screen.m_width/g_Screen.m_height, 1, 1000);
gluLookAt(0,0,250, 0,0,0, 0,1,0);
//updateBars();
inputUpdate();
// Process incoming events
while( SDL_PollEvent(&event) )
{
if (OpenFileDialog.m_Up)
{
if (event.type == SDL_KEYDOWN)
{
Uint16 key = event.key.keysym.sym;
SDLMod modifier = event.key.keysym.mod;
if (key == SDLK_BACKSPACE)
{
OpenFileDialog.decrementChar();
}
else if (key == SDLK_KP_ENTER || key == SDLK_RETURN)
{
OpenFileDialog.doFunction();
OpenFileDialog.deleteTextBox();
continue;
}
else if (key == SDLK_PAUSE ||
key == SDLK_ESCAPE)
{
//cancels current action and closes text box
//OpenFileDialog.text_pointer = NULL;
OpenFileDialog.deleteTextBox();
continue;
}
else if (key > 12 && key < 128)
{
if (modifier & KMOD_CAPS ||
modifier & KMOD_LSHIFT ||
modifier & KMOD_RSHIFT)
{
if (key >= 'a' && key <= 'z')
{
key = toupper(key);
}
else
{
key = shiftChar(key);
}
}
OpenFileDialog.incrementChar(key);
}
OpenFileDialog.updateTextBox();
//interrupts input when text box is up
continue;
}
}
else if (AddSubModelDialog.m_Up)
{
if (event.type == SDL_KEYDOWN)
{
Uint16 key = event.key.keysym.sym;
SDLMod modifier = event.key.keysym.mod;
if (key == SDLK_BACKSPACE)
{
AddSubModelDialog.decrementChar();
}
else if (key == SDLK_KP_ENTER || key == SDLK_RETURN)
{
AddSubModelDialog.doFunction();
AddSubModelDialog.deleteTextBox();
continue;
}
else if (key == SDLK_PAUSE ||
key == SDLK_ESCAPE)
{
//cancels current action and closes text box
//OpenFileDialog.text_pointer = NULL;
AddSubModelDialog.deleteTextBox();
continue;
}
else if (key > 12 && key < 128)
{
if (modifier & KMOD_CAPS ||
modifier & KMOD_LSHIFT ||
modifier & KMOD_RSHIFT)
{
if (key >= 'a' && key <= 'z')
{
key = toupper(key);
}
else
{
key = shiftChar(key);
}
}
AddSubModelDialog.incrementChar(key);
}
AddSubModelDialog.updateTextBox();
//interrupts input when text box is up
continue;
}
}
else if (AddSubModelFileDialog.m_Up)
{
if (event.type == SDL_KEYDOWN)
{
Uint16 key = event.key.keysym.sym;
SDLMod modifier = event.key.keysym.mod;
if (key == SDLK_BACKSPACE)
{
AddSubModelFileDialog.decrementChar();
}
else if (key == SDLK_KP_ENTER || key == SDLK_RETURN)
{
AddSubModelFileDialog.doFunction();
AddSubModelFileDialog.deleteTextBox();
continue;
}
else if (key == SDLK_PAUSE ||
key == SDLK_ESCAPE)
{
//cancels current action and closes text box
//OpenFileDialog.text_pointer = NULL;
AddSubModelFileDialog.deleteTextBox();
continue;
}
else if (key > 12 && key < 128)
{
if (modifier & KMOD_CAPS ||
modifier & KMOD_LSHIFT ||
modifier & KMOD_RSHIFT)
{
if (key >= 'a' && key <= 'z')
{
key = toupper(key);
}
else
{
key = shiftChar(key);
}
}
AddSubModelFileDialog.incrementChar(key);
}
AddSubModelFileDialog.updateTextBox();
//interrupts input when text box is up
continue;
}
}
else if (ReadAnimFileDialog.m_Up)
{
if (event.type == SDL_KEYDOWN)
{
Uint16 key = event.key.keysym.sym;
SDLMod modifier = event.key.keysym.mod;
if (key == SDLK_BACKSPACE)
{
ReadAnimFileDialog.decrementChar();
}
else if (key == SDLK_KP_ENTER || key == SDLK_RETURN)
{
ReadAnimFileDialog.doFunction();
ReadAnimFileDialog.deleteTextBox();
continue;
}
else if (key == SDLK_PAUSE ||
key == SDLK_ESCAPE)
{
//cancels current action and closes text box
//OpenFileDialog.text_pointer = NULL;
ReadAnimFileDialog.deleteTextBox();
continue;
}
else if (key > 12 && key < 128)
{
if (modifier & KMOD_CAPS ||
modifier & KMOD_LSHIFT ||
modifier & KMOD_RSHIFT)
{
if (key >= 'a' && key <= 'z')
{
key = toupper(key);
}
else
{
key = shiftChar(key);
}
}
ReadAnimFileDialog.incrementChar(key);
}
ReadAnimFileDialog.updateTextBox();
//interrupts input when text box is up
continue;
}
}
else if (WriteAnimFileDialog.m_Up)
{
if (event.type == SDL_KEYDOWN)
{
Uint16 key = event.key.keysym.sym;
SDLMod modifier = event.key.keysym.mod;
if (key == SDLK_BACKSPACE)
{
WriteAnimFileDialog.decrementChar();
}
else if (key == SDLK_KP_ENTER || key == SDLK_RETURN)
{
WriteAnimFileDialog.doFunction();
WriteAnimFileDialog.deleteTextBox();
continue;
}
else if (key == SDLK_PAUSE ||
key == SDLK_ESCAPE)
{
//cancels current action and closes text box
//OpenFileDialog.text_pointer = NULL;
WriteAnimFileDialog.deleteTextBox();
continue;
}
else if (key > 12 && key < 128)
{
if (modifier & KMOD_CAPS ||
modifier & KMOD_LSHIFT ||
modifier & KMOD_RSHIFT)
{
if (key >= 'a' && key <= 'z')
{
key = toupper(key);
}
else
{
key = shiftChar(key);
}
}
WriteAnimFileDialog.incrementChar(key);
}
WriteAnimFileDialog.updateTextBox();
//interrupts input when text box is up
continue;
}
}
if (event.type == SDL_KEYDOWN)
{
Uint16 key = event.key.keysym.sym;
SDLMod modifier = event.key.keysym.mod;
if ((key == SDLK_KP_ENTER || key == SDLK_RETURN) && modifier & KMOD_LALT)
{
// Resize SDL video mode
g_Screen.m_flags ^= SDL_FULLSCREEN;
if( !g_Screen.setVideoMode() )
fprintf(stderr, "WARNING: Video mode set failed: %s", SDL_GetError());
// Resize OpenGL viewport
glViewport(0, 0, g_Screen.m_width, g_Screen.m_height);
if (ResMaster.isTextureMapperUp())
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, g_Screen.m_width, 0, g_Screen.m_height, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
else
{
// Restore OpenGL states (SDL seems to lost them)
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
gluPerspective(30, (double)g_Screen.m_width/g_Screen.m_height, 1, 1000);
gluLookAt(0,0,250, 0,0,0, 0,1,0);
//glEnable(GL_LIGHTING);
//glEnable(GL_LIGHT0);
//glEnable(GL_NORMALIZE);
//glEnable(GL_COLOR_MATERIAL);
}
glDisable(GL_CULL_FACE);
//glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
// Reloads texture and bind
ResMaster.freeTexPages();
ResMaster.loadTexPages();
ResMaster.cacheGridsVertices();
// Flush vbo id's
Uint32 index;
for (index = 0;index < ResMaster.m_pieCount;index++)
{
ResMaster.getPieAt(index)->flushVBOPolys();
}
SDL_Event newEvent;
newEvent.type = SDL_VIDEORESIZE;
newEvent.resize.w = g_Screen.m_width;
newEvent.resize.h = g_Screen.m_height;
SDL_PushEvent(&newEvent);
}
}
// Send event to AntTweakBar
handled = TwEventSDL(&event);
// If event has not been handled by AntTweakBar, process it
if( !handled )
{
switch( event.type )
{
case SDL_KEYUP:
case SDL_KEYDOWN:
inputKeyEvent(event.key, event.type);
break;
case SDL_MOUSEMOTION:
inputMotionMouseEvent(event.motion);
break;
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEBUTTONDOWN:
inputButtonMouseEvent(event.button, event.type);
break;
case SDL_QUIT: // Window is closed
bQuit = true;
break;
case SDL_VIDEORESIZE: // Window size has changed
// Resize SDL video mode
g_Screen.m_width = event.resize.w;
g_Screen.m_height = event.resize.h;
if( !g_Screen.setVideoMode() )
fprintf(stderr, "WARNING: Video mode set failed: %s", SDL_GetError());
// Resize OpenGL viewport
glViewport(0, 0, g_Screen.m_width, g_Screen.m_height);
if (ResMaster.isTextureMapperUp())
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, g_Screen.m_width, 0, g_Screen.m_height, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
else
{
// Restore OpenGL states (SDL seems to lost them)
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
gluPerspective(30, (double)g_Screen.m_width/g_Screen.m_height, 1, 1000);
gluLookAt(0,0,250, 0,0,0, 0,1,0);
//glEnable(GL_LIGHTING);
//glEnable(GL_LIGHT0);
//glEnable(GL_NORMALIZE);
//glEnable(GL_COLOR_MATERIAL);
}
glDisable(GL_CULL_FACE);
//glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
// Reloads texture and bind
ResMaster.freeTexPages();
ResMaster.loadTexPages();
ResMaster.cacheGridsVertices();
// Flush vbo id's
Uint32 index;
for (index = 0;index < ResMaster.m_pieCount;index++)
{
ResMaster.getPieAt(index)->flushVBOPolys();
}
// TwWindowSize has been called by TwEventSDL, so it is not necessary to call it again here.
break;
}
}
else
{
// Resets all keys and buttons
inputInitialize();
// Input in TwBars rebuilds vbo's
switch( event.type )
{
case SDL_KEYUP:
case SDL_KEYDOWN:
case SDL_MOUSEMOTION:
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEBUTTONDOWN:
// Flush vbo id's
Uint32 index;
for (index = 0;index < ResMaster.m_pieCount;index++)
{
CPieInternal *temp = ResMaster.getPieAt(index);
if (temp)
{
temp->flushVBOPolys();
}
}
break;
default:
break;
}
}
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f,0.0f,0.0f);
glColor4ub(255, 255, 255, 255);
ResMaster.logic();
ResMaster.draw();
ResMaster.updateInput();
// Draw tweak bars
TwDraw();
// Present frame buffer
SDL_GL_SwapBuffers();
SDL_Delay(10);
}
// Remove TW bars
//removeBars();
// Terminate AntTweakBar
TwTerminate();
// Terminate SDL
SDL_Quit();
ResMaster.~CResMaster();
return 1;
}