scad-gltf 0.1.4 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,179 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import os from "os";
4
+ import { execSync, spawn } from "child_process";
5
+ import { fileURLToPath } from "url";
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+
10
+ const GODOT_VERSION = "4.7.2-stable";
11
+ const GODOT_SHORT_VERSION = "4.7.2.stable";
12
+ const BIN_DIR = path.resolve(__dirname, "../.godot-bin");
13
+
14
+ function getTemplatesDir() {
15
+ const isWin = os.platform() === "win32";
16
+ const isMac = os.platform() === "darwin";
17
+ let baseDir;
18
+ if (isWin) {
19
+ baseDir =
20
+ process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming");
21
+ return path.join(baseDir, "Godot", "export_templates", GODOT_SHORT_VERSION);
22
+ } else if (isMac) {
23
+ baseDir = path.join(os.homedir(), "Library", "Application Support");
24
+ return path.join(baseDir, "Godot", "export_templates", GODOT_SHORT_VERSION);
25
+ } else {
26
+ baseDir =
27
+ process.env.XDG_DATA_HOME || path.join(os.homedir(), ".local", "share");
28
+ return path.join(baseDir, "godot", "export_templates", GODOT_SHORT_VERSION);
29
+ }
30
+ }
31
+
32
+ export function ensureExportTemplates() {
33
+ const templateDir = getTemplatesDir();
34
+ if (!fs.existsSync(templateDir)) {
35
+ console.log(`⬇️ Downloading Godot Web export templates...`);
36
+ fs.mkdirSync(templateDir, { recursive: true });
37
+ fs.mkdirSync(BIN_DIR, { recursive: true });
38
+
39
+ const tpzPath = path.join(BIN_DIR, "templates.tpz");
40
+ execSync(
41
+ `curl -fL "https://github.com/godotengine/godot/releases/download/${GODOT_VERSION}/Godot_v${GODOT_VERSION}_export_templates.tpz" -o "${tpzPath}"`,
42
+ { stdio: "inherit" },
43
+ );
44
+
45
+ const extractTemp = path.join(BIN_DIR, "templates_temp");
46
+ fs.mkdirSync(extractTemp, { recursive: true });
47
+
48
+ if (os.platform() === "win32") {
49
+ execSync(`tar -xf "${tpzPath}" -C "${extractTemp}"`, { stdio: "ignore" });
50
+ } else {
51
+ execSync(`unzip -q -o "${tpzPath}" -d "${extractTemp}"`, {
52
+ stdio: "ignore",
53
+ });
54
+ }
55
+
56
+ const extractedTemplates = path.join(extractTemp, "templates");
57
+ if (fs.existsSync(extractedTemplates)) {
58
+ fs.cpSync(extractedTemplates, templateDir, { recursive: true });
59
+ }
60
+
61
+ fs.rmSync(extractTemp, { recursive: true, force: true });
62
+ try {
63
+ fs.unlinkSync(tpzPath);
64
+ } catch (e) {}
65
+ }
66
+ }
67
+
68
+ export function getGodotBin(withTemplates = false) {
69
+ try {
70
+ execSync("godot --version", { stdio: "ignore" });
71
+ if (withTemplates) ensureExportTemplates();
72
+ return "godot";
73
+ } catch {
74
+ const isWin = os.platform() === "win32";
75
+ const isMac = os.platform() === "darwin";
76
+ const localGodot = path.join(
77
+ BIN_DIR,
78
+ isWin ? "godot.exe" : isMac ? "Godot.app/Contents/MacOS/Godot" : "godot",
79
+ );
80
+
81
+ if (!fs.existsSync(localGodot)) {
82
+ console.log(`\n⬇️ Downloading Godot ${GODOT_VERSION} headless...`);
83
+ fs.mkdirSync(BIN_DIR, { recursive: true });
84
+ let zipUrl = "";
85
+
86
+ if (isWin) {
87
+ zipUrl = `https://github.com/godotengine/godot/releases/download/${GODOT_VERSION}/Godot_v${GODOT_VERSION}_win64.exe.zip`;
88
+ } else if (isMac) {
89
+ zipUrl = `https://github.com/godotengine/godot/releases/download/${GODOT_VERSION}/Godot_v${GODOT_VERSION}_macos.universal.zip`;
90
+ } else {
91
+ const arch = os.arch();
92
+ let linuxArch = "x86_64";
93
+ if (arch === "arm64") {
94
+ linuxArch = "arm64";
95
+ } else if (arch === "arm") {
96
+ linuxArch = "arm32";
97
+ } else if (arch === "ia32") {
98
+ linuxArch = "x86_32";
99
+ }
100
+ zipUrl = `https://github.com/godotengine/godot/releases/download/${GODOT_VERSION}/Godot_v${GODOT_VERSION}_linux.${linuxArch}.zip`;
101
+ }
102
+
103
+ const zipPath = path.join(BIN_DIR, "godot.zip");
104
+ execSync(`curl -fL "${zipUrl}" -o "${zipPath}"`, { stdio: "ignore" });
105
+
106
+ if (isWin) {
107
+ execSync(`tar -xf "${zipPath}" -C "${BIN_DIR}"`, { stdio: "ignore" });
108
+ } else {
109
+ execSync(`unzip -q -o "${zipPath}" -d "${BIN_DIR}"`, {
110
+ stdio: "ignore",
111
+ });
112
+ }
113
+
114
+ if (!isMac) {
115
+ const files = fs.readdirSync(BIN_DIR);
116
+ const extracted = files.find(
117
+ (f) =>
118
+ f.startsWith("Godot_v") &&
119
+ !f.endsWith(".zip") &&
120
+ fs.statSync(path.join(BIN_DIR, f)).isFile(),
121
+ );
122
+ if (extracted) {
123
+ fs.renameSync(path.join(BIN_DIR, extracted), localGodot);
124
+ }
125
+ }
126
+
127
+ fs.chmodSync(localGodot, 0o755);
128
+ try {
129
+ fs.unlinkSync(zipPath);
130
+ } catch (e) {}
131
+ }
132
+
133
+ if (withTemplates) ensureExportTemplates();
134
+ return localGodot;
135
+ }
136
+ }
137
+
138
+ export function runGodotAsync(args, cwd, timeoutMs) {
139
+ return new Promise((resolve) => {
140
+ let output = "";
141
+ const godotBin = getGodotBin();
142
+
143
+ const env = { ...process.env };
144
+ let spawnBin = godotBin;
145
+ let spawnArgs = args;
146
+
147
+ // ---------------------------------------------------------
148
+ // CRITICAL: Do not use real display on Linux. Run inside Xvfb
149
+ // to avoid popping up windows or failing in headless server environments.
150
+ // ---------------------------------------------------------
151
+ if (process.platform === "linux") {
152
+ spawnArgs = ["-a", "-s", "-screen 0 1024x768x24", spawnBin, ...args];
153
+ spawnBin = "xvfb-run";
154
+ }
155
+
156
+ const godotProcess = spawn(spawnBin, spawnArgs, { cwd, env });
157
+
158
+ godotProcess.stdout.on("data", (data) => {
159
+ output += data.toString();
160
+ });
161
+ godotProcess.stderr.on("data", (data) => {
162
+ output += data.toString();
163
+ });
164
+
165
+ const timer = setTimeout(() => {
166
+ godotProcess.kill();
167
+ }, timeoutMs);
168
+
169
+ godotProcess.on("close", (code) => {
170
+ clearTimeout(timer);
171
+ resolve({ code, output });
172
+ });
173
+
174
+ godotProcess.on("error", (err) => {
175
+ clearTimeout(timer);
176
+ resolve({ code: -1, output: `Process error: ${err.message}` });
177
+ });
178
+ });
179
+ }