Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Windows/GEDebugger/TabState.cpp
3186 views
1
// Copyright (c) 2012- PPSSPP Project.
2
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
6
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
11
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
14
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18
#include "Common/CommonWindows.h"
19
#include <commctrl.h>
20
#include <array>
21
#include "Common/CommonFuncs.h"
22
#include "Common/CommonTypes.h"
23
#include "Common/System/Request.h"
24
#include "Common/Data/Encoding/Utf8.h"
25
#include "Common/Data/Text/Parsers.h"
26
#include "Common/Log.h"
27
#include "Common/StringUtils.h"
28
#include "Windows/resource.h"
29
#include "Windows/InputBox.h"
30
#include "Windows/GEDebugger/GEDebugger.h"
31
#include "Windows/GEDebugger/TabState.h"
32
#include "Windows/W32Util/ContextMenu.h"
33
#include "GPU/GPUState.h"
34
#include "GPU/GeDisasm.h"
35
#include "GPU/Debugger/GECommandTable.h"
36
#include "GPU/Common/GPUDebugInterface.h"
37
#include "GPU/Debugger/Breakpoints.h"
38
#include "GPU/Debugger/Stepping.h"
39
#include "GPU/Debugger/State.h"
40
41
// First column is the breakpoint icon.
42
static const GenericListViewColumn stateValuesCols[] = {
43
{ L"", 0.03f },
44
{ L"Name", 0.40f },
45
{ L"Value", 0.57f },
46
};
47
48
GenericListViewDef stateValuesListDef = {
49
stateValuesCols,
50
ARRAY_SIZE(stateValuesCols),
51
nullptr,
52
false,
53
};
54
55
enum StateValuesCols {
56
STATEVALUES_COL_BREAKPOINT,
57
STATEVALUES_COL_NAME,
58
STATEVALUES_COL_VALUE,
59
};
60
61
static std::vector<GECommand> watchList;
62
63
const GECommand g_stateFlagsRows[] = {
64
GE_CMD_LIGHTINGENABLE,
65
GE_CMD_LIGHTENABLE0,
66
GE_CMD_LIGHTENABLE1,
67
GE_CMD_LIGHTENABLE2,
68
GE_CMD_LIGHTENABLE3,
69
GE_CMD_DEPTHCLAMPENABLE,
70
GE_CMD_CULLFACEENABLE,
71
GE_CMD_TEXTUREMAPENABLE,
72
GE_CMD_FOGENABLE,
73
GE_CMD_DITHERENABLE,
74
GE_CMD_ALPHABLENDENABLE,
75
GE_CMD_ALPHATESTENABLE,
76
GE_CMD_ZTESTENABLE,
77
GE_CMD_STENCILTESTENABLE,
78
GE_CMD_ANTIALIASENABLE,
79
GE_CMD_PATCHCULLENABLE,
80
GE_CMD_COLORTESTENABLE,
81
GE_CMD_LOGICOPENABLE,
82
GE_CMD_ZWRITEDISABLE,
83
};
84
const size_t g_stateFlagsRowsSize = ARRAY_SIZE(g_stateFlagsRows);
85
86
const GECommand g_stateLightingRows[] = {
87
GE_CMD_AMBIENTCOLOR,
88
GE_CMD_AMBIENTALPHA,
89
GE_CMD_MATERIALUPDATE,
90
GE_CMD_MATERIALEMISSIVE,
91
GE_CMD_MATERIALAMBIENT,
92
GE_CMD_MATERIALDIFFUSE,
93
GE_CMD_MATERIALALPHA,
94
GE_CMD_MATERIALSPECULAR,
95
GE_CMD_MATERIALSPECULARCOEF,
96
GE_CMD_REVERSENORMAL,
97
GE_CMD_SHADEMODE,
98
GE_CMD_LIGHTMODE,
99
GE_CMD_LIGHTTYPE0,
100
GE_CMD_LIGHTTYPE1,
101
GE_CMD_LIGHTTYPE2,
102
GE_CMD_LIGHTTYPE3,
103
GE_CMD_LX0,
104
GE_CMD_LX1,
105
GE_CMD_LX2,
106
GE_CMD_LX3,
107
GE_CMD_LDX0,
108
GE_CMD_LDX1,
109
GE_CMD_LDX2,
110
GE_CMD_LDX3,
111
GE_CMD_LKA0,
112
GE_CMD_LKA1,
113
GE_CMD_LKA2,
114
GE_CMD_LKA3,
115
GE_CMD_LKS0,
116
GE_CMD_LKS1,
117
GE_CMD_LKS2,
118
GE_CMD_LKS3,
119
GE_CMD_LKO0,
120
GE_CMD_LKO1,
121
GE_CMD_LKO2,
122
GE_CMD_LKO3,
123
GE_CMD_LAC0,
124
GE_CMD_LDC0,
125
GE_CMD_LSC0,
126
GE_CMD_LAC1,
127
GE_CMD_LDC1,
128
GE_CMD_LSC1,
129
GE_CMD_LAC2,
130
GE_CMD_LDC2,
131
GE_CMD_LSC2,
132
GE_CMD_LAC3,
133
GE_CMD_LDC3,
134
GE_CMD_LSC3,
135
};
136
const size_t g_stateLightingRowsSize = ARRAY_SIZE(g_stateLightingRows);
137
138
const GECommand g_stateTextureRows[] = {
139
GE_CMD_TEXADDR0,
140
GE_CMD_TEXSIZE0,
141
GE_CMD_TEXFORMAT,
142
GE_CMD_CLUTADDR,
143
GE_CMD_CLUTFORMAT,
144
GE_CMD_TEXSCALEU,
145
GE_CMD_TEXSCALEV,
146
GE_CMD_TEXOFFSETU,
147
GE_CMD_TEXOFFSETV,
148
GE_CMD_TEXMAPMODE,
149
GE_CMD_TEXSHADELS,
150
GE_CMD_TEXFUNC,
151
GE_CMD_TEXENVCOLOR,
152
GE_CMD_TEXMODE,
153
GE_CMD_TEXFILTER,
154
GE_CMD_TEXWRAP,
155
GE_CMD_TEXLEVEL,
156
GE_CMD_TEXLODSLOPE,
157
GE_CMD_TEXADDR1,
158
GE_CMD_TEXADDR2,
159
GE_CMD_TEXADDR3,
160
GE_CMD_TEXADDR4,
161
GE_CMD_TEXADDR5,
162
GE_CMD_TEXADDR6,
163
GE_CMD_TEXADDR7,
164
GE_CMD_TEXSIZE1,
165
GE_CMD_TEXSIZE2,
166
GE_CMD_TEXSIZE3,
167
GE_CMD_TEXSIZE4,
168
GE_CMD_TEXSIZE5,
169
GE_CMD_TEXSIZE6,
170
GE_CMD_TEXSIZE7,
171
};
172
const size_t g_stateTextureRowsSize = ARRAY_SIZE(g_stateTextureRows);
173
174
const GECommand g_stateSettingsRows[] = {
175
GE_CMD_FRAMEBUFPTR,
176
GE_CMD_FRAMEBUFPIXFORMAT,
177
GE_CMD_ZBUFPTR,
178
GE_CMD_VIEWPORTXSCALE,
179
GE_CMD_VIEWPORTXCENTER,
180
GE_CMD_SCISSOR1,
181
GE_CMD_REGION1,
182
GE_CMD_COLORTEST,
183
GE_CMD_ALPHATEST,
184
GE_CMD_CLEARMODE,
185
GE_CMD_STENCILTEST,
186
GE_CMD_STENCILOP,
187
GE_CMD_ZTEST,
188
GE_CMD_MASKRGB,
189
GE_CMD_MASKALPHA,
190
GE_CMD_TRANSFERSRC,
191
GE_CMD_TRANSFERSRCPOS,
192
GE_CMD_TRANSFERDST,
193
GE_CMD_TRANSFERDSTPOS,
194
GE_CMD_TRANSFERSIZE,
195
GE_CMD_VERTEXTYPE,
196
GE_CMD_OFFSETADDR,
197
GE_CMD_VADDR,
198
GE_CMD_IADDR,
199
GE_CMD_MINZ,
200
GE_CMD_MAXZ,
201
GE_CMD_OFFSETX,
202
GE_CMD_CULL,
203
GE_CMD_BLENDMODE,
204
GE_CMD_BLENDFIXEDA,
205
GE_CMD_BLENDFIXEDB,
206
GE_CMD_LOGICOP,
207
GE_CMD_FOG1,
208
GE_CMD_FOG2,
209
GE_CMD_FOGCOLOR,
210
GE_CMD_MORPHWEIGHT0,
211
GE_CMD_MORPHWEIGHT1,
212
GE_CMD_MORPHWEIGHT2,
213
GE_CMD_MORPHWEIGHT3,
214
GE_CMD_MORPHWEIGHT4,
215
GE_CMD_MORPHWEIGHT5,
216
GE_CMD_MORPHWEIGHT6,
217
GE_CMD_MORPHWEIGHT7,
218
GE_CMD_PATCHDIVISION,
219
GE_CMD_PATCHPRIMITIVE,
220
GE_CMD_PATCHFACING,
221
GE_CMD_DITH0,
222
GE_CMD_DITH1,
223
GE_CMD_DITH2,
224
GE_CMD_DITH3,
225
GE_CMD_VSCX,
226
GE_CMD_VSCZ,
227
GE_CMD_VTCS,
228
GE_CMD_VCV,
229
GE_CMD_VSCV,
230
GE_CMD_VFC,
231
GE_CMD_VAP,
232
};
233
const size_t g_stateSettingsRowsSize = ARRAY_SIZE(g_stateSettingsRows);
234
235
// TODO: Commands not present in the above lists (some because they don't have meaningful values...):
236
// GE_CMD_PRIM, GE_CMD_BEZIER, GE_CMD_SPLINE, GE_CMD_BOUNDINGBOX,
237
// GE_CMD_JUMP, GE_CMD_BJUMP, GE_CMD_CALL, GE_CMD_RET, GE_CMD_END, GE_CMD_SIGNAL, GE_CMD_FINISH,
238
// GE_CMD_BONEMATRIXNUMBER, GE_CMD_BONEMATRIXDATA, GE_CMD_WORLDMATRIXNUMBER, GE_CMD_WORLDMATRIXDATA,
239
// GE_CMD_VIEWMATRIXNUMBER, GE_CMD_VIEWMATRIXDATA, GE_CMD_PROJMATRIXNUMBER, GE_CMD_PROJMATRIXDATA,
240
// GE_CMD_TGENMATRIXNUMBER, GE_CMD_TGENMATRIXDATA,
241
// GE_CMD_LOADCLUT, GE_CMD_TEXFLUSH, GE_CMD_TEXSYNC,
242
// GE_CMD_TRANSFERSTART,
243
// GE_CMD_UNKNOWN_*
244
245
static void ToggleWatchList(const GECommand cmd) {
246
for (size_t i = 0; i < watchList.size(); ++i) {
247
if (watchList[i] == cmd) {
248
watchList.erase(watchList.begin() + i);
249
return;
250
}
251
}
252
watchList.push_back(cmd);
253
}
254
255
bool PromptStateValue(const GECmdInfo &info, HWND hparent, const char *title, u32 &value) {
256
wchar_t wtitle[1024];
257
ConvertUTF8ToWString(wtitle, ARRAY_SIZE(wtitle), title);
258
259
if (info.fmt == CMD_FMT_FLOAT24 || info.fmt == CMD_FMT_XYZ) {
260
union {
261
u32 u;
262
float f;
263
} temp = { value << 8 };
264
265
std::string strvalue = StringFromFormat("%f", temp.f);
266
bool res = InputBox_GetString(GetModuleHandle(NULL), hparent, wtitle, strvalue, strvalue);
267
if (!res)
268
return false;
269
270
// Okay, the result could be a simple float, hex (0x...), or invalid.
271
if (sscanf(strvalue.c_str(), "0x%08x", &value) == 1)
272
return true;
273
if (sscanf(strvalue.c_str(), "%f", &temp.f) == 1) {
274
value = temp.u >> 8;
275
return true;
276
}
277
return false;
278
}
279
return InputBox_GetHex(GetModuleHandle(NULL), hparent, wtitle, value, value);
280
}
281
282
CtrlStateValues::CtrlStateValues(const GECommand *rows, int rowCount, HWND hwnd)
283
: GenericListControl(hwnd, stateValuesListDef),
284
rows_(rows), rowCount_(rowCount) {
285
SetIconList(12, 12, { (HICON)LoadIcon(GetModuleHandle(nullptr), (LPCWSTR)IDI_BREAKPOINT_SMALL) });
286
Update();
287
}
288
289
void CtrlStateValues::GetColumnText(wchar_t *dest, size_t destSize, int row, int col) {
290
if (row < 0 || row >= rowCount_) {
291
return;
292
}
293
294
switch (col) {
295
case STATEVALUES_COL_BREAKPOINT:
296
wcscpy(dest, L" ");
297
break;
298
299
case STATEVALUES_COL_NAME:
300
{
301
ConvertUTF8ToWString(dest, destSize, GECmdInfoByCmd(rows_[row]).uiName);
302
break;
303
}
304
305
case STATEVALUES_COL_VALUE:
306
{
307
if (!gpuDebug) {
308
wcscpy(dest, L"N/A");
309
break;
310
}
311
312
const auto info = GECmdInfoByCmd(rows_[row]);
313
const auto state = gpuDebug->GetGState();
314
const bool enabled = info.enableCmd == 0 || (state.cmdmem[info.enableCmd] & 1) == 1;
315
const u32 value = state.cmdmem[info.cmd] & 0xFFFFFF;
316
const u32 otherValue = state.cmdmem[info.otherCmd] & 0xFFFFFF;
317
const u32 otherValue2 = state.cmdmem[info.otherCmd2] & 0xFFFFFF;
318
char temp[256];
319
FormatStateRow(gpuDebug, temp, sizeof(temp), info.fmt, value, enabled, otherValue, otherValue2);
320
ConvertUTF8ToWString(dest, destSize, temp);
321
break;
322
}
323
}
324
}
325
326
void CtrlStateValues::OnDoubleClick(int row, int column) {
327
if (gpuDebug == nullptr || row >= rowCount_) {
328
return;
329
}
330
331
const GECmdInfo &info = GECmdInfoByCmd(rows_[row]);
332
333
if (column == STATEVALUES_COL_BREAKPOINT) {
334
bool proceed = true;
335
if (gpuDebug->GetBreakpoints()->GetCmdBreakpointCond(info.cmd, nullptr)) {
336
int ret = MessageBox(GetHandle(), L"This breakpoint has a custom condition.\nDo you want to remove it?", L"Confirmation", MB_YESNO);
337
proceed = ret == IDYES;
338
}
339
if (proceed)
340
SetItemState(row, gpuDebug->GetBreakpoints()->ToggleCmdBreakpoint(info) ? 1 : 0);
341
return;
342
}
343
344
switch (info.fmt) {
345
case CMD_FMT_FLAG:
346
{
347
const auto state = gpuDebug->GetGState();
348
u32 newValue = state.cmdmem[info.cmd] ^ 1;
349
SetCmdValue(newValue);
350
}
351
break;
352
353
default:
354
{
355
char title[1024];
356
const auto state = gpuDebug->GetGState();
357
358
u32 newValue = state.cmdmem[info.cmd] & 0x00FFFFFF;
359
snprintf(title, sizeof(title), "New value for %s", info.uiName);
360
if (PromptStateValue(info, GetHandle(), title, newValue)) {
361
newValue |= state.cmdmem[info.cmd] & 0xFF000000;
362
SetCmdValue(newValue);
363
364
if (info.otherCmd) {
365
newValue = state.cmdmem[info.otherCmd] & 0x00FFFFFF;
366
snprintf(title, sizeof(title), "New value for %s (secondary)", info.uiName);
367
if (PromptStateValue(info, GetHandle(), title, newValue)) {
368
newValue |= state.cmdmem[info.otherCmd] & 0xFF000000;
369
SetCmdValue(newValue);
370
371
if (info.otherCmd2) {
372
newValue = state.cmdmem[info.otherCmd2] & 0x00FFFFFF;
373
snprintf(title, sizeof(title), "New value for %s (tertiary)", info.uiName);
374
if (PromptStateValue(info, GetHandle(), title, newValue)) {
375
newValue |= state.cmdmem[info.otherCmd2] & 0xFF000000;
376
SetCmdValue(newValue);
377
}
378
}
379
}
380
}
381
}
382
}
383
break;
384
}
385
}
386
387
void CtrlStateValues::OnRightClick(int row, int column, const POINT &point) {
388
if (gpuDebug == nullptr) {
389
return;
390
}
391
392
const GECommand cmd = rows_[row];
393
const GECmdInfo &info = GECmdInfoByCmd(cmd);
394
395
const auto state = gpuDebug->GetGState();
396
397
POINT screenPt(point);
398
ClientToScreen(GetHandle(), &screenPt);
399
400
HMENU subMenu = GetContextMenu(ContextMenuID::GEDBG_STATE);
401
SetMenuDefaultItem(subMenu, ID_REGLIST_CHANGE, FALSE);
402
EnableMenuItem(subMenu, ID_GEDBG_SETCOND, gpuDebug->GetBreakpoints()->GPUBreakpoints::IsCmdBreakpoint(info.cmd) ? MF_ENABLED : MF_GRAYED);
403
404
// Ehh, kinda ugly.
405
if (!watchList.empty() && rows_ == &watchList[0]) {
406
ModifyMenu(subMenu, ID_GEDBG_WATCH, MF_BYCOMMAND | MF_STRING, ID_GEDBG_WATCH, L"Remove Watch");
407
} else {
408
ModifyMenu(subMenu, ID_GEDBG_WATCH, MF_BYCOMMAND | MF_STRING, ID_GEDBG_WATCH, L"Add Watch");
409
}
410
if (info.fmt == CMD_FMT_FLAG) {
411
ModifyMenu(subMenu, ID_REGLIST_CHANGE, MF_BYCOMMAND | MF_STRING, ID_REGLIST_CHANGE, L"Toggle Flag");
412
} else {
413
ModifyMenu(subMenu, ID_REGLIST_CHANGE, MF_BYCOMMAND | MF_STRING, ID_REGLIST_CHANGE, L"Change...");
414
}
415
416
switch (TriggerContextMenu(ContextMenuID::GEDBG_STATE, GetHandle(), ContextPoint::FromClient(point)))
417
{
418
case ID_DISASM_TOGGLEBREAKPOINT: {
419
bool proceed = true;
420
if (gpuDebug->GetBreakpoints()->GetCmdBreakpointCond(info.cmd, nullptr)) {
421
int ret = MessageBox(GetHandle(), L"This breakpoint has a custom condition.\nDo you want to remove it?", L"Confirmation", MB_YESNO);
422
proceed = ret == IDYES;
423
}
424
if (proceed)
425
SetItemState(row, gpuDebug->GetBreakpoints()->ToggleCmdBreakpoint(info) ? 1 : 0);
426
break;
427
}
428
429
case ID_GEDBG_SETCOND:
430
PromptBreakpointCond(info);
431
break;
432
433
case ID_DISASM_COPYINSTRUCTIONHEX: {
434
char temp[16];
435
snprintf(temp, sizeof(temp), "%08x", gstate.cmdmem[info.cmd] & 0x00FFFFFF);
436
System_CopyStringToClipboard(temp);
437
break;
438
}
439
440
case ID_DISASM_COPYINSTRUCTIONDISASM: {
441
const bool enabled = info.enableCmd == 0 || (state.cmdmem[info.enableCmd] & 1) == 1;
442
const u32 value = state.cmdmem[info.cmd] & 0xFFFFFF;
443
const u32 otherValue = state.cmdmem[info.otherCmd] & 0xFFFFFF;
444
const u32 otherValue2 = state.cmdmem[info.otherCmd2] & 0xFFFFFF;
445
446
char dest[512];
447
FormatStateRow(gpuDebug, dest, sizeof(dest), info.fmt, value, enabled, otherValue, otherValue2);
448
System_CopyStringToClipboard(dest);
449
break;
450
}
451
452
case ID_GEDBG_COPYALL:
453
CopyRows(0, GetRowCount());
454
break;
455
456
case ID_REGLIST_CHANGE:
457
OnDoubleClick(row, STATEVALUES_COL_VALUE);
458
break;
459
460
case ID_GEDBG_WATCH:
461
ToggleWatchList(cmd);
462
SendMessage(GetParent(GetParent(GetHandle())), WM_GEDBG_UPDATE_WATCH, 0, 0);
463
break;
464
}
465
}
466
467
bool CtrlStateValues::OnRowPrePaint(int row, LPNMLVCUSTOMDRAW msg) {
468
if (gpuDebug && RowValuesChanged(row)) {
469
msg->clrText = RGB(255, 0, 0);
470
return true;
471
}
472
return false;
473
}
474
475
void CtrlStateValues::SetCmdValue(u32 op) {
476
SendMessage(GetParent(GetParent(GetHandle())), WM_GEDBG_SETCMDWPARAM, op, 0);
477
Update();
478
}
479
480
bool CtrlStateValues::RowValuesChanged(int row) {
481
_assert_(gpuDebug != nullptr && row >= 0 && row < rowCount_);
482
483
const auto &info = GECmdInfoByCmd(rows_[row]);
484
const auto state = gpuDebug->GetGState();
485
const auto lastState = GPUStepping::LastState();
486
487
if (state.cmdmem[info.cmd] != lastState.cmdmem[info.cmd])
488
return true;
489
if (info.otherCmd && state.cmdmem[info.otherCmd] != lastState.cmdmem[info.otherCmd])
490
return true;
491
if (info.otherCmd2 && state.cmdmem[info.otherCmd2] != lastState.cmdmem[info.otherCmd2])
492
return true;
493
494
return false;
495
}
496
497
void CtrlStateValues::PromptBreakpointCond(const GECmdInfo &info) {
498
std::string expression;
499
gpuDebug->GetBreakpoints()->GetCmdBreakpointCond(info.cmd, &expression);
500
if (!InputBox_GetString(GetModuleHandle(NULL), GetHandle(), L"Expression", expression, expression))
501
return;
502
503
std::string error;
504
if (!gpuDebug->GetBreakpoints()->SetCmdBreakpointCond(info.cmd, expression, &error)) {
505
MessageBox(GetHandle(), ConvertUTF8ToWString(error).c_str(), L"Invalid expression", MB_OK | MB_ICONEXCLAMATION);
506
} else {
507
if (info.otherCmd)
508
gpuDebug->GetBreakpoints()->SetCmdBreakpointCond(info.otherCmd, expression, &error);
509
if (info.otherCmd2)
510
gpuDebug->GetBreakpoints()->SetCmdBreakpointCond(info.otherCmd2, expression, &error);
511
}
512
}
513
514
TabStateValues::TabStateValues(const GECommand *rows, size_t rowCount, LPCSTR dialogID, HINSTANCE _hInstance, HWND _hParent)
515
: Dialog(dialogID, _hInstance, _hParent) {
516
values = new CtrlStateValues(rows, (int)rowCount, GetDlgItem(m_hDlg, IDC_GEDBG_VALUES));
517
}
518
519
TabStateValues::~TabStateValues() {
520
delete values;
521
}
522
523
void TabStateValues::UpdateSize(WORD width, WORD height) {
524
struct Position {
525
int x,y;
526
int w,h;
527
};
528
529
Position position;
530
static const int borderMargin = 5;
531
532
position.x = borderMargin;
533
position.y = borderMargin;
534
position.w = width - 2 * borderMargin;
535
position.h = height - 2 * borderMargin;
536
537
HWND handle = GetDlgItem(m_hDlg,IDC_GEDBG_VALUES);
538
MoveWindow(handle, position.x, position.y, position.w, position.h, TRUE);
539
}
540
541
BOOL TabStateValues::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
542
switch (message) {
543
case WM_INITDIALOG:
544
return TRUE;
545
546
case WM_SIZE:
547
UpdateSize(LOWORD(lParam), HIWORD(lParam));
548
return TRUE;
549
550
case WM_NOTIFY:
551
switch (wParam)
552
{
553
case IDC_GEDBG_VALUES:
554
SetWindowLongPtr(m_hDlg, DWLP_MSGRESULT, values->HandleNotify(lParam));
555
return TRUE;
556
}
557
break;
558
}
559
560
return FALSE;
561
}
562
563
TabStateFlags::TabStateFlags(HINSTANCE _hInstance, HWND _hParent)
564
: TabStateValues(g_stateFlagsRows, g_stateFlagsRowsSize, (LPCSTR)IDD_GEDBG_TAB_VALUES, _hInstance, _hParent) {
565
}
566
567
TabStateLighting::TabStateLighting(HINSTANCE _hInstance, HWND _hParent)
568
: TabStateValues(g_stateLightingRows, g_stateLightingRowsSize, (LPCSTR)IDD_GEDBG_TAB_VALUES, _hInstance, _hParent) {
569
}
570
571
TabStateSettings::TabStateSettings(HINSTANCE _hInstance, HWND _hParent)
572
: TabStateValues(g_stateSettingsRows, g_stateSettingsRowsSize, (LPCSTR)IDD_GEDBG_TAB_VALUES, _hInstance, _hParent) {
573
}
574
575
TabStateTexture::TabStateTexture(HINSTANCE _hInstance, HWND _hParent)
576
: TabStateValues(g_stateTextureRows, g_stateTextureRowsSize, (LPCSTR)IDD_GEDBG_TAB_VALUES, _hInstance, _hParent) {
577
}
578
579
TabStateWatch::TabStateWatch(HINSTANCE _hInstance, HWND _hParent)
580
: TabStateValues(nullptr, 0, (LPCSTR)IDD_GEDBG_TAB_VALUES, _hInstance, _hParent) {
581
}
582
583
void TabStateWatch::Update() {
584
if (watchList.empty()) {
585
values->UpdateRows(nullptr, 0);
586
} else {
587
values->UpdateRows(&watchList[0], (int)watchList.size());
588
}
589
TabStateValues::Update();
590
}
591
592