ScummVM API documentation
dt-internal.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef DIRECTOR_DEBUGER_DT_INTERNAL_H
23 #define DIRECTOR_DEBUGER_DT_INTERNAL_H
24 
25 #ifndef IMGUI_DEFINE_MATH_OPERATORS
26 #define IMGUI_DEFINE_MATH_OPERATORS
27 #endif
28 
29 #include "graphics/surface.h"
30 
31 #include "backends/imgui/imgui.h"
32 #include "backends/imgui/imgui_fonts.h"
33 #include "backends/imgui/components/imgui_logger.h"
34 #include "backends/imgui/components/imgui_memory_editor.h"
35 
36 #include "director/types.h"
37 #include "director/window.h"
38 #include "director/lingo/lingo.h"
39 #include "director/lingo/lingodec/ast.h"
40 #include "director/lingo/lingodec/handler.h"
41 
42 namespace Director {
43 namespace DT {
44 
45 #define kMaxColumnsInTable 512
46 
47 typedef struct ImGuiImage {
48  ImTextureID id;
49  int16 width;
50  int16 height;
51 } ImGuiImage;
52 
53 typedef struct ImGuiScriptCodeLine {
54  uint32 pc;
55  Common::String codeLine;
57 
58 typedef struct ImGuiScript {
59  bool score = false;
60  bool showByteCode = false;
61  CastMemberID id;
62  ScriptType type;
63  Common::String handlerId;
64  Common::String handlerName;
65  Common::String moviePath;
66  Common::Array<uint32> byteOffsets;
67  uint pc = 0;
68 
69  bool isMethod = false;
70  bool isGenericEvent = false;
71  Common::StringArray argumentNames;
72  Common::StringArray propertyNames;
73  Common::StringArray globalNames;
76  Common::Array<uint> startOffsets;
78  Common::String rawText;
79 
80  bool operator==(const ImGuiScript &c) const {
81  return moviePath == c.moviePath && score == c.score && id == c.id && handlerId == c.handlerId;
82  }
83  bool operator!=(const ImGuiScript &c) const {
84  return !(*this == c);
85  }
86 } ImGuiScript;
87 
88 typedef struct ImGuiWindows {
89  bool controlPanel = true;
90  bool vars = false;
91  bool channels = false;
92  bool cast = false;
93  bool castDetails = false;
94  bool funcList = false;
95  bool score = false;
96  bool bpList = false;
97  bool settings = false;
98  bool logger = false;
99  bool archive = false;
100  bool watchedVars = false;
101  bool executionContext = false;
102  bool scripts = false;
103  bool search = false;
104  bool imageViewer = false;
105  bool windows = false;
106  bool help = false;
107  bool profiler = false;
108 } ImGuiWindows;
109 
110 // Rebindable debugger actions. Keep in sync with kShortcutDefs (dt-help.cpp).
111 enum DebuggerAction {
112  kActContinue = 0,
113  kActStepOver,
114  kActStepInto,
115  kActStepOut,
116  kActQuickOpen,
117  kActPickFromStage,
118  kActToggleControlPanel,
119  kActToggleCast,
120  kActToggleScore,
121  kActToggleMouseIgnore,
122  kActCount
123 };
124 
125 typedef struct ShortcutDef {
126  const char *id; // stable key for save/load
127  const char *label; // display name
128  const char *help; // what it does
129  ImGuiKeyChord defaultChord;
130 } ShortcutDef;
131 
132 
133 enum SearchMode {
134  kSearchAll = 0,
135  kSearchHandlers,
136  kSearchVariables,
137  kSearchBody,
138 };
139 
140 typedef struct ScriptData {
142  uint _current = 0;
143  bool _showByteCode = false;
144  bool _showScript = false;
145  bool _scrollToCurrent = false; // pending scroll to the current script, consumed on render
146 } ScriptData;
147 
148 typedef struct WindowFlag {
149  const char *name;
150  bool *flag;
151 } WindowFlag;
152 
153 enum ThemeID {
154  kThemeDark = 0,
155  kThemeLight,
156  kThemeCount
157 };
158 
160  ImU32 tableLightColor;
161  ImU32 tableDarkColor;
162  ImU32 borderColor;
163  ImU32 sidebarTextColor;
164  ImU32 gridTextColor;
165  ImU32 playhead_color;
166  ImU32 current_statement_bg;
167  ImU32 channel_toggle;
168  ImU32 channel_hide_bg;
169  ImU32 channelSelectedCol;
170  ImU32 channelHoveredCol;
171  ImU32 contColors[6];
172 
173  // Breakpoints
174  ImVec4 bp_color_disabled;
175  ImVec4 bp_color_enabled;
176  ImVec4 bp_color_hover;
177 
178  // Syntax Highlighting
179  ImVec4 current_statement;
180  ImVec4 line_color;
181  ImVec4 call_color;
182  ImVec4 builtin_color;
183  ImVec4 var_color;
184  ImVec4 literal_color;
185  ImVec4 comment_color;
186  ImVec4 type_color;
187  ImVec4 keyword_color;
188  ImVec4 the_color;
189 
190  // Variable / Script References
191  ImVec4 script_ref;
192  ImVec4 var_ref;
193  ImVec4 var_ref_changed;
194  ImVec4 var_ref_out_of_scope;
195 
196  // Control Panel
197  ImVec4 cp_color;
198  ImVec4 cp_color_red;
199  ImVec4 cp_active_color;
200  ImVec4 cp_bgcolor;
201  ImVec4 cp_playing_color;
202  ImVec4 cp_path_color;
203 
204  // Logger
205  ImVec4 logger_error_b;
206  ImVec4 logger_warning_b;
207  ImVec4 logger_info_b;
208  ImVec4 logger_debug_b;
209  ImVec4 logger_error;
210  ImVec4 logger_warning;
211  ImVec4 logger_info;
212  ImVec4 logger_debug;
213 
214  // Profiler
215  ImVec4 prof_ruler_bg;
216  ImVec4 prof_grid_line;
217  ImVec4 prof_freeze;
218  ImVec4 prof_thaw;
219  ImVec4 prof_zone_border;
220  ImVec4 prof_zone_text;
221  ImVec4 prof_selected;
222  ImVec4 prof_highlight;
223  ImVec4 prof_live_edge;
224  ImVec4 prof_crosshair;
225 };
226 
228  Common::String label;
229  bool isHandler = false;
230  CastMemberID id;
231  ScriptType scriptType = kScoreScript;
232  Common::String handlerId;
233  Common::String handlerName;
234 };
235 
236 struct CastRowEntry {
237  const Cast *cast = nullptr;
238  CastMember *member = nullptr;
239  int id = 0;
240  Common::String name;
241 };
242 
243 typedef struct ImGuiState {
244 
245  struct WatchLogEntry {
246  Common::String varName;
247  Common::String value;
248  Common::String scriptRef;
249  };
250 
251  struct ScoreConfig {
252  float _sidebarWidth = 60.0f;
253  float _cellWidth = 14.0f;
254  float _cellHeight = 22.0f;
255  int _visibleFrames = 60;
256  int _visibleChannels = 20;
257  float _tableWidth = _cellWidth * _visibleFrames;
258  float _tableHeight = _cellHeight * _visibleChannels;
259  float _rulerHeight = 30.0f;
260  float _rulerWidth = _cellWidth * _visibleFrames;
261  float _sidebar1Height = _cellHeight * 6;
262  float _labelBarHeight = _cellHeight;
263  float _cellHeightExtended = 5 * _cellHeight;
264  } _scoreCfg;
265 
266  struct ScoreState {
267  int xSliderValue = 1; // first visible frame, 1 indexed
268  int channelScrollOffset = 1; // first visible channel, 1 indexed
269  } _scoreState;
270 
271  struct {
273  bool _listView = true;
274  bool _showGridNumbers = false;
275  int _thumbnailSize = 64;
276  ImGuiTextFilter _nameFilter;
277  int _typeFilter = 0xFFFF;
278  } _cast;
279 
280  struct {
281  ImGuiTextFilter _nameFilter;
282  bool _showScriptContexts = true;
283  Common::HashMap<Window *, ScriptData> _windowScriptData;
284  } _functions;
285  struct {
286  // stored as an ID: raw CastMember pointers dangle on movie switch
287  CastMemberID _castMemberID;
288  // name of the window whose movie owns the member
289  Common::String _window;
290  Common::HashMap<CastMemberID, int> _filmLoopCurrentFrame;
291  } _castDetails;
292 
293  struct {
294  bool _isScriptDirty = false; // indicates whether or not we have to display the script corresponding to the current stackframe
295  bool _hostExecutionContext = false; // true while the Execution Context window is rendering scripts
296  bool _scrollToPC = false;
297  uint _lastLinePC = 0;
298  uint _callstackSize = 0;
299  Common::String _highlightQuery; // lowercased, empty disables highlight
300  bool _suppressHighlight = false; // used to disable highlighting in Execution Context
301  } _dbg;
302 
303  struct {
304  char input[256] = {};
305  bool dirty = false;
306  int mode = kSearchAll;
308  } _search;
309 
310  struct {
311  DatumHash _locals;
312  DatumHash _globals;
313 
314  DatumHash _prevLocals;
315  DatumHash _prevGlobals;
316 
317  uint32 _lastTimeRefreshed = 0;
318  ImGuiTextFilter _nameFilter;
319  } _vars;
320 
321  struct {
322  ImGuiImage image;
323  Common::String text; // empty = no text panel
324  Common::String title; // optional title
325 
326  // cached normalized text
327  Common::String cachedRaw;
328  Common::String cachedNormalized;
329 
330  // reusable buffer
331  char *buffer = nullptr;
332  size_t bufferSize = 0;
333 
334  } _imageViewerState;
335 
336  ImGuiWindows _w;
337  ImGuiWindows _savedW;
338  bool _wasHidden = false;
339 
340  ScriptData _openScripts;
341  bool _showCompleteScript = true;
342 
343  // Quick-open (command palette): jump to a cast member or handler by name.
344  bool _quickOpen = false;
345  char _quickOpenInput[256] = {};
346 
347  // Pick-from-stage: next stage click selects the sprite under the cursor.
348  bool _pickMode = false;
349 
350  // Rebindable shortcut chords, indexed by DebuggerAction; -1 = not capturing.
351  ImGuiKeyChord _shortcuts[kActCount] = {};
352  int _shortcutCapture = -1;
353  ImGuiKeyChord _shortcutPending = ImGuiKey_None; // chord being held during a rebind
354 
356  int _prevFrame = -1;
357  struct {
358  int frame = -1;
359  int channel = -1;
360  bool isMainChannel = false;
361  } _selectedScoreCast;
362 
363  struct {
364  int frame = -1;
365  int channel = -1;
366  } _hoveredScoreCast;
367 
369  Common::String _loadedContinuationData;
370 
371  // archive paths of every window's movie, to detect movie switches
372  Common::String _movieSignature;
373 
375 
376  Common::String _scoreWindow;
377  Common::String _channelsWindow;
378  Common::String _castWindow;
379  Common::String _functionsWindow;
380  Common::String _executionContextWindow;
381  int _scoreMode = 0;
382  int _scoreFrameOffset = 1;
383  int _scorePageSlider = 0;
384  int _selectedChannel = -1;
385  bool _scrollToChannel = false;
386 
387  ImFont *_tinyFont = nullptr;
388 
389  int _activeThemeID = kThemeLight;
390  const DebuggerTheme *theme = nullptr;
391 
392  struct {
393  Common::Path path;
394  uint32 resType = 0;
395  uint32 resId = 0;
396 
397  byte *data = nullptr;
398  uint32 dataSize = 0;
399 
400  MemoryEditor memEdit;
401  } _archive;
402 
403  ImGuiEx::ImGuiLogger *_logger = nullptr;
404  bool _ignoreMouse = false;
405  bool _enableMultiViewport = true;
406 
407  Window *_windowToRedraw = nullptr;
408 
409  // Cached UI lists. Kept in the state (not file-static) so their Common::Strings
410  // free in onImGuiCleanup while g_system is alive, not at process exit.
411  Common::Array<CastRowEntry> _castRows;
412  Common::String _castRowsKey;
413  Common::Array<QuickOpenItem> _quickOpenItems;
414  bool _quickOpenGathered = false;
415 } ImGuiState;
416 
417 // debugtools.cpp
418 const LingoDec::Handler *getHandler(const Cast *cast, CastMemberID id, const Common::String &handlerId);
419 ImGuiScript toImGuiScript(ScriptType scriptType, CastMemberID id, const Common::String &handlerId);
420 ScriptContext *getScriptContext(CastMemberID id);
421 ScriptContext *getScriptContext(uint32 nameIndex, CastMemberID castId, Common::String handler);
422 ScriptContext *resolveHandlerContext(int32 nameIndex, const CastMemberID &refId, const Common::String &handlerName);
423 int getCastLibIDForContext(const ScriptContext *ctx);
424 ImGuiScript buildImGuiHandlerScript(ScriptContext *ctx, int castLibID, const Common::String &handlerName, const Common::String &moviePath);
425 void maybeHighlightLastItem(const Common::String &text);
426 void addToOpenHandlers(ImGuiScript handler);
427 void setScriptToDisplay(const ImGuiScript &script);
428 Director::Breakpoint *getBreakpoint(const Common::String &handlerName, uint16 scriptId, uint pc);
429 void displayScriptRef(CastMemberID &scriptId);
430 ImGuiImage getImageID(CastMember *castMember);
431 ImGuiImage getShapeID(CastMember *castMember);
432 ImGuiImage getTextID(CastMember *castMember);
433 Common::String getDisplayName(CastMember *castMember);
434 void showImage(const ImGuiImage &image, const char *name, float thumbnailSize);
435 void showImageWrappedBorder(const ImGuiImage &image, const char *name, float size);
436 ImVec4 convertColor(uint32 color);
437 void displayVariable(const Common::String &name, bool changed, bool outOfScope = false);
438 ImColor brightenColor(const ImColor &color, float factor);
439 Window *windowListCombo(Common::String *target);
440 Common::String movieId(const Movie *m);
441 Window *findWindowByName(const Common::String &name);
442 bool selectableViewButton(const char *label, bool selected);
443 Common::String formatHandlerName(int scriptId, int castId, Common::String handlerName, ScriptType scriptType, bool childScript);
444 void setTheme(int themeIndex);
445 void openImageViewer(ImGuiImage image, const Common::String &text = "", const Common::String &title = "");
446 
447 // helper to draw thin rectangles for table grid
448 inline void addThinRect(ImDrawList *dl, ImVec2 min, ImVec2 max, ImU32 col, float thickness = 0.1f) {
449  dl->AddLine(ImVec2(min.x, min.y), ImVec2(max.x, min.y), col, thickness); // top
450  dl->AddLine(ImVec2(max.x, min.y), ImVec2(max.x, max.y), col, thickness); // right
451  dl->AddLine(ImVec2(max.x, max.y), ImVec2(min.x, max.y), col, thickness); // bottom
452  dl->AddLine(ImVec2(min.x, max.y), ImVec2(min.x, min.y), col, thickness); // left
453 }
454 
455 void showCast(); // dt-cast.cpp
456 void showImageViewer(); // dt-castdetails.cpp
457 void showCastDetails(); // dt-castdetails.cpp
458 void showControlPanel();// dt-controlpanel.cpp
459 void handleDebuggerShortcuts(); // dt-controlpanel.cpp
460 void showProfiler(); // dt-profiler.cpp
461 
462 // dt-help.cpp
463 extern const ShortcutDef kShortcutDefs[kActCount];
464 void initShortcuts(); // load defaults into _state->_shortcuts
465 void resetShortcuts(); // restore defaults
466 void showHelp(); // the Help window (shortcuts + tips)
467 bool actionTriggered(DebuggerAction act); // Shortcut() honouring the current binding
468 
469 // dt-lists.cpp
470 void showVars();
471 void showWatchedVars();
472 void showBreakpointList();
473 void showArchive();
474 void showWindows();
475 
476 // dt-score.cpp
477 void showScore();
478 void showChannels();
479 
480 void renderOldScriptAST(ImGuiScript &script, bool showByteCode, bool scrollTo); // dt-script-d2.cpp
481 void renderScriptAST(ImGuiScript &script, bool showByteCode, bool scrollTo); // dt-script-d4.cpp
482 
483 // dt-scripts.cpp
484 void showFuncList();
485 void showExecutionContext();
486 void showScriptsWindow();
487 void showQuickOpen();
488 
489 // dt-save-state.cpp
490 void saveCurrentState();
491 void loadSavedState();
492 Common::Array<WindowFlag> getWindowFlags();
493 
494 // dt-search.cpp
495 void showSearchBar();
496 
497 extern ImGuiState *_state;
498 
499 } // End of namespace DT
500 
501 } // End of namespace Director
502 
503 #endif
Definition: dt-internal.h:227
Definition: cast.h:88
Definition: str.h:59
Definition: dt-internal.h:53
Definition: dt-internal.h:47
Definition: imgui.h:315
Definition: dt-internal.h:125
Definition: path.h:52
Definition: window.h:106
Definition: movie.h:88
Definition: archive.h:36
Definition: dt-internal.h:159
Definition: dt-internal.h:148
Definition: imgui.h:3398
Definition: imgui.h:302
Definition: imgui.h:3982
Definition: dt-internal.h:88
Definition: imgui_memory_editor.h:83
Definition: dt-internal.h:251
Definition: dt-internal.h:140
Definition: hashmap.h:85
Definition: dt-internal.h:236
Definition: dt-internal.h:245
Definition: imgui_logger.h:33
Definition: dt-internal.h:266
Definition: imgui.h:3086
Definition: imgui.h:2856
Definition: dt-internal.h:243
Definition: debugger.h:45
Definition: dt-internal.h:58
Definition: handler.h:29
Definition: castmember.h:48
Definition: types.h:424
Definition: lingo-object.h:213