Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/core/preview/game-preview.middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,15 @@ export default {
async handler(req: Request, res: Response, next: NextFunction) {
try {
const { default: scripting } = await import('../../core/scripting');
const serverBaseUrl = `${req.protocol}://${req.get('host')}`;
const host = req.get('host') || '';
const colon = host.lastIndexOf(':');
const scene = typeof req.query.scene === 'string' ? req.query.scene : '';
const sceneQuery = scene ? `?scene=${encodeURIComponent(scene)}` : '';
const renderData = {
title: `Cocos Creator - ${basename(scripting.projectPath)}`,
serverURL: serverBaseUrl,
ip: colon >= 0 ? host.slice(0, colon) : host,
port: colon >= 0 ? host.slice(colon + 1) : '',
https: req.protocol === 'https',
settingsJs: `/preview/settings.js${sceneQuery}`,
sceneQuery,
};
Expand Down
6 changes: 1 addition & 5 deletions src/core/scene/scene-process/engine-bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import * as EditorExtends from '../../engine/editor-extends';
import { Rpc } from './rpc';
import { serviceManager } from './service/service-manager';
import { Service as DecoratorService } from './service/core/decorator';
import { messageManager } from './service/message';
import { initLocalI18n } from './i18n';

import './service';
Expand Down Expand Up @@ -30,7 +29,7 @@ export async function startup(options: {
const features = (await modules.json()) as string[];
const { serverURL } = options;

serviceManager.initialize(serverURL);
serviceManager.init(serverURL);

const requiredModules = [
'cc',
Expand Down Expand Up @@ -84,9 +83,6 @@ export async function startup(options: {

(globalThis as any).cce = (globalThis as any).cce || {};
(globalThis as any).cce.Script = DecoratorService.Script;
(globalThis as any).cli = {};
(globalThis as any).cli.Scene = DecoratorService;
(globalThis as any).cli.SceneEvents = messageManager;

if (EditorExtends.init) {
await EditorExtends.init();
Expand Down
2 changes: 1 addition & 1 deletion src/core/scene/scene-process/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ async function startup() {
}

// 初始化 service-manager
serviceManager.initialize(serverURL ?? '');
serviceManager.init(serverURL ?? '');

await Engine.init(enginePath);
// 这里 importBase 与 nativeBase 用服务器是为了让服务器转换资源真实存放的路径
Expand Down
2 changes: 1 addition & 1 deletion src/core/scene/scene-process/service/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export class EngineService extends BaseService<IEngineEvents> implements IEngine
* 渲染调试视图(DebugView):单一通道调试 / 组合光照项开关 / 纯光照带固有色 / 级联阴影染色。
* 与 cocos-editor scene-facade-manager.changeDebugOption 对齐。
* 注意:不对外暴露为公共 API(未加入 IEngineService / EngineProxy,不生成到 cocos-cli-types);
* 目前仅由场景编辑器页面(scene-editor.ejs)在浏览器内通过 window.cli.Scene.Engine 直接调用。
* 目前仅由场景编辑器页面(scene-editor.ejs)在浏览器内通过 serviceManager.getServices().Engine 直接调用。
* @param key 'single' | 'composite' | 'LIGHTING_WITH_BASE_COLOR' | 'CSM_LAYER_COLORATION'
* @param value single: DebugViewSingleType 数值;composite: { key: DebugViewCompositeType | 10000(=ALL), value: boolean };其余: boolean
*/
Expand Down
26 changes: 25 additions & 1 deletion src/core/scene/scene-process/service/service-manager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { getServiceAll, IServiceEvents, ServiceEvents } from './core';
import { getServiceAll, IServiceEvents, ServiceEvents, Service } from './core';
import { InternalServiceEvents } from './core/internal-events';
import { IEditorEvents, INodeEvents, IComponentEvents, IScriptEvents, IAssetEvents, ISelectionEvents } from '../../common';
import { messageManager } from './message';
import type { IServiceManager } from './interfaces';
import type { GlobalEventManager } from './core/global-events';

type AllEvents = IEditorEvents & INodeEvents & IComponentEvents & IScriptEvents & IAssetEvents & ISelectionEvents;

Expand Down Expand Up @@ -99,10 +101,32 @@ export class ServiceManager {
this.registerAutoForwardEvents();
}

/** Alias of {@link initialize}; the public entry used by callers/boot. */
init(serverUrl: string) {
this.initialize(serverUrl);
}

getServerUrl() {
return this.serverUrl;
}

/**
* The typed service map (Engine / Editor / Camera / Preview / ...).
* Both cli's own browser pages and external IDEs go through this instead of
* the former `window.cli.Scene` global.
*/
getServices(): IServiceManager {
return Service;
}

/**
* The global service event bus where service events (e.g. `editor:open`)
* are actually emitted (see base-service emit -> ServiceEvents).
*/
getServiceEvents(): GlobalEventManager {
return ServiceEvents;
}

/**
* Camera/Gizmo 依赖的编辑器内置 effect UUID
*/
Expand Down
14 changes: 10 additions & 4 deletions src/core/scene/scene.scripting.middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ export default {
return res.redirect(302, '/scene-editor/');
}
const { default: scripting } = await import('../../core/scripting');
const serverBaseUrl = `${req.protocol}://${req.get('host')}`;
const host = req.get('host') || '';
const colon = host.lastIndexOf(':');
const renderData = {
title: `Cocos Creator Preview - ${basename(scripting.projectPath)}`,
serverURL: serverBaseUrl
ip: colon >= 0 ? host.slice(0, colon) : host,
port: colon >= 0 ? host.slice(colon + 1) : '',
https: req.protocol === 'https',
};
const templatePath = join(GlobalPaths.workspace, 'static', 'web', 'scene-editor.ejs');
const html = await ejs.renderFile(templatePath, renderData);
Expand All @@ -36,10 +39,13 @@ export default {
async handler(req: Request, res: Response, next: NextFunction) {
try {
const { default: scripting } = await import('../../core/scripting');
const serverBaseUrl = `${req.protocol}://${req.get('host')}`;
const host = req.get('host') || '';
const colon = host.lastIndexOf(':');
const renderData = {
title: `Resource Preview - ${basename(scripting.projectPath)}`,
serverURL: serverBaseUrl
ip: colon >= 0 ? host.slice(0, colon) : host,
port: colon >= 0 ? host.slice(colon + 1) : '',
https: req.protocol === 'https',
};
const templatePath = join(GlobalPaths.workspace, 'static', 'web', 'preview.ejs');
const html = await ejs.renderFile(templatePath, renderData);
Expand Down
9 changes: 0 additions & 9 deletions src/lib/cli.ts

This file was deleted.

13 changes: 13 additions & 0 deletions src/lib/scene/scene.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
import { init as sceneInit } from '../../core/scene';
import { GlobalPaths } from '../../global';

/**
* Public scene service interface, shared by external IDEs and cli's own browser
* pages (scene editor / preview). `Services` is the typed service map
* (Engine / Editor / Camera / Preview / ...); obtain the live instance at
* runtime via `serviceManager.getServices()`. `GlobalEventManager` is the
* service event bus, obtained via `serviceManager.getServiceEvents()`.
*/
export type {
IServiceManager as Services,
IPublicServiceManager,
} from '../../core/scene/scene-process/service/interfaces';
export type { GlobalEventManager } from '../../core/scene/scene-process/service/core/global-events';

/**
* Initialize the scene module.
* Registers the scene middleware and initializes scene config.
Expand Down
14 changes: 11 additions & 3 deletions static/web/editor-stub-preload.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
/* global window */

window.CC_EDITOR = true;
const serverUrl = window.WebEnv.serverURL;
/**
* Install the editor stub (window.Editor + fs/require mocks) used by the engine
* editor modules in the browser. The server address is passed in explicitly
* instead of read from a global.
* @param {string} serverURL
*/
export function initEditorStub(serverURL) {
window.CC_EDITOR = true;
const serverUrl = serverURL;

window.Editor = {
window.Editor = {
Message: {
request: async function (target, method, uuid) {
if (method === 'query-asset-info') {
Expand Down Expand Up @@ -104,4 +111,5 @@ if (typeof window.require === 'undefined') {
throw new Error('Module ' + name + ' not found in editor-stub-preload require mock');
};
window.require.cache = {};
}
}
24 changes: 19 additions & 5 deletions static/web/engine-loader.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
/* global window, document, System, fetch */

/**
* 由 ip / port 组装服务地址;未提供 ip 时回退到当前页面 origin。
* @param {{ ip?: string, port?: number|string, https?: boolean }} [addr]
* @returns {string}
*/
export function composeServerURL(addr = {}) {
const { ip, port, https } = addr;
if (!ip) return window.location.origin;
const protocol = https ? 'https' : 'http';
return port ? `${protocol}://${ip}:${port}` : `${protocol}://${ip}`;
}

/**
* 引擎加载公共流程。
*
Expand All @@ -8,12 +20,13 @@
* 预览以 PREVIEW 模式(EDITOR=false / PREVIEW=true)加载,场景编辑器以默认编辑器模式加载。
* 加载完成后各调用方自行 System.import('cc') 跑游戏,或 import scene-bundle 启服务。
*
* @param {string} serverURL 服务地址(http[s]://ip:port),由调用方(boot)传入。
* @param {{ preview?: boolean }} [options] preview=true 时以 PREVIEW 模式加载引擎。
* @returns {Promise<object>} 填充后的 window.WebEnv(含 serverURL / enginePath 等)。
* @returns {Promise<object>} 加载环境(含 serverURL / enginePath 等)。
*/
export async function loadEngine(options = {}) {
const env = window.WebEnv;
const envRes = await fetch(`${env.serverURL}/scripting/web-env`);
export async function loadEngine(serverURL, options = {}) {
const env = { serverURL };
const envRes = await fetch(`${serverURL}/scripting/web-env`);
Object.assign(env, await envRes.json());

await import('/static/web/polyfills.bundle.js');
Expand Down Expand Up @@ -41,7 +54,8 @@ export async function loadEngine(options = {}) {
return fetch(url).then((response) => response.json()).then((json) => ({ json, url: url.href }));
});

await import('/static/web/editor-stub-preload.js');
const { initEditorStub } = await import('/static/web/editor-stub-preload.js');
initEditorStub(serverURL);
if (options.preview) {
// 游戏预览必须以 PREVIEW 模式运行,而不是编辑器编辑模式。
// editor-stub-preload 会设置 window.CC_EDITOR=true(场景编辑器预览需要),
Expand Down
7 changes: 4 additions & 3 deletions static/web/game-boot.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* global window, document, System, globalThis, fetch, location */

import { loadEngine } from '/static/web/engine-loader.js';
import { loadEngine, composeServerURL } from '/static/web/engine-loader.js';

/**
* 浏览器游戏预览运行时引导。
Expand All @@ -9,7 +9,7 @@ import { loadEngine } from '/static/web/engine-loader.js';
* 共用 engine-loader.js,区别在于这里以 PREVIEW 模式加载,并在结尾调用 cc.game.init(settings)
* 运行启动场景,而不是加载场景编辑器 bundle。流程对齐编辑器 preview-app/src/main.ts。
*/
export default async function gameBoot() {
export default async function gameBoot(addr = {}) {
const showError = (e) => {
const el = document.getElementById('error');
if (el) {
Expand All @@ -20,7 +20,8 @@ export default async function gameBoot() {

try {
// 以 PREVIEW 模式加载引擎(EDITOR=false / PREVIEW=true)
const env = await loadEngine({ preview: true });
const serverURL = composeServerURL(addr);
const env = await loadEngine(serverURL, { preview: true });

const _originalSystem = System;
const cc = await System.import('cc');
Expand Down
3 changes: 1 addition & 2 deletions static/web/game.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
<div id="error"></div>

<script>
window.WebEnv = { serverURL: '<%= serverURL %>' };
window.__launchSceneQuery = '<%= sceneQuery %>';
</script>
<!-- 运行时 settings:定义 window._CCSettings -->
Expand All @@ -62,7 +61,7 @@
<script src="/socket.io/socket.io.js"></script>
<script type="module">
const { default: gameBoot } = await import('/static/web/game-boot.js');
await gameBoot();
await gameBoot({ ip: '<%= ip %>', port: '<%= port %>', https: <%= https %> });
</script>
</body>
</html>
18 changes: 13 additions & 5 deletions static/web/load-scene.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
/* global window, cc, fetch */
/* global cc, fetch */

/**
* 加载并打开场景/预制体。
*
* @param {{ services: object, events: object, serverURL: string }} ctx boot() 返回的场景服务上下文
* @param {string} [urlOrUUID] 场景/预制体 uuid 或 db:// url;缺省时自动挑选第一个用户场景
*/
export async function loadScene(ctx, urlOrUUID) {
const { services, events, serverURL } = ctx;

window.loadScene = async function (serverURL, urlOrUUID) {
if (!urlOrUUID) {
const sceneListPromise = await fetch(`${serverURL}/query-asset-infos/cc.SceneAsset`);
const sceneList = await sceneListPromise.json();
Expand All @@ -20,8 +28,8 @@ window.loadScene = async function (serverURL, urlOrUUID) {
return;
}

cli.SceneEvents.on('editor:open', () => {
events.on('editor:open', () => {
console.log('editor:open onCalled');
});
await cli.Scene.Editor.open({ urlOrUUID });
};
await services.Editor.open({ urlOrUUID });
}
Loading
Loading