Skip to content

Commit 460ff2e

Browse files
Support cubism5
1 parent c0ada53 commit 460ff2e

File tree

1 file changed

+190
-0
lines changed

1 file changed

+190
-0
lines changed

src/cubism5/index.js

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
/* global ResizeObserver, document, requestAnimationFrame */
2+
3+
import { LAppDelegate } from '@demo/lappdelegate.js';
4+
import { LAppSubdelegate } from '@demo/lappsubdelegate.js';
5+
import * as LAppDefine from '@demo/lappdefine.js';
6+
import { LAppModel } from '@demo/lappmodel.js';
7+
import { LAppPal } from '@demo/lapppal';
8+
import logger from '../logger.js';
9+
10+
// 自定义的子委托类,负责 Canvas 相关的初始化和渲染管理
11+
class AppSubdelegate extends LAppSubdelegate {
12+
/**
13+
* 初始化应用所需资源。
14+
* @param {HTMLCanvasElement} canvas 传入的画布对象
15+
*/
16+
initialize(canvas) {
17+
// 初始化 WebGL 管理器,失败则返回
18+
if (!this._glManager.initialize(canvas)) {
19+
return false;
20+
}
21+
22+
this._canvas = canvas;
23+
24+
// 画布尺寸设置,支持自动和指定尺寸
25+
if (LAppDefine.CanvasSize === 'auto') {
26+
this.resizeCanvas();
27+
} else {
28+
canvas.width = LAppDefine.CanvasSize.width;
29+
canvas.height = LAppDefine.CanvasSize.height;
30+
}
31+
32+
// 设置纹理管理器使用的 GL 管理器
33+
this._textureManager.setGlManager(this._glManager);
34+
35+
const gl = this._glManager.getGl();
36+
37+
// 若帧缓冲对象未初始化,获取当前的帧缓冲绑定
38+
if (!this._frameBuffer) {
39+
this._frameBuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
40+
}
41+
42+
// 启用混合模式以实现透明效果
43+
gl.enable(gl.BLEND);
44+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
45+
46+
// 初始化视图(AppView)
47+
this._view.initialize(this);
48+
this._view._gear = {
49+
render: () => {},
50+
isHit: () => {}
51+
};
52+
// this._view.initializeSprite();
53+
54+
// Live2D 管理器与当前 subdelegate 关联
55+
// this._live2dManager.initialize(this);
56+
this._live2dManager._subdelegate = this;
57+
58+
// 监听画布大小变化,实现响应式自适应
59+
this._resizeObserver = new ResizeObserver(
60+
(entries, observer) =>
61+
this.resizeObserverCallback.call(this, entries, observer)
62+
);
63+
this._resizeObserver.observe(this._canvas);
64+
65+
return true;
66+
}
67+
68+
/**
69+
* 画布大小变化时重新调整并重新初始化视图
70+
*/
71+
onResize() {
72+
this.resizeCanvas();
73+
this._view.initialize(this);
74+
// this._view.initializeSprite();
75+
}
76+
77+
/**
78+
* 渲染主循环,定期被调用以更新画面
79+
*/
80+
update() {
81+
// 检查 WebGL 上下文是否丢失,若丢失则不再渲染
82+
if (this._glManager.getGl().isContextLost()) {
83+
return;
84+
}
85+
86+
// 若标记需要调整尺寸,则调用 onResize
87+
if (this._needResize) {
88+
this.onResize();
89+
this._needResize = false;
90+
}
91+
92+
const gl = this._glManager.getGl();
93+
94+
// 初始化画布为全透明
95+
gl.clearColor(0.0, 0.0, 0.0, 0.0);
96+
97+
// 开启深度测试,保证模型遮挡关系正确
98+
gl.enable(gl.DEPTH_TEST);
99+
100+
// 设定深度函数,近处物体覆盖远处
101+
gl.depthFunc(gl.LEQUAL);
102+
103+
// 清除颜色和深度缓冲区
104+
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
105+
gl.clearDepth(1.0);
106+
107+
// 再次开启混合模式,保证透明度正常
108+
gl.enable(gl.BLEND);
109+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
110+
111+
// 渲染视图内容
112+
this._view.render();
113+
}
114+
}
115+
116+
// 应用主委托类,负责管理主循环、画布与模型切换等全局逻辑
117+
export class AppDelegate extends LAppDelegate {
118+
/**
119+
* 启动主循环。
120+
*/
121+
run() {
122+
// 主循环函数,负责更新时间与所有 subdelegate
123+
const loop = () => {
124+
// 更新时间
125+
LAppPal.updateTime();
126+
127+
// 遍历所有 subdelegate,调用 update 进行渲染
128+
for (let i = 0; i < this._subdelegates.getSize(); i++) {
129+
this._subdelegates.at(i).update();
130+
}
131+
132+
// 递归调用,实现动画循环
133+
requestAnimationFrame(loop);
134+
};
135+
loop();
136+
}
137+
138+
/**
139+
* 创建画布并初始化所有 Subdelegate
140+
*/
141+
initializeSubdelegates() {
142+
// 预留空间以提升性能
143+
this._canvases.prepareCapacity(LAppDefine.CanvasNum);
144+
this._subdelegates.prepareCapacity(LAppDefine.CanvasNum);
145+
146+
// 获取页面中的 live2d 画布元素
147+
const canvas = document.getElementById('live2d');
148+
this._canvases.pushBack(canvas);
149+
150+
// 设置画布样式尺寸,保持与实际尺寸一致
151+
canvas.style.width = canvas.width;
152+
canvas.style.height = canvas.height;
153+
154+
// 针对每个画布创建 subdelegate,并完成初始化
155+
for (let i = 0; i < this._canvases.getSize(); i++) {
156+
const subdelegate = new AppSubdelegate();
157+
subdelegate.initialize(this._canvases.at(i));
158+
this._subdelegates.pushBack(subdelegate);
159+
}
160+
161+
// 检查每个 subdelegate 的 WebGL 上下文是否丢失
162+
for (let i = 0; i < LAppDefine.CanvasNum; i++) {
163+
if (this._subdelegates.at(i).isContextLost()) {
164+
logger.error(
165+
`The context for Canvas at index ${i} was lost, possibly because the acquisition limit for WebGLRenderingContext was reached.`
166+
);
167+
}
168+
}
169+
}
170+
171+
/**
172+
* 切换模型
173+
* @param {string} modelSettingPath 模型设置文件路径
174+
*/
175+
changeModel(modelSettingPath) {
176+
const segments = modelSettingPath.split('/');
177+
const modelJsonName = segments.pop();
178+
const modelPath = segments.join('/') + '/';
179+
// 获取当前的 Live2D 管理器
180+
const live2dManager = this._subdelegates.at(0).getLive2DManager();
181+
// 释放所有旧模型
182+
live2dManager.releaseAllModel();
183+
// 新建模型实例,设置 subdelegate 并加载资源
184+
const instance = new LAppModel();
185+
instance.setSubdelegate(live2dManager._subdelegate);
186+
instance.loadAssets(modelPath, modelJsonName);
187+
// 将新模型加入到模型列表
188+
live2dManager._models.pushBack(instance);
189+
}
190+
}

0 commit comments

Comments
 (0)