421 lines
9.8 KiB
C++
421 lines
9.8 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 = (float)(cursor_pos.x - startx) / 200;
|
|
float diffposy = (float)(cursor_pos.y - starty) / 200;
|
|
yposition = startposy - diffposy;
|
|
xposition = startposx + diffposx;
|
|
}
|
|
}
|
|
|
|
void DrawActionVec(size_t nr, const string& s, int y, const TVector3d& 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;
|
|
|
|
// ------------- 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.SetProps("bold", 20, colYellow);
|
|
FT.DrawString(-1, 10, "Edit mode");
|
|
|
|
if (CharHasChanged()) DrawChanged();
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
FT.SetFont("normal");
|
|
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;
|
|
}
|