490 lines
11 KiB
C++
490 lines
11 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/>.
|
|
*
|
|
* $Revision$
|
|
* $Id$
|
|
* $HeadURL$
|
|
*/
|
|
|
|
#include "stdlib.h"
|
|
#include "stdio.h"
|
|
#include "string.h"
|
|
|
|
#include <SDL/SDL.h>
|
|
#include <AntTweakBar.h>
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h> // required by gl.h
|
|
#endif
|
|
#include <GL/gl.h>
|
|
#include <GL/glu.h>
|
|
|
|
#include "pie_types.h"
|
|
#include "imdloader.h"
|
|
#include "resmaster.h"
|
|
#include "physfs.h"
|
|
|
|
#include "screen.h"
|
|
#include "game_io.h"
|
|
|
|
static char mychars[255]; //temp char
|
|
static int mychars_index = 0; //temp char current index
|
|
static TwBar *textBar; //text box bar
|
|
static bool textboxUp = false; //whether textbox is up or not
|
|
|
|
static char *text_pointer = NULL;
|
|
|
|
// the dumbest shift kmod char handling function on planet earth :)
|
|
static uint16_t shiftChar(uint16_t key)
|
|
{
|
|
switch (key)
|
|
{
|
|
case '`':
|
|
key = '~';
|
|
break;
|
|
case '1':
|
|
key = '!';
|
|
break;
|
|
case '2':
|
|
key = '@';
|
|
break;
|
|
case '3':
|
|
key = '!';
|
|
break;
|
|
case '4':
|
|
key = '$';
|
|
break;
|
|
case '5':
|
|
key = '%';
|
|
break;
|
|
case '6':
|
|
key = '^';
|
|
break;
|
|
case '7':
|
|
key = '&';
|
|
break;
|
|
case '8':
|
|
key = '*';
|
|
break;
|
|
case '9':
|
|
key = '(';
|
|
break;
|
|
case '0':
|
|
key = ')';
|
|
break;
|
|
case '-':
|
|
key = '_';
|
|
break;
|
|
case '[':
|
|
key = '{';
|
|
break;
|
|
case ']':
|
|
key = '}';
|
|
break;
|
|
case ';':
|
|
key = ';';
|
|
break;
|
|
case '\'':
|
|
key = '\"';
|
|
break;
|
|
case ',':
|
|
key = '<';
|
|
break;
|
|
case '.':
|
|
key = '>';
|
|
break;
|
|
case '/':
|
|
key = '?';
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return key;
|
|
}
|
|
|
|
static void mychars_incr(uint16_t key)
|
|
{
|
|
if (mychars_index < 255 - 1)
|
|
{
|
|
char str = (uint8_t)key;
|
|
|
|
strncpy(&mychars[mychars_index], &str, 1);
|
|
mychars_index++;
|
|
}
|
|
}
|
|
|
|
static void mychars_decr()
|
|
{
|
|
if (mychars_index > 0)
|
|
{
|
|
mychars[mychars_index] = '\0';
|
|
mychars_index--;
|
|
}
|
|
}
|
|
|
|
static void TW_CALL addTextBox(void *clientData)
|
|
{
|
|
char test[255] = " label='";
|
|
//char test2[255] = "TextBox label='";
|
|
char *string = (char*)clientData;
|
|
int size = strlen(string);
|
|
|
|
if (textboxUp)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Sets the pointer
|
|
text_pointer = string;
|
|
|
|
textBar = TwNewBar("TextBox");
|
|
//snprintf(&test2[15], size, "%s", string);
|
|
//snprintf(&test2[15 + size], 1, "\'");
|
|
|
|
//TwDefine(&test2);
|
|
TwDefine("TextBox position = '200 400'");
|
|
TwDefine("TextBox size = '400 50'");
|
|
|
|
snprintf(&test[8], size, "%s", string);
|
|
snprintf(&test[8 + size], 1, "\'");
|
|
//strcat(&test[0], attr);
|
|
|
|
textboxUp = true;
|
|
|
|
strncpy(&mychars[0], string, size);
|
|
mychars_index = size;
|
|
|
|
TwAddVarRO(textBar, "textbox", TW_TYPE_INT32, &mychars_index, &test[0]);
|
|
}
|
|
|
|
static void deleteTextBox()
|
|
{
|
|
/*copies chars from mychars to text_pointer location if both
|
|
values are not null */
|
|
if (text_pointer && mychars_index)
|
|
{
|
|
int size = mychars_index;
|
|
strncpy(text_pointer, mychars, size);
|
|
text_pointer = NULL;
|
|
}
|
|
|
|
TwDeleteBar(textBar);
|
|
textboxUp = false;
|
|
}
|
|
|
|
static void updateTextBox(void)
|
|
{
|
|
char test[255] = " label='";
|
|
|
|
TwRemoveVar(textBar, "textbox");
|
|
|
|
snprintf(&test[8], mychars_index, "%s", &mychars[0]);
|
|
snprintf(&test[8 + mychars_index], 1, "\'");
|
|
|
|
TwAddVarRO(textBar, "textbox", TW_TYPE_INT32, &mychars_index, test);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
const SDL_VideoInfo* video = NULL;
|
|
bool bQuit = false;
|
|
const char path[] = "./";
|
|
|
|
PHYSFS_init(argv[0]);
|
|
|
|
PHYSFS_setWriteDir(path);
|
|
if (!PHYSFS_addToSearchPath( PHYSFS_getWriteDir(), 0 ))
|
|
{
|
|
fprintf(stderr, "unable to add path %s to physfs %s\n", PHYSFS_getLastError());
|
|
}
|
|
|
|
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;
|
|
g_Screen.m_flags = SDL_OPENGL | SDL_HWSURFACE | SDL_RESIZABLE;
|
|
g_Screen.m_width = 800;
|
|
g_Screen.m_height = 600;
|
|
|
|
|
|
//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_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_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->readTextureList("pages.txt");
|
|
|
|
ResMaster->loadTexPages();
|
|
|
|
ResMaster->addGUI();
|
|
|
|
//argc = 2;
|
|
//argv[1] = "drmbod08.pie";
|
|
|
|
if (argc < 2)
|
|
{
|
|
fprintf(stderr, "no file specified\n");
|
|
return 0;
|
|
}
|
|
|
|
testIMD = iV_ProcessIMD(argv[1]);
|
|
if (testIMD == NULL)
|
|
{
|
|
fprintf(stderr, "file %s doesn't exist\n", argv[1]);
|
|
return 0;
|
|
}
|
|
ResMaster->addPie(testIMD, argv[1]);
|
|
|
|
ResMaster->getPies()->ToFile("test13.pie");
|
|
|
|
|
|
while( !bQuit )
|
|
{
|
|
SDL_Event event;
|
|
int handled;
|
|
|
|
//glClearColor(0.6f, 0.95f, 1.0f, 1);
|
|
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 (textboxUp)
|
|
{
|
|
if (event.type == SDL_KEYDOWN)
|
|
{
|
|
uint16_t key = event.key.keysym.sym;
|
|
SDLMod modifier = event.key.keysym.mod;
|
|
|
|
if (key == SDLK_BACKSPACE)
|
|
{
|
|
mychars_decr();
|
|
}
|
|
else if (key == SDLK_KP_ENTER)
|
|
{
|
|
//finish and save changes to csv data
|
|
deleteTextBox();
|
|
continue;
|
|
}
|
|
else if (key == SDLK_PAUSE ||
|
|
key == SDLK_ESCAPE ||
|
|
key == SDLK_SPACE)
|
|
{
|
|
//cancels current action and closes text box
|
|
text_pointer = NULL;
|
|
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);
|
|
}
|
|
}
|
|
mychars_incr(key);
|
|
}
|
|
updateTextBox();
|
|
//interrupts input when text box is up
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// 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();
|
|
// TwWindowSize has been called by TwEventSDL, so it is not necessary to call it again here.
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
|
|
glTranslatef(0.0f,0.0f,0.0f);
|
|
|
|
glColor4ub(255, 255, 255, 255);
|
|
|
|
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();
|
|
|
|
delete ResMaster;
|
|
|
|
return 1;
|
|
}
|