1 module godot.util.generator.d; 2 3 import godot.util.tools.string; 4 import godot.util.generator.util; 5 import godot.util.generator.classes, godot.util.generator.methods; 6 7 import std.algorithm.iteration; 8 import std.range; 9 import std.path; 10 import std.conv : text; 11 import std.string; 12 13 private: 14 15 static immutable string copyrightNotice = 16 `Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. 17 Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md) 18 Copyright (c) 2017-2018 Godot-D contributors 19 Copyright (c) 2022-2022 Godot-DLang contributors`; 20 21 string[2] generatePackage(GodotClass c) { 22 if (c.name.godotType == "CoreConstants") 23 return [null, null]; 24 25 if (c.descendant_ptrs.length == 0) 26 return [null, null]; 27 28 string filename = buildPath("godot", c.name.moduleName, "all.d"); 29 string ret; 30 31 ret ~= "module godot."; 32 ret ~= c.name.moduleName; 33 ret ~= ".all;\n\n"; 34 35 ret ~= "public import\n\tgodot." ~ c.name.moduleName; 36 37 const(GodotClass)[] recursiveDescendants; 38 void addDescendant(GodotClass d) { 39 import std.algorithm.searching; 40 41 if (!recursiveDescendants[].canFind(d)) 42 recursiveDescendants ~= d; 43 foreach (rd; d.descendant_ptrs[]) 44 addDescendant(rd); 45 } 46 47 foreach (d; c.descendant_ptrs[]) 48 addDescendant(d); 49 50 foreach (di, d; recursiveDescendants[]) { 51 ret ~= ",\n\tgodot." ~ d.name.moduleName; 52 } 53 ret ~= ";\n"; 54 55 string[2] arr = [filename, ret]; 56 return arr; 57 } 58 59 string[2] generateClass(GodotClass c) { 60 if (c.name.godotType == "CoreConstants") 61 return [null, null]; 62 63 string folder = "godot"; 64 string filename = (c.descendant_ptrs.length == 0) ? 65 buildPath(folder, c.name.moduleName ~ ".d") : buildPath(folder, c.name.moduleName, "package.d"); 66 string ret; 67 68 ret ~= "/**\n" ~ c.ddocBrief ~ "\n\n"; 69 ret ~= "Copyright:\n" ~ copyrightNotice ~ "\n\n"; 70 ret ~= "License: $(LINK2 https://opensource.org/licenses/MIT, MIT License)\n\n"; 71 ret ~= "\n*/\n"; 72 73 // module names should be all lowercase in D 74 // https://dlang.org/dstyle.html 75 ret ~= "module godot."; 76 ret ~= c.name.moduleName; 77 ret ~= ";\n"; 78 ret ~= "import std.meta : AliasSeq, staticIndexOf;\n"; 79 ret ~= "import std.traits : Unqual;\n"; 80 ret ~= "import godot.api.traits;\nimport godot;\nimport godot.abi;\n"; 81 ret ~= "import godot.api.bind;\n"; 82 ret ~= "import godot.api.reference;\n"; 83 ret ~= "import godot.globalenums;\n"; 84 if (c.name.godotType != "Object") 85 ret ~= "import godot.object;\n"; 86 87 if (c.instanciable) { 88 ret ~= "import godot.classdb;\n"; 89 } 90 91 ret ~= c.source; 92 93 string[2] arr = [filename, ret]; 94 return arr; 95 } 96 97 string[2] generateGlobalConstants(GodotClass c) { 98 import std.conv : text; 99 import std.string; 100 import std.meta; 101 import std.algorithm.iteration, std.algorithm.searching, std.algorithm.sorting; 102 import std.range : array; 103 104 if (c.name.godotType != "CoreConstants") 105 return [null, null]; 106 107 string filename = buildPath("godot", "globalconstants.d"); 108 string ret; 109 110 ret ~= "/// \n"; 111 ret ~= "module godot.globalconstants;\n"; 112 ret ~= "public import godot.globalenums;\n"; 113 114 foreach (constant; c.constants) { 115 ret ~= "enum int " ~ constant.name.snakeToCamel.escapeD ~ " = " ~ text( 116 constant.value) ~ ";\n"; 117 } 118 119 string[2] arr = [filename, ret]; 120 return arr; 121 } 122 123 string[2] generateGlobalEnums(GodotClass c) { 124 import std.conv : text; 125 import std.string; 126 import std.meta; 127 import std.algorithm.iteration, std.algorithm.searching, std.algorithm.sorting; 128 import std.range : array; 129 130 if (c.name.godotType != "CoreConstants") 131 return [null, null]; 132 133 string filename = buildPath("godot", "globalenums.d"); 134 string ret; 135 136 ret ~= "/// \n"; 137 ret ~= "module godot.globalenums;\n"; 138 139 /// Try to put at least some of these in grouped enums 140 static struct Group { 141 string name; /// The name of the new enum 142 string prefix; /// The prefix to strip from original name 143 } 144 145 alias groups = AliasSeq!( 146 Group("Key", "KEY_"), 147 Group("MouseButton", "MOUSE_BUTTON_"), 148 Group("PropertyHint", "PROPERTY_HINT_"), 149 Group("PropertyUsage", "PROPERTY_USAGE_"), 150 Group("Type", "TYPE_"), 151 Group("TransferMode", "TRANSFER_MODE_"), 152 Group("InlineAlign", "INLINE_ALIGN_"), 153 ); 154 155 import godot.util.generator.enums; 156 157 foreach (g; c.enums) { 158 // Skip Variant.Type & Variant.Operator, they are defined in core C module 159 if (g.name.startsWith("Variant.") || g.name == "PropertyUsageFlags") 160 continue; 161 162 ret ~= "enum " ~ g.name ~ " : int\n{\n"; 163 164 foreach (e; g.values) { 165 ret ~= "\t" ~ e.name.snakeToCamel.escapeD 166 ~ " = " ~ text(e.value) ~ ",\n"; 167 } 168 169 ret ~= "}\n"; 170 } 171 172 // Godot itself never refers to these, but some modules like Goost do. 173 // Allow bindings for them to compile by keeping the original names. 174 //string[2][] aliases = [["KeyList", "Key"], ["PropertyUsageFlags", "PropertyUsage"], ["ButtonList", "MouseButton"]]; 175 //foreach(a; aliases) 176 //{ 177 // ret ~= "alias " ~ a[0] ~ " = " ~ a[1] ~ ";\n"; 178 //} 179 180 string[2] arr = [filename, ret]; 181 return arr; 182 }