|
3 | 3 | * @brief Build output templates for platform emitters |
4 | 4 | */ |
5 | 5 |
|
6 | | -import { getCustomExtensions, getAssetTypeEntry } from 'esengine'; |
| 6 | +import type { RuntimeBuildConfig } from './BuildService'; |
7 | 7 |
|
8 | 8 | // ============================================================================= |
9 | 9 | // Playable HTML Template |
@@ -81,219 +81,35 @@ export interface WeChatGameJsParams { |
81 | 81 | hasSpine: boolean; |
82 | 82 | hasPhysics: boolean; |
83 | 83 | physicsConfig: string; |
84 | | - runtimeConfig?: { |
85 | | - sceneTransitionDuration?: number; |
86 | | - sceneTransitionColor?: string; |
87 | | - defaultFontFamily?: string; |
88 | | - canvasScaleMode?: string; |
89 | | - canvasMatchWidthOrHeight?: number; |
90 | | - maxDeltaTime?: number; |
91 | | - maxFixedSteps?: number; |
92 | | - textCanvasSize?: number; |
93 | | - }; |
94 | | -} |
95 | | - |
96 | | -function generateRuntimeConfigBlock(rc?: WeChatGameJsParams['runtimeConfig']): string { |
97 | | - if (!rc) return ''; |
98 | | - const lines: string[] = []; |
99 | | - if (rc.maxDeltaTime !== undefined) { |
100 | | - lines.push(` SDK.RuntimeConfig.maxDeltaTime = ${rc.maxDeltaTime};`); |
101 | | - lines.push(` app.setMaxDeltaTime(${rc.maxDeltaTime});`); |
102 | | - } |
103 | | - if (rc.maxFixedSteps !== undefined) { |
104 | | - lines.push(` SDK.RuntimeConfig.maxFixedSteps = ${rc.maxFixedSteps};`); |
105 | | - lines.push(` app.setMaxFixedSteps(${rc.maxFixedSteps});`); |
106 | | - } |
107 | | - if (rc.textCanvasSize !== undefined) lines.push(` SDK.RuntimeConfig.textCanvasSize = ${rc.textCanvasSize};`); |
108 | | - if (rc.defaultFontFamily !== undefined) lines.push(` SDK.RuntimeConfig.defaultFontFamily = ${JSON.stringify(rc.defaultFontFamily)};`); |
109 | | - if (rc.sceneTransitionDuration !== undefined) lines.push(` SDK.RuntimeConfig.sceneTransitionDuration = ${rc.sceneTransitionDuration};`); |
110 | | - if (rc.sceneTransitionColor) { |
111 | | - const hex = rc.sceneTransitionColor.replace('#', ''); |
112 | | - const r = parseInt(hex.substring(0, 2), 16) / 255; |
113 | | - const g = parseInt(hex.substring(2, 4), 16) / 255; |
114 | | - const b = parseInt(hex.substring(4, 6), 16) / 255; |
115 | | - lines.push(` SDK.RuntimeConfig.sceneTransitionColor = {r:${r},g:${g},b:${b},a:1};`); |
116 | | - } |
117 | | - if (rc.canvasScaleMode !== undefined) { |
118 | | - const modeMap: Record<string, number> = { FixedWidth: 0, FixedHeight: 1, Expand: 2, Shrink: 3, Match: 4 }; |
119 | | - lines.push(` SDK.RuntimeConfig.canvasScaleMode = ${modeMap[rc.canvasScaleMode] ?? 1};`); |
120 | | - } |
121 | | - if (rc.canvasMatchWidthOrHeight !== undefined) lines.push(` SDK.RuntimeConfig.canvasMatchWidthOrHeight = ${rc.canvasMatchWidthOrHeight};`); |
122 | | - return lines.join('\n'); |
| 84 | + runtimeConfig?: RuntimeBuildConfig; |
123 | 85 | } |
124 | 86 |
|
125 | 87 | export function generateWeChatGameJs(params: WeChatGameJsParams): string { |
126 | 88 | const { userCode, firstSceneName, allSceneNames, hasSpine, hasPhysics, physicsConfig, runtimeConfig } = params; |
127 | | - const runtimeConfigBlock = generateRuntimeConfigBlock(runtimeConfig); |
128 | | - |
129 | | - const spineInit = hasSpine ? ` |
130 | | -async function initSpineModule() { |
131 | | - try { |
132 | | - var SpineFactory = require('./spine.js'); |
133 | | - spineModule = await SpineFactory({ |
134 | | - instantiateWasm: function(imports, successCallback) { |
135 | | - WXWebAssembly.instantiate('spine.wasm', imports).then(function(result) { |
136 | | - successCallback(result.instance, result.module); |
137 | | - }); |
138 | | - return {}; |
139 | | - } |
140 | | - }); |
141 | | - } catch(e) { console.warn('Spine module not available:', e); } |
142 | | -}` : ''; |
143 | 89 |
|
144 | | - const physicsInit = hasPhysics ? ` |
145 | | -async function initPhysicsModule() { |
146 | | - try { |
147 | | - var PhysicsFactory = require('./physics.js'); |
148 | | - physicsModule = await PhysicsFactory({ |
149 | | - instantiateWasm: function(imports, successCallback) { |
150 | | - WXWebAssembly.instantiate('physics.wasm', imports).then(function(result) { |
151 | | - successCallback(result.instance, result.module); |
152 | | - }); |
153 | | - return {}; |
154 | | - } |
155 | | - }); |
156 | | - } catch(e) { console.warn('Physics module not available:', e); } |
157 | | -}` : ''; |
158 | | - |
159 | | - const sceneNamesArray = JSON.stringify(allSceneNames); |
160 | | - |
161 | | - const sceneLoading = firstSceneName ? ` |
162 | | - try { |
163 | | - var provider = { |
164 | | - loadPixels: function(ref) { return SDK.wxLoadImagePixels(resolvePath(ref)); }, |
165 | | - loadPixelsRaw: function(ref) { return SDK.wxLoadImagePixels(resolvePath(ref)); }, |
166 | | - readText: function(ref) { |
167 | | - return new Promise(function(resolve, reject) { |
168 | | - wxfs.readFile({ filePath: resolvePath(ref), encoding: 'utf-8', |
169 | | - success: function(res) { resolve(res.data); }, |
170 | | - fail: function(err) { reject(new Error(err.errMsg)); } |
171 | | - }); |
172 | | - }); |
173 | | - }, |
174 | | - readBinary: function(ref) { |
175 | | - return new Promise(function(resolve, reject) { |
176 | | - wxfs.readFile({ filePath: resolvePath(ref), |
177 | | - success: function(res) { resolve(new Uint8Array(res.data)); }, |
178 | | - fail: function(err) { reject(new Error(err.errMsg)); } |
179 | | - }); |
180 | | - }); |
181 | | - }, |
182 | | - resolvePath: resolvePath |
183 | | - }; |
184 | | -
|
185 | | - function readSceneFile(name) { |
186 | | - return new Promise(function(resolve, reject) { |
187 | | - wxfs.readFile({ filePath: 'scenes/' + name + '.json', encoding: 'utf-8', |
188 | | - success: function(res) { resolve(JSON.parse(res.data)); }, |
189 | | - fail: function(err) { reject(new Error(err.errMsg)); } |
190 | | - }); |
191 | | - }); |
192 | | - } |
193 | | -
|
194 | | - var sceneNames = ${sceneNamesArray}; |
195 | | - var mgr = app.getResource(SDK.SceneManager); |
196 | | - var sceneOpts = { app: app, module: module, provider: provider, spineModule: spineModule, physicsModule: physicsModule, physicsConfig: ${physicsConfig}, manifest: manifest }; |
197 | | -
|
198 | | - for (var i = 0; i < sceneNames.length; i++) { |
199 | | - var sd = await readSceneFile(sceneNames[i]); |
200 | | - mgr.register(SDK.createRuntimeSceneConfig(sceneNames[i], sd, sceneOpts)); |
201 | | - } |
202 | | - mgr.setInitial('${firstSceneName}'); |
203 | | - await mgr.load('${firstSceneName}'); |
204 | | -
|
205 | | - var screenAspect = canvas.width / canvas.height; |
206 | | - SDK.updateCameraAspectRatio(app.world, screenAspect); |
207 | | - } catch (err) { |
208 | | - console.error('[ESEngine] Failed to load scene:', err); |
209 | | - } |
210 | | - ` : ''; |
| 90 | + const runtimeConfigJson = runtimeConfig ? JSON.stringify(runtimeConfig) : 'undefined'; |
211 | 91 |
|
212 | 92 | return ` |
213 | 93 | var ESEngineModule = require('./esengine.js'); |
214 | 94 | var SDK = require('./sdk.js'); |
215 | 95 | globalThis.__esengine_sdk = SDK; |
216 | 96 |
|
217 | | -var spineModule = null; |
218 | | -${spineInit} |
219 | | -
|
220 | | -var physicsModule = null; |
221 | | -${physicsInit} |
| 97 | +${userCode} |
222 | 98 |
|
223 | 99 | (async function() { |
224 | | - var wxfs = wx.getFileSystemManager(); |
225 | | - var manifest = await new Promise(function(resolve, reject) { |
226 | | - wxfs.readFile({ filePath: 'asset-manifest.json', encoding: 'utf-8', |
227 | | - success: function(res) { resolve(JSON.parse(res.data)); }, |
228 | | - fail: function(err) { reject(new Error(err.errMsg)); } |
| 100 | + try { |
| 101 | + await SDK.initWeChatRuntime({ |
| 102 | + engineFactory: ESEngineModule, |
| 103 | + sceneNames: ${JSON.stringify(allSceneNames)}, |
| 104 | + firstScene: ${JSON.stringify(firstSceneName)}, |
| 105 | + runtimeConfig: ${runtimeConfigJson}, |
| 106 | + physicsConfig: ${physicsConfig}, |
| 107 | + ${hasSpine ? "spineFactory: require('./spine.js')," : ''} |
| 108 | + ${hasPhysics ? "physicsFactory: require('./physics.js')," : ''} |
229 | 109 | }); |
230 | | - }); |
231 | | - var assetIndex = {}; |
232 | | - var pathIndex = {}; |
233 | | - for (var gn in manifest.groups) { |
234 | | - var g = manifest.groups[gn]; |
235 | | - for (var uuid in g.assets) { |
236 | | - assetIndex[uuid] = g.assets[uuid]; |
237 | | - pathIndex[g.assets[uuid].path] = g.assets[uuid]; |
238 | | - } |
239 | | - } |
240 | | - var _jsonExts = ${JSON.stringify(getCustomExtensions().filter(e => getAssetTypeEntry(e)?.contentType === 'json'))}; |
241 | | - function toBuildPath(p) { |
242 | | - for (var i = 0; i < _jsonExts.length; i++) { |
243 | | - if (p.endsWith(_jsonExts[i])) return p.substring(0, p.length - _jsonExts[i].length) + '.json'; |
244 | | - } |
245 | | - return p; |
246 | | - } |
247 | | - function resolvePath(ref) { |
248 | | - var resolved = toBuildPath(ref); |
249 | | - var entry = assetIndex[ref] || assetIndex[resolved] || pathIndex[resolved] || pathIndex[ref]; |
250 | | - return entry ? entry.path : resolved; |
251 | | - } |
252 | | -
|
253 | | - var canvas = wx.createCanvas(); |
254 | | - var info = wx.getSystemInfoSync(); |
255 | | - canvas.width = info.windowWidth * info.pixelRatio; |
256 | | - canvas.height = info.windowHeight * info.pixelRatio; |
257 | | -
|
258 | | - var module = await ESEngineModule({ |
259 | | - canvas: canvas, |
260 | | - instantiateWasm: function(imports, successCallback) { |
261 | | - WXWebAssembly.instantiate('esengine.wasm', imports).then(function(result) { |
262 | | - successCallback(result.instance, result.module); |
263 | | - }); |
264 | | - return {}; |
265 | | - } |
266 | | - }); |
267 | | -
|
268 | | - var gl = canvas.getContext('webgl2') || canvas.getContext('webgl'); |
269 | | - if (!gl) { |
270 | | - console.error('[ESEngine] Failed to create WebGL context'); |
271 | | - return; |
| 110 | + } catch (err) { |
| 111 | + console.error('[ESEngine] Runtime init error:', err); |
272 | 112 | } |
273 | | - var glHandle = module.GL.registerContext(gl, { |
274 | | - majorVersion: gl.getParameter(gl.VERSION).indexOf('WebGL 2') === 0 ? 2 : 1, |
275 | | - minorVersion: 0, |
276 | | - enableExtensionsByDefault: true |
277 | | - }); |
278 | | -
|
279 | | - var app = SDK.createWebApp(module, { |
280 | | - glContextHandle: glHandle, |
281 | | - getViewportSize: function() { |
282 | | - return { width: canvas.width, height: canvas.height }; |
283 | | - } |
284 | | - }); |
285 | | -
|
286 | | -${runtimeConfigBlock} |
287 | | -
|
288 | | - ${userCode} |
289 | | -
|
290 | | - SDK.flushPendingSystems(app); |
291 | | -
|
292 | | - ${hasSpine ? 'await initSpineModule();' : ''} |
293 | | - ${hasPhysics ? 'await initPhysicsModule();' : ''} |
294 | | -
|
295 | | - ${sceneLoading} |
296 | | - app.run(); |
297 | 113 | })(); |
298 | 114 | `; |
299 | 115 | } |
0 commit comments