424 lines
10 KiB
C++
424 lines
10 KiB
C++
/* --------------------------------------------------------------------
|
|
EXTREME TUXRACER
|
|
|
|
Copyright (C) 1999-2001 Jasmin F. Patry (Tuxracer)
|
|
Copyright (C) 2010 Extreme Tuxracer Team
|
|
|
|
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 2
|
|
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.
|
|
---------------------------------------------------------------------*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <etr_config.h>
|
|
#endif
|
|
|
|
#include "tool_char.h"
|
|
#include "tools.h"
|
|
#include "ogl.h"
|
|
#include "font.h"
|
|
#include "textures.h"
|
|
#include "spx.h"
|
|
#include "tux.h"
|
|
#include "winsys.h"
|
|
|
|
static size_t firstnode = 0;
|
|
static size_t lastnode;
|
|
static size_t curr_node = 0;
|
|
static size_t firstact = 0;
|
|
static size_t lastact;
|
|
static size_t curr_act = 0;
|
|
|
|
static float xposition = 0;
|
|
static float yposition = 0;
|
|
static float zposition = -3;
|
|
static float xrotation = 0;
|
|
static float yrotation = 0;
|
|
static float zrotation = 0;
|
|
|
|
static int drawcount = 0;
|
|
static int charbase = 24;
|
|
static bool must_render = true;
|
|
static TCharAction *action;
|
|
static bool shift = false;
|
|
static bool control = false;
|
|
static bool alt = false;
|
|
static TCharAction Undo;
|
|
static int startx, starty;
|
|
static double startrotx, startroty, startposx, startposy;
|
|
static bool rotactive = false;
|
|
static bool moveactive = false;
|
|
static int comp = 0;
|
|
|
|
void InitCharTools () {
|
|
charbase = (int)((Winsys.resolution.height - 200) / 18);
|
|
firstnode = 1;
|
|
lastnode = TestChar.GetNumNodes () -1;
|
|
curr_node = firstnode;
|
|
curr_act = firstact;
|
|
lastact = TestChar.GetNumActs (curr_node) -1;
|
|
action = TestChar.GetAction (curr_node);
|
|
StoreAction (action);
|
|
}
|
|
|
|
void StoreAction (TCharAction *act) {
|
|
for (size_t i=0; i<=act->num; i++) {
|
|
Undo.vec[i] = act->vec[i];
|
|
Undo.dval[i] = act->dval[i];
|
|
}
|
|
}
|
|
|
|
void RecallAction (TCharAction *act) {
|
|
for (size_t i=0; i<=act->num; i++) {
|
|
act->vec[i] = Undo.vec[i];
|
|
act->dval[i] = Undo.dval[i];
|
|
}
|
|
}
|
|
|
|
void ChangeValue (int type, double fact) {
|
|
if (type == 0 || type == 4) {
|
|
if (comp == 0) {
|
|
action->vec[curr_act].x += 0.02 * fact;
|
|
action->vec[curr_act].y += 0.02 * fact;
|
|
action->vec[curr_act].z += 0.02 * fact;
|
|
} else if (comp == 1) action->vec[curr_act].x += 0.02 * fact;
|
|
else if (comp == 2) action->vec[curr_act].y += 0.02 * fact;
|
|
else if (comp == 3) action->vec[curr_act].z += 0.02 * fact;
|
|
} else if (type > 0 && type < 4) {
|
|
action->dval[curr_act] += 1 * fact;
|
|
} else if (type == 5) {
|
|
action->dval[curr_act] += 1 * fact;
|
|
}
|
|
TestChar.RefreshNode (curr_node);
|
|
SetCharChanged (true);
|
|
}
|
|
|
|
void ChangeNode (int steps) {
|
|
bool ch;
|
|
if (steps > 0) ch = (curr_node + steps <= lastnode);
|
|
else ch = (curr_node + steps >= firstnode);
|
|
if (ch) {
|
|
curr_node += steps;
|
|
curr_act = firstact;
|
|
lastact = TestChar.GetNumActs (curr_node) -1;
|
|
action = TestChar.GetAction (curr_node);
|
|
if (action->num > 0 && action->type[0] == 4) comp = 0;
|
|
else comp = 1;
|
|
StoreAction (action);
|
|
}
|
|
}
|
|
|
|
void SetRotation (double x, double y, double z) {
|
|
xrotation = x;
|
|
yrotation = y;
|
|
zrotation = z;
|
|
}
|
|
|
|
void CharKeys (unsigned int key, bool special, bool release, int x, int y) {
|
|
must_render = true;
|
|
|
|
if (ToolsFinalStage ()) {
|
|
if (key == SDLK_y || key == SDLK_j) {
|
|
SaveToolCharacter ();
|
|
SaveToolFrame ();
|
|
State::manager.RequestQuit();
|
|
} else if (key == SDLK_n) State::manager.RequestQuit();
|
|
return;
|
|
}
|
|
|
|
if (key == 304) shift = !release;
|
|
if (key == 306) control = !release;
|
|
if (key == 308) alt = !release;
|
|
|
|
if (release) return;
|
|
|
|
int type = action->type[curr_act];
|
|
switch (key) {
|
|
case SDLK_TAB:
|
|
SetToolMode (1);
|
|
break;
|
|
case SDLK_ESCAPE:
|
|
case SDLK_q:
|
|
QuitTool ();
|
|
break;
|
|
case SDLK_F10:
|
|
ScreenshotN ();
|
|
break;
|
|
case SDLK_s:
|
|
SaveToolCharacter ();
|
|
break;
|
|
case SDLK_c:
|
|
ScreenshotN ();
|
|
break;
|
|
case SDLK_m:
|
|
TestChar.useMaterials = !TestChar.useMaterials;
|
|
break;
|
|
case SDLK_h:
|
|
TestChar.useHighlighting = !TestChar.useHighlighting;
|
|
break;
|
|
case SDLK_r:
|
|
TestChar.Reset ();
|
|
ReloadToolCharacter ();
|
|
Tools.Enter ();
|
|
break;
|
|
case SDLK_u:
|
|
if (action != NULL) {
|
|
RecallAction (action);
|
|
TestChar.RefreshNode (curr_node);
|
|
}
|
|
break;
|
|
case SDLK_PLUS:
|
|
case SDLK_EQUALS: // zoom in
|
|
zposition += 0.1;
|
|
xposition -= 0.03;
|
|
break;
|
|
case SDLK_MINUS: // zoom out
|
|
zposition -= 0.1;
|
|
xposition += 0.03;
|
|
break;
|
|
|
|
// set rotations for view
|
|
case SDLK_1:
|
|
SetRotation (0, 0, 0);
|
|
break;
|
|
case SDLK_2:
|
|
SetRotation (-50, 180, 15);
|
|
break;
|
|
case SDLK_3:
|
|
SetRotation (0, 180, 0);
|
|
break;
|
|
case SDLK_4:
|
|
SetRotation (0, -80, 0);
|
|
break;
|
|
|
|
// select node
|
|
case SDLK_PAGEUP:
|
|
ChangeNode (-1);
|
|
break;
|
|
case SDLK_PAGEDOWN:
|
|
ChangeNode (1);
|
|
break;
|
|
case SDLK_END:
|
|
ChangeNode (charbase);
|
|
break;
|
|
case SDLK_HOME:
|
|
ChangeNode (-charbase);
|
|
break;
|
|
|
|
// select action
|
|
case SDLK_DOWN:
|
|
if (curr_act < lastact) curr_act++;
|
|
if (action->type[curr_act] == 4) comp = 0;
|
|
else comp = 1;
|
|
break;
|
|
case SDLK_UP:
|
|
if (curr_act > 0) curr_act--;
|
|
if (action->type[curr_act] == 4) comp = 0;
|
|
else comp = 1;
|
|
break;
|
|
case SDLK_LEFT:
|
|
ChangeValue (type, -1);
|
|
break;
|
|
case SDLK_RIGHT:
|
|
ChangeValue (type, 1);
|
|
break;
|
|
|
|
// select value
|
|
case SDLK_SPACE:
|
|
if (type == 0 || type == 4) {
|
|
comp++;
|
|
if (comp > 3) comp = 0;
|
|
if (type == 0 && comp == 0) comp = 1;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CharMouse (int button, int state, int x, int y) {
|
|
must_render = true;
|
|
if (ToolsFinalStage ()) return;
|
|
|
|
if (state<1) {
|
|
rotactive = false;
|
|
moveactive = false;
|
|
return;
|
|
}
|
|
if (button == 1) {
|
|
startx = x;
|
|
starty = y;
|
|
startrotx = xrotation;
|
|
startroty = yrotation;
|
|
rotactive = true;
|
|
} else if (button == 3) {
|
|
startx = x;
|
|
starty = y;
|
|
startposx = xposition;
|
|
startposy = yposition;
|
|
moveactive = true;
|
|
} else if (button == 4) {
|
|
zposition -= 0.1;
|
|
xposition += 0.03;
|
|
} else if (button == 5) {
|
|
zposition += 0.1;
|
|
xposition -= 0.03;
|
|
}
|
|
}
|
|
|
|
void CharMotion (int x, int y) {
|
|
must_render = true;
|
|
if (rotactive) {
|
|
int diffx = cursor_pos.x - startx;
|
|
int diffy = cursor_pos.y - starty;
|
|
yrotation = startroty + diffx;
|
|
xrotation = startrotx + diffy;
|
|
}
|
|
if (moveactive) {
|
|
float diffposx = (double)(cursor_pos.x - startx) / 200;
|
|
float diffposy = (double)(cursor_pos.y - starty) / 200;
|
|
yposition = startposy - diffposy;
|
|
xposition = startposx + diffposx;
|
|
}
|
|
}
|
|
|
|
void DrawActionVec (size_t nr, const string& s, int y, const TVector3& v) {
|
|
FT.SetColor (colLGrey);
|
|
FT.DrawString (20, y, s);
|
|
if (nr == curr_act) {
|
|
if (comp == 0) {
|
|
FT.SetColor (colYellow);
|
|
FT.DrawString (100, y, Float_StrN (v.x, 2));
|
|
FT.DrawString (150, y, Float_StrN (v.y, 2));
|
|
FT.DrawString (200, y, Float_StrN (v.z, 2));
|
|
} else {
|
|
if (comp == 1) FT.SetColor (colYellow);
|
|
else FT.SetColor (colLGrey);
|
|
FT.DrawString (100, y, Float_StrN (v.x, 2));
|
|
if (comp == 2) FT.SetColor (colYellow);
|
|
else FT.SetColor (colLGrey);
|
|
FT.DrawString (150, y, Float_StrN (v.y, 2));
|
|
if (comp == 3) FT.SetColor (colYellow);
|
|
else FT.SetColor (colLGrey);
|
|
FT.DrawString (200, y, Float_StrN (v.z, 2));
|
|
}
|
|
} else {
|
|
FT.DrawString (100, y, Float_StrN (v.x, 2));
|
|
FT.DrawString (150, y, Float_StrN (v.y, 2));
|
|
FT.DrawString (200, y, Float_StrN (v.z, 2));
|
|
}
|
|
}
|
|
|
|
void DrawActionFloat (size_t nr, const string& s, int y, float f) {
|
|
FT.SetColor (colLGrey);
|
|
FT.DrawString (20, y, s);
|
|
if (nr == curr_act) FT.SetColor (colYellow);
|
|
else FT.SetColor (colLGrey);
|
|
FT.DrawString (100, y, Float_StrN (f, 2));
|
|
}
|
|
|
|
void RenderChar (double timestep) {
|
|
if (!must_render) return;
|
|
bool is_visible = false;
|
|
check_gl_error();
|
|
|
|
// ------------- 3d scenery ---------------------------------------
|
|
ScopedRenderMode rm1(TUX);
|
|
ClearRenderContext (colDDBackgr);
|
|
TestChar.highlight_node = TestChar.GetNodeName (curr_node);
|
|
|
|
glLoadIdentity ();
|
|
glPushMatrix ();
|
|
SetToolLight ();
|
|
|
|
TestChar.ResetRoot ();
|
|
TestChar.ResetJoints ();
|
|
glTranslatef (xposition, yposition, zposition);
|
|
glRotatef (xrotation, 1, 0, 0);
|
|
glRotatef (yrotation, 0, 1, 0);
|
|
glRotatef (zrotation, 0, 0, 1);
|
|
|
|
if (drawcount > 0) TestChar.Draw ();
|
|
glPopMatrix ();
|
|
drawcount++;
|
|
|
|
// --------------- 2d screen --------------------------------------
|
|
SetupGuiDisplay ();
|
|
ScopedRenderMode rm2(TEXFONT);
|
|
|
|
FT.SetFont ("bold");
|
|
FT.SetSize (20);
|
|
FT.SetColor (colYellow);
|
|
FT.DrawString (-1, 10, "Edit mode");
|
|
|
|
if (CharHasChanged ()) DrawChanged ();
|
|
|
|
FT.SetFont ("normal");
|
|
FT.SetSize (16);
|
|
for (size_t i=0; i<=lastnode; i++) {
|
|
if (i != curr_node) {
|
|
FT.SetColor (colLGrey);
|
|
FT.SetFont ("normal");
|
|
} else {
|
|
FT.SetColor (colYellow);
|
|
FT.SetFont ("bold");
|
|
}
|
|
int xl = ITrunc ((int)i, charbase) * 100 + 20;
|
|
int yt = IFrac ((int)i, charbase) * 18 + 60;
|
|
FT.DrawString (xl, yt, TestChar.GetNodeJoint (i));
|
|
}
|
|
|
|
size_t num = action->num;
|
|
int type;
|
|
if (num > 0) {
|
|
for (size_t i=0; i<num; i++) {
|
|
is_visible = false;
|
|
type = action->type[i];
|
|
int yt = Winsys.resolution.height - 120 + (int)i * 18;
|
|
switch (type) {
|
|
case 0:
|
|
DrawActionVec (i, "trans", yt, action->vec[i]);
|
|
break;
|
|
case 1:
|
|
DrawActionFloat (i, "x-rot", yt, action->dval[i]);
|
|
break;
|
|
case 2:
|
|
DrawActionFloat (i, "y-rot", yt, action->dval[i]);
|
|
break;
|
|
case 3:
|
|
DrawActionFloat (i, "z-rot", yt, action->dval[i]);
|
|
break;
|
|
case 4:
|
|
DrawActionVec (i, "scale", yt, action->vec[i]);
|
|
break;
|
|
case 5:
|
|
DrawActionFloat (i, "vis", yt, action->dval[i]);
|
|
is_visible = true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (is_visible) FT.SetColor (colYellow);
|
|
else FT.SetColor (colLGrey);
|
|
FT.DrawString (20, 20, action->name);
|
|
|
|
if (ToolsFinalStage ()) {
|
|
FT.SetSize (20);
|
|
FT.SetColor (colYellow);
|
|
FT.DrawString (-1, Winsys.resolution.height - 50, "Quit program. Save character list (y/n)");
|
|
}
|
|
|
|
Reshape (Winsys.resolution.width, Winsys.resolution.height);
|
|
Winsys.SwapBuffers ();
|
|
if (drawcount > 3) must_render = false;
|
|
}
|