@turnipxenon/pineapple 2.4.14 → 2.4.16

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.
Files changed (51) hide show
  1. package/.idea/workspace.xml +64 -49
  2. package/.svelte-kit/__package__/app.postcss +15 -1
  3. package/.svelte-kit/__package__/components/DialogOverlay.svelte +48 -47
  4. package/.svelte-kit/__package__/components/dialog_manager/DialogManager.d.ts +8 -3
  5. package/.svelte-kit/__package__/components/dialog_manager/DialogManager.js +35 -11
  6. package/.svelte-kit/__package__/components/dialog_manager/DialogManagerStore.js +1 -1
  7. package/.svelte-kit/__package__/components/layouts/SeaweedBaseLayout.svelte +2 -2
  8. package/.svelte-kit/__package__/components/pineapple/PineappleBaseLayout.svelte +20 -7
  9. package/.svelte-kit/__package__/components/pineapple/PineappleBaseLayout.svelte.d.ts +3 -1
  10. package/.svelte-kit/__package__/components/pineapple/toast/Toast.svelte +1 -0
  11. package/.svelte-kit/__package__/scripts/pineapple_fiber/PineappleFiberParser.d.ts +2 -0
  12. package/.svelte-kit/__package__/scripts/pineapple_fiber/PineappleFiberParser.js +137 -0
  13. package/.svelte-kit/__package__/scripts/pineapple_fiber/PineappleWeaver.js +3 -134
  14. package/.svelte-kit/__package__/types/pineapple_fiber/DialogState.d.ts +2 -1
  15. package/.svelte-kit/__package__/types/pineapple_fiber/DialogState.js +1 -0
  16. package/.svelte-kit/ambient.d.ts +2 -0
  17. package/.svelte-kit/generated/server/internal.js +1 -1
  18. package/dist/app.postcss +15 -1
  19. package/dist/components/DialogOverlay.svelte +48 -47
  20. package/dist/components/dialog_manager/DialogManager.d.ts +8 -3
  21. package/dist/components/dialog_manager/DialogManager.js +35 -11
  22. package/dist/components/dialog_manager/DialogManagerStore.js +1 -1
  23. package/dist/components/layouts/SeaweedBaseLayout.svelte +2 -2
  24. package/dist/components/pineapple/PineappleBaseLayout.svelte +20 -7
  25. package/dist/components/pineapple/PineappleBaseLayout.svelte.d.ts +3 -1
  26. package/dist/components/pineapple/toast/Toast.svelte +1 -0
  27. package/dist/scripts/pineapple_fiber/PineappleFiberParser.d.ts +2 -0
  28. package/dist/scripts/pineapple_fiber/PineappleFiberParser.js +137 -0
  29. package/dist/scripts/pineapple_fiber/PineappleWeaver.js +3 -134
  30. package/dist/types/pineapple_fiber/DialogState.d.ts +2 -1
  31. package/dist/types/pineapple_fiber/DialogState.js +1 -0
  32. package/package.json +1 -1
  33. package/src/lib/app.postcss +15 -1
  34. package/src/lib/components/DialogOverlay.svelte +56 -54
  35. package/src/lib/components/dialog_manager/DialogManager.ts +38 -12
  36. package/src/lib/components/dialog_manager/DialogManagerStore.ts +1 -1
  37. package/src/lib/components/layouts/SeaweedBaseLayout.svelte +2 -2
  38. package/src/lib/components/pineapple/PineappleBaseLayout.svelte +21 -6
  39. package/src/lib/components/pineapple/toast/Toast.svelte +1 -0
  40. package/src/lib/scripts/pineapple_fiber/PineappleFiberParser.ts +177 -0
  41. package/src/lib/scripts/pineapple_fiber/PineappleWeaver.ts +3 -176
  42. package/src/lib/types/pineapple_fiber/DialogState.ts +2 -1
  43. package/src/routes/(pineapple)/+page.svelte +2 -2
  44. package/src/routes/(pineapple)/pineapple/+page.svelte +19 -1
  45. package/src/routes/(pineapple)/pineapple/TestDialog.yarn +7 -0
  46. package/vite.config.ts +2 -1
  47. package/.svelte-kit/__package__/components/pineapple/overlay_manager/OverlayManager.d.ts +0 -0
  48. package/.svelte-kit/__package__/components/pineapple/overlay_manager/OverlayManager.js +0 -1
  49. package/dist/components/pineapple/overlay_manager/OverlayManager.d.ts +0 -0
  50. package/dist/components/pineapple/overlay_manager/OverlayManager.js +0 -1
  51. package/src/lib/components/pineapple/overlay_manager/OverlayManager.ts +0 -0
@@ -0,0 +1,137 @@
1
+ import { PortraitType } from "../../types/pineapple_fiber/PortraitType";
2
+ const shouldDebug = false;
3
+ export const parseYarn = async (fileContent) => {
4
+ const dialogDetailList = [];
5
+ fileContent.split("===").map((unparsedNode) => {
6
+ // todo: detect empty nodes
7
+ // todo: improve the code readability
8
+ if (unparsedNode.trim() === "") {
9
+ return;
10
+ }
11
+ const dialogDetails = {
12
+ // todo: dissect the line below and give comments because it is complex
13
+ dialogId: unparsedNode
14
+ .slice(unparsedNode.indexOf("title: "))
15
+ .split("\n")[0]
16
+ .split(" ")
17
+ .pop()
18
+ ?.trim(),
19
+ portraitType: PortraitType.AresNeutral,
20
+ textContent: "" // will be filled later below
21
+ };
22
+ let portraitUnset = true;
23
+ // parse the PineappleFiber metatags
24
+ const unparsedBody = unparsedNode.split("---").pop().trim();
25
+ const bodyList = unparsedBody.split("\n");
26
+ let contentIndexStart = 0;
27
+ for (let index = 0; index < bodyList.length; index++) {
28
+ const possibleTagPair = bodyList[index].split(": ");
29
+ const possibleTagName = possibleTagPair[0].toLowerCase();
30
+ if (!["portrait"].includes(possibleTagName)) {
31
+ break;
32
+ }
33
+ contentIndexStart = index + 1; // increase count for each viable tah
34
+ switch (possibleTagName) {
35
+ case "portrait":
36
+ portraitUnset = false;
37
+ // todo: implement a way to match the appropriate portrait based on the metatag
38
+ // from https://stackoverflow.com/a/17381004/17836168
39
+ dialogDetails.portraitType =
40
+ PortraitType[possibleTagPair[1].trim()];
41
+ if (shouldDebug) {
42
+ console.log("Portrait detected:", possibleTagPair[1], " => ", dialogDetails.portraitType);
43
+ }
44
+ break;
45
+ }
46
+ }
47
+ // portrait check
48
+ if (portraitUnset) {
49
+ console.warn(`Portrait missing for node: ${dialogDetails.dialogId}`);
50
+ dialogDetails.portraitType = PortraitType.AresNeutral;
51
+ }
52
+ // remove the metatags from the body
53
+ const unprocessedContent = bodyList.slice(contentIndexStart).join("\n");
54
+ const contentPair = unprocessedContent.split("<ChoiceBreak>");
55
+ if (contentPair.length === 2) {
56
+ // parse for the choice names in the options
57
+ let ChoiceParsingState;
58
+ (function (ChoiceParsingState) {
59
+ ChoiceParsingState[ChoiceParsingState["Free"] = 0] = "Free";
60
+ ChoiceParsingState[ChoiceParsingState["Line"] = 1] = "Line"; // previously detected an option, will try to detect for the next option
61
+ })(ChoiceParsingState || (ChoiceParsingState = {}));
62
+ let parsingState = ChoiceParsingState.Free;
63
+ const currentChoiceDetail = { jumpNode: "", name: "" };
64
+ const choiceList = [];
65
+ let shouldSkipChoices = false;
66
+ const checkChoiceForSave = () => {
67
+ if (currentChoiceDetail.name !== "") {
68
+ choiceList.push({
69
+ name: currentChoiceDetail.name,
70
+ jumpNode: currentChoiceDetail.jumpNode
71
+ });
72
+ }
73
+ };
74
+ contentPair[1]
75
+ .trim()
76
+ .split("\n")
77
+ .filter((line) => {
78
+ const trimmedLine = line.trim();
79
+ if (shouldSkipChoices) {
80
+ return false;
81
+ }
82
+ if (trimmedLine.startsWith("// ignore the rest")) {
83
+ shouldSkipChoices = true;
84
+ return false;
85
+ }
86
+ return true;
87
+ })
88
+ .map((line) => {
89
+ const trimmedLine = line.trim();
90
+ switch (parsingState) {
91
+ case ChoiceParsingState.Free:
92
+ if (trimmedLine.startsWith("->")) {
93
+ // save previous choice
94
+ checkChoiceForSave();
95
+ // write start of new choice
96
+ currentChoiceDetail.name = trimmedLine.split(" ").pop();
97
+ parsingState = ChoiceParsingState.Line;
98
+ }
99
+ break;
100
+ case ChoiceParsingState.Line:
101
+ if (trimmedLine.startsWith("<<jump")) {
102
+ const jumpNode = trimmedLine.split(" ").pop();
103
+ currentChoiceDetail.jumpNode = jumpNode.slice(0, jumpNode.length - 2); // remove ">>"
104
+ parsingState = ChoiceParsingState.Free;
105
+ }
106
+ break;
107
+ default:
108
+ console.error(`Unimplemented parsing state: ${parsingState}`);
109
+ break;
110
+ }
111
+ });
112
+ checkChoiceForSave();
113
+ dialogDetails.textContent = contentPair[0];
114
+ // handle choice start tags to a href
115
+ choiceList.forEach((choiceDetail) => {
116
+ const keyword = `<choice ${choiceDetail.name}>`;
117
+ while (dialogDetails.textContent.includes(keyword)) {
118
+ dialogDetails.textContent = dialogDetails.textContent.replace(keyword, `<a class="choice-${choiceDetail.jumpNode} dialog-choice" title="Click to continue the dialog">`);
119
+ }
120
+ });
121
+ const externalKeyword = "<a href=";
122
+ while (dialogDetails.textContent.includes(externalKeyword)) {
123
+ dialogDetails.textContent = dialogDetails.textContent.replace(externalKeyword, "<a target=\"_blank\" class=\"external-link\" href="); // make all external tags with a custom cursor
124
+ }
125
+ const choiceEndKeyword = "</choice>";
126
+ while (dialogDetails.textContent.includes(choiceEndKeyword)) {
127
+ dialogDetails.textContent = dialogDetails.textContent.replace(choiceEndKeyword, "</a>"); // convert all choice end tags to a tags
128
+ }
129
+ }
130
+ else {
131
+ // assume only one which indicates it is choiceless
132
+ dialogDetails.textContent = unprocessedContent;
133
+ }
134
+ dialogDetailList.push(dialogDetails);
135
+ });
136
+ return dialogDetailList;
137
+ };
@@ -9,147 +9,16 @@
9
9
  import { getAllFiles } from "../util/FileManagement";
10
10
  import fs, { readFileSync } from "fs";
11
11
  import { PortraitType } from "../../types/pineapple_fiber/PortraitType";
12
- const shouldDebug = false;
12
+ import { parseYarn } from "./PineappleFiberParser";
13
13
  const pineappleWeaverRun = () => {
14
14
  console.info("Starting Pineapple Weaver.");
15
15
  const BASE_PATH = "./src/routes";
16
16
  getAllFiles(BASE_PATH, (path) => {
17
17
  return path.split(".").pop() === "yarn";
18
- }).map((filePath) => {
18
+ }).map(async (filePath) => {
19
19
  console.info(`Converting: ${filePath}`);
20
20
  const fileContent = readFileSync(filePath, "utf-8");
21
- const dialogDetailList = [];
22
- fileContent.split("===").map((unparsedNode) => {
23
- // todo: detect empty nodes
24
- // todo: improve the code readability
25
- if (unparsedNode.trim() === "") {
26
- return;
27
- }
28
- const dialogDetails = {
29
- // todo: dissect the line below and give comments because it is complex
30
- dialogId: unparsedNode
31
- .slice(unparsedNode.indexOf("title: "))
32
- .split("\n")[0]
33
- .split(" ")
34
- .pop()
35
- ?.trim(),
36
- portraitType: PortraitType.AresNeutral,
37
- textContent: "" // will be filled later below
38
- };
39
- let portraitUnset = true;
40
- // parse the PineappleFiber metatags
41
- const unparsedBody = unparsedNode.split("---").pop().trim();
42
- const bodyList = unparsedBody.split("\n");
43
- let contentIndexStart = 0;
44
- for (let index = 0; index < bodyList.length; index++) {
45
- const possibleTagPair = bodyList[index].split(": ");
46
- const possibleTagName = possibleTagPair[0].toLowerCase();
47
- if (!["portrait"].includes(possibleTagName)) {
48
- break;
49
- }
50
- contentIndexStart = index + 1; // increase count for each viable tah
51
- switch (possibleTagName) {
52
- case "portrait":
53
- portraitUnset = false;
54
- // todo: implement a way to match the appropriate portrait based on the metatag
55
- // from https://stackoverflow.com/a/17381004/17836168
56
- dialogDetails.portraitType =
57
- PortraitType[possibleTagPair[1].trim()];
58
- if (shouldDebug) {
59
- console.log("Portrait detected:", possibleTagPair[1], " => ", dialogDetails.portraitType);
60
- }
61
- break;
62
- }
63
- }
64
- // portrait check
65
- if (portraitUnset) {
66
- console.warn(`Portrait missing for node: ${dialogDetails.dialogId}`);
67
- dialogDetails.portraitType = PortraitType.AresNeutral;
68
- }
69
- // remove the metatags from the body
70
- const unprocessedContent = bodyList.slice(contentIndexStart).join("\n");
71
- const contentPair = unprocessedContent.split("<ChoiceBreak>");
72
- if (contentPair.length === 2) {
73
- // parse for the choice names in the options
74
- let ChoiceParsingState;
75
- (function (ChoiceParsingState) {
76
- ChoiceParsingState[ChoiceParsingState["Free"] = 0] = "Free";
77
- ChoiceParsingState[ChoiceParsingState["Line"] = 1] = "Line"; // previously detected an option, will try to detect for the next option
78
- })(ChoiceParsingState || (ChoiceParsingState = {}));
79
- let parsingState = ChoiceParsingState.Free;
80
- const currentChoiceDetail = { jumpNode: "", name: "" };
81
- const choiceList = [];
82
- let shouldSkipChoices = false;
83
- const checkChoiceForSave = () => {
84
- if (currentChoiceDetail.name !== "") {
85
- choiceList.push({
86
- name: currentChoiceDetail.name,
87
- jumpNode: currentChoiceDetail.jumpNode
88
- });
89
- }
90
- };
91
- contentPair[1]
92
- .trim()
93
- .split("\n")
94
- .filter((line) => {
95
- const trimmedLine = line.trim();
96
- if (shouldSkipChoices) {
97
- return false;
98
- }
99
- if (trimmedLine.startsWith("// ignore the rest")) {
100
- shouldSkipChoices = true;
101
- return false;
102
- }
103
- return true;
104
- })
105
- .map((line) => {
106
- const trimmedLine = line.trim();
107
- switch (parsingState) {
108
- case ChoiceParsingState.Free:
109
- if (trimmedLine.startsWith("->")) {
110
- // save previous choice
111
- checkChoiceForSave();
112
- // write start of new choice
113
- currentChoiceDetail.name = trimmedLine.split(" ").pop();
114
- parsingState = ChoiceParsingState.Line;
115
- }
116
- break;
117
- case ChoiceParsingState.Line:
118
- if (trimmedLine.startsWith("<<jump")) {
119
- const jumpNode = trimmedLine.split(" ").pop();
120
- currentChoiceDetail.jumpNode = jumpNode.slice(0, jumpNode.length - 2); // remove ">>"
121
- parsingState = ChoiceParsingState.Free;
122
- }
123
- break;
124
- default:
125
- console.error(`Unimplemented parsing state: ${parsingState}`);
126
- break;
127
- }
128
- });
129
- checkChoiceForSave();
130
- dialogDetails.textContent = contentPair[0];
131
- // handle choice start tags to a href
132
- choiceList.forEach((choiceDetail) => {
133
- const keyword = `<choice ${choiceDetail.name}>`;
134
- while (dialogDetails.textContent.includes(keyword)) {
135
- dialogDetails.textContent = dialogDetails.textContent.replace(keyword, `<a class="choice-${choiceDetail.jumpNode} dialog-choice" title="Click to continue the dialog">`);
136
- }
137
- });
138
- const externalKeyword = "<a href=";
139
- while (dialogDetails.textContent.includes(externalKeyword)) {
140
- dialogDetails.textContent = dialogDetails.textContent.replace(externalKeyword, '<a target="_blank" class="external-link" href='); // make all external tags with a custom cursor
141
- }
142
- const choiceEndKeyword = "</choice>";
143
- while (dialogDetails.textContent.includes(choiceEndKeyword)) {
144
- dialogDetails.textContent = dialogDetails.textContent.replace(choiceEndKeyword, "</a>"); // convert all choice end tags to a tags
145
- }
146
- }
147
- else {
148
- // assume only one which indicates it's choiceless
149
- dialogDetails.textContent = unprocessedContent;
150
- }
151
- dialogDetailList.push(dialogDetails);
152
- });
21
+ const dialogDetailList = await parseYarn(fileContent);
153
22
  const dialogDetailToString = (detail) => {
154
23
  if (detail.portraitType === undefined) {
155
24
  detail.portraitType = PortraitType.AresNeutral;
@@ -1,5 +1,6 @@
1
1
  export declare enum DialogState {
2
2
  Invisible = 0,
3
3
  Visible = 1,
4
- Busy = 2
4
+ Busy = 2,
5
+ Inherit = 3
5
6
  }
@@ -3,4 +3,5 @@ export var DialogState;
3
3
  DialogState[DialogState["Invisible"] = 0] = "Invisible";
4
4
  DialogState[DialogState["Visible"] = 1] = "Visible";
5
5
  DialogState[DialogState["Busy"] = 2] = "Busy";
6
+ DialogState[DialogState["Inherit"] = 3] = "Inherit";
6
7
  })(DialogState || (DialogState = {}));
@@ -46,6 +46,7 @@ declare module '$env/static/private' {
46
46
  export const HOMEDRIVE: string;
47
47
  export const HOMEPATH: string;
48
48
  export const IDEA_INITIAL_DIRECTORY: string;
49
+ export const IJ_RESTARTER_LOG: string;
49
50
  export const INIT_CWD: string;
50
51
  export const JAVA_HOME: string;
51
52
  export const LOCALAPPDATA: string;
@@ -239,6 +240,7 @@ declare module '$env/dynamic/private' {
239
240
  HOMEDRIVE: string;
240
241
  HOMEPATH: string;
241
242
  IDEA_INITIAL_DIRECTORY: string;
243
+ IJ_RESTARTER_LOG: string;
242
244
  INIT_CWD: string;
243
245
  JAVA_HOME: string;
244
246
  LOCALAPPDATA: string;
@@ -21,7 +21,7 @@ export const options = {
21
21
  app: ({ head, body, assets, nonce, env }) => "<!DOCTYPE html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<link rel=\"icon\" href=\"" + assets + "/favicon.png\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width\" />\n\t\t" + head + "\n\t</head>\n\n\t<body data-sveltekit-preload-data=\"hover\" data-theme=\"crimson\">\n\t\t<div style=\"display: contents\" class=\"h-full overflow-hidden\">" + body + "</div>\n\t</body>\n</html>\n",
22
22
  error: ({ status, message }) => "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<title>" + message + "</title>\n\n\t\t<style>\n\t\t\tbody {\n\t\t\t\t--bg: white;\n\t\t\t\t--fg: #222;\n\t\t\t\t--divider: #ccc;\n\t\t\t\tbackground: var(--bg);\n\t\t\t\tcolor: var(--fg);\n\t\t\t\tfont-family:\n\t\t\t\t\tsystem-ui,\n\t\t\t\t\t-apple-system,\n\t\t\t\t\tBlinkMacSystemFont,\n\t\t\t\t\t'Segoe UI',\n\t\t\t\t\tRoboto,\n\t\t\t\t\tOxygen,\n\t\t\t\t\tUbuntu,\n\t\t\t\t\tCantarell,\n\t\t\t\t\t'Open Sans',\n\t\t\t\t\t'Helvetica Neue',\n\t\t\t\t\tsans-serif;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tjustify-content: center;\n\t\t\t\theight: 100vh;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t.error {\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tmax-width: 32rem;\n\t\t\t\tmargin: 0 1rem;\n\t\t\t}\n\n\t\t\t.status {\n\t\t\t\tfont-weight: 200;\n\t\t\t\tfont-size: 3rem;\n\t\t\t\tline-height: 1;\n\t\t\t\tposition: relative;\n\t\t\t\ttop: -0.05rem;\n\t\t\t}\n\n\t\t\t.message {\n\t\t\t\tborder-left: 1px solid var(--divider);\n\t\t\t\tpadding: 0 0 0 1rem;\n\t\t\t\tmargin: 0 0 0 1rem;\n\t\t\t\tmin-height: 2.5rem;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t}\n\n\t\t\t.message h1 {\n\t\t\t\tfont-weight: 400;\n\t\t\t\tfont-size: 1em;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t@media (prefers-color-scheme: dark) {\n\t\t\t\tbody {\n\t\t\t\t\t--bg: #222;\n\t\t\t\t\t--fg: #ddd;\n\t\t\t\t\t--divider: #666;\n\t\t\t\t}\n\t\t\t}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<div class=\"error\">\n\t\t\t<span class=\"status\">" + status + "</span>\n\t\t\t<div class=\"message\">\n\t\t\t\t<h1>" + message + "</h1>\n\t\t\t</div>\n\t\t</div>\n\t</body>\n</html>\n"
23
23
  },
24
- version_hash: "3q1q8i"
24
+ version_hash: "ti8fmh"
25
25
  };
26
26
 
27
27
  export async function get_hooks() {
package/dist/app.postcss CHANGED
@@ -92,7 +92,7 @@ ul {
92
92
  .default-page-container {
93
93
  @apply flex justify-center items-center;
94
94
  margin-top: 4em;
95
- margin-left: clamp(1em, 15vw, 10em);
95
+ margin-left: 1em;
96
96
  margin-right: 1em;
97
97
  flex-direction: column;
98
98
  z-index: 0;
@@ -191,3 +191,17 @@ a:active {
191
191
  background: rgba(var(--color-secondary-500));
192
192
  }
193
193
 
194
+ .dialog-box {
195
+ background-color: rgb(var(--color-surface-500) / 0.9);
196
+ position: fixed;
197
+ bottom: 0;
198
+ width: var(--dialog-box-width); /*75em + 4em padding*/
199
+ height: var(--dialog-box-height);
200
+ max-width: calc(100vw - ((var(--fab-margin) * 2) + 4em));
201
+ }
202
+
203
+ .dark .dialog-box {
204
+ background-color: rgb(var(--color-surface-900) / 0.95);
205
+ --tw-ring-color: rgb(var(--color-text-400));
206
+ /*background-color: red;*/
207
+ }
@@ -1,6 +1,7 @@
1
1
  <script>import AresHappy from "../assets/characters/ares/ares_happy.webp";
2
2
  import { onMount } from "svelte";
3
3
  import { dialogManager } from "./dialog_manager/DialogManagerStore";
4
+ import { DialogState } from "../types/pineapple_fiber/DialogState";
4
5
  let currentMessage = "";
5
6
  dialogManager.currentMessage.subscribe((value) => {
6
7
  currentMessage = value;
@@ -15,15 +16,25 @@ onMount(() => {
15
16
  dialogManager.update(0);
16
17
  });
17
18
  let hidePercent = 100;
19
+ let isHidden = true;
18
20
  dialogManager.hidePercent.subscribe((value) => {
19
21
  hidePercent = value * 0.4;
22
+ isHidden = false;
23
+ });
24
+ dialogManager.currentReadableState.subscribe((value) => {
25
+ isHidden = value === DialogState.Invisible;
26
+ if (value === DialogState.Invisible) {
27
+ }
20
28
  });
21
29
  const onDialogClick = () => {
22
30
  dialogManager.skipAnimation();
23
31
  };
24
32
  </script>
25
33
 
26
- <div class="dialog-elements" style="--hidePercentWidth: -{hidePercent}vw; --hidePercentHeight: {hidePercent}vh">
34
+ <div class="dialog-elements"
35
+ hidden={isHidden}
36
+ style="--hidePercentWidth: -{hidePercent}vw;
37
+ --hidePercentHeight: {hidePercent}vh;">
27
38
  <img src={currentPortrait} alt="Ares" class="dialog-portrait" />
28
39
  <div class="card dialog-box variant-ghost-primary" on:click={onDialogClick}>
29
40
  <div class="card dialog-name">
@@ -37,59 +48,49 @@ const onDialogClick = () => {
37
48
  </div>
38
49
 
39
50
  <style>
40
- .dialog-elements {
41
- position: absolute;
42
- z-index: 10;
43
- }
44
-
45
- .dialog-elements > img {
46
- transform: translateX(var(--hidePercentWidth));
47
- }
48
-
49
- .dialog-elements > div {
50
- transform: translateY(var(--hidePercentHeight));
51
- }
51
+ .dialog-elements {
52
+ position: fixed;
53
+ z-index: 10;
54
+ }
52
55
 
53
- .dialog-box {
54
- background-color: rgb(var(--color-surface-500) / 0.9);
55
- position: fixed;
56
- bottom: 0;
57
- left: var(--dialog-left-pad);
56
+ .dialog-elements > img {
57
+ transform: translateX(var(--hidePercentWidth));
58
+ }
58
59
 
59
- width: var(--dialog-box-width); /*75em + 4em padding*/
60
- height: var(--dialog-box-height);
61
- }
60
+ .dialog-elements > div {
61
+ transform: translateY(var(--hidePercentHeight));
62
+ }
62
63
 
63
- .dialog-box *,
64
- .dialog-name * {
65
- font-size: clamp(1em, 5vw, 1.3em);
66
- line-height: 1.5em;
67
- }
64
+ .dialog-box *,
65
+ .dialog-name * {
66
+ font-size: clamp(1em, 5vw, 1.3em);
67
+ line-height: 1.5em;
68
+ }
68
69
 
69
- .dialog-padding :global(p) {
70
- font-size: clamp(1em, 5vw, 1.3em) !important;
71
- line-height: 1.5em !important;
72
- }
70
+ .dialog-padding :global(p) {
71
+ font-size: clamp(1em, 5vw, 1.3em) !important;
72
+ line-height: 1.5em !important;
73
+ }
73
74
 
74
- .dialog-padding {
75
- padding: clamp(1.5em, 5vw, 1.75em) clamp(0em, 5vw - 0.5em, 2em) 0;
76
- }
75
+ .dialog-padding {
76
+ padding: clamp(1.5em, 5vw, 1.75em) clamp(0em, 5vw - 0.5em, 2em) 0;
77
+ }
77
78
 
78
- .dialog-name {
79
- padding-left: 1rem;
80
- padding-right: 1rem;
81
- padding-top: 0.5rem;
82
- position: fixed;
79
+ .dialog-name {
80
+ padding-left: 1rem;
81
+ padding-right: 1rem;
82
+ padding-top: 0.5rem;
83
+ position: fixed;
83
84
 
84
- /* for centering vertically */
85
- transform: translateX(clamp(0em, 5vw - 0.5em, 1em)) translateY(-50%);
85
+ /* for centering vertically */
86
+ transform: translateX(clamp(0em, 5vw - 0.5em, 1em)) translateY(-50%);
86
87
  }
87
88
 
88
- .dialog-portrait {
89
- position: fixed;
90
- bottom: 0;
91
- left: clamp(-4rem, calc(5vw - 5em), 0rem);
92
- height: clamp(30rem, 75vw, 40rem);
93
- width: auto;
94
- }
89
+ .dialog-portrait {
90
+ position: fixed;
91
+ bottom: 0;
92
+ left: clamp(-4rem, calc(5vw - 5em), 0rem);
93
+ height: clamp(30rem, 75vw, 40rem);
94
+ width: auto;
95
+ }
95
96
  </style>
@@ -8,7 +8,7 @@ import { DialogProcessor } from "./DialogProcessor";
8
8
  export type OnSetDialogChoiceCallback = (newMessage: DialogDetail) => void;
9
9
  export declare class DialogManager {
10
10
  dialogMessageMap: Map<string, DialogDetail>;
11
- dialogMessageList: DialogDetail[];
11
+ currentDialogTree: DialogDetail[];
12
12
  fullCurrentMessage: string;
13
13
  currentMessageMeta: DialogDetail;
14
14
  currentMessage: import("svelte/store").Writable<string>;
@@ -18,12 +18,14 @@ export declare class DialogManager {
18
18
  currentPortrait: import("svelte/store").Writable<unknown>;
19
19
  portraitMap: Map<string, any>;
20
20
  currentState: DialogState;
21
+ currentReadableState: import("svelte/store").Writable<DialogState>;
21
22
  hidePercent: import("svelte/motion").Tweened<number>;
22
23
  skipNextActiveTime: number;
23
24
  dialogProcessor: DialogProcessor;
24
25
  _setDialogChoiceQueue: DialogDetail[];
25
26
  _setDialogChoiceMutex: boolean;
26
27
  onSetDialogListeners: OnSetDialogChoiceCallback[];
28
+ enableDialogueOverlayCache: boolean;
27
29
  constructor();
28
30
  /**
29
31
  * when users interact with the dialog, they can skip the transition like in a game
@@ -39,9 +41,9 @@ export declare class DialogManager {
39
41
  * sets the possible dialog that might appear on the Dialog UI
40
42
  * note that it overwrites the previous tree and does not append on it due to the possibility
41
43
  * of node name conflicts
42
- * @param newMessageList
44
+ * @param newDialogTree
43
45
  */
44
- setDialogTree: (newMessageList: DialogDetail[]) => void;
46
+ setDialogTree: (newDialogTree: DialogDetail[]) => void;
45
47
  /**
46
48
  * Remember to call this before SetDialogTree
47
49
  * and unsubscribe during onDestroy
@@ -74,4 +76,7 @@ export declare class DialogManager {
74
76
  * ISSUE #81 https://github.com/TurnipXenon/pineapple/issues/81
75
77
  */
76
78
  update: (timestamp: number) => void;
79
+ enableDialogOverlay(enable: boolean): void;
80
+ toggleDialogOverlay(): void;
81
+ parseAndSetDialogTree(dialogYarn: string): Promise<DialogDetail[]>;
77
82
  }
@@ -4,7 +4,7 @@
4
4
  import { writable } from "svelte/store";
5
5
  import { DialogState } from "../../types/pineapple_fiber/DialogState";
6
6
  import { tweened } from "svelte/motion";
7
- import { cubicOut } from "svelte/easing";
7
+ import { backOut } from "svelte/easing";
8
8
  import { PortraitType } from "../../types/pineapple_fiber/PortraitType";
9
9
  import AresHappy from "../../assets/characters/ares/ares_happy.webp";
10
10
  import AresBlushing from "../../assets/characters/ares/ares_blushing.webp";
@@ -17,10 +17,11 @@ import AresSurprised from "../../assets/characters/ares/ares_surprised.webp";
17
17
  import AresYay from "../../assets/characters/ares/ares_yay.webp";
18
18
  import { defaultDialogMessage, dialogVariableStore, enableDialogueOverlay, updateRate } from "./DialogManagerStore";
19
19
  import { DialogProcessor } from "./DialogProcessor";
20
+ import { parseYarn } from "../../scripts/pineapple_fiber/PineappleFiberParser";
20
21
  const shouldDebugYarn = false;
21
22
  export class DialogManager {
22
23
  dialogMessageMap = new Map();
23
- dialogMessageList = [];
24
+ currentDialogTree = [];
24
25
  fullCurrentMessage = defaultDialogMessage[0].textContent;
25
26
  currentMessageMeta = defaultDialogMessage[0];
26
27
  currentMessage = writable("");
@@ -30,9 +31,10 @@ export class DialogManager {
30
31
  currentPortrait = writable();
31
32
  portraitMap = new Map();
32
33
  currentState = DialogState.Visible;
34
+ currentReadableState = writable(this.currentState);
33
35
  hidePercent = tweened(100, {
34
36
  duration: 400,
35
- easing: cubicOut
37
+ easing: backOut
36
38
  }); // 100 = 100%
37
39
  skipNextActiveTime = 0;
38
40
  dialogProcessor = new DialogProcessor();
@@ -40,16 +42,23 @@ export class DialogManager {
40
42
  _setDialogChoiceQueue = [];
41
43
  _setDialogChoiceMutex = false;
42
44
  onSetDialogListeners = [];
45
+ enableDialogueOverlayCache = false;
43
46
  constructor() {
44
47
  enableDialogueOverlay.subscribe((value) => {
45
48
  // todo: investigate why we cant put setDialogDefault inside the then clause
46
49
  // ISSUE #82 https://github.com/TurnipXenon/pineapple/issues/82
50
+ this.enableDialogueOverlayCache = value;
47
51
  if (value) {
48
- this.hidePercent.set(0);
49
- this.setDialogToDefault();
52
+ this.hidePercent.set(0).then(() => {
53
+ this.currentState = DialogState.Visible;
54
+ this.currentReadableState.set(this.currentState);
55
+ });
50
56
  }
51
57
  else {
52
- this.hidePercent.set(100);
58
+ this.hidePercent.set(100).then(() => {
59
+ this.currentState = DialogState.Invisible;
60
+ this.currentReadableState.set(this.currentState);
61
+ });
53
62
  this.setDialogTree([{ textContent: "" }]);
54
63
  }
55
64
  });
@@ -78,12 +87,12 @@ export class DialogManager {
78
87
  * sets the possible dialog that might appear on the Dialog UI
79
88
  * note that it overwrites the previous tree and does not append on it due to the possibility
80
89
  * of node name conflicts
81
- * @param newMessageList
90
+ * @param newDialogTree
82
91
  */
83
- setDialogTree = (newMessageList) => {
84
- this.dialogMessageList = newMessageList;
92
+ setDialogTree = (newDialogTree) => {
93
+ this.currentDialogTree = newDialogTree;
85
94
  this.dialogMessageMap.clear();
86
- newMessageList.map((value) => {
95
+ newDialogTree.map((value) => {
87
96
  if (value.dialogId) {
88
97
  this.dialogMessageMap.set(value.dialogId, value);
89
98
  }
@@ -100,7 +109,7 @@ export class DialogManager {
100
109
  this.portraitMap.set(PortraitType.AresSurprised.toString(), AresSurprised);
101
110
  this.portraitMap.set(PortraitType.AresYay.toString(), AresYay);
102
111
  }
103
- this.setDialogChoice(newMessageList[0]);
112
+ this.setDialogChoice(newDialogTree[0]);
104
113
  };
105
114
  /**
106
115
  * Remember to call this before SetDialogTree
@@ -236,4 +245,19 @@ export class DialogManager {
236
245
  ++this.currentIndex;
237
246
  window.requestAnimationFrame(this.update);
238
247
  };
248
+ enableDialogOverlay(enable) {
249
+ enableDialogueOverlay.set(enable);
250
+ }
251
+ toggleDialogOverlay() {
252
+ enableDialogueOverlay.set(!this.enableDialogueOverlayCache);
253
+ }
254
+ ;
255
+ async parseAndSetDialogTree(dialogYarn) {
256
+ return parseYarn(dialogYarn)
257
+ .then((dialogTree) => {
258
+ console.log(dialogTree);
259
+ this.setDialogTree(dialogTree);
260
+ return dialogTree;
261
+ });
262
+ }
239
263
  }
@@ -26,7 +26,7 @@ export const updateRate = 40 / 1000; // *at least* 40ms per letter
26
26
  // todo: if we go through doing yarn to typescript, move this!
27
27
  export const defaultDialogMessage = [
28
28
  {
29
- textContent: `<p>Have you drank water? Or perhaps, you've checked out <a target="_blank" class="external-link" href="http://crouton.net">one of the best webpages</a> out there?`
29
+ textContent: `<p>I don't really have anything to say. Have you drank water? Or perhaps, you've checked out <a target="_blank" class="external-link" href="http://crouton.net">one of the best webpages</a> out there?`
30
30
  }
31
31
  ];
32
32
  /**
@@ -56,8 +56,8 @@ let shouldDisplaySocialIcons = writable(false);
56
56
 
57
57
  <style>
58
58
  :root {
59
- --dialog-left-pad: clamp(0em, 5vw, 2em);
60
- --dialog-box-width: min(calc(50em + 4em), calc(100vw - var(--dialog-left-pad) - var(--theme-border-base)));
59
+ --dialog-start-pad: clamp(0em, 5vw, 2em);
60
+ --dialog-box-width: min(calc(50em + 4em), calc(100vw - var(--dialog-start-pad) - var(--theme-border-base)));
61
61
  --dialog-box-height: clamp(15em, 50vw, 18em);
62
62
  }
63
63