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