Skip to content
Merged
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
1 change: 1 addition & 0 deletions packages/webgal/src/Core/Modules/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export class Events {
public userInteractNext = formEvent('__NEXT');
public fullscreenDbClick = formEvent('fullscreen-dbclick');
public styleUpdate = formEvent('style-update');
public afterStyleUpdate = formEvent('after-style-update');
}

const eventBus = mitt();
Expand Down
2 changes: 1 addition & 1 deletion packages/webgal/src/Core/gameScripts/choose/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export const choose = (sentence: ISentence): IPerform => {
function Choose(props: { chooseOptions: ChooseOption[] }) {
const font = useFontFamily();
const { playSeEnter, playSeClick } = useSEByWebgalStore();
const applyStyle = useApplyStyle('Stage/Choose/choose.scss');
const applyStyle = useApplyStyle('choose');
// 运行时计算JSX.Element[]
const runtimeBuildList = (chooseListFull: ChooseOption[]) => {
return chooseListFull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { buildFontOptionsFromTemplate } from '@/Core/util/fonts/fontOptions';
import { webgalStore } from '@/store/store';
import { setFontOptions } from '@/store/GUIReducer';
import { setOptionData } from '@/store/userDataReducer';
import { scss2cssinjsParser } from '@/Core/controller/customUI/scss2cssinjsParser';
import { injectGlobal } from '@emotion/css';

const TEMPLATE_PATH = './game/template/template.json';
const TEMPLATE_FONT_STYLE_SELECTOR = 'style[data-webgal-template-fonts]';
Expand All @@ -17,6 +19,8 @@ export async function loadTemplate(): Promise<WebgalTemplate | null> {
const fonts = data.fonts ?? [];
injectTemplateFonts(fonts);
updateFontOptions(fonts);
await loadStyleFiles();
WebGAL.events.styleUpdate.on(loadStyleFiles);
return data;
} catch (error) {
logger.warn('加载模板文件失败', error);
Expand Down Expand Up @@ -76,3 +80,29 @@ function resolveTemplateAssetPath(path: string): string {
const normalized = path.replace(/^[./]+/, '');
return `./game/template/${normalized}`;
}

async function loadStyleFiles() {
// TODO: 以后应该改成从 templates.json 读取,而不是现在这样写死
const TEMPLATES: { ui: string; path: string }[] = [
{ ui: 'title', path: 'UI/Title/title.scss' },
{ ui: 'textbox', path: 'Stage/TextBox/textbox.scss' },
{ ui: 'choose', path: 'Stage/Choose/choose.scss' },
];

await Promise.all(
TEMPLATES.map(async (templatePath) => {
try {
logger.info(`加载模板样式文件: ${templatePath.path}`);
const resp = await axios.get(`game/template/${templatePath.path}`);
const scssStr = resp.data;
const styleObject = scss2cssinjsParser(scssStr);
WebGAL.styleObjects.set(templatePath.ui, styleObject);
injectGlobal(styleObject.others);
} catch (error) {
logger.warn(`加载模板样式文件失败: ${templatePath.path}`, error);
}
}),
);

WebGAL.events.afterStyleUpdate.emit();
}
2 changes: 2 additions & 0 deletions packages/webgal/src/Core/webgalCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Gameplay } from './Modules/gamePlay';
import { Events } from '@/Core/Modules/events';
import { SteamIntegration } from '@/Core/integration/steamIntegration';
import { WebgalTemplate } from '@/types/template';
import { IWebGALStyleObj } from 'webgal-parser/build/types/styleParser';

export class WebgalCore {
public sceneManager = new SceneManager();
Expand All @@ -17,4 +18,5 @@ export class WebgalCore {
public events = new Events();
public steam = new SteamIntegration();
public template: WebgalTemplate | null = null;
public styleObjects: Map<string, IWebGALStyleObj> = new Map();
}
2 changes: 1 addition & 1 deletion packages/webgal/src/Stage/TextBox/IMSSTextbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default function IMSSTextbox(props: ITextboxProps) {
textSizeState,
} = props;

const applyStyle = useApplyStyle('Stage/TextBox/textbox.scss');
const applyStyle = useApplyStyle('textbox');

useEffect(() => {
function settleText() {
Expand Down
2 changes: 1 addition & 1 deletion packages/webgal/src/UI/Title/Title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default function Title() {
const tCommon = useTrans('common.');
const { playSeEnter, playSeClick } = useSoundEffect();

const applyStyle = useApplyStyle('UI/Title/title.scss');
const applyStyle = useApplyStyle('title');
useConfigData(); // 监听基础ConfigData变化

const appreciationItems = useSelector((state: RootState) => state.userData.appreciationData);
Expand Down
28 changes: 9 additions & 19 deletions packages/webgal/src/hooks/useApplyStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { RootState } from '@/store/store';
import { IWebGALStyleObj } from 'webgal-parser/build/types/styleParser';
import { logger } from '@/Core/util/logger';

export default function useApplyStyle(url: string) {
const styleObject = useValue<IWebGALStyleObj>({ classNameStyles: {}, others: '' });
export default function useApplyStyle(ui: string) {
const styleObject = useValue<IWebGALStyleObj>(WebGAL.styleObjects.get(ui) ?? { classNameStyles: {}, others: '' });
const replaced = useSelector((state: RootState) => state.stage.replacedUIlable);

const applyStyle = (classNameLable: string, fallbackClassName: string) => {
Expand All @@ -23,32 +23,22 @@ export default function useApplyStyle(url: string) {
return fallbackClassName;
};

const updateStyleFile = async () => {
logger.debug('更新 Scss 文件', url);
const resp = await axios.get(`game/template/${url}`);
const scssStr = resp.data;
styleObject.set(scss2cssinjsParser(scssStr));
const updateStyleObject = () => {
styleObject.value = WebGAL.styleObjects.get(ui) ?? { classNameStyles: {}, others: '' };
};

useEffect(() => {
updateStyleFile();
}, []);

useEffect(() => {
injectGlobal(styleObject.value.others);
}, [styleObject.value.others]);

useRigisterStyleUpdate(updateStyleFile);
useRegisterAfterStyleUpdate(updateStyleObject);

return applyStyle;
}

function useRigisterStyleUpdate(callback: Function) {
function useRegisterAfterStyleUpdate(callback: Function) {
// TODO : 这里可能需要加个依赖项数组?但是当前由于使用了 useValue,状态过期问题可能被规避了,并且之前一直表现正常
const handler = () => {
callback();
};
useEffect(() => {
WebGAL.events.styleUpdate.on(handler);
return () => WebGAL.events.styleUpdate.off(handler);
WebGAL.events.afterStyleUpdate.on(handler);
return () => WebGAL.events.afterStyleUpdate.off(handler);
}, []);
}