1 #include "debugscript.h"
9 void DebugScript::ParseAction(View * view, Screen * scr)
12 if (m_input == NULL || !m_input->good())
14 istream & inp = *m_input;
15 Debug("Get action type...");
16 std::string actionType;
18 Debug("Action type: %s", actionType.c_str());
20 while (actionType[0] == '#')
23 std::getline(inp, tmp);
24 inp >> std::ws >> actionType;
26 if (actionType == "loop")
28 inp >> currentAction.loops >> actionType;
32 currentAction.loops = 1;
35 if (actionType == "wait")
37 currentAction.type = AT_WaitFrame;
40 else if (actionType == "translate")
44 currentAction.type = AT_Translate;
45 currentAction.x = RealFromStr(_x.c_str());
46 currentAction.y = RealFromStr(_y.c_str());
49 else if (actionType == "zoom")
51 std::string _x, _y, _z;
52 inp >> _x >> _y >> _z;
53 currentAction.type = AT_Zoom;
54 currentAction.x = RealFromStr(_x.c_str());
55 currentAction.y = RealFromStr(_y.c_str());
56 currentAction.z = RealFromStr(_z.c_str());
58 else if (actionType == "pxtranslate")
60 inp >> currentAction.ix >> currentAction.iy;
61 currentAction.type = AT_TranslatePx;
63 else if (actionType == "pxzoom")
65 inp >> currentAction.ix >> currentAction.iy >> currentAction.iz;
66 currentAction.type = AT_ZoomPx;
68 else if (actionType == "gpu")
70 currentAction.type = AT_SetGPURendering;
72 else if (actionType == "cpu")
74 currentAction.type = AT_SetCPURendering;
76 else if (actionType == "lazy")
78 currentAction.type = AT_EnableLazyRendering;
80 else if (actionType == "nolazy")
82 currentAction.type = AT_DisableLazyRendering;
84 else if (actionType == "quit")
86 currentAction.type = AT_Quit;
88 else if (actionType == "loadsvg")
90 currentAction.type = AT_LoadSVG;
91 inp >> currentAction.textargs;
93 else if (actionType == "label")
95 currentAction.type = AT_Label;
96 inp >> currentAction.textargs;
98 else if (actionType == "goto")
100 currentAction.type = AT_Goto;
101 inp >> currentAction.textargs;
103 else if (actionType == "debug")
105 currentAction.type = AT_Debug;
106 getline(inp,currentAction.textargs);
108 else if (actionType == "clear")
110 currentAction.type = AT_ClearDocument;
112 else if (actionType == "clearperf")
114 currentAction.type = AT_ClearPerformance;
116 else if (actionType == "printperf")
118 currentAction.type = AT_PrintPerformance;
120 else if (actionType == "recordperf")
122 currentAction.type = AT_RecordPerformance;
124 else if (actionType == "debugfont")
126 currentAction.type = AT_DebugFont;
127 inp >> currentAction.textargs;
129 else if (actionType == "approachz") // approach zenoistically
131 currentAction.type = AT_ApproachBoundsZeno;
132 std::string _x, _y, _w, _h, _z;
133 inp >> _x >> _y >> _w >> _h >> _z;
134 currentAction.x = RealFromStr(_x.c_str());
135 currentAction.y = RealFromStr(_y.c_str());
136 currentAction.w = RealFromStr(_w.c_str());
137 currentAction.h = RealFromStr(_h.c_str());
138 currentAction.z = RealFromStr(_z.c_str());
140 else if (actionType == "approachl") // approach linearly
142 currentAction.type = AT_ApproachBoundsLinear;
143 std::string _x, _y, _w, _h, _z;
144 inp >> _x >> _y >> _w >> _h >> _z;
145 currentAction.x = RealFromStr(_x.c_str());
146 currentAction.y = RealFromStr(_y.c_str());
147 currentAction.w = RealFromStr(_w.c_str());
148 currentAction.h = RealFromStr(_h.c_str());
149 currentAction.z = RealFromStr(_z.c_str());
150 currentAction.x = (currentAction.x - view->GetBounds().x)/currentAction.z;
151 currentAction.y = (currentAction.y - view->GetBounds().y)/currentAction.z;
152 currentAction.w = (currentAction.w - view->GetBounds().w)/currentAction.z;
153 currentAction.h = (currentAction.h - view->GetBounds().h)/currentAction.z;
155 else if (actionType == "setbounds")
157 currentAction.type = AT_SetBounds;
158 std::string _x, _y, _w, _h;
159 inp >> _x >> _y >> _w >> _h;
160 currentAction.x = RealFromStr(_x.c_str());
161 currentAction.y = RealFromStr(_y.c_str());
162 currentAction.w = RealFromStr(_w.c_str());
163 currentAction.h = RealFromStr(_h.c_str());
165 else if (actionType == "querygpubounds")
167 currentAction.type = AT_QueryGPUBounds;
168 inp >> currentAction.textargs;
169 currentAction.loops = 1;
171 else if (actionType == "screenshot")
173 currentAction.type = AT_ScreenShot;
174 inp >> currentAction.textargs;
176 else if (actionType == "printfps")
178 currentAction.type = AT_PrintFPS;
179 currentAction.iz = currentAction.loops;
182 m_fps_cpu_stddev = 0;
183 m_fps_gpu_stddev = 0;
185 else if (actionType == "printbounds")
187 currentAction.type = AT_PrintBounds;
189 else if (actionType == "profileon")
191 currentAction.type = AT_ProfileDisplay;
192 currentAction.iz = 1;
194 else if (actionType == "profileoff")
196 currentAction.type = AT_ProfileDisplay;
197 currentAction.iz = 0;
200 Fatal("Unknown action %s", actionType.c_str());
204 bool DebugScript::Execute(View *view, Screen *scr)
206 if (currentAction.loops <= 0)
208 if (m_index >= m_actions.size())
210 ParseAction(view, scr);
211 if (m_labels.size() > 0)
213 m_actions.push_back(currentAction);
219 currentAction = m_actions[m_index++];
222 switch(currentAction.type)
229 view->Translate(currentAction.x, currentAction.y);
232 view->Translate(Real(currentAction.ix)/Real(scr->ViewportWidth()), Real(currentAction.iy)/Real(scr->ViewportHeight()));
235 view->ScaleAroundPoint(currentAction.x, currentAction.y, currentAction.z);
238 view->ScaleAroundPoint(Real(currentAction.ix)/Real(scr->ViewportWidth()),Real(currentAction.iy)/Real(scr->ViewportHeight()), Real(expf(-currentAction.iz/20.f)));
240 case AT_SetGPURendering:
241 view->SetGPURendering(true);
243 case AT_SetCPURendering:
244 view->SetGPURendering(false);
246 case AT_EnableLazyRendering:
247 view->SetLazyRendering(true);
249 case AT_DisableLazyRendering:
250 view->SetLazyRendering(false);
254 #ifndef QUADTREE_DISABLED
255 view->Doc().SetQuadtreeInsertNode(view->GetCurrentQuadtreeNode());
257 #ifdef TRANSFORM_OBJECTS_NOT_VIEW
258 view->Doc().LoadSVG(currentAction.textargs, Rect(Real(1)/Real(2),Real(1)/Real(2),Real(1)/Real(800),Real(1)/Real(600)));
260 const Rect & bounds = view->GetBounds();
261 view->Doc().LoadSVG(currentAction.textargs, Rect(bounds.x+bounds.w/Real(2),bounds.y+bounds.h/Real(2),bounds.w/Real(800),bounds.h/Real(600)));
263 #ifndef QUADTREE_DISABLED
264 view->Doc().PropagateQuadChanges(view->GetCurrentQuadtreeNode());
266 currentAction.type = AT_WaitFrame;
267 view->ForceRenderDirty();
268 view->ForceBufferDirty();
269 view->ForceBoundsDirty();
270 currentAction.loops = 1;
274 m_labels[currentAction.textargs] = m_index;
275 currentAction.type = AT_WaitFrame;
276 currentAction.loops = 1;
279 m_index = m_labels[currentAction.textargs];
280 currentAction.loops = 1;
283 Debug("View bounds: %s", view->GetBounds().Str().c_str());
284 if (currentAction.textargs.size() > 0)
285 Debug("%s", currentAction.textargs.c_str());
287 case AT_ClearDocument:
288 view->Doc().ClearObjects();
289 currentAction.loops = 1;
291 case AT_ClearPerformance:
292 ClearPerformance(view, scr);
293 currentAction.loops = 1;
295 case AT_PrintPerformance:
296 PrintPerformance(view, scr);
297 currentAction.loops = 1;
299 case AT_RecordPerformance:
300 PrintPerformance(view, scr);
303 scr->ShowDebugFont(currentAction.textargs == "1" || currentAction.textargs == "on");
304 currentAction.loops = 1;
307 case AT_ApproachBoundsZeno:
309 VRect target(currentAction.x, currentAction.y, currentAction.w, currentAction.h);
310 if (currentAction.z != VReal(1))
312 target.x = view->GetBounds().x + (target.x-view->GetBounds().x)/VReal(currentAction.z);
313 target.y = view->GetBounds().y + (target.y-view->GetBounds().y)/VReal(currentAction.z);
314 target.w = view->GetBounds().w + (target.w-view->GetBounds().w)/VReal(currentAction.z);
315 target.h = view->GetBounds().h + (target.h-view->GetBounds().h)/VReal(currentAction.z);
319 VReal s = target.w/(view->GetBounds().w);
324 x0 = (view->GetBounds().x - target.x)/((s - VReal(1))*view->GetBounds().w);
325 y0 = (view->GetBounds().y - target.y)/((s - VReal(1))*view->GetBounds().h);
326 view->ScaleAroundPoint(x0, y0, s);
327 currentAction.loops++;
331 Debug("Already at target view; Waiting for remaining %d frames", currentAction.loops);
332 currentAction.type = AT_WaitFrame;
336 case AT_ApproachBoundsLinear:
338 VRect target(currentAction.x, currentAction.y, currentAction.w, currentAction.h);
339 target.x += view->GetBounds().x;
340 target.y += view->GetBounds().y;
341 target.w += view->GetBounds().w;
342 target.h += view->GetBounds().h;
343 VReal s = target.w/(view->GetBounds().w);
348 x0 = (view->GetBounds().x - target.x)/((s - VReal(1))*view->GetBounds().w);
349 y0 = (view->GetBounds().y - target.y)/((s - VReal(1))*view->GetBounds().h);
350 view->ScaleAroundPoint(x0, y0, s);
351 currentAction.loops++;
355 Debug("Already at target view; Waiting for remaining %d frames", currentAction.loops);
356 currentAction.type = AT_WaitFrame;
362 VRect target(currentAction.x, currentAction.y, currentAction.w, currentAction.h);
363 view->SetBounds(target);
367 case AT_QueryGPUBounds:
369 view->QueryGPUBounds(currentAction.textargs.c_str(), "w");
370 currentAction.loops = 1;
375 view->SaveBMP(currentAction.textargs.c_str());
376 currentAction.loops = 1;
381 // Using a (apparently) Soviet trick to calculate the stddev in one pass
382 // This was my favourite algorithm in my Physics honours project
384 // The horrible horrible memories
385 // At least things won't get that bad
387 if (currentAction.loops <= 1)
389 double n = double(currentAction.iz);
393 m_fps_cpu_stddev = sqrt(m_fps_cpu_stddev / n - m_fps_cpu_mean*m_fps_cpu_mean);
394 m_fps_gpu_stddev = sqrt(m_fps_gpu_stddev / n - m_fps_gpu_mean*m_fps_gpu_mean);
398 printf("%d\t%f\t%f\t%f\t%f\n", currentAction.iz,
399 m_fps_gpu_mean, m_fps_gpu_stddev,
400 m_fps_cpu_mean, m_fps_cpu_stddev);
405 double fps_cpu = 1.0/scr->GetLastFrameTimeCPU();
406 double fps_gpu = 1.0/scr->GetLastFrameTimeGPU();
408 m_fps_cpu_mean += fps_cpu;
409 m_fps_gpu_mean += fps_gpu;
411 m_fps_cpu_stddev += fps_cpu*fps_cpu;
412 m_fps_gpu_stddev += fps_gpu*fps_gpu;
418 printf("%s\t%s\t%s\t%s\n", Str(view->GetBounds().x).c_str(), Str(view->GetBounds().y).c_str(), Str(view->GetBounds().w).c_str(), Str(view->GetBounds().h).c_str());
421 case AT_ProfileDisplay:
423 g_profiler.Enable(currentAction.iz);
427 Fatal("Unknown script command in queue.");
429 currentAction.loops--;
433 void DebugScript::ClearPerformance(View * view, Screen * scr)
435 m_perf_start.clock = clock();
436 m_perf_start.object_count = view->Doc().ObjectCount();
437 m_perf_start.view_bounds = view->GetBounds();
438 m_perf_last = m_perf_start;
441 void DebugScript::PrintPerformance(View * view, Screen * scr)
443 DebugScript::PerformanceData now;
445 now.object_count = view->Doc().ObjectCount();
446 now.view_bounds = view->GetBounds();
448 // object_count clock delta_clock x Log10(x) y Log10(y) w Log10(w) Size(w)
449 #ifdef QUADTREE_DISABLED
450 printf("%d\t%llu\t%llu\t%s\t%s\t%s\t%s\t%s\t%s\t%u\n",
451 now.object_count, (long long unsigned)now.clock,
452 (long long unsigned)(now.clock - m_perf_last.clock),
453 Str(now.view_bounds.x).c_str(), Str(Log10(Abs(now.view_bounds.x))).c_str(),
454 Str(now.view_bounds.y).c_str(), Str(Log10(Abs(now.view_bounds.y))).c_str(),
455 Str(now.view_bounds.w).c_str(), Str(Log10(now.view_bounds.w)).c_str(),
456 (unsigned)Size(now.view_bounds.w));