1 module re.ng.diag.default_commands;
2 
3 import re.core;
4 import re.ecs;
5 import std.range;
6 import std.array;
7 import std.algorithm;
8 import std.string;
9 
10 debug static class DefaultCommands {
11     alias log = Core.log;
12     alias scenes = Core.scenes;
13     alias dbg = Core.debugger;
14     alias con = dbg.console;
15 
16     static void c_help(string[] args) {
17         auto sb = appender!string();
18         sb ~= "available commmands:\n";
19         auto command_names = con.commands.keys.sort();
20         foreach (command_name; command_names) {
21             auto command = con.commands[command_name];
22             sb ~= format("%s - %s\n", command.name, command.help);
23         }
24         log.info(sb.data);
25     }
26 
27     static void c_entities(string[] args) {
28         auto sb = appender!string();
29         sb ~= "ENTITY LIST:\n";
30         foreach (i, scene; scenes) {
31             // print scene header
32             sb ~= format("-- Scene[%d]: %s --\n", i, typeid(scene).name);
33             foreach (entity; scene.ecs.entities) {
34                 // get list of components
35                 auto component_types = entity.get_all_components().map!(x => x.classinfo.name);
36                 sb ~= format("  %s: pos(%s) components[%d] {%s}\n", entity.name,
37                         entity.position, entity.components.length, component_types);
38             }
39         }
40         log.info(sb.data);
41     }
42 
43     private static bool pick_entity(string name, out Entity entity) {
44         // find entities in all scenes
45         foreach (scene; scenes) {
46             if (scene.ecs.has_entity(name)) {
47                 entity = scene.get_entity(name);
48                 log.info(format("selected entity '%s' in scene %s",
49                         entity.name, typeid(scene).name));
50                 return true;
51             }
52         }
53 
54         log.err(format("entity '%s' not found", name));
55         return false;
56     }
57 
58     private static bool pick_component(string[] args, out Component comp) {
59         if (args.length < 2) {
60             log.err("usage: <entity> <component>");
61             return false;
62         }
63         Entity entity;
64         if (!pick_entity(args[0], entity))
65             return false;
66         auto comp_search = args[1].toLower;
67         // find matching component
68         auto matches = entity.get_all_components()
69             .find!(x => x.classinfo.name.toLower.indexOf(comp_search) > 0);
70         if (matches.length == 0) {
71             log.err(format("no matching component for '%s'", comp_search));
72             return false;
73         }
74         comp = matches.front;
75         return true;
76     }
77 
78     static void c_dump(string[] args) {
79         Component comp;
80         if (!pick_component(args, comp))
81             return;
82         // dump this component
83         auto sb = appender!(string);
84         auto comp_class = comp.getMetaType;
85         log.info(format("dumping: %s", comp_class.getName));
86         foreach (field; comp_class.getFields) {
87             sb ~= format("%s = %s\n", field.getName, field.get(comp));
88         }
89         log.info(sb.data);
90     }
91 
92     static void c_inspect(string[] args) {
93         if (args.length == 0 && dbg.inspector.open) {
94             // close inspector when run without args
95             dbg.inspector.close();
96             return;
97         }
98         Entity entity;
99         if (!pick_entity(args[0], entity))
100             return;
101         if (dbg.inspector.open)
102             dbg.inspector.close(); // close the existing inspector
103 
104         // attach the inspector to this entity
105         dbg.inspector.inspect(entity);
106     }
107 }