]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/ui/MarkerWindow.cpp
hello world
[icculus/iodoom3.git] / neo / ui / MarkerWindow.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21
22 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.
23
24 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.
25
26 ===========================================================================
27 */
28
29 #include "../idlib/precompiled.h"
30 #pragma hdrstop
31
32 // included for image uploading for player stat graph
33 #include "../renderer/Image.h"
34
35 #include "DeviceContext.h"
36 #include "Window.h"
37 #include "UserInterfaceLocal.h"
38 #include "MarkerWindow.h"
39
40 class idImage;
41 void idMarkerWindow::CommonInit() {
42         numStats = 0;
43         currentTime = -1;
44         currentMarker = -1;
45         stopTime = -1;
46         imageBuff = NULL;
47         markerMat = NULL;
48         markerStop = NULL;
49 }
50
51 idMarkerWindow::idMarkerWindow(idDeviceContext *d, idUserInterfaceLocal *g) : idWindow(d, g) {
52         dc = d;
53         gui = g;
54         CommonInit();
55 }
56
57 idMarkerWindow::idMarkerWindow(idUserInterfaceLocal *g) : idWindow(g) {
58         gui = g;
59         CommonInit();
60 }
61
62 idMarkerWindow::~idMarkerWindow() {
63 }
64
65 bool idMarkerWindow::ParseInternalVar(const char *_name, idParser *src) {
66         if (idStr::Icmp(_name, "markerMat") == 0) {
67                 idStr str;
68                 ParseString(src, str);
69                 markerMat = declManager->FindMaterial(str);
70                 markerMat->SetSort( SS_GUI );
71                 return true;
72         }
73         if (idStr::Icmp(_name, "markerStop") == 0) {
74                 idStr str;
75                 ParseString(src, str);
76                 markerStop = declManager->FindMaterial(str);
77                 markerStop->SetSort( SS_GUI );
78                 return true;
79         }
80         if (idStr::Icmp(_name, "markerColor") == 0) {
81                 ParseVec4(src, markerColor);
82                 return true;
83         }
84         return idWindow::ParseInternalVar(_name, src);
85 }
86
87 idWinVar *idMarkerWindow::GetWinVarByName(const char *_name, bool fixup) {
88         return idWindow::GetWinVarByName(_name, fixup);
89 }
90
91 const char *idMarkerWindow::HandleEvent(const sysEvent_t *event, bool *updateVisuals) {
92
93         if (!(event->evType == SE_KEY && event->evValue2)) {
94                 return "";
95         }
96
97         int key = event->evValue;
98         if (event->evValue2 && key == K_MOUSE1) {
99                 gui->GetDesktop()->SetChildWinVarVal("markerText", "text", "");
100                 idRectangle r;
101                 int c = markerTimes.Num();
102                 int i;
103                 for (i = 0; i < c; i++) {
104                         markerData_t &md = markerTimes[i];
105                         if (md.rect.Contains(gui->CursorX(), gui->CursorY())) {
106                                 currentMarker = i;
107                                 gui->SetStateInt( "currentMarker", md.time );
108                                 stopTime = md.time;
109                                 gui->GetDesktop()->SetChildWinVarVal("markerText", "text", va("Marker set at %.2i:%.2i", md.time / 60 / 60, (md.time / 60) % 60));
110                                 gui->GetDesktop()->SetChildWinVarVal("markerText", "visible", "1");
111                                 gui->GetDesktop()->SetChildWinVarVal("markerBackground", "matcolor", "1 1 1 1");
112                                 gui->GetDesktop()->SetChildWinVarVal("markerBackground", "text", "");
113                                 gui->GetDesktop()->SetChildWinVarVal("markerBackground", "background", md.mat->GetName());
114                                 break;
115                         }
116                 }
117                 if ( i == c ) {
118                         // no marker selected;
119                         currentMarker = -1;
120                         gui->SetStateInt( "currentMarker", currentTime );
121                         stopTime = currentTime;
122                         gui->GetDesktop()->SetChildWinVarVal("markerText", "text", va("Marker set at %.2i:%.2i", currentTime / 60 / 60, (currentTime / 60) % 60));
123                         gui->GetDesktop()->SetChildWinVarVal("markerText", "visible", "1");
124                         gui->GetDesktop()->SetChildWinVarVal("markerBackground", "matcolor", "0 0 0 0");
125                         gui->GetDesktop()->SetChildWinVarVal("markerBackground", "text", "No Preview");
126                 }
127                 float pct = gui->State().GetFloat( "loadPct" );
128                 int len = gui->State().GetInt( "loadLength" );
129                 if (stopTime > len * pct) {
130                         return "cmdDemoGotoMarker";
131                 }
132         } else if (key == K_MOUSE2) {
133                 stopTime = -1;
134                 gui->GetDesktop()->SetChildWinVarVal("markerText", "text", "");
135                 gui->SetStateInt( "currentMarker", -1 );
136                 return "cmdDemoGotoMarker";
137         } else if (key == K_SPACE) {
138                 return "cmdDemoPauseFrame";
139         }
140
141         return "";
142 }
143
144 void idMarkerWindow::PostParse() {
145         idWindow::PostParse();
146 }
147
148 static const int HEALTH_MAX = 100;
149 static const int COMBAT_MAX = 100;
150 static const int RATE_MAX = 125;
151 static const int STAMINA_MAX = 12;
152 void idMarkerWindow::Draw(int time, float x, float y) {
153         float pct;
154         idRectangle r = clientRect;
155         int len = gui->State().GetInt( "loadLength" );
156         if (len == 0) {
157                 len = 1;
158         }
159         if (numStats > 1) {
160                 int c = markerTimes.Num();
161                 if (c > 0) {
162                         for (int i = 0; i < c; i++) {
163                                 markerData_t &md = markerTimes[i];
164                                 if (md.rect.w == 0) {
165                                         md.rect.x = (r.x + r.w * ((float)md.time / len)) - 8;
166                                         md.rect.y = r.y + r.h - 20;
167                                         md.rect.w = 16;
168                                         md.rect.h = 16;
169                                 }
170                                 dc->DrawMaterial(md.rect.x, md.rect.y, md.rect.w, md.rect.h, markerMat, markerColor);
171                         }
172                 }
173         }
174
175         r.y += 10;
176         if (r.w > 0 && r.Contains(gui->CursorX(), gui->CursorY())) {
177                 pct = (gui->CursorX() - r.x) / r.w;
178                 currentTime = len * pct;
179                 r.x = (gui->CursorX() > r.x + r.w - 40) ? gui->CursorX() - 40 : gui->CursorX();
180                 r.y = gui->CursorY() - 15;
181                 r.w = 40;
182                 r.h = 20;
183                 dc->DrawText(va("%.2i:%.2i", currentTime / 60 / 60, (currentTime / 60) % 60), 0.25, 0, idDeviceContext::colorWhite, r, false);
184         }
185
186         if (stopTime >= 0 && markerStop) {
187                 r = clientRect;
188                 r.y += (r.h - 32) / 2;
189                 pct = (float)stopTime / len;
190                 r.x += (r.w * pct) - 16;
191                 idVec4 color(1, 1, 1, 0.65f);
192                 dc->DrawMaterial(r.x, r.y, 32, 32, markerStop, color);
193         }
194
195 }
196
197
198
199 const char *idMarkerWindow::RouteMouseCoords(float xd, float yd) {
200         const char * ret = idWindow::RouteMouseCoords(xd, yd);
201         idRectangle r;
202         int i, c = markerTimes.Num();
203         int len = gui->State().GetInt( "loadLength" );
204         if (len == 0) {
205                 len = 1;
206         }
207         for (i = 0; i < c; i++) {
208                 markerData_t &md = markerTimes[i];
209                 if (md.rect.Contains(gui->CursorY(), gui->CursorX())) {
210                         gui->GetDesktop()->SetChildWinVarVal("markerBackground", "background", md.mat->GetName());
211                         gui->GetDesktop()->SetChildWinVarVal("markerBackground", "matcolor", "1 1 1 1");
212                         gui->GetDesktop()->SetChildWinVarVal("markerBackground", "text", "");
213                         break;
214                 }
215         }
216
217         if (i >= c) {
218                 if (currentMarker == -1) {
219                         gui->GetDesktop()->SetChildWinVarVal("markerBackground", "matcolor", "0 0 0 0");
220                         gui->GetDesktop()->SetChildWinVarVal("markerBackground", "text", "No Preview");
221                 } else {
222                         markerData_t &md = markerTimes[currentMarker];
223                         gui->GetDesktop()->SetChildWinVarVal("markerBackground", "background", md.mat->GetName());
224                         gui->GetDesktop()->SetChildWinVarVal("markerBackground", "matcolor", "1 1 1 1");
225                         gui->GetDesktop()->SetChildWinVarVal("markerBackground", "text", "");
226                 }
227         }
228         return ret;
229 }
230
231 void idMarkerWindow::Point(int x, int y, dword *out, dword color) {
232         int index = (63-y) * 512 + x;
233         if (index >= 0 && index < 512 * 64) {
234                 out[index] = color;
235         } else {
236                 common->Warning("Out of bounds on point %i : %i", x, y);
237         }
238 }
239
240 void idMarkerWindow::Line(int x1, int y1, int x2, int y2, dword* out, dword color) {
241         int deltax = abs(x2 - x1);
242         int deltay = abs(y2 - y1);
243         int incx = (x1 > x2) ? -1 : 1;
244         int incy = (y1 > y2) ? -1 : 1;
245         int right, up, dir;
246         if (deltax > deltay) {
247                 right = deltay * 2;
248                 up = right - deltax * 2;
249                 dir = right - deltax;
250                 while (deltax-- >= 0) {
251                         Point(x1, y1, out, color);
252                         x1 += incx;
253                         y1 += (dir > 0) ? incy : 0;
254                         dir += (dir > 0) ? up : right;
255                 }
256         } else {
257                 right = deltax * 2;
258                 up = right - deltay * 2;
259                 dir = right - deltay;
260                 while ( deltay-- >= 0) {
261                         Point(x1, y1, out, color);
262                         x1 += (dir > 0) ? incx : 0;
263                         y1 += incy;
264                         dir += (dir > 0) ? up : right;
265                 }
266         }
267 }
268
269
270 void idMarkerWindow::Activate(bool activate, idStr &act) {
271         idWindow::Activate(activate, act);
272         if (activate) {
273                 int i;
274                 gui->GetDesktop()->SetChildWinVarVal("markerText", "text", "");
275                 imageBuff = (dword*)Mem_Alloc(512*64*4);
276                 markerTimes.Clear();
277                 currentMarker = -1;
278                 currentTime = -1;
279                 stopTime = -1;
280                 statData = gui->State().GetString( "statData" );
281                 numStats = 0;
282                 if (statData.Length()) {
283                         idFile *file = fileSystem->OpenFileRead(statData);
284                         if (file) {
285                                 file->Read(&numStats, sizeof(numStats));
286                                 file->Read(loggedStats, numStats * sizeof(loggedStats[0]));
287                                 for (i = 0; i < numStats; i++) {
288                                         if (loggedStats[i].health < 0) {
289                                                 loggedStats[i].health = 0;
290                                         }
291                                         if (loggedStats[i].stamina < 0) {
292                                                 loggedStats[i].stamina = 0;
293                                         }
294                                         if (loggedStats[i].heartRate < 0) {
295                                                 loggedStats[i].heartRate = 0;
296                                         }
297                                         if (loggedStats[i].combat < 0) {
298                                                 loggedStats[i].combat = 0;
299                                         }
300                                 }
301                                 fileSystem->CloseFile(file);
302                         }
303                 }
304
305                 if (numStats > 1 && background) {
306                         idStr markerPath = statData;
307                         markerPath.StripFilename();
308                         idFileList *markers;
309                         markers = fileSystem->ListFiles( markerPath, ".tga", false, true );
310                         idStr name;
311                         for ( i = 0; i < markers->GetNumFiles(); i++ ) {
312                                 name = markers->GetFile( i );
313                                 markerData_t md;
314                                 md.mat = declManager->FindMaterial( name );
315                                 md.mat->SetSort( SS_GUI );
316                                 name.StripPath();
317                                 name.StripFileExtension();
318                                 md.time = atoi(name);
319                                 markerTimes.Append(md);
320                         }
321                         fileSystem->FreeFileList( markers );
322                         memset(imageBuff, 0, 512*64*4);
323                         float step = 511.0f / (numStats - 1);
324                         float startX = 0;
325                         float x1, y1, x2, y2;
326                         x1 = 0 - step;
327                         for (i = 0; i < numStats-1; i++) {
328                                 x1 += step;
329                                 x2 = x1 + step;
330                                 y1 = 63 * ((float)loggedStats[i].health / HEALTH_MAX);
331                                 y2 = 63 * ((float)loggedStats[i+1].health / HEALTH_MAX);
332                                 Line(x1, y1, x2, y2, imageBuff, 0xff0000ff);
333                                 y1 = 63 * ((float)loggedStats[i].heartRate / RATE_MAX);
334                                 y2 = 63 * ((float)loggedStats[i+1].heartRate / RATE_MAX);
335                                 Line(x1, y1, x2, y2, imageBuff, 0xff00ff00);
336                                 // stamina not quite as high on graph so health does not get obscured with both at 100%
337                                 y1 = 62 * ((float)loggedStats[i].stamina / STAMINA_MAX);
338                                 y2 = 62 * ((float)loggedStats[i+1].stamina / STAMINA_MAX);
339                                 Line(x1, y1, x2, y2, imageBuff, 0xffff0000);
340                                 y1 = 63 * ((float)loggedStats[i].combat / COMBAT_MAX);
341                                 y2 = 63 * ((float)loggedStats[i+1].combat / COMBAT_MAX);
342                                 Line(x1, y1, x2, y2, imageBuff, 0xff00ffff);
343                         }
344                         const shaderStage_t *stage = background->GetStage(0);
345                         if (stage) {
346                                 stage->texture.image->UploadScratch((byte*)imageBuff, 512, 64);                 
347                         }
348                         Mem_Free(imageBuff);
349                 }
350         }
351 }
352
353 void idMarkerWindow::MouseExit() {
354         idWindow::MouseExit();
355 }
356
357 void idMarkerWindow::MouseEnter() {
358         idWindow::MouseEnter();
359 }