@vylos/core 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vylos/core",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/DevOpsBenjamin/Vylos"
@@ -6,28 +6,31 @@
6
6
  <!-- z-10: Foreground / character sprites -->
7
7
  <ForegroundLayer />
8
8
 
9
- <!-- z-15: Drawable events (clickable characters/objects) -->
10
- <DrawableOverlay />
11
-
12
- <!-- z-20: Location + Action overlays (left / right panels) -->
13
- <LocationOverlay />
14
- <ActionOverlay />
15
-
16
- <!-- z-25: Top bar -->
17
- <TopBar />
18
-
19
- <!-- z-30: Dialogue box -->
20
- <DialogueBox />
21
-
22
- <!-- z-35: Choice panel (inside DialogueBox z-range) -->
23
- <ChoicePanel />
24
-
25
- <!-- z-40: Custom overlay -->
26
- <CustomOverlay />
9
+ <!-- UI layer hidden with H key (Ren'Py style) -->
10
+ <template v-if="!engineState.uiHidden">
11
+ <!-- z-15–25: HUD (hidden during dialogue/choices) -->
12
+ <template v-if="!hideHud">
13
+ <DrawableOverlay />
14
+ <LocationOverlay />
15
+ <ActionOverlay />
16
+ <TopBar />
17
+ </template>
18
+
19
+ <!-- z-30: Dialogue box -->
20
+ <DialogueBox />
21
+
22
+ <!-- z-35: Choice panel (inside DialogueBox z-range) -->
23
+ <ChoicePanel />
24
+
25
+ <!-- z-40: Custom overlay -->
26
+ <CustomOverlay />
27
+ </template>
27
28
  </div>
28
29
  </template>
29
30
 
30
31
  <script setup lang="ts">
32
+ import { computed } from 'vue';
33
+ import { useEngineStateStore } from '../../stores/engineState';
31
34
  import BackgroundLayer from '../core/BackgroundLayer.vue';
32
35
  import ForegroundLayer from '../core/ForegroundLayer.vue';
33
36
  import DrawableOverlay from '../core/DrawableOverlay.vue';
@@ -37,4 +40,7 @@ import CustomOverlay from '../core/CustomOverlay.vue';
37
40
  import ActionOverlay from '../menu/ActionOverlay.vue';
38
41
  import LocationOverlay from '../menu/LocationOverlay.vue';
39
42
  import TopBar from '../menu/TopBar.vue';
43
+
44
+ const engineState = useEngineStateStore();
45
+ const hideHud = computed(() => !!engineState.dialogue || !!engineState.choices);
40
46
  </script>
@@ -184,6 +184,13 @@ function handleForward(): void {
184
184
 
185
185
  function handleViewportClick(e: MouseEvent): void {
186
186
  if (!engine) return;
187
+
188
+ // Any click unhides UI
189
+ if (engineState.uiHidden) {
190
+ engineState.uiHidden = false;
191
+ return;
192
+ }
193
+
187
194
  // Only during Running phase, no menu open, no choices showing
188
195
  if (!isRunning.value || engineState.menuOpen || engineState.choices) return;
189
196
 
@@ -211,6 +218,18 @@ onMounted(() => {
211
218
  return;
212
219
  }
213
220
 
221
+ // H toggles UI visibility
222
+ if (action === 'hide-ui') {
223
+ engineState.uiHidden = !engineState.uiHidden;
224
+ return;
225
+ }
226
+
227
+ // Any other key unhides UI first
228
+ if (engineState.uiHidden) {
229
+ engineState.uiHidden = false;
230
+ return;
231
+ }
232
+
214
233
  switch (action) {
215
234
  case 'continue':
216
235
  handleKeyboardContinue();
@@ -1,27 +1,32 @@
1
1
  <template>
2
2
  <Transition name="dlg-slide">
3
3
  <div
4
- v-if="engineState.dialogue"
5
- class="dlg-wrapper"
6
- @click="handleClick"
4
+ v-if="engineState.dialogue && !engineState.overlayId"
5
+ class="absolute bottom-0 left-0 right-0 z-30 p-[2cqh_2cqw] pointer-events-none select-none"
7
6
  >
8
- <div class="dlg-box" :class="{ 'dlg-box--history': engineState.historyBrowsing }">
7
+ <div
8
+ class="bg-black/80 border border-white/20 rounded-[1cqw] p-[2cqh_2.5cqw] max-w-[85cqw] mx-auto transition-colors duration-200"
9
+ :class="{ 'border-blue-300/40': engineState.historyBrowsing }"
10
+ >
9
11
  <!-- Speaker name -->
10
12
  <div
11
13
  v-if="engineState.dialogue.speaker"
12
- class="dlg-speaker"
14
+ class="font-bold text-[1.8cqw] mb-[1cqh] uppercase tracking-wider text-yellow-300"
13
15
  :style="engineState.dialogue.speaker.color ? { color: engineState.dialogue.speaker.color } : undefined"
14
16
  >
15
17
  {{ speakerName }}
16
18
  </div>
17
19
 
18
20
  <!-- Dialogue text -->
19
- <p class="dlg-text" :class="{ 'dlg-text--narration': engineState.dialogue.isNarration }">
21
+ <p
22
+ class="text-white text-[2cqw] leading-relaxed m-0"
23
+ :class="{ 'italic text-white/80': engineState.dialogue.isNarration }"
24
+ >
20
25
  {{ engineState.dialogue.text }}
21
26
  </p>
22
27
 
23
28
  <!-- Continue / History indicator -->
24
- <div class="dlg-continue">
29
+ <div class="text-right text-white/40 text-[1.2cqw] mt-[1cqh]">
25
30
  <template v-if="engineState.historyBrowsing">
26
31
  &#9664; &#9654; history
27
32
  </template>
@@ -35,14 +40,11 @@
35
40
  </template>
36
41
 
37
42
  <script setup lang="ts">
38
- import { inject, computed } from 'vue';
43
+ import { computed } from 'vue';
39
44
  import { useEngineStateStore } from '../../stores/engineState';
40
- import { ENGINE_INJECT_KEY } from '../../composables/useEngine';
41
45
  import { useLanguage } from '../../composables/useLanguage';
42
- import type { Engine } from '../../engine/core/Engine';
43
46
 
44
47
  const engineState = useEngineStateStore();
45
- const engine = inject<Engine>(ENGINE_INJECT_KEY);
46
48
  const { resolveText } = useLanguage();
47
49
 
48
50
  const speakerName = computed(() => {
@@ -50,44 +52,6 @@ const speakerName = computed(() => {
50
52
  if (!speaker) return '';
51
53
  return resolveText(speaker.name);
52
54
  });
53
-
54
- function handleClick(): void {
55
- if (!engine) return;
56
-
57
- if (engine.eventRunner.isBrowsingHistory) {
58
- // In history mode — advance through history (click = forward)
59
- const step = engine.eventRunner.historyForward();
60
- if (step) {
61
- if (step.type === 'say' && step.dialogue) {
62
- engineState.setDialogue(step.dialogue);
63
- engineState.setChoices(null);
64
- } else if (step.type === 'choice' && step.choiceOptions) {
65
- engineState.setDialogue(null);
66
- engineState.setChoices({
67
- prompt: null,
68
- options: step.choiceOptions,
69
- historyStepIndex: step.stepIndex,
70
- historySelectedValue: step.choiceResult,
71
- });
72
- }
73
- }
74
- if (!engine.eventRunner.isBrowsingHistory) {
75
- engineState.historyBrowsing = false;
76
- const live = engine.eventRunner.getLiveDialogue();
77
- if (live) {
78
- engineState.setDialogue({
79
- text: live.text,
80
- speaker: live.speaker,
81
- isNarration: !live.speaker,
82
- });
83
- }
84
- engineState.setChoices(null);
85
- }
86
- } else {
87
- // Normal mode — resolve the wait to advance dialogue
88
- engine.eventRunner.resolveWait();
89
- }
90
- }
91
55
  </script>
92
56
 
93
57
  <style scoped>
@@ -100,57 +64,4 @@ function handleClick(): void {
100
64
  transform: translateY(100%);
101
65
  opacity: 0;
102
66
  }
103
-
104
- .dlg-wrapper {
105
- position: absolute;
106
- bottom: 0;
107
- left: 0;
108
- right: 0;
109
- z-index: 30;
110
- padding: 2cqh 2cqw;
111
- cursor: pointer;
112
- user-select: none;
113
- }
114
-
115
- .dlg-box {
116
- background: rgba(0, 0, 0, 0.8);
117
- border: 1px solid rgba(255, 255, 255, 0.2);
118
- border-radius: 1cqw;
119
- padding: 2cqh 2.5cqw;
120
- max-width: 85cqw;
121
- margin: 0 auto;
122
- transition: border-color 0.2s ease;
123
- }
124
-
125
- .dlg-box--history {
126
- border-color: rgba(147, 197, 253, 0.4);
127
- }
128
-
129
- .dlg-speaker {
130
- color: #fde047; /* default — overridden by Character.color via :style */
131
- font-weight: 700;
132
- font-size: 1.8cqw;
133
- margin-bottom: 1cqh;
134
- text-transform: uppercase;
135
- letter-spacing: 0.05em;
136
- }
137
-
138
- .dlg-text {
139
- color: white;
140
- font-size: 2cqw;
141
- line-height: 1.6;
142
- margin: 0;
143
- }
144
-
145
- .dlg-text--narration {
146
- font-style: italic;
147
- color: rgba(255, 255, 255, 0.8);
148
- }
149
-
150
- .dlg-continue {
151
- text-align: right;
152
- color: rgba(255, 255, 255, 0.4);
153
- font-size: 1.2cqw;
154
- margin-top: 1cqh;
155
- }
156
67
  </style>
@@ -89,10 +89,14 @@ export class InputManager {
89
89
  if (key === 'ArrowRight') return 'forward';
90
90
  if (key === 'ArrowLeft') return 'back';
91
91
 
92
+ // Hide UI toggle (Ren'Py style)
93
+ if (key === 'h' || key === 'H') return 'hide-ui';
94
+
92
95
  // Skip toggle — same key on both layouts
93
96
  if (key === 's' || key === 'S') return 'skip-toggle';
94
97
 
95
- // Forward key: E on both layouts
98
+ // Forward / continue: D on both layouts, E on both layouts
99
+ if (key === 'd' || key === 'D') return 'forward';
96
100
  if (key === 'e' || key === 'E') return 'continue';
97
101
 
98
102
  // Layout-dependent back key
@@ -23,6 +23,7 @@ export const useEngineStateStore = defineStore('engineState', () => {
23
23
  const skipMode = ref(false);
24
24
  const autoMode = ref(false);
25
25
  const historyBrowsing = ref(false);
26
+ const uiHidden = ref(false);
26
27
  const drawableEvents = ref<DrawableEventEntry[]>([]);
27
28
  const overlayId = ref<string | null>(null);
28
29
  const overlayProps = ref<Record<string, unknown> | null>(null);
@@ -89,6 +90,7 @@ export const useEngineStateStore = defineStore('engineState', () => {
89
90
  skipMode.value = false;
90
91
  autoMode.value = false;
91
92
  historyBrowsing.value = false;
93
+ uiHidden.value = false;
92
94
  drawableEvents.value = [];
93
95
  overlayId.value = null;
94
96
  overlayProps.value = null;
@@ -107,6 +109,7 @@ export const useEngineStateStore = defineStore('engineState', () => {
107
109
  skipMode,
108
110
  autoMode,
109
111
  historyBrowsing,
112
+ uiHidden,
110
113
  drawableEvents,
111
114
  overlayId,
112
115
  overlayProps,