Skip to content

Commit

Permalink
feat: custom scenes working + new plugin hook (#290)
Browse files Browse the repository at this point in the history
  • Loading branch information
liana-p committed Jul 13, 2024
1 parent dcb1924 commit 75a0905
Show file tree
Hide file tree
Showing 13 changed files with 86 additions and 21 deletions.
1 change: 1 addition & 0 deletions docs/.vitepress/config-en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ function sidebarPlugins(): DefaultTheme.SidebarItem[] {
link: '/plugins/godot/godot-plugin',
},
{ text: 'Plugin API', link: '/plugins/plugins' },
{ text: 'Plugin hooks', link: '/plugins/plugin-hooks' },
];
}

Expand Down
20 changes: 20 additions & 0 deletions docs/plugins/plugin-hooks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
title: Narrat Plugin Hooks
description: The Narrat plugin API has hooks called by the engine at various stages of loading which can let you run custom code at those points.
---

## Plugin hooks

Plugins can define hook functions that the engine will call at various stages of loading. These hooks can be used to run custom code at those points.

### Available hooks

- `onPageLoaded`: Earliest hook called as soon as the page starts
- `onNarratSetup`: Called when the narrat app is created but before anything is mounted
- `onAppMounted`: Called when the main narrat app has been mounted to the DOM
- `onAssetsLoaded`: Called as soon as asset loading is over
- `onGameSetup`: Called at the very end of the game loading process, before the engine properly starts
- `onStartScreenMounted`: Called when the start screen has been mounted to the DOM
- `onGameStart`: Called when a game starts via pressing new game or continue
- `onGameMounted`: Called when the in-game scene has been mounted to the DOM (game has started playing)
- `onGameUnmounted`: Called when the in-game scene has been unmounted from the DOM (game has stopped playing)
2 changes: 2 additions & 0 deletions packages/narrat/src/components/StartMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import {
startNewGame,
loadAndStartGame,
} from '@/application/application-utils';
import { vm } from '@/vm/vm';
const inputListener = ref<InputListener | null>(
useInputs().registerInputListener('start-menu', {}),
Expand Down Expand Up @@ -237,6 +238,7 @@ onMounted(() => {
if (audioConfig().options.defaultMusic) {
musicId.value = standalonePlayMusic(audioConfig().options.defaultMusic!);
}
vm.callHook('onStartScreenMounted');
});
function setupButtons() {
Expand Down
2 changes: 1 addition & 1 deletion packages/narrat/src/components/game-splash/game-splash.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const gameLoaded = computed(() => main.loading.loaded);
const gameTitle = computed(() => getCommonConfig().gameTitle || 'Narrat Game');
function goToStartMenu() {
useScenes().changeScene('start-menu');
useScenes().goToStartMenuScene();
}
onMounted(() => {
inputListener.value = useInputs().registerInputListener('game-splash', {
Expand Down
3 changes: 2 additions & 1 deletion packages/narrat/src/components/scenes/chapter-title.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import { onMounted, onUnmounted, ref } from 'vue';
import { useScenes } from '@/stores/scenes-store';
import { useVM } from '@/stores/vm-store';
import { BuiltInScene } from '@/scenes/default-scenes';
const props = defineProps<{
options: {
Expand All @@ -26,7 +27,7 @@ const props = defineProps<{
const timeout = ref<any>(null);
function finishedTimeout() {
timeout.value = null;
useScenes().changeScene('playing');
useScenes().changeScene(BuiltInScene.Playing);
useVM().jumpToLabel(props.options.next_label);
}
onMounted(() => {
Expand Down
11 changes: 11 additions & 0 deletions packages/narrat/src/config/common-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,13 @@ export type ScriptsConfig = Static<typeof ScriptsConfigSchema>;

export const defaultScriptsConfig = [];

export const ScenesConfigSchema = Type.Object({
startMenuScene: Type.Optional(Type.String()),
gameScene: Type.Optional(Type.String()),
});

export type ScenesConfig = Static<typeof ScenesConfigSchema>;

export const CommonConfigInputSchema = Type.Object({
baseAssetsPath: Type.Optional(Type.String()),
baseDataPath: Type.Optional(Type.String()),
Expand All @@ -158,7 +165,9 @@ export const CommonConfigInputSchema = Type.Object({
debugging: Type.Optional(DebuggingConfigSchema),
saves: Type.Optional(SavesConfigSchema),
hotkeys: HotkeysConfigSchema,
scenes: Type.Optional(ScenesConfigSchema),
});

export type CommonConfigInput = Static<typeof CommonConfigInputSchema>;

export interface CommonConfig {
Expand All @@ -184,6 +193,7 @@ export interface CommonConfig {
debugging: DebuggingConfig;
saves: SavesConfig;
hotkeys: HotkeysConfig;
scenes: ScenesConfig;
}

export const defaultCommonConfig: CommonConfig = {
Expand Down Expand Up @@ -228,4 +238,5 @@ export const defaultCommonConfig: CommonConfig = {
slots: 10,
},
hotkeys: {},
scenes: {},
};
1 change: 1 addition & 0 deletions packages/narrat/src/exports/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export * from '@/exports/components';
export * from '@/exports/utils';
export * from '@/exports/optionals';
export * from '@/exports/plugins-list';
export * from '@/exports/scenes';
2 changes: 2 additions & 0 deletions packages/narrat/src/exports/scenes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export type { SceneConfig } from '@/scenes/scene-types';
export { BuiltInScene } from '@/scenes/default-scenes';
1 change: 0 additions & 1 deletion packages/narrat/src/exports/stores.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,3 @@ export { useTooltips } from '@/stores/tooltip-store';
export { useVM } from '@/stores/vm-store';
export { useAchievements } from '@/stores/achievements-store';
export { useScenes } from '@/stores/scenes-store';
export type { SceneConfig } from '@/scenes/scene-types';
3 changes: 2 additions & 1 deletion packages/narrat/src/plugins/NarratPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export class NarratPlugin<T = any> implements NarratPluginObject<T> {
onAppMounted() {}
onAssetsLoaded() {}
onGameSetup() {}
onStartScreenMounted() {}
onGameStart() {}
onGameMounted() {}
onGameDismounted() {}
onGameUnmounted() {}
}
28 changes: 18 additions & 10 deletions packages/narrat/src/scenes/default-scenes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,37 @@ import ChapterTitle from '@/components/scenes/chapter-title.vue';
import { shallowRef } from 'vue';
import { SceneConfig, SceneKey } from './scene-types';

export enum BuiltInScene {
EngineSplash = 'engine-splash',
GameSplash = 'game-splash',
StartMenu = 'start-menu',
Playing = 'playing',
ChapterTitle = 'chapter-title',
}

export const defaultScenes = {
'engine-splash': {
id: 'engine-splash',
[BuiltInScene.EngineSplash]: {
id: BuiltInScene.EngineSplash,
component: shallowRef(EngineSplash),
props: {},
},
'game-splash': {
id: 'game-splash',
[BuiltInScene.GameSplash]: {
id: BuiltInScene.GameSplash,
component: shallowRef(GameSplash),
props: {},
},
'start-menu': {
id: 'start-menu',
[BuiltInScene.StartMenu]: {
id: BuiltInScene.StartMenu,
component: shallowRef(StartMenu),
props: {},
},
playing: {
id: 'playing',
[BuiltInScene.Playing]: {
id: BuiltInScene.Playing,
component: shallowRef(InGame),
props: {},
},
'chapter-title': {
id: 'chapter-title',
[BuiltInScene.ChapterTitle]: {
id: BuiltInScene.ChapterTitle,
component: shallowRef(ChapterTitle),
props: {},
},
Expand Down
4 changes: 2 additions & 2 deletions packages/narrat/src/stores/main-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export const useMain = defineStore('main', {
prepareToPlay() {
this.ready = true;
this.startPlaying();
useScenes().changeScene('playing');
useScenes().goToGameScene();
},
setSaveSlot(slot: string) {
this.saveSlot = slot;
Expand Down Expand Up @@ -167,7 +167,7 @@ export const useMain = defineStore('main', {
},
menuReturn() {
// this.reset();
useScenes().changeScene('start-menu');
useScenes().goToStartMenuScene();
},
createError(text: string) {
this.errors.push({
Expand Down
29 changes: 24 additions & 5 deletions packages/narrat/src/stores/scenes-store.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { defineStore, acceptHMRUpdate } from 'pinia';
import { SceneConfig, SceneKey } from '@/scenes/scene-types';
import { getCommonConfig } from '@/config';
import { BuiltInScene } from '@/scenes/default-scenes';

export interface ScenesStoreState {
scenes: Record<string, SceneConfig>;
Expand All @@ -16,15 +18,15 @@ export const useScenes = defineStore('scenes-store', {
state: () =>
({
scenes: {},
activeScene: 'engine-splash',
activeScene: BuiltInScene.EngineSplash,
currentOptions: {},
}) as ScenesStoreState,
getters: {
isPlaying(state) {
return (
state.activeScene !== 'engine-splash' &&
state.activeScene !== 'game-splash' &&
state.activeScene !== 'start-menu'
state.activeScene !== BuiltInScene.EngineSplash &&
state.activeScene !== BuiltInScene.GameSplash &&
state.activeScene !== BuiltInScene.StartMenu
);
},
},
Expand All @@ -37,7 +39,10 @@ export const useScenes = defineStore('scenes-store', {
loadSaveData(saveData: ScenesStoreSave) {
// this.activeScene = saveData.activeScene;
},
changeScene(newScene: SceneKey, options?: Record<string, any>) {
changeScene(
newScene: string | BuiltInScene,
options?: Record<string, any>,
) {
const currentScene = this.activeScene;
if (currentScene && currentScene !== newScene) {
const currentSceneConfig = this.scenes[currentScene];
Expand All @@ -63,6 +68,20 @@ export const useScenes = defineStore('scenes-store', {
this.scenes[sceneId].onFinished!();
}
},
goToStartMenuScene() {
let destination = BuiltInScene.StartMenu as string;
if (getCommonConfig().scenes.startMenuScene) {
destination = getCommonConfig().scenes.startMenuScene!;
}
this.changeScene(destination);
},
goToGameScene() {
let destination = BuiltInScene.Playing as string;
if (getCommonConfig().scenes.gameScene) {
destination = getCommonConfig().scenes.gameScene!;
}
this.changeScene(destination);
},
addNewScene(sceneConfig: SceneConfig) {
this.scenes[sceneConfig.id] = sceneConfig;
},
Expand Down

0 comments on commit 75a0905

Please sign in to comment.