quadrilateralcowboy/ui/MarkerWindow.cpp

360 lines
11 KiB
C++

/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code 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.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../idlib/precompiled.h"
#pragma hdrstop
// included for image uploading for player stat graph
#include "../renderer/Image.h"
#include "DeviceContext.h"
#include "Window.h"
#include "UserInterfaceLocal.h"
#include "MarkerWindow.h"
class idImage;
void idMarkerWindow::CommonInit() {
numStats = 0;
currentTime = -1;
currentMarker = -1;
stopTime = -1;
imageBuff = NULL;
markerMat = NULL;
markerStop = NULL;
}
idMarkerWindow::idMarkerWindow(idDeviceContext *d, idUserInterfaceLocal *g) : idWindow(d, g) {
dc = d;
gui = g;
CommonInit();
}
idMarkerWindow::idMarkerWindow(idUserInterfaceLocal *g) : idWindow(g) {
gui = g;
CommonInit();
}
idMarkerWindow::~idMarkerWindow() {
}
bool idMarkerWindow::ParseInternalVar(const char *_name, idParser *src) {
if (idStr::Icmp(_name, "markerMat") == 0) {
idStr str;
ParseString(src, str);
markerMat = declManager->FindMaterial(str);
markerMat->SetSort( SS_GUI );
return true;
}
if (idStr::Icmp(_name, "markerStop") == 0) {
idStr str;
ParseString(src, str);
markerStop = declManager->FindMaterial(str);
markerStop->SetSort( SS_GUI );
return true;
}
if (idStr::Icmp(_name, "markerColor") == 0) {
ParseVec4(src, markerColor);
return true;
}
return idWindow::ParseInternalVar(_name, src);
}
idWinVar *idMarkerWindow::GetWinVarByName(const char *_name, bool fixup) {
return idWindow::GetWinVarByName(_name, fixup);
}
const char *idMarkerWindow::HandleEvent(const sysEvent_t *event, bool *updateVisuals) {
if (!(event->evType == SE_KEY && event->evValue2)) {
return "";
}
int key = event->evValue;
if (event->evValue2 && key == K_MOUSE1) {
gui->GetDesktop()->SetChildWinVarVal("markerText", "text", "");
idRectangle r;
int c = markerTimes.Num();
int i;
for (i = 0; i < c; i++) {
markerData_t &md = markerTimes[i];
if (md.rect.Contains(gui->CursorX(), gui->CursorY())) {
currentMarker = i;
gui->SetStateInt( "currentMarker", md.time );
stopTime = md.time;
gui->GetDesktop()->SetChildWinVarVal("markerText", "text", va("Marker set at %.2i:%.2i", md.time / 60 / 60, (md.time / 60) % 60));
gui->GetDesktop()->SetChildWinVarVal("markerText", "visible", "1");
gui->GetDesktop()->SetChildWinVarVal("markerBackground", "matcolor", "1 1 1 1");
gui->GetDesktop()->SetChildWinVarVal("markerBackground", "text", "");
gui->GetDesktop()->SetChildWinVarVal("markerBackground", "background", md.mat->GetName());
break;
}
}
if ( i == c ) {
// no marker selected;
currentMarker = -1;
gui->SetStateInt( "currentMarker", currentTime );
stopTime = currentTime;
gui->GetDesktop()->SetChildWinVarVal("markerText", "text", va("Marker set at %.2i:%.2i", currentTime / 60 / 60, (currentTime / 60) % 60));
gui->GetDesktop()->SetChildWinVarVal("markerText", "visible", "1");
gui->GetDesktop()->SetChildWinVarVal("markerBackground", "matcolor", "0 0 0 0");
gui->GetDesktop()->SetChildWinVarVal("markerBackground", "text", "No Preview");
}
float pct = gui->State().GetFloat( "loadPct" );
int len = gui->State().GetInt( "loadLength" );
if (stopTime > len * pct) {
return "cmdDemoGotoMarker";
}
} else if (key == K_MOUSE2) {
stopTime = -1;
gui->GetDesktop()->SetChildWinVarVal("markerText", "text", "");
gui->SetStateInt( "currentMarker", -1 );
return "cmdDemoGotoMarker";
} else if (key == K_SPACE) {
return "cmdDemoPauseFrame";
}
return "";
}
void idMarkerWindow::PostParse() {
idWindow::PostParse();
}
static const int HEALTH_MAX = 100;
static const int COMBAT_MAX = 100;
static const int RATE_MAX = 125;
static const int STAMINA_MAX = 12;
void idMarkerWindow::Draw(int time, float x, float y) {
float pct;
idRectangle r = clientRect;
int len = gui->State().GetInt( "loadLength" );
if (len == 0) {
len = 1;
}
if (numStats > 1) {
int c = markerTimes.Num();
if (c > 0) {
for (int i = 0; i < c; i++) {
markerData_t &md = markerTimes[i];
if (md.rect.w == 0) {
md.rect.x = (r.x + r.w * ((float)md.time / len)) - 8;
md.rect.y = r.y + r.h - 20;
md.rect.w = 16;
md.rect.h = 16;
}
dc->DrawMaterial(md.rect.x, md.rect.y, md.rect.w, md.rect.h, markerMat, markerColor);
}
}
}
r.y += 10;
if (r.w > 0 && r.Contains(gui->CursorX(), gui->CursorY())) {
pct = (gui->CursorX() - r.x) / r.w;
currentTime = len * pct;
r.x = (gui->CursorX() > r.x + r.w - 40) ? gui->CursorX() - 40 : gui->CursorX();
r.y = gui->CursorY() - 15;
r.w = 40;
r.h = 20;
dc->DrawText(va("%.2i:%.2i", currentTime / 60 / 60, (currentTime / 60) % 60), 0.25, 0, idDeviceContext::colorWhite, r, false);
}
if (stopTime >= 0 && markerStop) {
r = clientRect;
r.y += (r.h - 32) / 2;
pct = (float)stopTime / len;
r.x += (r.w * pct) - 16;
idVec4 color(1, 1, 1, 0.65f);
dc->DrawMaterial(r.x, r.y, 32, 32, markerStop, color);
}
}
const char *idMarkerWindow::RouteMouseCoords(float xd, float yd) {
const char * ret = idWindow::RouteMouseCoords(xd, yd);
idRectangle r;
int i, c = markerTimes.Num();
int len = gui->State().GetInt( "loadLength" );
if (len == 0) {
len = 1;
}
for (i = 0; i < c; i++) {
markerData_t &md = markerTimes[i];
if (md.rect.Contains(gui->CursorY(), gui->CursorX())) {
gui->GetDesktop()->SetChildWinVarVal("markerBackground", "background", md.mat->GetName());
gui->GetDesktop()->SetChildWinVarVal("markerBackground", "matcolor", "1 1 1 1");
gui->GetDesktop()->SetChildWinVarVal("markerBackground", "text", "");
break;
}
}
if (i >= c) {
if (currentMarker == -1) {
gui->GetDesktop()->SetChildWinVarVal("markerBackground", "matcolor", "0 0 0 0");
gui->GetDesktop()->SetChildWinVarVal("markerBackground", "text", "No Preview");
} else {
markerData_t &md = markerTimes[currentMarker];
gui->GetDesktop()->SetChildWinVarVal("markerBackground", "background", md.mat->GetName());
gui->GetDesktop()->SetChildWinVarVal("markerBackground", "matcolor", "1 1 1 1");
gui->GetDesktop()->SetChildWinVarVal("markerBackground", "text", "");
}
}
return ret;
}
void idMarkerWindow::Point(int x, int y, dword *out, dword color) {
int index = (63-y) * 512 + x;
if (index >= 0 && index < 512 * 64) {
out[index] = color;
} else {
common->Warning("Out of bounds on point %i : %i", x, y);
}
}
void idMarkerWindow::Line(int x1, int y1, int x2, int y2, dword* out, dword color) {
int deltax = abs(x2 - x1);
int deltay = abs(y2 - y1);
int incx = (x1 > x2) ? -1 : 1;
int incy = (y1 > y2) ? -1 : 1;
int right, up, dir;
if (deltax > deltay) {
right = deltay * 2;
up = right - deltax * 2;
dir = right - deltax;
while (deltax-- >= 0) {
Point(x1, y1, out, color);
x1 += incx;
y1 += (dir > 0) ? incy : 0;
dir += (dir > 0) ? up : right;
}
} else {
right = deltax * 2;
up = right - deltay * 2;
dir = right - deltay;
while ( deltay-- >= 0) {
Point(x1, y1, out, color);
x1 += (dir > 0) ? incx : 0;
y1 += incy;
dir += (dir > 0) ? up : right;
}
}
}
void idMarkerWindow::Activate(bool activate, idStr &act) {
idWindow::Activate(activate, act);
if (activate) {
int i;
gui->GetDesktop()->SetChildWinVarVal("markerText", "text", "");
imageBuff = (dword*)Mem_Alloc(512*64*4);
markerTimes.Clear();
currentMarker = -1;
currentTime = -1;
stopTime = -1;
statData = gui->State().GetString( "statData" );
numStats = 0;
if (statData.Length()) {
idFile *file = fileSystem->OpenFileRead(statData);
if (file) {
file->Read(&numStats, sizeof(numStats));
file->Read(loggedStats, numStats * sizeof(loggedStats[0]));
for (i = 0; i < numStats; i++) {
if (loggedStats[i].health < 0) {
loggedStats[i].health = 0;
}
if (loggedStats[i].stamina < 0) {
loggedStats[i].stamina = 0;
}
if (loggedStats[i].heartRate < 0) {
loggedStats[i].heartRate = 0;
}
if (loggedStats[i].combat < 0) {
loggedStats[i].combat = 0;
}
}
fileSystem->CloseFile(file);
}
}
if (numStats > 1 && background) {
idStr markerPath = statData;
markerPath.StripFilename();
idFileList *markers;
markers = fileSystem->ListFiles( markerPath, ".tga", false, true );
idStr name;
for ( i = 0; i < markers->GetNumFiles(); i++ ) {
name = markers->GetFile( i );
markerData_t md;
md.mat = declManager->FindMaterial( name );
md.mat->SetSort( SS_GUI );
name.StripPath();
name.StripFileExtension();
md.time = atoi(name);
markerTimes.Append(md);
}
fileSystem->FreeFileList( markers );
memset(imageBuff, 0, 512*64*4);
float step = 511.0f / (numStats - 1);
float startX = 0;
float x1, y1, x2, y2;
x1 = 0 - step;
for (i = 0; i < numStats-1; i++) {
x1 += step;
x2 = x1 + step;
y1 = 63 * ((float)loggedStats[i].health / HEALTH_MAX);
y2 = 63 * ((float)loggedStats[i+1].health / HEALTH_MAX);
Line(x1, y1, x2, y2, imageBuff, 0xff0000ff);
y1 = 63 * ((float)loggedStats[i].heartRate / RATE_MAX);
y2 = 63 * ((float)loggedStats[i+1].heartRate / RATE_MAX);
Line(x1, y1, x2, y2, imageBuff, 0xff00ff00);
// stamina not quite as high on graph so health does not get obscured with both at 100%
y1 = 62 * ((float)loggedStats[i].stamina / STAMINA_MAX);
y2 = 62 * ((float)loggedStats[i+1].stamina / STAMINA_MAX);
Line(x1, y1, x2, y2, imageBuff, 0xffff0000);
y1 = 63 * ((float)loggedStats[i].combat / COMBAT_MAX);
y2 = 63 * ((float)loggedStats[i+1].combat / COMBAT_MAX);
Line(x1, y1, x2, y2, imageBuff, 0xff00ffff);
}
const shaderStage_t *stage = background->GetStage(0);
if (stage) {
stage->texture.image->UploadScratch((byte*)imageBuff, 512, 64);
}
Mem_Free(imageBuff);
}
}
}
void idMarkerWindow::MouseExit() {
idWindow::MouseExit();
}
void idMarkerWindow::MouseEnter() {
idWindow::MouseEnter();
}