1 /*
2 * Portions of this file are copyright Rebirth contributors and licensed as
3 * described in COPYING.txt.
4 * Portions of this file are copyright Parallax Software and licensed
5 * according to the Parallax license below.
6 * See COPYING.txt for license details.
7
8 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
9 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
10 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
11 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
12 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
13 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
14 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
15 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
16 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
17 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
18 */
19
20 /*
21 *
22 * Print debugging info in ui.
23 *
24 */
25
26 #include <cinttypes>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "inferno.h"
32 #include "window.h"
33 #include "segment.h"
34 #include "event.h"
35 #include "gr.h"
36 #include "ui.h"
37 #include "editor.h"
38 #include "editor/esegment.h"
39 #include "dxxerror.h"
40 #include "textures.h"
41 #include "object.h"
42 #include "wall.h"
43 #include "switch.h"
44 #include "info.h"
45 #include "d_levelstate.h"
46
47 int init_info;
48
49 namespace dcx {
50
51 namespace {
52
53 typedef const char object_type_name[13];
54 typedef const char control_type_name[15];
55 typedef const char movement_type_name[15];
56 typedef const char ai_type_name[13];
57
get_object_type(int num)58 static object_type_name &get_object_type(int num)
59 {
60 switch (num) {
61 case OBJ_NONE:
62 return "OBJ_NONE ";
63 case OBJ_WALL:
64 return "OBJ_WALL ";
65 case OBJ_FIREBALL:
66 return "OBJ_FIREBALL";
67 case OBJ_ROBOT:
68 return "OBJ_ROBOT ";
69 case OBJ_HOSTAGE:
70 return "OBJ_HOSTAGE ";
71 case OBJ_PLAYER:
72 return "OBJ_PLAYER ";
73 case OBJ_WEAPON:
74 return "OBJ_WEAPON ";
75 case OBJ_CAMERA:
76 return "OBJ_CAMERA ";
77 case OBJ_POWERUP:
78 return "OBJ_POWERUP ";
79 default:
80 return " (unknown) ";
81 }
82 }
83
get_control_type(const typename object_base::control_type num)84 static control_type_name &get_control_type(const typename object_base::control_type num)
85 {
86 switch (num) {
87 case object::control_type::None:
88 return "CT_NONE ";
89 case object::control_type::ai:
90 return "CT_AI ";
91 case object::control_type::explosion:
92 return "CT_EXPLOSION ";
93 case object::control_type::flying:
94 return "CT_FLYING ";
95 case object::control_type::slew:
96 return "CT_SLEW ";
97 case object::control_type::flythrough:
98 return "CT_FLYTHROUGH ";
99 case object::control_type::weapon:
100 return "CT_WEAPON ";
101 default:
102 return " (unknown) ";
103 }
104 }
105
get_movement_type(const typename object_base::movement_type num)106 static movement_type_name &get_movement_type(const typename object_base::movement_type num)
107 {
108 switch (num) {
109 case object::movement_type::None:
110 return "MT_NONE ";
111 case object::movement_type::physics:
112 return "MT_PHYSICS ";
113 case object::movement_type::spinning:
114 return "MT_SPINNING ";
115 default:
116 return " (unknown) ";
117 }
118 }
119
info_display_object_placement(grs_canvas & canvas,const grs_font & cv_font,const vcobjptridx_t & obj)120 static void info_display_object_placement(grs_canvas &canvas, const grs_font &cv_font, const vcobjptridx_t &obj)
121 {
122 gr_uprintf(canvas, cv_font, 0, 0, "Object id: %4d\n", obj.get_unchecked_index());
123 auto &o = *obj;
124 gr_uprintf(canvas, cv_font, 0, 16, "Type: %s\n", get_object_type(o.type));
125 gr_uprintf(canvas, cv_font, 0, 32, "Movmnt: %s\n", get_movement_type(o.movement_source));
126 gr_uprintf(canvas, cv_font, 0, 48, "Cntrl: %s\n", get_control_type(o.control_source));
127 }
128
129 }
130
131 }
132
133 namespace dsx {
134
135 namespace {
136
137 struct info_dialog_window : window
138 {
139 using window::window;
140 virtual window_event_result event_handler(const d_event &) override;
141 };
142
get_ai_behavior(ai_behavior num)143 static ai_type_name &get_ai_behavior(ai_behavior num)
144 {
145 switch (num) {
146 case ai_behavior::AIB_STILL:
147 return "STILL ";
148 case ai_behavior::AIB_NORMAL:
149 return "NORMAL ";
150 #if defined(DXX_BUILD_DESCENT_I)
151 case ai_behavior::AIB_HIDE:
152 return "HIDE ";
153 case ai_behavior::AIB_FOLLOW_PATH:
154 return "FOLLOW_PATH ";
155 #elif defined(DXX_BUILD_DESCENT_II)
156 case ai_behavior::AIB_BEHIND:
157 return "BEHIND ";
158 case ai_behavior::AIB_SNIPE:
159 return "SNIPE ";
160 case ai_behavior::AIB_FOLLOW:
161 return "FOLLOW ";
162 #endif
163 case ai_behavior::AIB_RUN_FROM:
164 return "RUN_FROM ";
165 default:
166 return " (unknown) ";
167 }
168 }
169
170 // ---------------------------------------------------------------------------------------------------
info_display_object_placement(grs_canvas & canvas,const grs_font & cv_font)171 static void info_display_object_placement(grs_canvas &canvas, const grs_font &cv_font)
172 {
173 if (Cur_object_index == object_none)
174 {
175 gr_ustring(canvas, cv_font, 0, 0, "Object id: None\n");
176 return;
177 }
178 auto &Objects = LevelUniqueObjectState.Objects;
179 const auto &obj = Objects.vcptridx(Cur_object_index);
180 gr_uprintf(canvas, cv_font, 0, 64, "Mode: %s\n", get_ai_behavior(obj->ctype.ai_info.behavior));
181 ::dcx::info_display_object_placement(canvas, cv_font, obj);
182 }
183
184 }
185
186 }
187
188 namespace dcx {
189
190 namespace {
191
192 // ---------------------------------------------------------------------------------------------------
info_display_segsize(grs_canvas & canvas,const grs_font & cv_font)193 static void info_display_segsize(grs_canvas &canvas, const grs_font &cv_font)
194 {
195 const char *name;
196 switch (SegSizeMode) {
197 case SEGSIZEMODE_FREE: name = "free "; break;
198 case SEGSIZEMODE_ALL: name = "all "; break;
199 case SEGSIZEMODE_CURSIDE: name = "curside"; break;
200 case SEGSIZEMODE_EDGE: name = "edge "; break;
201 case SEGSIZEMODE_VERTEX: name = "vertex "; break;
202 default:
203 throw std::runtime_error("illegal value for SegSizeMode in " __FILE__ "/info_display_segsize");
204 }
205 gr_uprintf(canvas, cv_font, 0, 0, "Mode: %s\n", name);
206 }
207
208 // ------------------------------------------------------------------------------------
clear_pad_display(grs_canvas & canvas)209 static void clear_pad_display(grs_canvas &canvas)
210 {
211 gr_clear_canvas(canvas, CWHITE);
212 gr_set_fontcolor(canvas, CBLACK, CWHITE);
213 }
214
215 }
216
217 }
218
219 namespace dsx {
220
221 namespace {
222
223 // ---------------------------------------------------------------------------------------------------
info_display_default(grs_canvas & canvas,const grs_font & cv_font)224 static void info_display_default(grs_canvas &canvas, const grs_font &cv_font)
225 {
226 auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
227 auto &TmapInfo = LevelUniqueTmapInfoState.TmapInfo;
228
229 {
230 init_info = 0;
231 }
232
233 gr_set_fontcolor(canvas, CBLACK, CWHITE);
234
235 //--------------- Number of segments ----------------
236
237 gr_uprintf(canvas, cv_font, 0, 0, "Segments: %4d/%4" PRIuFAST32, LevelSharedSegmentState.Num_segments, static_cast<uint_fast32_t>(MAX_SEGMENTS));
238
239 //---------------- Number of vertics -----------------
240
241 gr_uprintf(canvas, cv_font, 0, 16, "Vertices: %4d/%4" PRIuFAST32, LevelSharedVertexState.Num_vertices, static_cast<uint_fast32_t>(MAX_VERTICES));
242
243 //---------------- Number of objects -----------------
244
245 {
246 const auto num_objects = LevelUniqueObjectState.num_objects;
247 gr_uprintf(canvas, cv_font, 0, 32, "Objs: %3d/%3" DXX_PRI_size_type, num_objects, MAX_OBJECTS.value);
248 }
249
250 //--------------- Current_segment_number -------------
251 //--------------- Current_side_number -------------
252
253 {
254 gr_uprintf(canvas, cv_font, 0, 48, "Cursegp/side: %3hu/%1d", static_cast<segnum_t>(Cursegp), Curside);
255 unique_segment &useg = *Cursegp;
256 auto &uside = useg.sides[Curside];
257 gr_uprintf(canvas, cv_font, 0, 128, " tmap1,2,o: %3d/%3dx%1u", get_texture_index(uside.tmap_num), get_texture_index(uside.tmap_num2), static_cast<unsigned>(get_texture_rotation_low(uside.tmap_num2)));
258 }
259
260 //--------------- Current_vertex_numbers -------------
261
262 {
263 using U = std::underlying_type<vertnum_t>::type;
264 gr_uprintf(canvas, cv_font, 0, 64, "{%3u,%3u,%3u,%3u,", static_cast<U>(Cursegp->verts[0]), static_cast<U>(Cursegp->verts[1]), static_cast<U>(Cursegp->verts[2]), static_cast<U>(Cursegp->verts[3]));
265 gr_uprintf(canvas, cv_font, 0, 80, " %3u,%3u,%3u,%3u}", static_cast<U>(Cursegp->verts[4]), static_cast<U>(Cursegp->verts[5]), static_cast<U>(Cursegp->verts[6]), static_cast<U>(Cursegp->verts[7]));
266 }
267
268 //--------------- Num walls/links/triggers -------------------------
269
270 auto &Walls = LevelUniqueWallSubsystemState.Walls;
271 gr_uprintf(canvas, cv_font, 0, 96, "Walls %3d", Walls.get_count());
272
273 //--------------- Num triggers ----------------------
274
275 auto &Triggers = LevelUniqueWallSubsystemState.Triggers;
276 gr_uprintf(canvas, cv_font, 0, 112, "Num_triggers %2d", Triggers.get_count());
277
278 //--------------- Current texture number -------------
279 gr_uprintf(canvas, cv_font, 0, 144, "Tex/Light: %3d %5.2f", CurrentTexture, f2fl(TmapInfo[CurrentTexture].lighting));
280 }
281
282 // ------------------------------------------------------------------------------------
event_handler(const d_event & event)283 window_event_result info_dialog_window::event_handler(const d_event &event)
284 {
285 static int old_padnum = -1;
286 int padnum; // always redraw
287 grs_canvas *save_canvas = grd_curcanv;
288
289 switch (event.type)
290 {
291 case EVENT_WINDOW_DRAW:
292 {
293 gr_set_current_canvas(w_canv);
294 auto &canvas = *grd_curcanv;
295
296 padnum = ui_pad_get_current();
297 Assert(padnum <= MAX_PAD_ID);
298
299 if (padnum != old_padnum) {
300 old_padnum = padnum;
301 clear_pad_display(canvas);
302 }
303
304 switch (padnum) {
305 case OBJECT_PAD_ID: // Object placement
306 info_display_object_placement(canvas, *canvas.cv_font);
307 break;
308 case SEGSIZE_PAD_ID: // Segment sizing
309 info_display_segsize(canvas, *canvas.cv_font);
310 break;
311 default:
312 info_display_default(canvas, *canvas.cv_font);
313 break;
314 }
315 grd_curcanv = save_canvas;
316 return window_event_result::handled;
317 }
318 case EVENT_WINDOW_CLOSE:
319 Pad_info = NULL;
320 break;
321
322 default:
323 break;
324 }
325 return window_event_result::ignored;
326 }
327
328 }
329
330 // ------------------------------------------------------------------------------------
info_window_create(void)331 window *info_window_create(void)
332 {
333 auto wind = window_create<info_dialog_window>(*Canv_editor, PAD_X + 250, PAD_Y + 8, 180, 160);
334 wind->set_modal(0);
335 return wind;
336 }
337
338 }
339