Compare commits

..

210 Commits

Author SHA1 Message Date
d075963a77 feat(build): Clear pipeline, fix api cfg. #215
Some checks failed
Gymkhana exports / All exports (push) Failing after 18s
2025-11-07 22:34:28 +01:00
1d777b422b feat(achievements): Notification counter. Closes #248 2025-11-07 21:52:17 +01:00
c5ea76f7de feat(story): more warnings about spoilers 2025-11-07 21:42:50 +01:00
62e5a044c1 feat(credits): On submit to credits, confetti for perfect, achiemevement literal. #247, #249, #246 2025-11-07 21:39:41 +01:00
459d1a121b feat(build): Create api file. #215 2025-11-07 21:16:23 +01:00
afcf8530e6 feat(story): palestina libre, closes #154 2025-11-07 20:52:47 +01:00
022d4c8a22 fix(creditos): Bat bi hiru lau. Closes #226 2025-11-07 15:43:30 +01:00
985d03c716 feat(creditos): Avisar puntuación se pierde. Closes #224 2025-11-07 15:37:20 +01:00
88f1973e97 feat(achievements): Amante de la música. Closes #209 2025-11-07 15:32:24 +01:00
0da6bcad9c feat(achievements): Ordenado eneko. #209 2025-11-07 15:11:32 +01:00
8a66bd18f9 chore: fix warnings 2025-11-07 15:09:49 +01:00
734a3a6bc2 feat(achievements): Ordenado. 2025-11-07 15:09:25 +01:00
33035e29b7 fix(cursor): Hotspot & overlapping collissions. Closes #242 2025-11-07 14:41:08 +01:00
5490162365 fix(ui): Unify theme 2025-11-07 14:36:03 +01:00
4274570e2f feat(dev): Colored values. 2025-11-07 13:57:25 +01:00
9d1b8e069f chore: format 2025-11-07 13:57:25 +01:00
be10ebf97a fix(core): Item manager has fix. #244 2025-11-07 13:57:25 +01:00
b22be297c4 feat(build): Encripted exports #215 2025-11-07 13:57:25 +01:00
3085622579 fix(i18n): missing texts in main_menu.csv 2025-11-07 13:25:42 +01:00
392e042615 feat(credits): watching credits is mandatory 2025-11-07 13:05:55 +01:00
22ed3a0fba fix(rtmi-ui): language buttons now has the exact same color that background, fixes #235 2025-11-07 12:19:46 +01:00
712c5bc7e2 feat(story): no retar al usuario con no usar shift, i18 fixes and more 2025-11-07 12:01:57 +01:00
29ae3ae5ef feat(achievements): show current/total in notification 2025-11-06 20:07:23 +01:00
ed0ac3c59f feat(achievements): 5 from 7 2025-11-06 19:41:25 +01:00
3946947331 fix(story): interaction_angle was 0 for all items, fixed where needed, fixes #229 2025-11-06 17:43:56 +01:00
27820d6d99 fix(rtmi-ui): initialize rtmi-score-manager on pause_menu, to avoid process being freezed on pause, fixes #230 2025-11-06 16:27:37 +01:00
cc060d6147 feat(rtmi-ui): pause menu uses old music loop, closes #227 2025-11-06 10:40:42 +01:00
fba8c70103 fix(rtmi-ui): 'click to skip the text' label has a confusing onFocus, deleted, fixes #240 2025-11-06 10:23:19 +01:00
2af4bea9b8 fix(i18n): dynamic tooltips from despensa's bidon, fixes #200 2025-11-06 10:15:45 +01:00
d47b4f40cc fix(speech): oier's first audios ending was missing 2025-11-06 09:49:42 +01:00
7aeab80166 fix(speech): clean up, deleted all audios and regenerated 2025-11-06 09:18:47 +01:00
0a986268cb fix(i18n): add cocina_ordenador_action2_say literal 2025-11-06 08:57:53 +01:00
f86bebd7ca fix(credits): crash if text file not found 2025-11-05 23:50:19 +01:00
eca4cc1d7b fix(scoreboard): prev/next page buttons, fixes #232 2025-11-05 19:17:53 +01:00
372d7cb3fe feat(i18n): remaining FR translations, except Palestina 2025-11-05 17:52:02 +01:00
8432bcd3f8 feat(scoreboard): submit score with hash! 2025-11-05 17:17:29 +01:00
a86ebb6526 chore: Some errors and warnings fixed. 2025-11-05 03:08:24 +01:00
f90b094fb4 fix(i18n): Some fr literals, tested and closed #35 2025-11-04 22:29:40 +01:00
333b6d6824 fix(video player): avoid crash if no subtitle file found 2025-11-04 19:39:05 +01:00
9bcb4445cc feat(i18n): FR translation thanks to Miette. 2025-11-04 19:10:35 +01:00
0acd750bf5 feat(story): palestina texts 2025-11-04 00:42:59 +01:00
db03051a8d feat(speech): eneko is morpheous 2025-11-04 00:26:24 +01:00
d1dc2d1219 fix(speech): dont pick pegatinas 2025-11-04 00:13:32 +01:00
d4ff624914 fix(story): Pegatinas muchs veces. #200 2025-11-04 00:05:31 +01:00
947ecc08f0 fix(story): Fix madera say 2025-11-04 00:05:31 +01:00
20098b250d fix(story): Fix input none 2025-11-04 00:05:31 +01:00
233723e47e feat(palestina): Say & tooltips. #154 2025-11-04 00:05:31 +01:00
1562bcb4bb fix(esc-dialog-option): add patch to fix say_last_option 2025-11-03 23:59:27 +01:00
07b3208dfc fix(speech) 2025-11-03 23:44:41 +01:00
7254168f23 fix(speech) 2025-11-03 22:25:32 +01:00
05c88881db feat(speech): Eneko 2025-11-03 21:04:17 +01:00
50e5402c40 feat(speech): Oiergit status 2025-11-03 19:36:07 +01:00
1665d77602 feat(rtmi-dialog): end dialog on speech finish, closes #225 2025-11-03 12:40:26 +01:00
f367f31d28 feat(speech): morpheo 2025-11-03 02:20:00 +01:00
c41165c193 feat(deploy): Remove publish. moved to it's own repo.
Some checks failed
Gymkhana exports / All exports (push) Failing after 1m35s
2025-11-03 02:19:51 +01:00
537a082f20 feat(build): Remove fullscreen from default for web export. Closes #216 2025-11-03 02:19:51 +01:00
5bc0362918 fix(achievements): show position before score submit, closes #223 2025-11-03 00:57:59 +01:00
13ec6d6080 fix(story): Sin pajaricos en los creditos. Fixes #221 2025-11-02 23:43:25 +01:00
2a5a0dfbfb feat(rtmi): Fullscreen button. Closess #217 2025-11-02 23:40:39 +01:00
703193513f feat(scoreboard): order by time 2025-11-02 22:50:39 +01:00
2c8f2fed4b feat(achievements): Stop time on pause. 2025-11-02 22:42:37 +01:00
420a4c5cd2 feat(scoreboard): From pause menu. Closes #218 2025-11-02 22:42:03 +01:00
7d32cbb659 feat(scoreboard): ui_enter event. Closes #222 2025-11-02 22:04:25 +01:00
8377181bef fix(rtmi): Smaller wait cursor 2025-11-02 21:56:38 +01:00
d7d73351fc feat(i18n): Credits from file 2025-11-02 21:28:33 +01:00
369628256e feat(scoreboard): submit scores! 2025-11-02 20:55:12 +01:00
0303316c4b feat(creditos): Menu order, back to menu. Closes #219 2025-11-02 19:51:21 +01:00
ffc5491733 fix(story): don't mix matrix and they live 2025-11-02 18:44:49 +01:00
cd067dd8b0 feat(scoreboard): auth with cookies. Will be replaced with encrypted checksum. 2025-11-02 15:59:03 +01:00
77520ddaea feat(video): Srt resources 2025-11-02 15:56:52 +01:00
fa0e43982d fix(video): Await to load 2025-11-02 13:41:47 +01:00
3e68c2eeeb feat(achievements): Creditos order change. confetti #168 2025-11-02 13:41:23 +01:00
43728d8190 fix(rtmi): Hide outline if no input
Some checks failed
Gymkhana exports / All exports (push) Failing after 1m31s
2025-11-02 01:30:17 +01:00
8b7ad7fe4a fix(story): Olla vacia walk and input 2025-11-02 01:13:50 +01:00
b5202e462c fix(rtmi): Item highlight and shift key 2025-11-02 00:48:56 +01:00
78eb9f5235 fix(rtmi): Outline handling rework. Closes #212 2025-11-01 23:34:09 +01:00
98ef52a19e feat(dialog): Minimum talking time, fix options. Closes #213 #204 2025-11-01 21:07:28 +01:00
d1c5d159a5 feat(rtmi): Custom cursors 2025-11-01 19:49:59 +01:00
eddd73036e feat(video): Reformat and mv to dir 2025-11-01 19:37:45 +01:00
2e5895a36f feat(cursor): Removed item arrow, added watch & hand, items with custom cursor. fixes #211 2025-11-01 19:30:46 +01:00
2a15b5466d chore: Format code 2025-11-01 16:30:31 +01:00
784236fe5c feat(rtmi): Mouse release for use. Fixes #210 2025-11-01 15:13:54 +01:00
378780a5f3 chore(format): Reformat code 2025-11-01 14:38:11 +01:00
0ef823b500 feat(scoreboard): Spinner #168 2025-11-01 04:02:26 +01:00
f271d13877 feat(scoreboard): Pagination #168 2025-11-01 03:02:52 +01:00
ecb266ec34 feat(achievements): Code format. #168 2025-11-01 02:09:01 +01:00
f645e8055c feat(achievements): Summary, perfect score button, i18n 2025-11-01 01:32:58 +01:00
c013f5412a feat(scoreboard): Name validation & colors 2025-11-01 00:29:44 +01:00
00a43ccbdb feat(achievements): Time tracker null check #168 2025-11-01 00:21:49 +01:00
3430fe2e7c feat(i18n): English translation 2025-10-30 01:17:56 +01:00
54a8ba491e feat(i18n): Double quotes for empty strings. 2025-10-30 01:17:56 +01:00
076f666125 fix(scoreboard): api.ini -> api.cfg 2025-10-30 00:24:19 +01:00
44b1f0b884 feat(scoreboard): get session coockie and api config file 2025-10-30 00:20:09 +01:00
1df26a6b28 feat(deploy): Itch.io fixes. Web export update.
Some checks failed
Gymkhana exports / All exports (push) Failing after 1m23s
2025-10-29 03:28:21 +01:00
02dcf8ed64 feat(achivements): add position column 2025-10-29 00:46:47 +01:00
d04cca26f8 feat(achivements): add name column, scoreboard panel with monospace font 2025-10-29 00:35:05 +01:00
3e1bf6a8af feat(achievements): add RTMIScoreRow model 2025-10-28 19:37:38 +01:00
dcd1082e67 feat(achievements): refactor http using await 2025-10-28 19:05:37 +01:00
9c435b7777 feat(linter): add gdlint rules 2025-10-28 17:15:17 +01:00
6c9ab5775a feat(achievements): Get scores, basic HTTP request. #168 2025-10-28 10:20:44 +01:00
c625c15f9d feat(achievements): UI, highscores, credits summary, time tracker commands, score manager, main & pause menu. #168 2025-10-28 03:16:02 +01:00
d36b5010f9 feat(achievements): Time tracker. #168 2025-10-27 18:44:15 +01:00
96b0de7405 feat(achievements): Example when entering cocina, unlock once ignore after, notification glitch when changing room. #168 2025-10-27 01:06:16 +01:00
5f4ab5354e feat(achievements): Inspector dev tool. #168 2025-10-27 00:57:21 +01:00
fb8b7541f5 feat(achievements): UI & localization. #168 2025-10-27 00:41:25 +01:00
12dcdc4c86 feat(achievements): Basic UI 2025-10-27 00:10:08 +01:00
5f58980496 feat(achievements): Basic manager, unlock command, listo from project. #168 2025-10-27 00:10:08 +01:00
fdda79be2d chore(build): source colors. 2025-10-27 00:10:08 +01:00
e1a74ed87d feat(story): use mechero with economica, closes #191. 2025-10-26 23:07:41 +01:00
6230a219fd feat(build): Consistent version from git. No intermediary file. #203
Some checks failed
Gymkhana exports / All exports (push) Failing after 1m19s
2025-10-26 21:24:44 +01:00
c0bc458440 feat(build) Fix touch. #203
Some checks failed
Gymkhana exports / All exports (push) Failing after 1m18s
2025-10-26 21:17:38 +01:00
6b9b57dbd4 feat(build) ensure verions.txt exists. #203
Some checks failed
Gymkhana exports / All exports (push) Failing after 1m20s
2025-10-26 21:14:45 +01:00
33fb914ea0 feat(deploy): Return to project path. #203
Some checks failed
Gymkhana exports / All exports (push) Failing after 1m19s
2025-10-26 21:06:51 +01:00
0c14d68393 feat(deploy): Fix flag. #203
Some checks failed
Gymkhana exports / All exports (push) Failing after 1m19s
2025-10-26 21:03:21 +01:00
5a3feeb5a3 feat(deploy): Itch, version from file. #203
Some checks failed
Gymkhana exports / All exports (push) Failing after 1m19s
2025-10-26 20:45:07 +01:00
36423bfa54 feat(deploy): Executable publish script
Some checks failed
Gymkhana exports / All exports (push) Failing after 1m19s
2025-10-26 20:40:14 +01:00
378e11d8a5 feat(deploy): Butlter API Key secret & unify. #203
Some checks failed
Gymkhana exports / All exports (push) Failing after 1m19s
2025-10-26 20:35:59 +01:00
c6fcab6b11 feat(deploy): Itch.io publishing. #203
Some checks failed
Gymkhana exports / All exports (push) Failing after 1m27s
2025-10-26 20:22:28 +01:00
1c1f32e2aa feat(build): Publish version txt
Some checks failed
Gymkhana exports / All exports (push) Has been cancelled
2025-10-26 16:55:51 +01:00
325aacaae6 feat(build): Publish to Itch.io 2025-10-26 16:51:53 +01:00
1d4bc3bb6d fix(ui): Don't show UI after unpause in credits. Fixes #208 2025-10-26 16:17:35 +01:00
9d17301d52 feat(dialog): Adds progress bar. #204 2025-10-26 15:43:33 +01:00
ab7af66259 feat(dialog): Remove dialog tip when click to continue is enabled. #204 2025-10-26 15:09:48 +01:00
debf48ad15 fix(rtmi-ui): do not outline non interactive items when pushing shift 2025-10-26 13:22:01 +01:00
57db233d4e fix: remove unneeded accept_input(SKIP) 2025-10-26 13:08:29 +01:00
016210c1d9 fix(rtmi-ui): don't show neither tooltip nor outline if accept_input is not ALL, fixes #207. 2025-10-26 13:00:40 +01:00
36b8d58d9e feat(rtmi-dialog): warn Click to skip label is not a button, closes #169. 2025-10-26 12:27:37 +01:00
81dcfb2bff feat(build): add *.cfgs to allow override.
All checks were successful
Gymkhana exports / All exports (push) Successful in 1m27s
2025-10-26 04:59:53 +01:00
78350d5533 feat(build): Action, apply patches.
All checks were successful
Gymkhana exports / All exports (push) Successful in 1m29s
2025-10-26 04:41:35 +01:00
f52ea5d9fd feat(build): override.cfg, tweak script, version from project settings. 2025-10-26 04:40:01 +01:00
c97c49e902 feat(settings): Get or default custom settings. Fixes #184 2025-10-26 03:38:32 +01:00
8ebd345dd2 feat(dialog): Click to continue, remove timer, always show message, hint clamped to the right. #204 2025-10-26 02:47:50 +01:00
279b427b32 feat(dialog): Click for next dialog #204 2025-10-26 02:36:46 +01:00
a316c1fe60 feat(dialog): Remove typewriter effect #204 2025-10-26 02:32:29 +01:00
22c2e40203 fix(ashes): Interpreter loading & earlier cache. Fixes #205 2025-10-26 02:42:48 +02:00
fc868cf6f7 feat(ashes): Interpreter factory calls patch. 2025-10-25 01:16:19 +02:00
8a006ac0ff feat(git): Local patches 2025-10-25 01:15:21 +02:00
d743c77244 fix(ashes): Interpreter factory fix 2025-10-24 22:10:40 +02:00
a01fcfbd8f feat(ashes): Globals lookup override. 2025-10-24 22:06:05 +02:00
34d0002af3 feat(git): Escoria core patcher 2025-10-24 22:05:26 +02:00
9dca9affe3 fix(creditos): Default language. 2025-10-24 02:02:20 +02:00
60dce58ad0 fix(performance): Ashes cache & disabled automatic transitions #150 2025-10-24 01:44:28 +02:00
38f6065055 chore(cleanup): Remove unused variables. 2025-10-24 00:21:41 +02:00
21ed959322 feat(i18n): more basque translation. Say SHIFT is optional, closes #188. 2025-10-23 23:35:36 +02:00
1e67ec9d54 fix(rtmi-ui): Always clear cursor when awaiting item closes #202 2025-10-22 02:04:39 +02:00
08165cd59d fix(rtmi-ui): use correct global for check catando. re fixes #195 2025-10-22 01:53:29 +02:00
f9abe054b2 fix(story): Explicit walk to olla_llena. Closes #191 2025-10-22 01:36:06 +02:00
91fa8cdf6b fix(rtmi-ui): Check if no tool for cursor change. Closes #32 2025-10-22 01:19:48 +02:00
2f85e28aea feat(i18n): Skip video literal. Closes #200 2025-10-22 01:06:46 +02:00
be1b6a2541 feat(palestina): Item, placeholder texts, song 2025-10-22 01:00:57 +02:00
1742cc0f6e fix(rtmi-ui): item outline only in default game state. Fixes #199 2025-10-22 00:39:18 +02:00
a52fac3b09 fix(i18n): deleted unused translations 2025-10-21 19:18:47 +02:00
5905309c44 feat(i18n): add basque in language selector and remove german, closes #198 2025-10-21 19:10:35 +02:00
990801a79e fix(i18n): commas in csv 2025-10-21 18:41:39 +02:00
10c8d59442 feat(i18n): basque translations (WIP) 2025-10-21 18:40:13 +02:00
7c528361eb fix(rmti-ui): Handle many outline cases 2025-10-21 04:00:11 +02:00
33109267dd fix(rtmi-ui): Don't remove highlight if hint key still pressed. 2025-10-21 03:56:26 +02:00
84697ca929 fix(rtmi-ui): Don't remove outline after hint release if item under mouse. 2025-10-21 03:16:28 +02:00
4f24c77a39 feat(rtmi-ui): Highlight inventory item combinations #171 2025-10-21 02:35:10 +02:00
e9a2b67673 fix(story): Usar patatas 2025-10-21 02:07:30 +02:00
45b8c9236c feat(rtmi-dialog): Slow dialogs mode. Closes #75 2025-10-21 01:59:07 +02:00
472d936623 feat(rtmi-ui): Inventory mouse wheel. Closes #126 2025-10-21 01:37:27 +02:00
128ab47aef fix(rtmi-ui): Ensure that clicked item has event with tool. Fixes #183 2025-10-21 01:28:24 +02:00
2227e58ae3 fix(rtmi-ui): display tooltips after dialog if cursor on inventory item, fixes #197 2025-10-21 01:01:41 +02:00
19820c3d00 fix(rtmi-ui): display tooltips after dialog if cursor on item, fixes #172 2025-10-20 16:52:08 +02:00
257945a5fe feat(build): Savegame & debug disabled 2025-10-19 23:42:18 +02:00
e6033823cb feat(ui): Option button explicit sound and size 2025-10-19 23:41:19 +02:00
f5e48a95b9 feat(menu): Show language selector command 2025-10-19 23:30:19 +02:00
28efc6af3d chore(cleanup): Remove old code comments 2025-10-19 23:06:39 +02:00
59044135d5 feat(cursor): The way of the cursor. Both web & linux export with the same code. re closes #181 2025-10-19 23:05:26 +02:00
6b670fd6e5 feat(inventory): Don't allow tu use items in inventory while eneko catando 2025-10-19 22:55:05 +02:00
9ad12a5d8e feat(inventory): center texture 2025-10-19 20:58:31 +02:00
2d94dbc04d feat(debug): Override source for time 2025-10-19 19:52:10 +02:00
06082fe0ad feat(cursor): cleanup, web export exception, base cursor. Closes #181 2025-10-19 19:51:21 +02:00
4071daef78 feat(dialog): Chooser in the middle. Closes #155 2025-10-19 03:58:57 +02:00
f4c369e744 feat(video): Hide cursor. Closes #187 2025-10-19 03:05:53 +02:00
514307a8ad feat(ambient): don't restart ambient outside. Despensa less pan. 2025-10-19 02:37:31 +02:00
c6abbba1cb feat(inventory): adjust size with rooms. Ignore texture to use project settings. Closes #186 2025-10-19 02:36:56 +02:00
eaaca3bc34 feat(music): Ordenador. Closes #54 2025-10-19 02:16:10 +02:00
aed598afbe feat(debug): hover stack tool 2025-10-19 01:23:06 +02:00
b06abcaea3 feat(music): Ajuste distancia 2025-10-18 22:05:50 +02:00
59136e5295 feat(ambient): Pajaricos. Closes #151 2025-10-18 22:05:50 +02:00
38da699d25 feat(i18n): add double commas to all strings 2025-10-18 21:00:51 +02:00
feb6029ee6 feat(i18n): add some fr translations 2025-10-18 20:54:47 +02:00
83a3d257fd fix(video subtitles): clear current subtitle on video start, fixes #177 2025-10-18 20:19:24 +02:00
54ebc3222b fix(story): peso not interactive after returning to its place, fixes #194 2025-10-18 19:56:05 +02:00
dbbb514963 feat(story): explain this is bread, closes #189 2025-10-18 19:35:24 +02:00
145142bd64 fix(i18n): olla vacia literals, fixes #190 2025-10-18 19:02:55 +02:00
33c4fda635 feat(creditos): Translatable scrolling. Closes #179 2025-10-18 18:50:59 +02:00
07678d7c06 fix(story): cuchillo and patata grande combination tooltip, fixes #192 2025-10-18 18:39:48 +02:00
3fb93c35a3 fix(music): File not found error message 2025-10-18 17:38:19 +02:00
020ce32a06 chore: clean up 2025-10-18 03:37:14 +02:00
d9c027854d Merge branch 'main' into feature/music-manager 2025-10-18 03:35:45 +02:00
328feea5d8 feat(music): Playlist, palestina, distance 2025-10-18 03:35:03 +02:00
0af698d76a feat(assets): use jpg for backgrounds 2025-10-17 22:20:32 +02:00
884db14b39 feat(fix): revert music 2025-10-17 20:43:14 +02:00
059c573801 feat(debug): Rooms loading time 2025-10-17 00:05:37 +02:00
181bb8074c feat(debug): Timer 2025-10-16 23:18:04 +02:00
0f54667255 fix(story): show peso in scene when removed from inventory, fixes #180 2025-10-16 13:21:21 +02:00
7196ebab75 fix(story): use turno_cocina_cuchillo_picked instead of 'in inventory', fixes #182 2025-10-15 23:57:49 +02:00
942c77e996 feat(palestina): Bandera. Closes #154 2025-10-15 23:15:42 +02:00
8f8cfeae0a feat(rtmi-ui): refactor, remove target_when_selected_action_is_in. Closes #166 2025-10-15 22:06:40 +02:00
6bc8dc7321 feat(story): peso and bidon central combination, closes #178 2025-10-14 23:56:06 +02:00
82c6505a09 feat(story): Eneko gives tips, closes #163 2025-10-14 23:17:02 +02:00
bef7e48535 feat(story): Eneko gives tips (finished except translations) 2025-10-14 00:39:45 +02:00
1cb61b20b3 feat(creditos): Buttons. Closes #176 2025-10-13 02:07:56 +02:00
6957802020 feat(video): Video Manager with music handling. 2025-10-13 02:06:44 +02:00
b490f57c0d feat(story): Eneko gives tips (WIP) 2025-10-12 22:21:37 +02:00
a71727fba5 feat(text): Click to continue tip. Closes #137 2025-10-11 04:09:11 +02:00
59b670b9df fix(item): Coger pegatinas. Fixes #173 2025-10-11 03:53:36 +02:00
695 changed files with 9249 additions and 2437 deletions

47
.gdlintrc Normal file
View File

@@ -0,0 +1,47 @@
class-definitions-order:
- tools
- classnames
- extends
- docstrings
- signals
- enums
- consts
- staticvars
- exports
- pubvars
- prvvars
- onreadypubvars
- onreadyprvvars
- others
class-load-variable-name: (([A-Z][a-z0-9]*)+|_?[a-z][a-z0-9]*(_[a-z0-9]+)*)
class-name: ([A-Z][a-z0-9]*)+
class-variable-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)*
comparison-with-itself: null
constant-name: _?[A-Z][A-Z0-9]*(_[A-Z0-9]+)*
disable: []
duplicated-load: null
enum-element-name: '[A-Z][A-Z0-9]*(_[A-Z0-9]+)*'
enum-name: ([A-Z][a-z0-9]*)+
excluded_directories: !!set
.git: null
expression-not-assigned: null
function-argument-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)*
function-arguments-number: 10
function-name: (_on_([A-Z][a-z0-9]*)+(_[a-z0-9]+)*|_?[a-z][a-z0-9]*(_[a-z0-9]+)*)
function-preload-variable-name: ([A-Z][a-z0-9]*)+
function-variable-name: '[a-z][a-z0-9]*(_[a-z0-9]+)*'
load-constant-name: (([A-Z][a-z0-9]*)+|_?[A-Z][A-Z0-9]*(_[A-Z0-9]+)*)
loop-variable-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)*
max-file-lines: 1000
max-line-length: 300
max-public-methods: 20
max-returns: 6
mixed-tabs-and-spaces: null
no-elif-return: null
no-else-return: null
signal-name: '[a-z][a-z0-9]*(_[a-z0-9]+)*'
sub-class-name: _?([A-Z][a-z0-9]*)+
tab-characters: 1
trailing-whitespace: null
unnecessary-pass: null
unused-argument: null

View File

@@ -9,7 +9,7 @@ env:
GODOT_VERSION: 4.5
EXPORT_NAME: LasGymkhanikasDeUli
PROJECT_PATH: .
jobs:
all-exports:
name: All exports
@@ -24,12 +24,18 @@ jobs:
- name: Setup
run: |
git clone https://github.com/godot-escoria/escoria-demo-game $PROJECT_PATH/../escoria-demo-game
- name: Setup
run: |
mkdir -p $PROJECT_PATH/secret
echo ${{ secrets.APPWRITE_API_CFG }} > $PROJECT_PATH/secret/api.cfg
- name: All builds
run: |
./apply_patches.sh
./build.sh
- name: Upload Artifact
uses: akkuman/gitea-release-action@v1
with:
files: |
build/**/*.appimage
build/**/*.tar.gz
build/**/*.tar.gz
build/**/*.zip

4
.gitignore vendored
View File

@@ -17,3 +17,7 @@ addons/escoria-core/default_bus_layout.tres
addons/godot-plugin-refresher/
addons/script-ide/
build/
.env
# API credentials
secret/

83
Itch_io_publishing.patch Normal file
View File

@@ -0,0 +1,83 @@
Subject: [PATCH] feat(deploy): Itch.io publishing. #203
---
Index: .gitea/workflows/push-release.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/.gitea/workflows/push-release.yml b/.gitea/workflows/push-release.yml
--- a/.gitea/workflows/push-release.yml (revision 1c1f32e2aa839ccf963326d88f5f21bb3085ba1d)
+++ b/.gitea/workflows/push-release.yml (revision 8d2907c071001995b91dc6234ec511729fd49137)
@@ -34,16 +34,6 @@
files: |
build/**/*.appimage
build/**/*.tar.gz
- - name: Publish AMD to itch.io
- uses: yeslayla/butler-publish-itchio-action@master
- env:
- BUTLER_CREDENTIALS: ${{ secrets.BUTLER_API_KEY }}
- CHANNEL: linux
- PACKAGE: build/debug/amd64/*.appimage
- - name: Publish ARM to itch.io
- uses: yeslayla/butler-publish-itchio-action@master
- env:
- BUTLER_CREDENTIALS: ${{ secrets.BUTLER_API_KEY }}
- CHANNEL: linux
- PACKAGE: build/debug/arm64/*.appimage
- VERSION_FILE: build/version.txt
\ No newline at end of file
+ - name: Publishing
+ run: |
+ ./publish.sh
\ No newline at end of file
Index: bash_colors.sh
===================================================================
diff --git a/bash_colors.sh b/bash_colors.sh
new file mode 100644
--- /dev/null (revision 8d2907c071001995b91dc6234ec511729fd49137)
+++ b/bash_colors.sh (revision 8d2907c071001995b91dc6234ec511729fd49137)
@@ -0,0 +1,6 @@
+NOCOLOR='\033[0m' # No Color
+BLUE='\e[34m' # BrightBlue
+BOLD_BLUE='\033[1;94m' # BrightBlue
+GREEN='\e[49;32m' # Green
+ORANGE='\033[1;33m'
+RED='\033[1;31m'
\ No newline at end of file
Index: publish.sh
===================================================================
diff --git a/publish.sh b/publish.sh
new file mode 100644
--- /dev/null (revision 8d2907c071001995b91dc6234ec511729fd49137)
+++ b/publish.sh (revision 8d2907c071001995b91dc6234ec511729fd49137)
@@ -0,0 +1,29 @@
+#!/bin/bash
+source bash_colors.sh
+
+ITCHIO_ENABLED=true
+
+VERSION=`cat build/version.txt`
+echo -e "Publishing ${GREEN}v${VERSION}${NOCOLOR}"
+
+# Publish to Itch.io
+if [ "$ITCHIO_ENABLED" = true ] ; then
+ echo -e "${BLUE}Publishing to Itch.io${NOCOLOR}"
+ if ! command -v butler >/dev/null 2>&1
+ then
+ echo -e "${RED}butler could not be found. Aborting!${NOCOLOR}"
+ exit 1
+ fi
+
+
+
+ echo -e "${ORANGE}Publishing AMD64${NOCOLOR}"
+ butler push build/debug/amd64/LasGymkhanikasDeUli--debug.x86_64.appimage uliwood/las-gymkhanikas-de-uli-turno-cocina:linux-amd64 --userversion $VERSION
+
+ echo -e "${ORANGE}Publishing ARM64${NOCOLOR}"
+ butler push build/debug/arm64/LasGymkhanikasDeUli--debug.arm_64.appimage uliwood/las-gymkhanikas-de-uli-turno-cocina:linux-arm64 --userversion $VERSION
+
+
+ else
+ echo -e "${ORANGE}Itch.io not enabled.{NOCOLOR}"
+fi
\ No newline at end of file

View File

@@ -3,11 +3,17 @@
Point-and-click adventure game developed using Escoria framework and Godot engine.
## Building from source
### Assumed folder structure
```
any-folder
├── gymkhana -> This project.
└── escoria-demo-game -> Folder for escoria core.
```
### Steps
1) Clone `gymkhana` repo
2) Clone `escoria-demo-game` repo (develop branch)
3) Create `gymkhana/addons/escoria-core` symlink pointing to `escoria-demo-game/addons/escoria-core`
2) Clone `escoria-demo-game` repo (main branch)
3) Apply patches from the root folder. Run: `./apply_patches.sh`
## Video export.
- 1280 x 720 | 25fps
@@ -23,6 +29,7 @@ Point-and-click adventure game developed using Escoria framework and Godot engin
## Sound attributions:
- button_clicking.ogg | Button Clicking 1 by Sheyvan -- https://freesound.org/s/475188/ -- License: Creative Commons 0
- menu_button.ogg | Videogame Menu BUTTON CLICK by Christopherderp -- https://freesound.org/s/342200/ -- License: Creative Commons 0
- birds_ambient_loop.ogg | https://freesound.org/people/Garuda1982/sounds/691629/ -- License: Creative Commons 0
## Icon attributions:
- Translate button: Noun Project. Public domain

View File

@@ -6,3 +6,4 @@
[node name="Button" type="Button"]
theme = ExtResource("1_k44u5")
script = ExtResource("2_e65rn")
with_sound = false

View File

@@ -22,7 +22,7 @@ func _ready() -> void:
# Process the timeout display
func _process(delta: float) -> void:
if $MarginContainer.visible and self.dialog and self.dialog.timeout > 0:
if %MarginContainer.visible and self.dialog and self.dialog.timeout > 0:
$TimerProgress.value = (
self.dialog.timeout - $Timer.time_left
) / self.dialog.timeout * 100
@@ -30,12 +30,10 @@ func _process(delta: float) -> void:
# Show the chooser
func show_chooser():
var _vbox = $MarginContainer/ScrollContainer/VBoxContainer
var _vbox = %VBoxContainer
for option_node in _vbox.get_children():
_vbox.remove_child(option_node)
_remove_avatar()
for option in self.dialog.options:
if option.is_valid():
var _option_node = chooser_button.instantiate()
@@ -52,21 +50,21 @@ func show_chooser():
_no_more_options = true
$Timer.start(0.05)
return
if self.dialog.avatar != "-":
$AvatarContainer.add_child(
ResourceLoader.load(self.dialog.avatar).instantiate()
)
$MarginContainer.show()
%MarginContainer.show()
# Position in the middle of the screen.
# Must be called after show
%MarginContainer.position.x = get_viewport_rect().size.x / 2 - _vbox.size.x /2
%MarginContainer.position.y = get_viewport_rect().size.y / 2 - _vbox.size.y /2
if self.dialog.timeout > 0:
$Timer.start(self.dialog.timeout)
# Hide the chooser
func hide_chooser():
$MarginContainer.hide()
%MarginContainer.hide()
# An option was choosen, emit the option
@@ -74,7 +72,6 @@ func hide_chooser():
# #### Parameters
# - option: Option that was chosen
func _option_chosen(option: ESCDialogOption):
_remove_avatar()
$TimerProgress.value = 0
option_chosen.emit(option)
@@ -93,12 +90,6 @@ func _on_Timer_timeout() -> void:
_no_more_options = false
_option_chosen(option_chosen)
# Remove the avatar
func _remove_avatar():
if $AvatarContainer.get_child_count() > 0:
$AvatarContainer.remove_child($AvatarContainer.get_child(0))
# Handler managing pause notification from Escoria
func _on_paused():
hide_chooser()

View File

@@ -11,42 +11,42 @@ gradient = SubResource("1")
[node name="text_dialog_choice" type="Control"]
layout_mode = 3
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = 258.0
offset_top = -5.0
offset_right = 258.0
offset_bottom = -5.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 6
anchors_preset = 0
size_flags_horizontal = 4
size_flags_vertical = 4
theme = ExtResource("2")
script = ExtResource("1")
color_hover = Color(0.0704665, 0.552225, 0, 1)
[node name="MarginContainer" type="MarginContainer" parent="."]
clip_contents = true
layout_mode = 0
offset_left = 2.0
offset_top = 10.0
offset_right = 1280.0
offset_bottom = 185.0
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -20.0
offset_top = -20.0
offset_right = 20.0
offset_bottom = 20.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
theme_override_constants/margin_left = 20
theme_override_constants/margin_top = 20
theme_override_constants/margin_right = 20
theme_override_constants/margin_bottom = 20
[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer"]
custom_minimum_size = Vector2(0, 800)
clip_contents = false
layout_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/ScrollContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 6
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/separation = 10
[node name="Timer" type="Timer" parent="."]
@@ -59,7 +59,4 @@ anchor_right = 1.0
nine_patch_stretch = true
texture_progress = SubResource("2")
[node name="AvatarContainer" type="Node2D" parent="."]
position = Vector2(94, 68)
[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"]

View File

@@ -39,8 +39,8 @@ func run(_command_params: Array) -> int:
escoria.dialog_player.say(
speaking_character_global_id,
"",
last_chosen_option,
last_chosen_option
last_chosen_option.get_translated_option(),
last_chosen_option.get_translation_id()
)
await escoria.dialog_player.say_finished
escoria.current_state = escoria.GAME_STATE.DEFAULT

View File

@@ -1 +0,0 @@
uid://nh6csabra4mk

View File

@@ -1,16 +1,13 @@
[gd_scene load_steps=2 format=3 uid="uid://dyi4lxm20wgne"]
[gd_scene load_steps=3 format=3 uid="uid://dyi4lxm20wgne"]
[sub_resource type="GDScript" id="GDScript_qv4n7"]
script/source = "extends Label
func _enter_tree():
create_tween().tween_property(self, \"modulate:a\",1.0,0.1).from(0.0).set_trans(Tween.TRANS_SINE)
"
[ext_resource type="Theme" uid="uid://dvpaon5mw2w8l" path="res://addons/escoria-ui-return-monkey-island/theme.tres" id="1_3renm"]
[node name="Label" type="Label"]
offset_left = 1011.0
offset_left = 1073.0
offset_top = 508.0
offset_right = 1248.0
offset_bottom = 531.0
text = "click_to_speed_up_text"
script = SubResource("GDScript_qv4n7")
grow_horizontal = 0
mouse_filter = 1
theme = ExtResource("1_3renm")
text = "click_to_skip_dialog"

View File

@@ -44,6 +44,11 @@ func _disable_plugin():
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_FAST
)
ESCProjectSettingsManager.remove_setting(
RTMISimpleDialogSettings.SLOW_TEXT_MODE
)
ESCProjectSettingsManager.remove_setting(
RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY
)
@@ -100,10 +105,10 @@ func _enable_plugin():
"type": TYPE_FLOAT
}
)
ESCProjectSettingsManager.register_setting(
RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY,
false,
RTMISimpleDialogSettings.SLOW_TEXT_MODE,
RTMISimpleDialogSettings.SLOW_TEXT_MODE_DEFAULT_VALUE,
{
"type": TYPE_BOOL
}

View File

@@ -2,9 +2,13 @@
extends ESCDialogManager
class_name ESCReturnToMonekyIslandDialogs
# State machine that governs how the dialog manager behaves
var state_machine = preload("res://addons/escoria-ui-return-monkey-island-dialog-simple/rtmi_dialog_simple_state_machine.gd").new()
var state_machine = (
preload(
"res://addons/escoria-ui-return-monkey-island-dialog-simple/rtmi_dialog_simple_state_machine.gd"
)
. new()
)
# The currently running player
var _type_player: Node = null
@@ -16,6 +20,9 @@ var _dialog_player: Node = null
# Reference to the dialog hint ("click to speed up")
var _dialog_tip: Node = null
# Config holder for click to continue feature.
var _click_to_continue: bool
# Basic state tracking
var _is_saying: bool = false
@@ -24,6 +31,12 @@ var _is_saying: bool = false
var _should_preserve_dialog_box: bool = false
func _init() -> void:
_click_to_continue = escoria.settings_manager.get_custom_setting(
RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY_KEY, false
)
func _ready() -> void:
add_child(state_machine)
escoria.connect("paused", Callable(self, "_on_paused"))
@@ -38,6 +51,7 @@ func _ready() -> void:
func has_type(type: String) -> bool:
return true if type == "floating" else false
# Check whether a specific chooser type is supported by the
# dialog plugin
#
@@ -57,6 +71,7 @@ func has_chooser_type(type: String) -> bool:
func enable_preserve_dialog_box() -> void:
_should_preserve_dialog_box = true
# Instructs the dialog manager to no longer preserve the currently-preserved
# dialog box or to not preserve the next dialog box used by a `say` command
# (this is the default state).
@@ -103,29 +118,38 @@ func say(dialog_player: Node, global_id: String, text: String, type: String, key
state_machine._change_state("say")
func do_say(global_id: String, text: String) -> void:
func do_say(global_id: String, text: String, has_audio: bool = false) -> void:
# Only add_child here in order to prevent _type_player from running its _process method
# before we're ready, and only if it's necessary
if not _dialog_player.get_children().has(_type_player):
_dialog_player.add_child(_type_player)
add_dialog_tip()
_type_player.say(global_id, text)
if not _click_to_continue:
add_dialog_tip()
_type_player.say(global_id, text, has_audio)
escoria.game_scene.clear_highlights()
gymkhana.cursor_manager.clear_cursor()
func _init_type_player(type: String) -> void:
if type == "floating":
_type_player = preload(\
"res://addons/escoria-ui-return-monkey-island-dialog-simple/types/floating.tscn"\
).instantiate()
_dialog_tip = preload(\
"res://addons/escoria-ui-return-monkey-island-dialog-simple/dialog_tip.tscn"\
).instantiate()
_type_player = (
preload(
"res://addons/escoria-ui-return-monkey-island-dialog-simple/types/floating.tscn"
)
. instantiate()
)
_dialog_tip = (
preload("res://addons/escoria-ui-return-monkey-island-dialog-simple/dialog_tip.tscn")
. instantiate()
)
_type_player.say_finished.connect(_on_say_finished)
_type_player.say_visible.connect(_on_say_visible)
func _initialize_say_states(global_id: String, text: String, type: String, key: String) -> void:
state_machine.states_map["say"].initialize(self, global_id, text, type, key)
state_machine.states_map["finish"].initialize(_dialog_player)
@@ -138,15 +162,13 @@ func _initialize_say_states(global_id: String, text: String, type: String, key:
func _on_say_finished():
if not _should_preserve_dialog_box and _dialog_player.get_children().has(_type_player):
_dialog_player.remove_child(_type_player)
hide_dialop_tip()
_is_saying = false
#_dialog_player.say_finished.emit()
say_finished.emit()
func _on_say_visible():
escoria.game_scene.hide_tooltips()
say_visible.emit()
@@ -164,20 +186,22 @@ func choose(dialog_player: Node, dialog: ESCDialog, type: String):
state_machine.states_map["choices"].initialize(dialog_player, self, dialog, type)
state_machine._change_state("choices")
escoria.game_scene.clear_highlights()
func do_choose(dialog_player: Node, dialog: ESCDialog, type: String = "simple"):
escoria.game_scene.hide_tooltips()
var chooser
if type == "simple" or type == "":
chooser = preload(\
"res://addons/escoria-ui-return-monkey-island-dialog-simple/chooser/simple.tscn"\
).instantiate()
chooser = (
preload(
"res://addons/escoria-ui-return-monkey-island-dialog-simple/chooser/simple.tscn"
)
. instantiate()
)
dialog_player.add_child(chooser)
chooser.set_dialog(dialog)
chooser.show_chooser()
@@ -187,20 +211,24 @@ func do_choose(dialog_player: Node, dialog: ESCDialog, type: String = "simple"):
# MODIFIED FOR RETURN TO MONKEY UI
if option is ESCDialogOption:
escoria.globals_manager.set_global("ESC_DIALOG_CHOSEN_OPTION", option.option)
escoria.globals_manager.set_global("ESC_DIALOG_CHOSEN_OPTION", option)
# END MODIFIED FOR RETURN TO MONKEY UI
option_chosen.emit(option)
escoria.game_scene.hide_tooltips()
escoria.game_scene.update_highlights()
# Trigger running the dialogue faster
func speedup():
(escoria.object_manager.get_object(escoria.object_manager.SPEECH).node as ESCSpeechPlayer).set_state("off")
if is_instance_valid(_type_player):
_type_player.speedup()
# Trigger an instant finish of the current dialog
func finish():
(escoria.object_manager.get_object(escoria.object_manager.SPEECH).node as ESCSpeechPlayer).set_state("off")
if is_instance_valid(_type_player):
_type_player.finish()
@@ -209,9 +237,12 @@ func finish():
func interrupt():
if _dialog_player.get_children().has(_type_player):
(
escoria.object_manager.get_object(escoria.object_manager.SPEECH).node\
as ESCSpeechPlayer
).set_state("off")
(
escoria.object_manager.get_object(escoria.object_manager.SPEECH).node
as ESCSpeechPlayer
)
. set_state("off")
)
if not _should_preserve_dialog_box and _dialog_player.get_children().has(_type_player):
_dialog_player.remove_child(_type_player)
@@ -226,15 +257,15 @@ func add_dialog_tip():
_dialog_tip.visible = true
func remove_dialop_tip():
_dialog_player.remove_child(_dialog_tip)
func show_dialog_tip():
pass
func hide_dialop_tip():
if _dialog_player.get_children().has(_dialog_tip):
_dialog_tip.visible = false
func _on_paused():
hide_dialop_tip()
## To be called if voice audio has finished.
func voice_audio_finished():
if is_instance_valid(_type_player) and _type_player.has_method("voice_audio_finished"):
_type_player.voice_audio_finished()

View File

@@ -8,6 +8,9 @@ const TEXT_TIME_PER_LETTER_MS = "%s/text_time_per_letter_ms" % SETTINGS_ROOT
const TEXT_TIME_PER_LETTER_MS_DEFAULT_VALUE = 100
const TEXT_TIME_PER_LETTER_MS_FAST = "%s/text_time_per_fast_letter_ms" % SETTINGS_ROOT
const TEXT_TIME_PER_LETTER_MS_FAST_DEFAULT_VALUE = 25
const SLOW_TEXT_MODE_KEY = "slow_text_mode"
const SLOW_TEXT_MODE = "%s/slow_text_mode" % SETTINGS_ROOT
const SLOW_TEXT_MODE_DEFAULT_VALUE = false
const READING_SPEED_IN_WPM = "%s/reading_speed_in_wpm" % SETTINGS_ROOT
const READING_SPEED_IN_WPM_DEFAULT_VALUE = 200
const CLEAR_TEXT_BY_CLICK_ONLY_KEY = "clear_text_by_click_only"

View File

@@ -5,7 +5,7 @@ func _init():
_add_states_to_machine()
current_state_name = "idle"
START_STATE = states_map[current_state_name]
initialize(states_map[current_state_name])

View File

@@ -23,6 +23,8 @@ var _ready_to_say: bool
# (other states rely on the setup that the dialog manager does)
var _say_started: bool
var _has_audio: bool = false
var _stop_talking_animation_on_option: String
@@ -69,6 +71,7 @@ func enter():
escoria.logger.trace(self, "Dialog State Machine: Entered 'say'.")
_say_started = false
_has_audio = false
if not _dialog_manager.say_visible.is_connected(_on_say_visible):
_dialog_manager.say_visible.connect(_on_say_visible)
@@ -86,6 +89,7 @@ func enter():
escoria.object_manager.get_object(escoria.object_manager.SPEECH).node\
as ESCSpeechPlayer
).set_state(_speech_resource)
_has_audio = true
if _stop_talking_animation_on_option == RTMISimpleDialogSettings.STOP_TALKING_ANIMATION_ON_END_OF_AUDIO:
if not (
@@ -115,13 +119,13 @@ func enter():
func exit() -> void:
if not _say_started:
_dialog_manager.do_say(_character, _text)
_dialog_manager.do_say(_character, _text, _has_audio)
_say_started = true
func update(_delta):
if _ready_to_say:
_dialog_manager.do_say(_character, _text)
_dialog_manager.do_say(_character, _text, _has_audio)
_say_started = true
_ready_to_say = false

View File

@@ -31,7 +31,7 @@ func handle_input(_event):
_dialog_manager.say_finished.disconnect(_on_say_finished)
finished.emit("interrupt")
get_viewport().set_input_as_handled()
#get_viewport().set_input_as_handled()
# Handles the end of a say function after it has emitted say_finished.

View File

@@ -21,8 +21,8 @@ corner_radius_bottom_left = 5
bg_color = Color(0, 0, 0, 0.65882355)
corner_radius_top_left = 10
corner_radius_top_right = 10
corner_radius_bottom_right = 10
corner_radius_bottom_left = 10
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
[resource]
Label/colors/font_color = Color(1, 1, 1, 1)

View File

@@ -1,13 +1,21 @@
# A dialog GUI showing a dialog box and character portraits
extends Window
# Signal emitted when text has been said
signal say_finished
# Signal emitted when text has just become fully visible
signal say_visible
const SLOW_TEXT_MODE_MULTIPLIER: float = 2
# Progress bar feature flag
const PROGRESS_BAR_ENABLED: bool = false
const MINIMUM_TALKING_TIME: float = 2.0
const DEFAULT_SPEECH_SPEED_MULTIPLIER: float = 1.0
@export var centered_text: bool
# The text speed per character for normal display
var _text_time_per_character: float
@@ -31,21 +39,44 @@ var _is_speeding_up: bool = false
# The current line of text being displayed.
var _current_line: String
# The tween node for text animations
@onready var tween: Tween3 = Tween3.new(self)
# If the current line has audio or not.
var _has_audio: bool
# Timer for character talking
var _talking_timer
# Timer for clearing the dialog
var _clearing_timer
var _x_position_offset: int = -10
var _y_position_offset: int = -20
var _dialog_location_node = null
# Click to continue flag from settings.
var _click_to_continue: bool = false
# Slow text flag from settings.
var _slow_text_mode: bool = false
# Progress var Tween reference
var _progress_tween: Tween
# Whether the dialog manager is paused
@onready var is_paused: bool = true
var dialog_location_node = null
@export var centered_text: bool
var X_POSITION_OFFSET: int = -10
var Y_POSITION_OFFSET: int = -20
# Build up the UI
func _ready():
_click_to_continue = escoria.settings_manager.get_custom_setting(
RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY_KEY,
RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY_DEFAULT_VALUE
)
_slow_text_mode = escoria.settings_manager.get_custom_setting(
RTMISimpleDialogSettings.SLOW_TEXT_MODE_KEY,
RTMISimpleDialogSettings.SLOW_TEXT_MODE_DEFAULT_VALUE
)
_text_time_per_character = ProjectSettings.get_setting(
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS
)
@@ -53,11 +84,13 @@ func _ready():
if _text_time_per_character < 0:
escoria.logger.warn(
self,
"%s setting must be a non-negative number. Will use default value of %s." %
[
(
"%s setting must be a non-negative number. Will use default value of %s."
% [
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS,
escoria.TEXT_TIME_PER_LETTER_MS_DEFAULT_VALUE
]
)
)
_text_time_per_character = escoria.TEXT_TIME_PER_LETTER_MS_DEFAULT_VALUE
@@ -69,11 +102,13 @@ func _ready():
if _fast_text_time_per_character < 0:
escoria.logger.warn(
self,
"%s setting must be a non-negative number. Will use default value of %s." %
[
(
"%s setting must be a non-negative number. Will use default value of %s."
% [
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_FAST,
escoria.TEXT_TIME_PER_LETTER_MS_FAST_DEFAULT_VALUE
]
)
)
_fast_text_time_per_character = escoria.TEXT_TIME_PER_LETTER_MS_FAST_DEFAULT_VALUE
@@ -85,11 +120,13 @@ func _ready():
if _reading_speed_in_wpm <= 0:
escoria.logger.warn(
self,
"%s setting must be a positive number. Will use default value of %s." %
[
(
"%s setting must be a positive number. Will use default value of %s."
% [
RTMISimpleDialogSettings.READING_SPEED_IN_WPM,
escoria.READING_SPEED_IN_WPM_DEFAULT_VALUE
]
)
)
_reading_speed_in_wpm = escoria.READING_SPEED_IN_WPM_DEFAULT_VALUE
@@ -97,58 +134,72 @@ func _ready():
_word_regex.compile("\\S+")
%text_node.bbcode_enabled = true
tween.finished.connect(_on_dialog_line_typed.bind("", ""))
_talking_timer = Timer.new()
_talking_timer.one_shot = true
_talking_timer.timeout.connect(_on_dialog_line_typed)
add_child(_talking_timer)
_clearing_timer = Timer.new()
_clearing_timer.one_shot = true
_clearing_timer.timeout.connect(_on_dialog_finished)
add_child(_clearing_timer)
tree_exiting.connect(_on_tree_exiting)
escoria.paused.connect(_on_paused)
escoria.resumed.connect(_on_resumed)
_current_line = ""
if PROGRESS_BAR_ENABLED:
_progress_tween = create_tween()
# Make a character say something
#
# #### Parameters
# - character: The global id of the character speaking
# - line: Line to say
func say(character: String, line: String) :
func say(character: String, line: String, has_audio: bool = false):
_current_line = line
_has_audio = has_audio
show()
# Hide in case the same box is used
%ClickToContinueTip.visible = true if _click_to_continue else false
_is_speeding_up = false
# Position the RichTextLabel on the character's dialog position, if any.
_current_character = escoria.object_manager.get_object(character).node
var dialog_location_count:int = 0
var dialog_location_count: int = 0
for c in escoria.object_manager.get_object(character).node.get_children():
if c is Marker2D:
# Identify any Postion2D nodes
if c is ESCDialogLocation:
dialog_location_count += 1
dialog_location_node = c
_dialog_location_node = c
if dialog_location_count > 1:
escoria.logger.warn(
self,
"Multiple ESCDialogLocation nodes found " +
"object %s. Last one will be used." % _current_character)
(
"Multiple ESCDialogLocation nodes found "
+ "object %s. Last one will be used." % _current_character
)
)
# Set text color to color set in the actor
var text_color = _current_character.dialog_color
var text_color_html = text_color.to_html(false)
%text_node.text = "[color=#" + text_color_html + "]" \
.format([text_color_html]) + tr(line) + "[/color]"
%text_node.text = (
"[color=#" + text_color_html + "]".format([text_color_html]) + tr(line) + "[/color]"
)
if centered_text:
%text_node.text = "[center]" + %text_node.text + "[/center]"
if _current_character.is_inside_tree() and \
is_instance_valid(dialog_location_node):
position = dialog_location_node.get_global_transform_with_canvas().origin
if _current_character.is_inside_tree() and is_instance_valid(_dialog_location_node):
position = _dialog_location_node.get_global_transform_with_canvas().origin
position.x -= size.x / 2
else:
@@ -161,121 +212,134 @@ func say(character: String, line: String) :
_current_character.start_talking()
%text_node.visible_ratio = 0.0
var time_show_full_text = _text_time_per_character / 1000 * len(_current_line)
var slow_text_mode = ProjectSettings.get_setting(RTMISimpleDialogSettings.SLOW_TEXT_MODE)
tween.reset()
var time_show_full_text = _calculate_talking_time()
# We keep the timer as a way to simulate reading time.
_talking_timer.start(time_show_full_text)
if PROGRESS_BAR_ENABLED:
var total_time: float = _calculate_total_time()
%ProgressBar.visible = true
%ProgressBar.value = 0
_progress_tween.tween_property(%ProgressBar, "value", 100, total_time)
tween.interpolate_property(%text_node, "visible_ratio",
0.0, 1.0, time_show_full_text,
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
tween.play()
set_process(true)
# Called by the dialog player when the
func speedup():
if not _is_speeding_up:
_is_speeding_up = true
var time_show_full_text = _fast_text_time_per_character / 1000 * len(_current_line)
tween.reset()
tween.interpolate_property(%text_node, "visible_ratio",
%text_node.visible_ratio, 1.0, time_show_full_text,
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
tween.play()
say_visible.emit()
say_finished.emit()
# Called by the dialog player when user wants to finish dialogue immediately.
func finish():
tween.reset()
tween.interpolate_property(%text_node, "visible_ratio",
%text_node.visible_ratio, 1.0, 0.0)
tween.play()
say_visible.emit()
say_finished.emit()
# To be called if voice audio has finished.
func voice_audio_finished():
_stop_character_talking()
if not _click_to_continue:
_stop_character_talking()
finish();
# Handler to deal with this node being removed
# Handler to deal with this node being removed
func _on_tree_exiting() -> void:
_stop_character_talking()
# The dialog line was printed, start the waiting time and then finish
# the dialog
func _on_dialog_line_typed(object, key):
func _on_dialog_line_typed():
_stop_character_talking()
%text_node.visible_characters = -1
var time_to_disappear: float = _calculate_time_to_disappear()
$Timer.start(time_to_disappear)
$Timer.timeout.connect(_on_dialog_finished)
# This signal is for the core.
say_visible.emit()
# Start time to pass line, except click is required or line has audio.
if not _click_to_continue and not _has_audio:
var time_to_disappear: float = _calculate_time_to_disappear()
_clearing_timer.start(time_to_disappear)
func _calculate_talking_time() -> float:
if _slow_text_mode:
escoria.logger.info(self, "Text in Slow mode")
_text_time_per_character = _text_time_per_character * SLOW_TEXT_MODE_MULTIPLIER
var time = _text_time_per_character / 1000 * len(_current_line)
var minimum_time = MINIMUM_TALKING_TIME
if _slow_text_mode:
minimum_time = MINIMUM_TALKING_TIME * SLOW_TEXT_MODE_MULTIPLIER
if time < minimum_time:
return minimum_time
return time
func _calculate_time_to_disappear() -> float:
return (_get_number_of_words() / _reading_speed_in_wpm as float) * 60
return _get_number_of_words() as float / _reading_speed_in_wpm as float
func _calculate_total_time() -> float:
return _calculate_talking_time() + _calculate_time_to_disappear()
func _get_number_of_words() -> int:
var a = _word_regex.search_all(%text_node.get_text())
var b = _word_regex.search_all(%text_node.get_text()).size()
return _word_regex.search_all(%text_node.get_text()).size()
# Ending the dialog
func _on_dialog_finished():
$Timer.stop()
# Only trigger to clear the text if we aren't limiting the clearing trigger to a click.
var custom_setings = escoria.settings_manager.get_settings()["custom_settings"]
var click_to_continue = custom_setings[RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY_KEY] if custom_setings.has(RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY_KEY) else false
if not click_to_continue:
say_finished.emit()
say_finished.emit()
# Handler managing pause notification from Escoria
func _on_paused():
if tween.is_running():
is_paused = true
tween.stop()
_talking_timer.set_paused(true)
# Handler managing resume notification from Escoria
func _on_resumed():
if not tween.is_running():
# We can't rely on "show()" to make an invisible popup reappear, as per the docs for
# CanvasItem. Instead, we need to use one of the popup_* methods.
if is_inside_tree():
popup_centered()
_talking_timer.set_paused(false)
is_paused = false
tween.resume()
func _stop_character_talking():
# Make the speaking item animation stop talking, if it is still alive
if is_instance_valid(_current_character) and _current_character != null:
_current_character.stop_talking()
func _on_tree_exited():
_stop_character_talking()
func _account_for_margin_x() -> void:
if position.x < 0:
position.x = 0
var screen_margin_x = position.x + size.x - \
ProjectSettings.get("display/window/size/viewport_width")
var screen_margin_x = (
position.x + size.x - ProjectSettings.get("display/window/size/viewport_width")
)
if screen_margin_x > 0:
position.x -= screen_margin_x + X_POSITION_OFFSET
position.x -= screen_margin_x + _x_position_offset
func _account_for_margin_y() -> void:
if position.y < 0:
position.y = 0
var screen_margin_y = position.y + size.y - \
ProjectSettings.get("display/window/size/viewport_height")
var screen_margin_y = (
position.y + size.y - ProjectSettings.get("display/window/size/viewport_height")
)
if screen_margin_y > 0:
position.y -= screen_margin_y + Y_POSITION_OFFSET
position.y -= screen_margin_y + _y_position_offset

View File

@@ -1,13 +1,17 @@
[gd_scene load_steps=4 format=3 uid="uid://cp75ofyuetxux"]
[gd_scene load_steps=7 format=3 uid="uid://cp75ofyuetxux"]
[ext_resource type="Script" uid="uid://d12nyx86nlc6h" path="res://addons/escoria-ui-return-monkey-island-dialog-simple/types/floating.gd" id="1"]
[ext_resource type="Texture2D" uid="uid://cn1fjp4q7b5e0" path="res://addons/escoria-ui-return-monkey-island/cursors/rounded_mouse_left.png" id="2_4itiw"]
[ext_resource type="Theme" uid="uid://dvwfrnya2nhxu" path="res://addons/escoria-ui-return-monkey-island-dialog-simple/theme/dialog.tres" id="2_7uovn"]
[ext_resource type="Theme" uid="uid://dlo07cyfhpilq" path="res://addons/escoria-ui-return-monkey-island-dialog-simple/theme.tres" id="2_f1tsx"]
[ext_resource type="Theme" uid="uid://bf2eet52fueam" path="res://addons/escoria-ui-return-monkey-island/theme/ui.tres" id="3_xhqtt"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_4itiw"]
[node name="dialog_box" type="Window"]
transparent_bg = true
oversampling_override = 1.0
size = Vector2i(600, 150)
size = Vector2i(600, 167)
unresizable = true
borderless = true
transparent = true
@@ -15,8 +19,6 @@ popup_window = true
script = ExtResource("1")
centered_text = true
[node name="Timer" type="Timer" parent="."]
[node name="PanelContainer" type="PanelContainer" parent="."]
custom_minimum_size = Vector2(600, 60)
offset_right = 600.0
@@ -24,14 +26,21 @@ offset_bottom = 60.0
scale = Vector2(0.9775281, 1)
theme = ExtResource("2_7uovn")
[node name="MarginContainer" type="MarginContainer" parent="PanelContainer"]
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"]
layout_mode = 2
[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/VBoxContainer"]
layout_mode = 2
theme_override_constants/margin_left = 15
theme_override_constants/margin_top = 15
theme_override_constants/margin_right = 15
theme_override_constants/margin_bottom = 15
[node name="text_node" type="RichTextLabel" parent="PanelContainer/MarginContainer"]
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/MarginContainer"]
layout_mode = 2
theme_override_constants/separation = 20
[node name="text_node" type="RichTextLabel" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
clip_contents = false
layout_mode = 2
@@ -43,3 +52,30 @@ fit_content = true
scroll_active = false
autowrap_mode = 2
justification_flags = 171
[node name="ClickToContinueTip" type="HBoxContainer" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 4
[node name="icon" type="Sprite2D" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/ClickToContinueTip"]
position = Vector2(1, 8)
scale = Vector2(0.583333, 0.583333)
texture = ExtResource("2_4itiw")
offset = Vector2(-28, 1)
[node name="label" type="Label" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/ClickToContinueTip"]
layout_mode = 2
theme = ExtResource("3_xhqtt")
theme_override_font_sizes/font_size = 12
theme_override_styles/normal = SubResource("StyleBoxEmpty_4itiw")
text = "CLICK_TO_CONTINUE_TIP"
[node name="ProgressBar" type="ProgressBar" parent="PanelContainer/VBoxContainer"]
unique_name_in_owner = true
visible = false
layout_mode = 2
value = 50.0
rounded = true
show_percentage = false

View File

@@ -0,0 +1,104 @@
class_name RTMIAchievementManager
signal unlocked(achievement_id)
## Called each second
signal time_updated(current_time)
var time_tracker: RTMIAchievementTimeTracker
var played_time: int:
get:
return time_tracker.time if time_tracker != null else 0
var _game_achievements: Array = ProjectSettings.get(RTMIUiSettings.ACHIEVEMENT_LIST)
## Track unlocked achievements
var _achievement_tracker: Dictionary = {}
func _init() -> void:
_load_achievements()
escoria.new_game_started.connect(_on_new_game_started)
func _ready() -> void:
escoria.get_escoria().add_child(time_tracker)
func _on_new_game_started() -> void:
if time_tracker == null:
time_tracker = RTMIAchievementTimeTracker.new()
escoria.main.add_child(time_tracker)
func get_achievements() -> Dictionary:
return _achievement_tracker.duplicate()
func get_achievements_total() -> int:
return _game_achievements.size()
func get_unlocked_achievements_total() -> int:
var unlocked_achievements_total = 0
for key in _achievement_tracker:
if _achievement_tracker.get(key):
unlocked_achievements_total += 1
return unlocked_achievements_total
func reset_achievements() -> void:
_achievement_tracker.clear()
_load_achievements()
time_tracker.restart()
func _load_achievements() -> void:
for achievement_id in _game_achievements:
_achievement_tracker.set(achievement_id, false)
func unlock_achievement(achievement_id) -> void:
if not is_unlocked(achievement_id):
escoria.logger.info(self, "Achievent '%s' unlocked." % achievement_id)
_achievement_tracker.set(achievement_id, true)
unlocked.emit(achievement_id)
func is_unlocked(achievement_id: String) -> bool:
if not has(achievement_id):
escoria.logger.error(self, "Achievement '%s' not found.")
return false
return _achievement_tracker.get(achievement_id)
func has(achievement_id: String) -> bool:
return _achievement_tracker.has(achievement_id)
func generate_achievement_literal(achievement_id: String, variant: String = "_title") -> String:
var literal = "achievement_%s" % achievement_id
if variant != "":
literal += "_%s" % variant
return literal
func start_tracking_time() -> void:
if not time_tracker == null:
time_tracker.restart()
func pause_tracking_time() -> void:
if not time_tracker == null:
time_tracker.pause()
func resume_tracking_time() -> void:
if not time_tracker == null:
time_tracker.resume()
func stop_tracking_time() -> void:
if not time_tracker == null:
time_tracker.stop()

View File

@@ -0,0 +1 @@
uid://dsyi6bph3dfai

View File

@@ -0,0 +1,50 @@
class_name RTMIAchievementNotification
extends Control
const _FADE_IN_TIME: float = 0.5
const _CLEAR_DELAY: float = 4
const _FADE_OUT_TIME: float = 0.5
var achievement_id: String:
get:
return achievement_id
set(p_achievement_id):
achievement_id = p_achievement_id
%AchievementTitle.text = tr(gymkhana.achievement_manager.generate_achievement_literal(
achievement_id, "title"
))
%AchievementCounter.text = "(%s/%s)" % [gymkhana.achievement_manager.get_unlocked_achievements_total(), gymkhana.achievement_manager.get_achievements_total()]
var _timer: Timer = Timer.new()
var _first_time = true
func _enter_tree() -> void:
if _first_time:
var tween: Tween = create_tween()
tween.tween_property(self, "modulate:a", 1.0, _FADE_IN_TIME).from(0.0)
_timer.one_shot = true
_timer.timeout.connect(_clear_timer_timeout)
add_child(_timer)
_timer.start(_CLEAR_DELAY)
_first_time = false
func _clear_timer_timeout() -> void:
var tween: Tween = create_tween()
tween.tween_property(self, "modulate:a", 0.0, _FADE_OUT_TIME).from(1.0)
tween.finished.connect(_fade_out_finished)
func _fade_out_finished() -> void:
queue_free()
func _on_clear_button_button_up() -> void:
_timer.stop()
var tween: Tween = create_tween()
tween.tween_property(self, "modulate:a", 0.0, _FADE_OUT_TIME).from(1.0)
tween.finished.connect(_fade_out_finished)

View File

@@ -0,0 +1 @@
uid://cbc01kasyr4uf

View File

@@ -0,0 +1,63 @@
[gd_scene load_steps=3 format=3 uid="uid://dip0jl80tklyg"]
[ext_resource type="Script" uid="uid://cbc01kasyr4uf" path="res://addons/escoria-ui-return-monkey-island/achievements/rtmi_achievement_notification.gd" id="1_fsunq"]
[sub_resource type="LabelSettings" id="LabelSettings_fw80s"]
font_color = Color(1, 0.6166667, 0, 1)
[node name="AchievementNotification" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_fsunq")
[node name="PanelContainer" type="PanelContainer" parent="."]
layout_mode = 0
offset_right = 40.0
offset_bottom = 40.0
[node name="MarginContainer" type="MarginContainer" parent="PanelContainer"]
layout_mode = 2
theme_override_constants/margin_left = 10
theme_override_constants/margin_top = 10
theme_override_constants/margin_right = 15
theme_override_constants/margin_bottom = 10
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/MarginContainer"]
layout_mode = 2
theme_override_constants/separation = 8
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/MarginContainer/HBoxContainer"]
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/MarginContainer/HBoxContainer/VBoxContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="PanelContainer/MarginContainer/HBoxContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
text = "ACHIEVEMENT_UNLOCKED_NOTIFICATION_LABEL"
[node name="AchievementCounter" type="Label" parent="PanelContainer/MarginContainer/HBoxContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "(1/2)"
horizontal_alignment = 2
[node name="AchievementTitle" type="Label" parent="PanelContainer/MarginContainer/HBoxContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "ACHIEVEMENT_ACHIVEMENT_ID_TITLE"
label_settings = SubResource("LabelSettings_fw80s")
[node name="ClearButton" type="Button" parent="PanelContainer/MarginContainer/HBoxContainer"]
visible = false
custom_minimum_size = Vector2(30, 30)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 0
text = "X"
[connection signal="button_up" from="PanelContainer/MarginContainer/HBoxContainer/ClearButton" to="." method="_on_clear_button_button_up"]

View File

@@ -0,0 +1,13 @@
class_name RTMIAchievementNotificationContainer
extends PanelContainer
var _achievement_notification_scene = preload("res://addons/escoria-ui-return-monkey-island/achievements/rtmi_achievement_notification.tscn")
func _ready() -> void:
gymkhana.achievement_manager.unlocked.connect(_achievement_unlocked)
func _achievement_unlocked(achievement_id) -> void:
var achivement_notification = _achievement_notification_scene.instantiate() as RTMIAchievementNotification
achivement_notification.achievement_id = achievement_id
%Container.add_child(achivement_notification)

View File

@@ -0,0 +1,18 @@
[gd_scene load_steps=3 format=3 uid="uid://d3kgkl2r5xe4d"]
[ext_resource type="Script" uid="uid://bsfo4u74sp5qn" path="res://addons/escoria-ui-return-monkey-island/achievements/rtmi_achievement_notification_container.gd" id="1_omhs5"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_117yv"]
[node name="AchievementContainer" type="PanelContainer"]
offset_right = 40.0
offset_bottom = 40.0
theme_override_styles/panel = SubResource("StyleBoxEmpty_117yv")
script = ExtResource("1_omhs5")
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 2
[node name="Container" type="VBoxContainer" parent="MarginContainer"]
unique_name_in_owner = true
layout_mode = 2

View File

@@ -0,0 +1,54 @@
class_name RTMIAchievementTimeTracker
extends Node
const TIMEOUT_TIME: float = 1.0
## Timer node
var _timer: Timer
## Elapsed time tracker, in seconds.
var _elapsed_seconds: int
var time: int:
get:
return _elapsed_seconds
func _ready():
process_mode = Node.PROCESS_MODE_ALWAYS
func _enter_tree() -> void:
_timer = Timer.new()
_timer.timeout.connect(_timer_timeout)
add_child(_timer)
start()
func _timer_timeout() -> void:
_elapsed_seconds += 1
gymkhana.achievement_manager.time_updated.emit(_elapsed_seconds)
func elapsed_seconds() -> int:
return _elapsed_seconds
func start() -> void:
_timer.start(TIMEOUT_TIME)
func reset() -> void:
_elapsed_seconds = 0
func stop() -> void:
_timer.stop()
_timer.timeout.disconnect(_timer_timeout)
func pause() -> void:
_timer.paused = true
func resume() -> void:
_timer.paused = false
func restart() -> void:
reset()
start()
func get_time() -> int:
return _elapsed_seconds

View File

@@ -0,0 +1 @@
uid://bpbe3rklkaddi

View File

@@ -0,0 +1,34 @@
@tool
extends Control
func get_registry_id():
return "achievement_inspector"
func _ready() -> void:
gymkhana.achievement_manager.unlocked.connect(_on_achievement_unlocked)
gymkhana.achievement_manager.time_updated.connect(_on_time_updated)
update()
func _on_achievement_unlocked(_achievement_id: String) -> void:
update()
func update() -> void:
clear()
var achievements = gymkhana.achievement_manager.get_achievements()
achievements.sort()
for key in achievements:
%Container.add_child(UiEscoriaVariableBuilder.create(key, achievements[key]))
func clear() -> void:
for child in %Container.get_children():
%Container.remove_child(child)
child.queue_free()
func _on_time_updated(elapsed_time_in_seconds: int) -> void:
%TimeTrackerLabel.text = str(elapsed_time_in_seconds)

View File

@@ -0,0 +1 @@
uid://vqxa0p3tqchn

View File

@@ -0,0 +1,36 @@
[gd_scene load_steps=2 format=3 uid="uid://diaqb8q4cula7"]
[ext_resource type="Script" uid="uid://vqxa0p3tqchn" path="res://addons/escoria-ui-return-monkey-island/achievements/rtmi_achievements_dev_tool.gd" id="1_1st1v"]
[node name="AchievementInspector" type="Control"]
layout_mode = 3
anchors_preset = 0
size_flags_horizontal = 3
size_flags_vertical = 3
script = ExtResource("1_1st1v")
[node name="PanelContainer" type="PanelContainer" parent="."]
layout_mode = 0
offset_right = 4.0
offset_bottom = 404.0
[node name="MarginContainer" type="MarginContainer" parent="PanelContainer"]
layout_mode = 2
theme_override_constants/margin_left = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 2
[node name="ScrollContainer" type="ScrollContainer" parent="PanelContainer/MarginContainer"]
custom_minimum_size = Vector2(0, 400)
layout_mode = 2
horizontal_scroll_mode = 0
[node name="Container" type="VBoxContainer" parent="PanelContainer/MarginContainer/ScrollContainer"]
unique_name_in_owner = true
layout_mode = 2
[node name="TimeTrackerLabel" type="Label" parent="PanelContainer/MarginContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "00:00:00"

View File

@@ -0,0 +1,13 @@
class_name RTMIScoreRow
var name: String
var time: int
var date: String
func _init(document: Dictionary) -> void:
name = document.get("name")
time = document.get("time")
date = document.get("$createdAt")

View File

@@ -0,0 +1 @@
uid://8c4xr4s71geu

View File

@@ -0,0 +1,145 @@
class_name RTMIScoreManager
extends Node
## Score manager to get and submit scores from and to Scoreboard web service.
const PERFECT = "perfect"
const FASTEST = "fastest"
const SUBMIT = "submit"
const API_CONFIG_PATH = "res://secret/api.cfg"
const API_CONFIG_DB_SECTION = "score_db"
const API_CONFIG_SUBMIT_SECTION = "score_submit"
# Variables loaded from api.cfg
var api_url: String
var project_id: String
var database_id: String
var score_submit_url: String
var score_submit_key: String
# Session cookie used for authentication. Needed for score submitting. Stored encrypted in session_cookie.cfg
# using session_cookie_encrypted_pass as key.
var session_cookie: String = ""
# Session cookie expiry date in seconds from Unix epoch.
var session_cookie_expiry_date: int = -1
var http_requests: Dictionary = {
PERFECT: HTTPRequest.new(),
FASTEST: HTTPRequest.new(),
SUBMIT: HTTPRequest.new(),
}
func _init(scene) -> void:
_load_api_config()
# TODO: remove when https://functions.app.fosil.eu has a valid certificate
http_requests[SUBMIT].set_tls_options(TLSOptions.client_unsafe())
scene.add_child(http_requests[PERFECT])
scene.add_child(http_requests[FASTEST])
scene.add_child(http_requests[SUBMIT])
func _load_api_config() -> void:
var config = ConfigFile.new()
var error = config.load(API_CONFIG_PATH)
if error != OK:
push_error("An error occurred loading api config: error=%s" % error)
return
api_url = config.get_value(API_CONFIG_DB_SECTION, "url", "")
project_id = config.get_value(API_CONFIG_DB_SECTION, "project_id", "")
database_id = config.get_value(API_CONFIG_DB_SECTION, "database_id", "")
score_submit_url = config.get_value(API_CONFIG_SUBMIT_SECTION, "url", "")
score_submit_key = config.get_value(API_CONFIG_SUBMIT_SECTION, "key", "")
func get_scores(collection: String) -> Array[RTMIScoreRow]:
var http_request = http_requests[collection]
var response_data = await _score_http_request(http_request, "%s/databases/%s/collections/%s/documents" % [api_url, database_id, collection])
if not response_data:
return []
# Map DB rows to RTMIScoreRow
var scores_untyped = response_data.get("documents").map(func(document): return RTMIScoreRow.new(document))
scores_untyped.sort_custom(func(first, last): return first.time < last.time)
# Array.map() does not support typing, we need to use Array.assign to set the type.
var scores: Array[RTMIScoreRow]
scores.assign(scores_untyped)
return scores
func submit_score(collection: String, name: String, time: int) -> bool:
var hash = ("%s_%s_%s_%s" % [collection, name, time, score_submit_key]).sha256_text()
var request_data: String = (
JSON
. new()
. stringify(
{
"collectionId": collection,
"score":
{
"name": name,
"time": time,
},
"hash": hash
}
)
)
var response_data = await _score_http_request(http_requests[SUBMIT], score_submit_url, HTTPClient.METHOD_POST, request_data)
if not response_data.success:
push_error("Error submitting score: error=%s" % response_data.errorMsg)
return response_data.success
## Calculates a certain time which position would have in scoreboard. First position is 0.
func calculate_score_position(collection: String, time: int) -> int:
var scores: Array[RTMIScoreRow] = await get_scores(collection)
var pos = scores.find_custom(func(score): return time < score.time)
if pos < 0:
return scores.size()
return pos
func _score_http_request(
http_request: HTTPRequest, url: String, method: int = HTTPClient.METHOD_GET, request_data: String = "", additional_headers: Array = []
) -> Variant:
var headers = ["X-Appwrite-Project: %s" % project_id, "Content-Type: application/json"]
headers.append_array(additional_headers)
var error = http_request.request(url, headers, method, request_data)
if error:
push_error("An error occurred creating the HTTP request: error=%s" % error)
return null
var response: Array = await http_request.request_completed
var result: int = response[0]
var http_status: int = response[1]
var response_body: PackedByteArray = response[3]
if result != HTTPRequest.RESULT_SUCCESS or http_status < 200 or http_status >= 300:
push_error("HTTP request returned an error: result=%s http_status=%s body=%s" % [result, http_status, response_body.get_string_from_utf8()])
return null
var response_data = JSON.parse_string(response_body.get_string_from_utf8())
if not response_data:
push_error("Error parsing HTTP response body.")
return null
return response_data
func format_time(time: int) -> String:
var hours = time / 3600
var minutes = (time % 3600) / 60
var seconds = time % 60
if hours:
return "%dh %02dm %02ds" % [hours, minutes, seconds]
return "%dm %02ds" % [minutes, seconds]

View File

@@ -0,0 +1 @@
uid://br2xa7lcrals3

View File

@@ -0,0 +1,16 @@
extends Control
func _ready() -> void:
refresh()
func refresh():
%FastestScores.refresh()
%PerfectScores.refresh()
func _on_back_pressed() -> void:
hide()
func _on_refresh_pressed() -> void:
refresh()

View File

@@ -0,0 +1 @@
uid://bhi02d1pasur4

View File

@@ -0,0 +1,59 @@
[gd_scene load_steps=5 format=3 uid="uid://cqgluci3f3v3n"]
[ext_resource type="Script" uid="uid://bhi02d1pasur4" path="res://addons/escoria-ui-return-monkey-island/achievements/scoreboard/rtmi_scoreboard.gd" id="1_efvuy"]
[ext_resource type="Theme" uid="uid://djtwqnfbbt5t8" path="res://addons/escoria-ui-return-monkey-island/theme/menu.tres" id="1_ip2kf"]
[ext_resource type="PackedScene" uid="uid://ooknv238745j" path="res://addons/escoria-ui-return-monkey-island/achievements/scoreboard/rtmi_scoreboard_panel.tscn" id="1_o5uv4"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_efvuy"]
bg_color = Color(0.22, 0.22, 0.22, 1)
[node name="RtmiScoreboard" type="PanelContainer"]
process_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme = ExtResource("1_ip2kf")
theme_override_styles/panel = SubResource("StyleBoxFlat_efvuy")
script = ExtResource("1_efvuy")
[node name="CenterContainer" type="CenterContainer" parent="."]
layout_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"]
layout_mode = 2
theme_override_constants/separation = 20
alignment = 1
[node name="HBoxContainer2" type="HBoxContainer" parent="CenterContainer/VBoxContainer"]
layout_mode = 2
[node name="FastestScores" parent="CenterContainer/VBoxContainer/HBoxContainer2" instance=ExtResource("1_o5uv4")]
unique_name_in_owner = true
layout_mode = 2
collection = "fastest"
[node name="PerfectScores" parent="CenterContainer/VBoxContainer/HBoxContainer2" instance=ExtResource("1_o5uv4")]
unique_name_in_owner = true
layout_mode = 2
collection = "perfect"
[node name="HBoxContainer" type="HBoxContainer" parent="CenterContainer/VBoxContainer"]
layout_mode = 2
alignment = 1
[node name="Back" type="Button" parent="CenterContainer/VBoxContainer/HBoxContainer"]
custom_minimum_size = Vector2(300, 50)
layout_mode = 2
text = "SCOREBOARD_BACK"
[node name="Refresh" type="Button" parent="CenterContainer/VBoxContainer/HBoxContainer"]
custom_minimum_size = Vector2(300, 50)
layout_mode = 2
text = "SCOREBOARD_REFRESH"
[connection signal="pressed" from="CenterContainer/VBoxContainer/HBoxContainer/Back" to="." method="_on_back_pressed"]
[connection signal="pressed" from="CenterContainer/VBoxContainer/HBoxContainer/Refresh" to="." method="_on_refresh_pressed"]

View File

@@ -0,0 +1,115 @@
@tool
class_name RTMISocoreboardPanel
extends PanelContainer
const RECORDS_PER_PAGE: int = 10
@export var collection: String
var scores: Array[RTMIScoreRow]
var total_records: int = 0
var current_page: int = 0
var total_pages: int = 0
@onready var prev_button: RTMIMenuButton = %PrevButton
@onready var next_button: RTMIMenuButton = %NextButton
@onready var spinner: Spinner = %Spinner
func _ready() -> void:
%Title.text = str("SCOREBOARD_%s_TITLE" % collection).to_upper()
spinner.hide()
prev_button.pressed.connect(_prev_page)
next_button.pressed.connect(_next_page)
func refresh() -> void:
current_page = 0
total_records = 0
spinner.show()
await _get_scores()
spinner.hide()
_fill_scores()
func _fill_scores():
_clear_scores()
total_records = scores.size()
total_pages = total_records / RECORDS_PER_PAGE
if total_records % RECORDS_PER_PAGE > 0:
total_pages += 1
_update_pager()
if scores.is_empty():
return
var start_score = current_page * RECORDS_PER_PAGE
var end_score = (current_page + 1) * RECORDS_PER_PAGE
if end_score >= total_records:
end_score = total_records + 1
var scores_slice = scores.slice(start_score, end_score)
var pos: int = RECORDS_PER_PAGE * current_page + 1
for score in scores_slice:
# ToDo create and add rich label
var label = Label.new()
label.add_theme_font_override("font", load("res://addons/escoria-ui-return-monkey-island/fonts/SpaceMono-Regular.ttf"))
label.text = (" %2s. %-24s %10s %19s" % [pos, score.name.to_upper(), _format_time(score.time), _format_date(score.date)])
%Scores.add_child(label)
pos += 1
func _clear_scores() -> void:
for child in %Scores.get_children():
%Scores.remove_child(child)
child.queue_free()
func _get_scores() -> void:
if gymkhana.score_manager == null:
return
scores = await gymkhana.score_manager.get_scores(collection)
func _prev_page() -> void:
if current_page > 0:
current_page -= 1
_fill_scores()
func _next_page() -> void:
if current_page < total_pages - 1:
current_page += 1
_fill_scores()
func _update_pager() -> void:
prev_button.disabled = true
prev_button.focus_mode = FOCUS_NONE
next_button.disabled = true
next_button.focus_mode = FOCUS_NONE
if current_page > 0:
prev_button.disabled = false
if current_page < total_pages - 1:
next_button.disabled = false
func _format_date(iso_date: String) -> String:
var date = Time.get_datetime_dict_from_datetime_string(iso_date, false)
return "%s/%02d/%02d %02d:%02d" % [date["year"], date["month"], date["day"], date["hour"], date["minute"]]
func _format_time(time: int) -> String:
var hours = time / 3600
var minutes = (time % 3600) / 60
var seconds = time % 60
if hours:
return "%dh %02dm %02ds" % [hours, minutes, seconds]
return "%dm %02ds" % [minutes, seconds]

View File

@@ -0,0 +1 @@
uid://cxvhsdqap7w1b

View File

@@ -0,0 +1,194 @@
[gd_scene load_steps=8 format=3 uid="uid://ooknv238745j"]
[ext_resource type="Script" uid="uid://cxvhsdqap7w1b" path="res://addons/escoria-ui-return-monkey-island/achievements/scoreboard/rtmi_scoreboard_panel.gd" id="1_35c2h"]
[ext_resource type="Theme" uid="uid://djtwqnfbbt5t8" path="res://addons/escoria-ui-return-monkey-island/theme/menu.tres" id="1_ine7w"]
[ext_resource type="FontFile" uid="uid://bq0vin2knt0or" path="res://addons/escoria-ui-return-monkey-island/fonts/SpaceMono-Regular.ttf" id="2_bn406"]
[ext_resource type="Script" uid="uid://elqkwjm0r5c7" path="res://addons/escoria-ui-return-monkey-island/menus/rtmi_menu_button.gd" id="2_hgepf"]
[ext_resource type="Script" uid="uid://doqt8bqgwakt" path="res://addons/tattomoosa.spinner/spinner.gd" id="4_bn406"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ine7w"]
bg_color = Color(0.2520276, 0.25202766, 0.25202754, 1)
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_hgepf"]
[node name="ScoreBoardPanel" type="PanelContainer"]
size_flags_horizontal = 3
size_flags_vertical = 3
theme = ExtResource("1_ine7w")
theme_override_styles/panel = SubResource("StyleBoxFlat_ine7w")
script = ExtResource("1_35c2h")
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 2
theme_override_constants/margin_left = 10
theme_override_constants/margin_top = 10
theme_override_constants/margin_right = 10
theme_override_constants/margin_bottom = 10
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
layout_mode = 2
[node name="Title" type="Label" parent="MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
theme_override_fonts/font = ExtResource("2_bn406")
theme_override_font_sizes/font_size = 23
text = "SCOREBOARD__TITLE"
horizontal_alignment = 1
vertical_alignment = 1
[node name="Scores" type="VBoxContainer" parent="MarginContainer/VBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(600, 280)
layout_mode = 2
[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Scores"]
layout_mode = 2
text = "PLAYER_NAME - TIME - DATE"
fit_content = true
scroll_active = false
horizontal_alignment = 1
[node name="RichTextLabel2" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Scores"]
layout_mode = 2
text = "PLAYER_NAME - TIME - DATE"
fit_content = true
horizontal_alignment = 1
[node name="RichTextLabel3" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Scores"]
layout_mode = 2
text = "PLAYER_NAME - TIME - DATE"
fit_content = true
horizontal_alignment = 1
[node name="RichTextLabel4" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Scores"]
layout_mode = 2
text = "PLAYER_NAME - TIME - DATE"
fit_content = true
horizontal_alignment = 1
[node name="RichTextLabel5" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Scores"]
layout_mode = 2
text = "PLAYER_NAME - TIME - DATE"
fit_content = true
horizontal_alignment = 1
[node name="RichTextLabel6" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Scores"]
layout_mode = 2
text = "PLAYER_NAME - TIME - DATE"
fit_content = true
horizontal_alignment = 1
[node name="RichTextLabel7" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Scores"]
layout_mode = 2
text = "PLAYER_NAME - TIME - DATE"
fit_content = true
horizontal_alignment = 1
[node name="RichTextLabel8" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Scores"]
layout_mode = 2
text = "PLAYER_NAME - TIME - DATE"
fit_content = true
horizontal_alignment = 1
[node name="RichTextLabel9" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Scores"]
layout_mode = 2
text = "PLAYER_NAME - TIME - DATE"
fit_content = true
horizontal_alignment = 1
[node name="RichTextLabel10" type="RichTextLabel" parent="MarginContainer/VBoxContainer/Scores"]
layout_mode = 2
text = "PLAYER_NAME - TIME - DATE"
fit_content = true
horizontal_alignment = 1
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
alignment = 1
[node name="PrevButton" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
theme_override_styles/focus = SubResource("StyleBoxEmpty_hgepf")
text = "< "
script = ExtResource("2_hgepf")
metadata/_custom_type_script = "uid://elqkwjm0r5c7"
[node name="NextButton" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = ">"
script = ExtResource("2_hgepf")
metadata/_custom_type_script = "uid://elqkwjm0r5c7"
[node name="Spinner" type="Range" parent="."]
_import_path = NodePath("")
unique_name_in_owner = true
process_mode = 0
process_priority = 0
process_physics_priority = 0
process_thread_group = 0
physics_interpolation_mode = 2
auto_translate_mode = 0
editor_description = ""
visible = false
modulate = Color(1, 1, 1, 1)
self_modulate = Color(1, 1, 1, 1)
show_behind_parent = false
top_level = false
clip_children = 0
light_mask = 1
visibility_layer = 1
z_index = 0
z_as_relative = true
y_sort_enabled = false
texture_filter = 0
texture_repeat = 0
material = null
use_parent_material = false
clip_contents = true
custom_minimum_size = Vector2(100, 100)
layout_direction = 0
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
size_flags_stretch_ratio = 1.0
localize_numeral_system = true
tooltip_text = ""
tooltip_auto_translate_mode = 0
focus_neighbor_left = NodePath("")
focus_neighbor_top = NodePath("")
focus_neighbor_right = NodePath("")
focus_neighbor_bottom = NodePath("")
focus_next = NodePath("")
focus_previous = NodePath("")
focus_mode = 0
focus_behavior_recursive = 0
mouse_filter = 0
mouse_behavior_recursive = 0
mouse_force_pass_scroll_events = true
mouse_default_cursor_shape = 0
accessibility_name = ""
accessibility_description = ""
accessibility_live = 0
accessibility_controls_nodes = Array[NodePath]([])
accessibility_described_by_nodes = Array[NodePath]([])
accessibility_labeled_by_nodes = Array[NodePath]([])
accessibility_flow_to_nodes = Array[NodePath]([])
theme = null
theme_type_variation = &""
min_value = 0.0
max_value = 100.0
step = 1.0
value = 0.0
exp_edit = false
rounded = false
allow_greater = false
allow_lesser = false
script = ExtResource("4_bn406")
spin_fill_percent = 0.091
color_progress = Color(1, 1, 1, 1)
color_background = Color(0, 0, 0, 0)

View File

@@ -0,0 +1,147 @@
class_name RTMIAchievementSummaryContainer
extends PanelContainer
signal score_submitted()
const CHARACTER_LIMIT: int = 32
const ALLOWED_CHARACTERS = "[à-ÿÀ-ŸA-Za-z0-9 _-]"
var perfect = false
var collection: String
@onready var input_name: LineEdit = %InputName
@onready var total_time: Label = %TotalTime
@onready var pos: Label = %Position
@onready var achievement_count: Label = %AchievementCount
@onready var unlocked_achievements_container: VBoxContainer = %UnlockedAchievementsContainer
@onready var submit_button: RTMIMenuButton = %SubmitButton
@onready var spinner: Spinner = %Spinner
func _ready() -> void:
_fill()
input_name.text_changed.connect(_on_input_name_changed)
input_name.grab_focus()
func show():
super.show()
func _input(event: InputEvent) -> void:
if event.is_action_pressed("ui_enter"):
_on_submit_button_up()
func _fill():
_clear()
total_time.text = gymkhana.score_manager.format_time(gymkhana.achievement_manager.played_time)
var achievements = gymkhana.achievement_manager.get_achievements()
var unlocked = 0
for achievement_key in achievements:
var label = Label.new()
label.text = tr(gymkhana.achievement_manager.generate_achievement_literal(
achievement_key, "title"
))
label.add_theme_color_override("font_color", Color.DIM_GRAY)
if achievements.get(achievement_key):
label.add_theme_color_override("font_color", Color.GREEN)
unlocked += 1
unlocked_achievements_container.add_child(label)
achievement_count.text = "%s / %s" % [unlocked, achievements.size()]
if unlocked == achievements.size():
submit_button.text = tr("SUBMIT_PERFECT_SCORE")
perfect = true
collection = gymkhana.score_manager.PERFECT if perfect else gymkhana.score_manager.FASTEST
check_score()
func check_score():
if perfect:
escoria.game_scene.launch_confetti()
var played_time = floor(randf() * 1000)
var pos_int = await gymkhana.score_manager.calculate_score_position(collection, gymkhana.achievement_manager.played_time)
pos.text = "#" + str(pos_int + 1)
func _clear() -> void:
for child in unlocked_achievements_container.get_children():
unlocked_achievements_container.remove_child(child)
child.queue_free()
func _get_all_achievements() -> Array:
var unlocked_achievements: Array = []
var all_achievements = gymkhana.achievement_manager.get_achievements()
for achievement in all_achievements:
if all_achievements.get(achievement) == true:
unlocked_achievements.append(achievement)
return unlocked_achievements
func _on_input_name_changed(_new_text: String):
var valid = _validate_name()
if not valid:
_set_label_error()
return
_set_label_no_error()
func _on_submit_button_up() -> void:
var valid = _validate_name()
if not valid:
_set_label_error()
return
spinner.show()
var success: bool = await gymkhana.score_manager.submit_score(collection, input_name.text, gymkhana.achievement_manager.played_time)
if success:
_set_submit_ok()
input_name.editable = false
input_name.selecting_enabled = false
input_name.focus_mode = FOCUS_NONE
submit_button.disabled = true
submit_button.focus_mode = FOCUS_NONE
score_submitted.emit()
else:
_set_submit_error()
spinner.hide()
func _validate_name() -> bool:
if input_name.text == "":
return false
var regex = RegEx.new()
regex.compile(ALLOWED_CHARACTERS)
var result = regex.sub(input_name.text, "", true)
var valid_name = ""
for char in regex.search_all(input_name.text):
valid_name += char.get_string()
input_name.text = valid_name
input_name.caret_column = valid_name.length()
return true
func _set_label_error() -> void:
input_name.modulate = Color.RED
func _set_label_no_error() -> void:
input_name.modulate = Color.WHITE
func _set_submit_ok() -> void:
submit_button.modulate = Color.GREEN
func _set_submit_error() -> void:
submit_button.modulate = Color.RED

View File

@@ -0,0 +1,228 @@
[gd_scene load_steps=5 format=3 uid="uid://ch5d4emoxq6t4"]
[ext_resource type="Script" uid="uid://wor3bvk7tdh0" path="res://addons/escoria-ui-return-monkey-island/achievements/summary/rtmi_achievement_summary.gd" id="1_vcqj7"]
[ext_resource type="Script" uid="uid://elqkwjm0r5c7" path="res://addons/escoria-ui-return-monkey-island/menus/rtmi_menu_button.gd" id="2_3d1qx"]
[ext_resource type="Script" uid="uid://doqt8bqgwakt" path="res://addons/tattomoosa.spinner/spinner.gd" id="3_co5jd"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_co5jd"]
[node name="AchievementSummary" type="PanelContainer"]
custom_minimum_size = Vector2(300, 0)
offset_right = 40.0
offset_bottom = 40.0
script = ExtResource("1_vcqj7")
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 2
theme_override_constants/margin_left = 10
theme_override_constants/margin_top = 10
theme_override_constants/margin_right = 10
theme_override_constants/margin_bottom = 10
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="TotalTimeLabel" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 20
text = "TOTAL_TIME"
horizontal_alignment = 1
[node name="TotalTime" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
theme_override_font_sizes/font_size = 24
text = "0h 00m 00s"
horizontal_alignment = 1
vertical_alignment = 2
[node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="PositionLabel" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2"]
layout_mode = 2
theme_override_font_sizes/font_size = 20
text = "POSITION"
horizontal_alignment = 1
[node name="Position" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer/VBoxContainer2"]
unique_name_in_owner = true
layout_mode = 2
theme_override_font_sizes/font_size = 24
text = "-"
horizontal_alignment = 1
vertical_alignment = 2
[node name="HSeparator" type="HSeparator" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_styles/separator = SubResource("StyleBoxEmpty_co5jd")
[node name="MarginContainer2" type="MarginContainer" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="HBoxContainer2" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="AchievementTitle" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer2"]
layout_mode = 2
theme_override_font_sizes/font_size = 12
text = "ACHIEVEMENT_SUMMARY"
[node name="AchievementCount" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer2"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
theme_override_font_sizes/font_size = 12
text = "1 / 7"
horizontal_alignment = 2
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_constants/margin_top = 10
theme_override_constants/margin_bottom = 10
[node name="UnlockedAchievementsContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/MarginContainer"]
unique_name_in_owner = true
layout_mode = 2
theme_override_constants/separation = 4
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/MarginContainer/UnlockedAchievementsContainer"]
layout_mode = 2
text = "ACHIEVEMENT TEXT PLACEHOLDER"
[node name="Label2" type="Label" parent="MarginContainer/VBoxContainer/MarginContainer/UnlockedAchievementsContainer"]
layout_mode = 2
text = "ACHIEVEMENT TEXT PLACEHOLDER"
[node name="Label3" type="Label" parent="MarginContainer/VBoxContainer/MarginContainer/UnlockedAchievementsContainer"]
layout_mode = 2
text = "ACHIEVEMENT TEXT PLACEHOLDER"
[node name="Label4" type="Label" parent="MarginContainer/VBoxContainer/MarginContainer/UnlockedAchievementsContainer"]
layout_mode = 2
text = "ACHIEVEMENT TEXT PLACEHOLDER"
[node name="Label5" type="Label" parent="MarginContainer/VBoxContainer/MarginContainer/UnlockedAchievementsContainer"]
layout_mode = 2
text = "ACHIEVEMENT TEXT PLACEHOLDER"
[node name="Label6" type="Label" parent="MarginContainer/VBoxContainer/MarginContainer/UnlockedAchievementsContainer"]
layout_mode = 2
text = "ACHIEVEMENT TEXT PLACEHOLDER"
[node name="HSeparator3" type="HSeparator" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_styles/separator = SubResource("StyleBoxEmpty_co5jd")
[node name="InputName" type="LineEdit" parent="MarginContainer/VBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 60)
layout_mode = 2
placeholder_text = "NAME_PLACEHOLDER"
clear_button_enabled = true
caret_blink = true
[node name="HSeparator2" type="HSeparator" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_styles/separator = SubResource("StyleBoxEmpty_co5jd")
[node name="SubmitButton" type="Button" parent="MarginContainer/VBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(0, 60)
layout_mode = 2
text = "SUBMIT_SCORE"
script = ExtResource("2_3d1qx")
metadata/_custom_type_script = "uid://elqkwjm0r5c7"
[node name="Spinner" type="Range" parent="MarginContainer/VBoxContainer/SubmitButton"]
_import_path = NodePath("")
unique_name_in_owner = true
process_mode = 0
process_priority = 0
process_physics_priority = 0
process_thread_group = 0
physics_interpolation_mode = 2
auto_translate_mode = 0
editor_description = ""
visible = false
modulate = Color(1, 1, 1, 1)
self_modulate = Color(1, 1, 1, 1)
show_behind_parent = false
top_level = false
clip_children = 0
light_mask = 1
visibility_layer = 1
z_index = 0
z_as_relative = true
y_sort_enabled = false
texture_filter = 0
texture_repeat = 0
material = null
use_parent_material = false
clip_contents = true
custom_minimum_size = Vector2(16, 16)
layout_direction = 0
layout_mode = 1
anchors_preset = 4
anchor_left = 0.0
anchor_top = 0.5
anchor_right = 0.0
anchor_bottom = 0.5
offset_left = 20.0
offset_top = -20.0
offset_right = 60.0
offset_bottom = 20.0
grow_horizontal = 1
grow_vertical = 2
rotation = 0.0
scale = Vector2(1, 1)
pivot_offset = Vector2(0, 0)
size_flags_horizontal = 1
size_flags_vertical = 1
size_flags_stretch_ratio = 1.0
localize_numeral_system = true
tooltip_text = ""
tooltip_auto_translate_mode = 0
focus_neighbor_left = NodePath("")
focus_neighbor_top = NodePath("")
focus_neighbor_right = NodePath("")
focus_neighbor_bottom = NodePath("")
focus_next = NodePath("")
focus_previous = NodePath("")
focus_mode = 0
focus_behavior_recursive = 0
mouse_filter = 0
mouse_behavior_recursive = 0
mouse_force_pass_scroll_events = true
mouse_default_cursor_shape = 0
accessibility_name = ""
accessibility_description = ""
accessibility_live = 0
accessibility_controls_nodes = Array[NodePath]([])
accessibility_described_by_nodes = Array[NodePath]([])
accessibility_labeled_by_nodes = Array[NodePath]([])
accessibility_flow_to_nodes = Array[NodePath]([])
theme = null
theme_type_variation = &""
min_value = 0.0
max_value = 100.0
step = 1.0
value = 0.0
exp_edit = false
rounded = false
allow_greater = false
allow_lesser = false
script = ExtResource("3_co5jd")
color_progress = Color(0.98, 0.98, 0.98, 1)
color_background = Color(0, 0, 0, 0)
metadata/_custom_type_script = "uid://doqt8bqgwakt"
[connection signal="button_up" from="MarginContainer/VBoxContainer/SubmitButton" to="." method="_on_submit_button_up"]

View File

@@ -6,7 +6,6 @@ extends TextureButton
@export var music_disabled_texture: Texture2D
@export var music_disabled_hover_texture: Texture2D
# Called when the node enters the scene tree for the first time.
func _ready():
gymkhana.music_manager.toggled.connect(_music_toggled)
set_texture(gymkhana.music_manager.music_enabled)

View File

@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="128"
height="128"
viewBox="0 0 128 128"
fill="none"
version="1.1"
id="svg5"
sodipodi:docname="arrow.svg"
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview5"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="11.294988"
inkscape:cx="17.397098"
inkscape:cy="20.053143"
inkscape:window-width="1680"
inkscape:window-height="941"
inkscape:window-x="1920"
inkscape:window-y="15"
inkscape:window-maximized="1"
inkscape:current-layer="g5" />
<g
id="g5"
transform="matrix(0.28239848,0,0,0.28239848,1.1963533e-7,0.36640485)">
<g
filter="url(#filter0_d_18_113)"
id="g2"
transform="matrix(0.41664582,0,0,0.41664582,-24.496608,-11.993109)">
<path
d="M 74.3177,39.3652 74.1548,178.66 c -0.0025,2.106 1.6813,3.832 3.7847,3.941 8.8629,0.457 31.2815,2.402 45.6585,10.577 10.789,6.135 11.755,13.002 23.111,7.993 11.356,-5.009 6.351,-10.094 9.095,-22.199 3.651,-16.107 16.936,-33.789 22.433,-40.594 1.316,-1.629 1.168,-4.019 -0.38,-5.428 L 74.8532,39.129 c -0.2054,-0.1871 -0.5352,-0.0416 -0.5355,0.2362 z"
fill="#0000ff"
id="path1" />
<path
d="m 69.1977,39.3592 v 0 L 69.0348,178.654 c -0.0058,4.913 3.8938,8.815 8.6409,9.06 4.3013,0.222 11.8834,0.806 20.099,2.317 8.2933,1.525 16.8373,3.927 23.2923,7.598 2.359,1.341 4.203,2.732 5.898,4.089 0.286,0.228 0.582,0.469 0.887,0.716 1.359,1.103 2.885,2.342 4.4,3.277 2.065,1.274 4.475,2.249 7.475,2.306 2.874,0.054 5.834,-0.744 9.048,-2.162 3.204,-1.413 5.788,-3.056 7.653,-5.238 1.961,-2.296 2.767,-4.765 3.121,-7.126 0.239,-1.591 0.294,-3.427 0.342,-5.048 0.014,-0.486 0.028,-0.952 0.047,-1.387 0.087,-2.097 0.268,-4.345 0.859,-6.952 1.645,-7.256 5.548,-15.147 9.896,-22.242 4.31,-7.032 8.861,-12.966 11.527,-16.267 l -3.499,-2.826 3.499,2.826 c 2.966,-3.672 2.697,-9.141 -0.915,-12.43 L 78.3009,35.3438 v 0 c -3.491,-3.1798 -9.0976,-0.7068 -9.1032,4.0154 z"
stroke="#0000ff"
stroke-width="10.24"
id="path2"
style="fill:#f2f2f2;stroke:#ffffff;stroke-opacity:1" />
</g>
<path
d="m 6.4680104,4.1068365 -0.06883,58.8658875 c -7.09e-4,0.584971 0.46281,1.064114 1.047281,1.089112 3.2398786,0.13791 13.2513366,0.848291 19.5535216,4.431862 4.495191,2.556122 4.897671,5.417231 9.629101,3.330251 4.731426,-2.087396 2.646118,-4.20604 3.789394,-9.249121 1.601172,-7.063397 7.648372,-14.853007 9.679512,-17.322051 0.36957,-0.448727 0.32582,-1.108694 -0.10416,-1.500341 z"
fill="#00ff00"
id="path3"
style="stroke-width:0.416646;fill:#666666" />
</g>
<defs
id="defs5">
<filter
id="filter0_d_18_113"
x="58.7948"
y="28.784901"
width="135.694"
height="197.15401"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood3" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix3" />
<feOffset
dy="7.68"
id="feOffset3" />
<feGaussianBlur
stdDeviation="2.56"
id="feGaussianBlur3" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
id="feColorMatrix4" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_18_113"
id="feBlend4" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_18_113"
result="shape"
id="feBlend5" />
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 428 B

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="128"
height="128"
viewBox="0 0 128 128"
fill="none"
version="1.1"
id="svg5"
sodipodi:docname="blank.svg"
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview5"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="11.294988"
inkscape:cx="17.485632"
inkscape:cy="20.141677"
inkscape:window-width="1680"
inkscape:window-height="941"
inkscape:window-x="1920"
inkscape:window-y="15"
inkscape:window-maximized="1"
inkscape:current-layer="g5" />
<g
id="g5"
transform="matrix(0.28239848,0,0,0.28239848,1.1963533e-7,0.36640485)" />
<defs
id="defs5">
<filter
id="filter0_d_18_113"
x="58.7948"
y="28.784901"
width="135.694"
height="197.15401"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood3" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix3" />
<feOffset
dy="7.68"
id="feOffset3" />
<feGaussianBlur
stdDeviation="2.56"
id="feGaussianBlur3" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
id="feColorMatrix4" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_18_113"
id="feBlend4" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_18_113"
result="shape"
id="feBlend5" />
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="128"
height="128"
viewBox="0 0 128 128"
fill="none"
version="1.1"
id="svg5"
sodipodi:docname="east.svg"
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview5"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="3.9933811"
inkscape:cx="57.219683"
inkscape:cy="60.224655"
inkscape:window-width="1680"
inkscape:window-height="941"
inkscape:window-x="1920"
inkscape:window-y="15"
inkscape:window-maximized="1"
inkscape:current-layer="g5" /><g
id="g5"
transform="matrix(0.28239848,0,0,0.28239848,1.1963533e-7,0.36640485)"><g
style="fill:none"
id="g1"
transform="matrix(-0.82301095,0,0,-0.82301095,182.41215,136.85333)"><path
d="m 42.8435,124.893 c -1.433,0.787 -2.3236,2.292 -2.3236,3.927 0,1.635 0.8906,3.14 2.3236,3.927 l 54.7779,30.08 c 0.627191,0.34422 1.302043,0.52288 1.973343,0.54975 1.581207,0.0633 3.142697,-0.71559 4.015257,-2.15675 l -3.8322,-2.32 c 3.8322,2.32 3.8332,2.319 3.8332,2.319 l 10e-4,-0.002 0.002,-0.003 0.006,-0.01 0.018,-0.03 0.063,-0.106 c 0.054,-0.091 0.131,-0.221 0.228,-0.387 0.194,-0.333 0.469,-0.812 0.807,-1.418 0.675,-1.21 1.601,-2.93 2.619,-4.992 1.631,-3.303 3.548,-7.578 5.037,-12.096 0.307,-0.002 0.635,-0.003 0.982,-0.004 2.728,-0.008 6.629,-0.009 11.318,-0.006 9.291,0.006 21.656,0.029 34.074,0.052 l 0.342,10e-4 c 12.53,0.023 25.088,0.047 34.56,0.052 4.735,0.003 8.704,0.002 11.516,-0.007 1.404,-0.004 2.528,-0.009 3.317,-0.017 0.392,-0.004 0.717,-0.009 0.958,-0.014 0.117,-0.003 0.238,-0.006 0.347,-0.011 0.051,-0.002 0.131,-0.006 0.22,-0.013 0.028,-0.003 0.07,-0.006 0.12,-0.011 0.021,-0.002 0.041,-0.004 0.062,-0.006 0.185,-0.019 0.387,-0.051 0.605,-0.099 0.437,-0.097 0.923,-0.262 1.427,-0.523 1.038,-0.539 1.973,-1.395 2.726,-2.567 1.424,-2.219 2.194,-5.552 2.194,-10.51 0,-4.959 -0.77,-8.292 -2.194,-10.511 -0.753,-1.172 -1.688,-2.028 -2.726,-2.566 -0.504,-0.262 -0.99,-0.427 -1.427,-0.524 -0.218,-0.048 -0.42,-0.08 -0.605,-0.099 -0.015,-0.001 -0.031,-0.003 -0.046,-0.004 -0.047,-0.005 -0.087,-0.009 -0.115,-0.011 -0.092,-0.008 -0.175,-0.012 -0.229,-0.015 -0.114,-0.006 -0.239,-0.009 -0.359,-0.012 -0.247,-0.007 -0.577,-0.012 -0.973,-0.016 -0.797,-0.009 -1.929,-0.015 -3.339,-0.02 -2.825,-0.009 -6.806,-0.01 -11.552,-0.007 -9.476,0.007 -22.022,0.033 -34.545,0.06 h -0.071 c -12.549,0.027 -25.067,0.053 -34.452,0.059 -4.694,0.004 -8.597,0.002 -11.327,-0.007 -0.364,-0.002 -0.706,-0.003 -1.025,-0.004 -1.494,-4.388 -3.363,-8.515 -4.946,-11.701 -0.989,-1.991 -1.884,-3.6474 -2.534,-4.8119 -0.326,-0.5829 -0.591,-1.044 -0.778,-1.3639 -0.093,-0.16 -0.167,-0.2848 -0.219,-0.372 l -0.061,-0.1022 -0.018,-0.0294 -0.005,-0.0092 -0.002,-0.0032 -10e-4,-0.0013 c 0,-5e-4 -0.001,-0.001 -3.8332,2.3188 l 3.8322,-2.3198 c -1.243,-2.0539 -3.8841,-2.7627 -5.9886,-1.607 z"
stroke="#0000ff"
stroke-width="8.96"
stroke-linecap="round"
stroke-linejoin="round"
id="path1-3"
sodipodi:nodetypes="csccscccccccccccccsccccsccccccccscccccccccccccccccccsccccccccc"
style="stroke:#f2f2f2;stroke-opacity:1" /><path
d="M 44.9999,128.82 99.7778,98.7397 c 0,0 6.1412,10.1473 9.0922,20.5063 0.06,0.213 99.974,-0.211 100.842,0 0,0 2.968,0 2.968,9.246 0,9.245 -2.968,9.245 -2.968,9.245 -0.76,0.188 -100.609,-0.186 -100.66,0 -2.87,10.583 -9.2742,21.163 -9.2742,21.163 z"
fill="#00ff00"
id="path2-6"
style="fill:#666666;fill-opacity:1" /></g></g><defs
id="defs5"><filter
id="filter0_d_18_113"
x="58.7948"
y="28.784901"
width="135.694"
height="197.15401"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood3" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix3" /><feOffset
dy="7.68"
id="feOffset3" /><feGaussianBlur
stdDeviation="2.56"
id="feGaussianBlur3" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
id="feColorMatrix4" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_18_113"
id="feBlend4" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_18_113"
result="shape"
id="feBlend5" /></filter></defs></svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="128"
height="128"
viewBox="0 0 128 128"
fill="none"
version="1.1"
id="svg5"
sodipodi:docname="hand.svg"
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview5"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="11.294988"
inkscape:cx="17.397098"
inkscape:cy="20.053143"
inkscape:window-width="1680"
inkscape:window-height="941"
inkscape:window-x="1920"
inkscape:window-y="15"
inkscape:window-maximized="1"
inkscape:current-layer="g5" /><g
id="g5"
transform="matrix(0.28239848,0,0,0.28239848,1.1963533e-7,0.36640485)"><g
style="fill:none"
id="g3"
transform="matrix(0.38020692,0,0,0.38020692,-9.40517,-10.599142)"><g
filter="url(#filter0_d_21_2)"
id="g1"><path
d="m 117.348,35.02 c -6.215,0 -12.306,3.0662 -16.178,8.2326 -3.8717,5.1664 -5.7582,12.2574 -5.7582,20.307 V 125.03 c -4.8514,-3.593 -10.5586,-9.073 -14.807,-10.977 -8.5854,-3.847 -16.4297,-4.602 -22.759,-2.744 -12.6585,3.715 -16.7264,15.916 -16.7264,15.916 l -1.9194,6.312 5.484,3.841 c 12.0713,8.157 24.3061,28.164 35.9208,46.652 5.8073,9.243 11.5325,17.911 18.0975,24.972 6.5647,7.06 14.6697,12.962 24.6787,12.898 l 77.325,-0.274 7.952,-0.274 0.822,-7.684 8.775,-87.814 c 1.302,-12.594 -6.33,-23.323 -16.178,-26.6188 -4.753,-1.5907 -10.207,-0.7745 -15.081,1.3718 -3.201,-4.9067 -7.388,-8.6174 -12.614,-9.8788 -4.451,-1.0743 -9.19,-0.1265 -13.436,1.6465 -3.049,-4.3574 -7.035,-7.5296 -11.791,-9.0558 -3.062,-0.9828 -6.554,-0.2214 -9.871,0.2739 V 63.5602 c 0,-8.0497 -1.886,-15.1407 -5.758,-20.3071 -3.872,-5.1663 -9.963,-8.2325 -16.178,-8.2325 z"
fill="#0000ff"
id="path1-3"
style="fill:#ffffff;fill-opacity:1" /></g><path
d="m 123.063,212.94 77.496,-0.503 8.772,-88.175 c 1.84,-17.873 -20.2,-25.3098 -26.318,-8.818 0.079,-19.819 -20.208,-22.2988 -26.318,-8.817 0.765,-16.375 -19.934,-22.7127 -26.318,-8.818 V 62.5394 c 0,-26.4526 -26.318,-26.4526 -26.318,0 V 141.897 C 60.195,97.8095 49.4399,129.489 49.4399,129.489 c 29.8072,20.228 48.039,83.617 73.6231,83.451 z"
fill="#00ff00"
id="path2-6"
style="fill:#666666;fill-opacity:1" /></g></g><defs
id="defs5"><filter
id="filter0_d_18_113"
x="58.7948"
y="28.784901"
width="135.694"
height="197.15401"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood3" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix3" /><feOffset
dy="7.68"
id="feOffset3" /><feGaussianBlur
stdDeviation="2.56"
id="feGaussianBlur3" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
id="feColorMatrix4" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_18_113"
id="feBlend4" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_18_113"
result="shape"
id="feBlend5" /></filter><filter
id="filter0_d_21_2"
x="34.08"
y="35.02"
width="189.44"
height="199.68"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood2" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix2" /><feOffset
dy="7.68"
id="feOffset2" /><feGaussianBlur
stdDeviation="2.56"
id="feGaussianBlur2" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
id="feColorMatrix3-7" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_21_2"
id="feBlend3" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_21_2"
result="shape"
id="feBlend4-5" /></filter></defs></svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 B

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="128"
height="128"
viewBox="0 0 128 128"
fill="none"
version="1.1"
id="svg5"
sodipodi:docname="north.svg"
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview5"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="3.9933811"
inkscape:cx="57.720512"
inkscape:cy="68.989158"
inkscape:window-width="1680"
inkscape:window-height="941"
inkscape:window-x="1920"
inkscape:window-y="15"
inkscape:window-maximized="1"
inkscape:current-layer="g5" /><g
id="g5"
transform="matrix(0.28239848,0,0,0.28239848,1.1963533e-7,0.36640485)"><g
style="fill:none"
id="g1"
transform="matrix(0,0.82301095,-0.82301095,0,138.15081,-30.958707)"><path
d="m 42.8435,124.893 c -1.433,0.787 -2.3236,2.292 -2.3236,3.927 0,1.635 0.8906,3.14 2.3236,3.927 l 54.7779,30.08 c 0.627191,0.34422 1.302043,0.52288 1.973343,0.54975 1.581207,0.0633 3.142697,-0.71559 4.015257,-2.15675 l -3.8322,-2.32 c 3.8322,2.32 3.8332,2.319 3.8332,2.319 l 10e-4,-0.002 0.002,-0.003 0.006,-0.01 0.018,-0.03 0.063,-0.106 c 0.054,-0.091 0.131,-0.221 0.228,-0.387 0.194,-0.333 0.469,-0.812 0.807,-1.418 0.675,-1.21 1.601,-2.93 2.619,-4.992 1.631,-3.303 3.548,-7.578 5.037,-12.096 0.307,-0.002 0.635,-0.003 0.982,-0.004 2.728,-0.008 6.629,-0.009 11.318,-0.006 9.291,0.006 21.656,0.029 34.074,0.052 l 0.342,10e-4 c 12.53,0.023 25.088,0.047 34.56,0.052 4.735,0.003 8.704,0.002 11.516,-0.007 1.404,-0.004 2.528,-0.009 3.317,-0.017 0.392,-0.004 0.717,-0.009 0.958,-0.014 0.117,-0.003 0.238,-0.006 0.347,-0.011 0.051,-0.002 0.131,-0.006 0.22,-0.013 0.028,-0.003 0.07,-0.006 0.12,-0.011 0.021,-0.002 0.041,-0.004 0.062,-0.006 0.185,-0.019 0.387,-0.051 0.605,-0.099 0.437,-0.097 0.923,-0.262 1.427,-0.523 1.038,-0.539 1.973,-1.395 2.726,-2.567 1.424,-2.219 2.194,-5.552 2.194,-10.51 0,-4.959 -0.77,-8.292 -2.194,-10.511 -0.753,-1.172 -1.688,-2.028 -2.726,-2.566 -0.504,-0.262 -0.99,-0.427 -1.427,-0.524 -0.218,-0.048 -0.42,-0.08 -0.605,-0.099 -0.015,-0.001 -0.031,-0.003 -0.046,-0.004 -0.047,-0.005 -0.087,-0.009 -0.115,-0.011 -0.092,-0.008 -0.175,-0.012 -0.229,-0.015 -0.114,-0.006 -0.239,-0.009 -0.359,-0.012 -0.247,-0.007 -0.577,-0.012 -0.973,-0.016 -0.797,-0.009 -1.929,-0.015 -3.339,-0.02 -2.825,-0.009 -6.806,-0.01 -11.552,-0.007 -9.476,0.007 -22.022,0.033 -34.545,0.06 h -0.071 c -12.549,0.027 -25.067,0.053 -34.452,0.059 -4.694,0.004 -8.597,0.002 -11.327,-0.007 -0.364,-0.002 -0.706,-0.003 -1.025,-0.004 -1.494,-4.388 -3.363,-8.515 -4.946,-11.701 -0.989,-1.991 -1.884,-3.6474 -2.534,-4.8119 -0.326,-0.5829 -0.591,-1.044 -0.778,-1.3639 -0.093,-0.16 -0.167,-0.2848 -0.219,-0.372 l -0.061,-0.1022 -0.018,-0.0294 -0.005,-0.0092 -0.002,-0.0032 -10e-4,-0.0013 c 0,-5e-4 -0.001,-0.001 -3.8332,2.3188 l 3.8322,-2.3198 c -1.243,-2.0539 -3.8841,-2.7627 -5.9886,-1.607 z"
stroke="#0000ff"
stroke-width="8.96"
stroke-linecap="round"
stroke-linejoin="round"
id="path1-3"
sodipodi:nodetypes="csccscccccccccccccsccccsccccccccscccccccccccccccccccsccccccccc"
style="stroke:#f2f2f2;stroke-opacity:1" /><path
d="M 44.9999,128.82 99.7778,98.7397 c 0,0 6.1412,10.1473 9.0922,20.5063 0.06,0.213 99.974,-0.211 100.842,0 0,0 2.968,0 2.968,9.246 0,9.245 -2.968,9.245 -2.968,9.245 -0.76,0.188 -100.609,-0.186 -100.66,0 -2.87,10.583 -9.2742,21.163 -9.2742,21.163 z"
fill="#00ff00"
id="path2-6"
style="fill:#666666;fill-opacity:1" /></g></g><defs
id="defs5"><filter
id="filter0_d_18_113"
x="58.7948"
y="28.784901"
width="135.694"
height="197.15401"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood3" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix3" /><feOffset
dy="7.68"
id="feOffset3" /><feGaussianBlur
stdDeviation="2.56"
id="feGaussianBlur3" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
id="feColorMatrix4" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_18_113"
id="feBlend4" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_18_113"
result="shape"
id="feBlend5" /></filter></defs></svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="128"
height="128"
viewBox="0 0 128 128"
fill="none"
version="1.1"
id="svg5"
sodipodi:docname="south.svg"
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview5"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="3.9933811"
inkscape:cx="57.219683"
inkscape:cy="60.224655"
inkscape:window-width="1680"
inkscape:window-height="941"
inkscape:window-x="1920"
inkscape:window-y="15"
inkscape:window-maximized="1"
inkscape:current-layer="g5" /><g
id="g5"
transform="matrix(0.28239848,0,0,0.28239848,1.1963533e-7,0.36640485)"><g
style="fill:none"
id="g1"
transform="matrix(0,-0.82301095,0.82301095,0,-73.90381,181.97657)"><path
d="m 42.8435,124.893 c -1.433,0.787 -2.3236,2.292 -2.3236,3.927 0,1.635 0.8906,3.14 2.3236,3.927 l 54.7779,30.08 c 0.627191,0.34422 1.302043,0.52288 1.973343,0.54975 1.581207,0.0633 3.142697,-0.71559 4.015257,-2.15675 l -3.8322,-2.32 c 3.8322,2.32 3.8332,2.319 3.8332,2.319 l 10e-4,-0.002 0.002,-0.003 0.006,-0.01 0.018,-0.03 0.063,-0.106 c 0.054,-0.091 0.131,-0.221 0.228,-0.387 0.194,-0.333 0.469,-0.812 0.807,-1.418 0.675,-1.21 1.601,-2.93 2.619,-4.992 1.631,-3.303 3.548,-7.578 5.037,-12.096 0.307,-0.002 0.635,-0.003 0.982,-0.004 2.728,-0.008 6.629,-0.009 11.318,-0.006 9.291,0.006 21.656,0.029 34.074,0.052 l 0.342,10e-4 c 12.53,0.023 25.088,0.047 34.56,0.052 4.735,0.003 8.704,0.002 11.516,-0.007 1.404,-0.004 2.528,-0.009 3.317,-0.017 0.392,-0.004 0.717,-0.009 0.958,-0.014 0.117,-0.003 0.238,-0.006 0.347,-0.011 0.051,-0.002 0.131,-0.006 0.22,-0.013 0.028,-0.003 0.07,-0.006 0.12,-0.011 0.021,-0.002 0.041,-0.004 0.062,-0.006 0.185,-0.019 0.387,-0.051 0.605,-0.099 0.437,-0.097 0.923,-0.262 1.427,-0.523 1.038,-0.539 1.973,-1.395 2.726,-2.567 1.424,-2.219 2.194,-5.552 2.194,-10.51 0,-4.959 -0.77,-8.292 -2.194,-10.511 -0.753,-1.172 -1.688,-2.028 -2.726,-2.566 -0.504,-0.262 -0.99,-0.427 -1.427,-0.524 -0.218,-0.048 -0.42,-0.08 -0.605,-0.099 -0.015,-0.001 -0.031,-0.003 -0.046,-0.004 -0.047,-0.005 -0.087,-0.009 -0.115,-0.011 -0.092,-0.008 -0.175,-0.012 -0.229,-0.015 -0.114,-0.006 -0.239,-0.009 -0.359,-0.012 -0.247,-0.007 -0.577,-0.012 -0.973,-0.016 -0.797,-0.009 -1.929,-0.015 -3.339,-0.02 -2.825,-0.009 -6.806,-0.01 -11.552,-0.007 -9.476,0.007 -22.022,0.033 -34.545,0.06 h -0.071 c -12.549,0.027 -25.067,0.053 -34.452,0.059 -4.694,0.004 -8.597,0.002 -11.327,-0.007 -0.364,-0.002 -0.706,-0.003 -1.025,-0.004 -1.494,-4.388 -3.363,-8.515 -4.946,-11.701 -0.989,-1.991 -1.884,-3.6474 -2.534,-4.8119 -0.326,-0.5829 -0.591,-1.044 -0.778,-1.3639 -0.093,-0.16 -0.167,-0.2848 -0.219,-0.372 l -0.061,-0.1022 -0.018,-0.0294 -0.005,-0.0092 -0.002,-0.0032 -10e-4,-0.0013 c 0,-5e-4 -0.001,-0.001 -3.8332,2.3188 l 3.8322,-2.3198 c -1.243,-2.0539 -3.8841,-2.7627 -5.9886,-1.607 z"
stroke="#0000ff"
stroke-width="8.96"
stroke-linecap="round"
stroke-linejoin="round"
id="path1-3"
sodipodi:nodetypes="csccscccccccccccccsccccsccccccccscccccccccccccccccccsccccccccc"
style="stroke:#f2f2f2;stroke-opacity:1" /><path
d="M 44.9999,128.82 99.7778,98.7397 c 0,0 6.1412,10.1473 9.0922,20.5063 0.06,0.213 99.974,-0.211 100.842,0 0,0 2.968,0 2.968,9.246 0,9.245 -2.968,9.245 -2.968,9.245 -0.76,0.188 -100.609,-0.186 -100.66,0 -2.87,10.583 -9.2742,21.163 -9.2742,21.163 z"
fill="#00ff00"
id="path2-6"
style="fill:#666666;fill-opacity:1" /></g></g><defs
id="defs5"><filter
id="filter0_d_18_113"
x="58.7948"
y="28.784901"
width="135.694"
height="197.15401"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood3" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix3" /><feOffset
dy="7.68"
id="feOffset3" /><feGaussianBlur
stdDeviation="2.56"
id="feGaussianBlur3" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
id="feColorMatrix4" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_18_113"
id="feBlend4" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_18_113"
result="shape"
id="feBlend5" /></filter></defs></svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="128"
height="128"
viewBox="0 0 128 128"
fill="none"
version="1.1"
id="svg5"
sodipodi:docname="wait.svg"
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview5"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="22.589975"
inkscape:cx="8.9198859"
inkscape:cy="13.435163"
inkscape:window-width="1680"
inkscape:window-height="941"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="g5" /><g
id="g5"
transform="matrix(0.28239848,0,0,0.28239848,1.1963533e-7,0.36640485)"><g
id="g1"
transform="matrix(0.59297639,0,0,0.60377959,-187.61608,-90.048853)"><path
d="m 351.44777,217.73491 c 26.5867,0 30.72994,-21.55277 30.72994,-48.1394 h -59.67743 c 0,26.58663 2.36086,48.1394 28.94749,48.1394 z m 0,0 c 26.5867,0 32.15216,21.55269 32.15216,48.13939 h -60.49837 c 0,-26.5867 1.75958,-48.13939 28.34621,-48.13939 z"
stroke="#000000"
stroke-width="10.3156"
stroke-linecap="round"
stroke-linejoin="round"
id="path1"
style="fill:#666666;fill-opacity:1;stroke:#f2f2f2;stroke-opacity:1"
sodipodi:nodetypes="sccssccs" /><path
d="m 324.48025,154.99424 28.56986,-0.59425 h 30.04925"
stroke="#000000"
stroke-width="10.3156"
stroke-linecap="round"
stroke-linejoin="round"
id="path2"
style="stroke:#f2f2f2;stroke-opacity:1"
sodipodi:nodetypes="ccc" /><path
d="m 321.60178,280.75129 29.97802,0.69482 32.82485,0.16418"
stroke="#000000"
stroke-width="10.3156"
stroke-linecap="round"
stroke-linejoin="round"
id="path3"
style="stroke:#f2f2f2;stroke-opacity:1"
sodipodi:nodetypes="ccc" /></g></g><defs
id="defs5"><filter
id="filter0_d_18_113"
x="58.7948"
y="28.784901"
width="135.694"
height="197.15401"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood3" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix3" /><feOffset
dy="7.68"
id="feOffset3" /><feGaussianBlur
stdDeviation="2.56"
id="feGaussianBlur3" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
id="feColorMatrix4" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_18_113"
id="feBlend4" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_18_113"
result="shape"
id="feBlend5" /></filter></defs></svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="128"
height="128"
viewBox="0 0 128 128"
fill="none"
version="1.1"
id="svg5"
sodipodi:docname="west.svg"
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview5"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="3.9933811"
inkscape:cx="57.219683"
inkscape:cy="60.224655"
inkscape:window-width="1680"
inkscape:window-height="941"
inkscape:window-x="1920"
inkscape:window-y="15"
inkscape:window-maximized="1"
inkscape:current-layer="g5" /><g
id="g5"
transform="matrix(0.28239848,0,0,0.28239848,1.1963533e-7,0.36640485)"><g
style="fill:none"
id="g1"
transform="matrix(0.82301095,0,0,0.82301095,-29.661233,-75.201285)"><path
d="m 42.8435,124.893 c -1.433,0.787 -2.3236,2.292 -2.3236,3.927 0,1.635 0.8906,3.14 2.3236,3.927 l 54.7779,30.08 c 0.627191,0.34422 1.302043,0.52288 1.973343,0.54975 1.581207,0.0633 3.142697,-0.71559 4.015257,-2.15675 l -3.8322,-2.32 c 3.8322,2.32 3.8332,2.319 3.8332,2.319 l 10e-4,-0.002 0.002,-0.003 0.006,-0.01 0.018,-0.03 0.063,-0.106 c 0.054,-0.091 0.131,-0.221 0.228,-0.387 0.194,-0.333 0.469,-0.812 0.807,-1.418 0.675,-1.21 1.601,-2.93 2.619,-4.992 1.631,-3.303 3.548,-7.578 5.037,-12.096 0.307,-0.002 0.635,-0.003 0.982,-0.004 2.728,-0.008 6.629,-0.009 11.318,-0.006 9.291,0.006 21.656,0.029 34.074,0.052 l 0.342,10e-4 c 12.53,0.023 25.088,0.047 34.56,0.052 4.735,0.003 8.704,0.002 11.516,-0.007 1.404,-0.004 2.528,-0.009 3.317,-0.017 0.392,-0.004 0.717,-0.009 0.958,-0.014 0.117,-0.003 0.238,-0.006 0.347,-0.011 0.051,-0.002 0.131,-0.006 0.22,-0.013 0.028,-0.003 0.07,-0.006 0.12,-0.011 0.021,-0.002 0.041,-0.004 0.062,-0.006 0.185,-0.019 0.387,-0.051 0.605,-0.099 0.437,-0.097 0.923,-0.262 1.427,-0.523 1.038,-0.539 1.973,-1.395 2.726,-2.567 1.424,-2.219 2.194,-5.552 2.194,-10.51 0,-4.959 -0.77,-8.292 -2.194,-10.511 -0.753,-1.172 -1.688,-2.028 -2.726,-2.566 -0.504,-0.262 -0.99,-0.427 -1.427,-0.524 -0.218,-0.048 -0.42,-0.08 -0.605,-0.099 -0.015,-0.001 -0.031,-0.003 -0.046,-0.004 -0.047,-0.005 -0.087,-0.009 -0.115,-0.011 -0.092,-0.008 -0.175,-0.012 -0.229,-0.015 -0.114,-0.006 -0.239,-0.009 -0.359,-0.012 -0.247,-0.007 -0.577,-0.012 -0.973,-0.016 -0.797,-0.009 -1.929,-0.015 -3.339,-0.02 -2.825,-0.009 -6.806,-0.01 -11.552,-0.007 -9.476,0.007 -22.022,0.033 -34.545,0.06 h -0.071 c -12.549,0.027 -25.067,0.053 -34.452,0.059 -4.694,0.004 -8.597,0.002 -11.327,-0.007 -0.364,-0.002 -0.706,-0.003 -1.025,-0.004 -1.494,-4.388 -3.363,-8.515 -4.946,-11.701 -0.989,-1.991 -1.884,-3.6474 -2.534,-4.8119 -0.326,-0.5829 -0.591,-1.044 -0.778,-1.3639 -0.093,-0.16 -0.167,-0.2848 -0.219,-0.372 l -0.061,-0.1022 -0.018,-0.0294 -0.005,-0.0092 -0.002,-0.0032 -10e-4,-0.0013 c 0,-5e-4 -0.001,-0.001 -3.8332,2.3188 l 3.8322,-2.3198 c -1.243,-2.0539 -3.8841,-2.7627 -5.9886,-1.607 z"
stroke="#0000ff"
stroke-width="8.96"
stroke-linecap="round"
stroke-linejoin="round"
id="path1-3"
sodipodi:nodetypes="csccscccccccccccccsccccsccccccccscccccccccccccccccccsccccccccc"
style="stroke:#f2f2f2;stroke-opacity:1" /><path
d="M 44.9999,128.82 99.7778,98.7397 c 0,0 6.1412,10.1473 9.0922,20.5063 0.06,0.213 99.974,-0.211 100.842,0 0,0 2.968,0 2.968,9.246 0,9.245 -2.968,9.245 -2.968,9.245 -0.76,0.188 -100.609,-0.186 -100.66,0 -2.87,10.583 -9.2742,21.163 -9.2742,21.163 z"
fill="#00ff00"
id="path2-6"
style="fill:#666666;fill-opacity:1" /></g></g><defs
id="defs5"><filter
id="filter0_d_18_113"
x="58.7948"
y="28.784901"
width="135.694"
height="197.15401"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB"><feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood3" /><feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix3" /><feOffset
dy="7.68"
id="feOffset3" /><feGaussianBlur
stdDeviation="2.56"
id="feGaussianBlur3" /><feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"
id="feColorMatrix4" /><feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_18_113"
id="feBlend4" /><feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_18_113"
result="shape"
id="feBlend5" /></filter></defs></svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -0,0 +1,28 @@
# `debug_time_start`
#
# Starts debug timer
#
# @ESC
extends ESCBaseCommand
class_name DebugTimeStart
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new()
# Validate wether the given arguments match the command descriptor
func validate(arguments: Array):
return super.validate(arguments)
# Run the command
func run(command_params: Array) -> int:
gymkhana.start_time()
return ESCExecution.RC_OK
# Function called when the command is interrupted.
func interrupt():
# Do nothing
pass

View File

@@ -0,0 +1 @@
uid://cgcew1grem33l

View File

@@ -0,0 +1,28 @@
# `debug_time_stop`
#
# Stops debug timer and prints the elapsed time
#
# @ESC
extends ESCBaseCommand
class_name DebugTimeStop
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new()
# Validate wether the given arguments match the command descriptor
func validate(arguments: Array):
return super.validate(arguments)
# Run the command
func run(command_params: Array) -> int:
gymkhana.stop_time()
return ESCExecution.RC_OK
# Function called when the command is interrupted.
func interrupt():
# Do nothing
pass

View File

@@ -0,0 +1 @@
uid://q4ad3j5duwpa

View File

@@ -1,4 +1,4 @@
# `music_enable`
# `force_music`
#
# Enable music volume
#

View File

@@ -0,0 +1,29 @@
# `play_game_music`
#
# Enable music volume
#
# @ESC
extends ESCBaseCommand
class_name PlayGameMusic
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new()
# Validate wether the given arguments match the command descriptor
func validate(arguments: Array):
return super.validate(arguments)
# Run the command
func run(command_params: Array) -> int:
gymkhana.music_manager.play_game()
return ESCExecution.RC_OK
# Function called when the command is interrupted.
func interrupt():
# Do nothing
pass

View File

@@ -0,0 +1 @@
uid://djaltfgdliq57

View File

@@ -0,0 +1,28 @@
# `play_menu_music`
#
# Enable music volume
#
# @ESC
class_name PlayMenuMusic
extends ESCBaseCommand
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new()
# Validate wether the given arguments match the command descriptor
func validate(arguments: Array):
return super.validate(arguments)
# Run the command
func run(_command_params: Array) -> int:
gymkhana.music_manager.play_menu()
return ESCExecution.RC_OK
# Function called when the command is interrupted.
func interrupt():
# Do nothing
pass

View File

@@ -0,0 +1 @@
uid://fk5rxeuobhve

View File

@@ -0,0 +1,28 @@
# `play_palestina_music`
#
# Enable music volume
#
# @ESC
class_name PlayPalestinaMusic
extends ESCBaseCommand
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new()
# Validate wether the given arguments match the command descriptor
func validate(arguments: Array):
return super.validate(arguments)
# Run the command
func run(_command_params: Array) -> int:
gymkhana.music_manager.play_palestina()
return ESCExecution.RC_OK
# Function called when the command is interrupted.
func interrupt():
# Do nothing
pass

View File

@@ -0,0 +1 @@
uid://b843rkmac55l6

View File

@@ -0,0 +1,37 @@
# `play_selected_song`
#
# Enable music volume
#
# @ESC
extends ESCBaseCommand
class_name PlaySelectedSong
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new(
1,
[TYPE_INT],
[null]
)
# Validate wether the given arguments match the command descriptor
func validate(arguments: Array):
if arguments[0] == null:
return false
if gymkhana.music_manager.game_songs.size() <= arguments[0]:
return false
return super.validate(arguments)
# Run the command
func run(command_params: Array) -> int:
gymkhana.music_manager.select_song(command_params[0])
return ESCExecution.RC_OK
# Function called when the command is interrupted.
func interrupt():
# Do nothing
pass

View File

@@ -0,0 +1 @@
uid://b4yutd054fvb4

View File

@@ -35,8 +35,8 @@ func validate(arguments: Array):
# Run the command
func run(command_params: Array) -> int:
escoria.game_scene.play_video(command_params[0])
#We wait for the video to emit "finished" signal with yield
await escoria.game_scene.get_video_player().finished
gymkhana.video_manager.play_video(command_params[0])
#We wait for the video to emit "finished" signal
await gymkhana.video_manager.get_video_player().finished
escoria.game_scene.open_inventory()
return ESCExecution.RC_OK

View File

@@ -0,0 +1,34 @@
# `set_distance_to_music`
#
# Set audio filter resonance simulating distance to music
#
# @ESC
extends ESCBaseCommand
class_name SetDistanceToMusic
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new(
0,
[TYPE_INT, TYPE_FLOAT],
[0, 0.0]
)
# Validate wether the given arguments match the command descriptor
func validate(arguments: Array):
if gymkhana.music_manager.game_songs.size() <= arguments[0]:
return false
return super.validate(arguments)
# Run the command
func run(command_params: Array) -> int:
gymkhana.music_manager.set_distance_to_music(command_params[0], command_params[1])
return ESCExecution.RC_OK
# Function called when the command is interrupted.
func interrupt():
# Do nothing
pass

View File

@@ -0,0 +1 @@
uid://b6hle34ay06py

View File

@@ -0,0 +1,29 @@
# `show_language_selector`
#
# Enable music volume
#
# @ESC
extends ESCBaseCommand
class_name ShowLanguageSelector
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new()
# Validate wether the given arguments match the command descriptor
func validate(arguments: Array):
return super.validate(arguments)
# Run the command
func run(command_params: Array) -> int:
escoria.game_scene.show_language_selector()
return ESCExecution.RC_OK
# Function called when the command is interrupted.
func interrupt():
# Do nothing
pass

View File

@@ -0,0 +1 @@
uid://dckmj1sjltwnu

View File

@@ -0,0 +1,29 @@
# `start_time_tracker`
#
# Starts tracking game playing time.
#
# **Parameters**
#
# - *achievement_id*: Achievement id to unlock
#
# @ESC
extends ESCBaseCommand
class_name StartTimeTracker
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new(
0,
[]
)
# Validate whether the given arguments match the command descriptor
func validate(arguments: Array):
return super.validate(arguments)
# Run the command
func run(command_params: Array) -> int:
gymkhana.achievement_manager.start_tracking_time()
return ESCExecution.RC_OK

View File

@@ -0,0 +1 @@
uid://kf8mm5ay41y1

View File

@@ -0,0 +1,29 @@
# `start_time_tracker`
#
# Stops tracking game playing time.
#
# **Parameters**
#
# - *achievement_id*: Achievement id to unlock
#
# @ESC
extends ESCBaseCommand
class_name StopTimeTracker
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new(
0,
[]
)
# Validate whether the given arguments match the command descriptor
func validate(arguments: Array):
return super.validate(arguments)
# Run the command
func run(command_params: Array) -> int:
gymkhana.achievement_manager.stop_tracking_time()
return ESCExecution.RC_OK

View File

@@ -0,0 +1 @@
uid://daci1mgkkh4f8

View File

@@ -0,0 +1,40 @@
# `unlock_achivement achievement_id`
#
# Unlocks an achievement.
#
# **Parameters**
#
# - *achievement_id*: Achievement id to unlock
#
# @ESC
extends ESCBaseCommand
class_name UnlockAchievement
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new(
1,
[TYPE_STRING],
[""]
)
# Validate whether the given arguments match the command descriptor
func validate(arguments: Array):
if not super.validate(arguments):
return false
if not gymkhana.achievement_manager.has(arguments[0]):
escoria.logger.error(
self,
"[%s]: invalid parameter. Achievement %s not found."
% [get_command_name(), arguments[0]]
)
return false
return true
# Run the command
func run(command_params: Array) -> int:
gymkhana.achievement_manager.unlock_achievement(command_params[0])
return ESCExecution.RC_OK

View File

@@ -0,0 +1 @@
uid://be74n0jultsq8

View File

@@ -335,7 +335,7 @@ func _set_tool_and_action(obj: ESCObject, default_action: bool):
if current_action and current_tool:
# MODIFIED FOR RETURN TO MONKEY UI
if (not current_action in escoria.action_manager \
.current_tool.node.combine_when_selected_action_is_in and not current_action in obj.node.target_when_selected_action_is_in):
.current_tool.node.combine_when_selected_action_is_in and not is_target_for_tool(current_tool.node, obj.node, current_action)):
current_tool = obj
tool_just_set = true
elif default_action:
@@ -349,6 +349,18 @@ func _set_tool_and_action(obj: ESCObject, default_action: bool):
return tool_just_set
func is_target_for_tool(tool: ESCItem, target: ESCItem, action: String):
var target_tooltips = target.custom_data.get("target_tooltips")
if target_tooltips == null:
return false
var action_target_tooltips = target_tooltips.get(action)
if action_target_tooltips == null:
return false
return tool.global_id in action_target_tooltips
# Checks if object requires a combination with another, according to
# currently selected action verb (or check with default action of the item).
#
@@ -359,7 +371,7 @@ func _check_item_needs_combine_obj(obj: ESCObject) -> bool:
and current_tool \
and (current_action in current_tool.node.combine_when_selected_action_is_in
# MODIFIED FOR RETURN TO MONKEY UI
or current_action in obj.node.target_when_selected_action_is_in)
or is_target_for_tool(current_tool.node, obj.node, current_action))
func has_actions(current_target_object):
@@ -369,21 +381,27 @@ func has_actions(current_target_object):
var item_in_inventory = escoria.inventory_manager.inventory_has(current_target_object.global_id)
var waiting_for_target_item = escoria.action_manager.action_state == ESCActionManager.ACTION_INPUT_STATE.AWAITING_TARGET_ITEM
var action1_text = get_action_target_text(current_target_object.action3_target_texts) if waiting_for_target_item else get_tooltip_from_current_target("action3",current_target_object) if item_in_inventory else get_tooltip_from_current_target("action1",current_target_object)
var action1_text = gymkhana.tooltip_manager.get_target_tooltip(current_target_object, "action3") if waiting_for_target_item else get_tooltip_from_current_target("action3",current_target_object) if item_in_inventory else get_tooltip_from_current_target("action1",current_target_object)
if(action1_text != ""):
return true
var action2_text = get_action_target_text(current_target_object.action4_target_texts) if waiting_for_target_item else get_tooltip_from_current_target("action4",current_target_object) if item_in_inventory else get_tooltip_from_current_target("action2",current_target_object)
var action2_text = gymkhana.tooltip_manager.get_target_tooltip(current_target_object, "action4") if waiting_for_target_item else get_tooltip_from_current_target("action4",current_target_object) if item_in_inventory else get_tooltip_from_current_target("action2",current_target_object)
if(action2_text != ""):
return true
return false
func get_tooltip_from_current_target(verb,current_target_object):
return gymkhana.tooltip_manager.getTooltip(current_target_object.global_id, verb)
func get_action_target_text(action_target_texts: Dictionary):
var action_target_text = action_target_texts.get(escoria.action_manager.current_tool.global_id)
return action_target_text if action_target_text else ""
func _telekinetic_applies_to(event: ESCGrammarStmts.Event) -> bool:
return super(event) if event != null else false
# MODIFIED FOR RETURN TO MONKEY UI
## Sets the current state of action input.[br]
## [br]
## #### Parameters[br]
## [br]
## - p_state: the action input state to set.
func set_action_input_state(p_state) -> void:
action_state = p_state
action_input_state_changed.emit(p_state)

View File

@@ -17,3 +17,15 @@ func getTooltip(global_id, verb):
if(tooltips.has(verb)):
return tooltips.get(verb)
return ""
func get_target_tooltip(target: ESCItem, action: String):
var target_tooltips = target.custom_data.get("target_tooltips")
if target_tooltips == null:
return ""
var action_target_tooltips = target_tooltips.get(action)
if action_target_tooltips == null:
return ""
var action_target_tooltip = action_target_tooltips.get(escoria.action_manager.current_tool.global_id)
return action_target_tooltip if action_target_tooltip else ""

View File

@@ -1,35 +1,37 @@
@tool
@icon("res://addons/escoria-core/design/esc_item.svg")
extends ESCItem
class_name ESCItemWithTooltip
extends ESCItem
## Action 3 tooltip texts if item is target. Dictionary with tool's global id as key.
@export var action3_target_texts: Dictionary = {}
## Action 4 tooltip texts if item is target. Dictionary with tool's global id as key
@export var action4_target_texts: Dictionary = {}
## If action used by player is in this list, this is a valid target (second item in combination)
@export var target_when_selected_action_is_in: Array = []
# custom_data["target_tooltips"]: Dictionary[String, Dictionary]
# Tooltip texts if item is target. Dictionary with action as key ("action3" or "action4") and an inner dictionary as value.
# The inner dictionary has tool's global id as key and the tooltip text (usually the translation id) as value.
## Enables automatic ESCItemComponetPickedObserver loading.
@export var with_is_picked_component = false
## Custom cursor
@export var custom_cursor: String = ""
## ESCItemComponents children of this node
var components: Dictionary = {}
var cursor: String:
get:
return custom_cursor if custom_cursor != "" else "hand"
func _ready():
super._ready()
register_components()
func has_component(key: String)->bool:
func has_component(key: String) -> bool:
return components.has(key)
func get_component(key: String):
if(has_component(key)):
if has_component(key):
return components[key]
return null
@@ -37,7 +39,7 @@ func get_component(key: String):
func register_components():
autoload_components()
for child in get_children():
if(child is ESCItemComponent):
if child is ESCItemComponent:
child = child as ESCItemComponent
components[child.get_component_type()] = child
child.register(custom_data)
@@ -45,22 +47,23 @@ func register_components():
func autoload_components():
add_child(ESCItemComponentOutline.new())
# Adds picked observer when configured.
if with_is_picked_component:
add_child(ESCItemComponentPickedObserver.new())
func set_custom_data(data: Dictionary) -> void:
super.set_custom_data(data)
if custom_data.has("count"):
ESCItemCountManager.new().update_sprite(self)
func _get_inventory_texture_hovered() -> Texture2D:
if custom_data.has("count"):
return inventory_texture
elif inventory_texture_hovered == null:
if inventory_texture_hovered == null:
return _get_inventory_texture()
else:
return inventory_texture_hovered
return inventory_texture_hovered

View File

@@ -1,18 +1,5 @@
extends ESCGame
class_name RMTIGame
# Left mouse button on item
const ACTION1 = "action1"
# Right mouse button on item
const ACTION2 = "action2"
# Left mouse button on inventory item
const ACTION3 = "action3"
# Right mouse button on inventory item
const ACTION4 = "action4"
const VERB_USE = "use"
const VERB_WALK = "walk"
extends ESCGame
"""
Implement methods to react to inputs.
@@ -51,53 +38,144 @@ Implement methods to react to inputs.
- _on_event_done(event_name: String)
"""
# Left mouse button on item
const ACTION1 = "action1"
# Right mouse button on item
const ACTION2 = "action2"
# Left mouse button on inventory item
const ACTION3 = "action3"
# Right mouse button on inventory item
const ACTION4 = "action4"
const VERB_USE = "use"
const VERB_WALK = "walk"
# Input action for use by InputMap
const ESC_UI_CHANGE_VERB_ACTION = "esc_change_verb"
# Tracks the mouse's current position onscreen.
var _current_mouse_pos = Vector2.ZERO
var last_target: Object
@export var inventory_ui: ESCInventory
@export var rtmi_tooltip_node: RTMIRichTooltip
@export var dev_tools_node: Control
@export var video_player: RTMIVideoPlayer
@export var language_selector: RTMILanguageSelector
@export var confetti: RTMIConfetti
# Tracks the mouse's current position onscreen.
var _current_mouse_pos = Vector2.ZERO
func _init():
gymkhana.item_count_manager = ESCItemCountManager.new()
gymkhana.tooltip_manager = ESCTootltipManager.new()
gymkhana.global_observer = RTMIGlobalObserver.new()
escoria.di = RTMIDependencyInjector.new()
if ProjectSettings.get_setting( RTMIUiSettings.DEBUG_ENABLED):
gymkhana.dev_tools_registry.register(preload("res://addons/escoria-ui-return-monkey-island/tools/dev/room_objects.tscn").instantiate())
gymkhana.dev_tools_registry.register(preload("res://addons/escoria-ui-return-monkey-island/tools/dev/global_inspector.tscn").instantiate())
gymkhana.dev_tools_registry.register(preload("res://addons/escoria-ui-return-monkey-island/tools/dev/globals_watcher.tscn").instantiate())
# Overrides for ashes cache.
escoria.room_manager = RTMIRoomManager.new()
escoria.esc_compiler = RTMICompiler.new()
# Cache warmer
gymkhana.warm_esc_cache()
# Override for ashes interpreter, fixes global lookup.
escoria.interpreter_factory = (
preload("res://addons/escoria-ui-return-monkey-island/overrides/esc_interpreter_factory.gd")
. new()
)
if ProjectSettings.get_setting(RTMIUiSettings.DEBUG_ENABLED):
gymkhana.dev_tools_registry.register(
(
preload("res://addons/escoria-ui-return-monkey-island/tools/dev/room_objects.tscn")
. instantiate()
)
)
gymkhana.dev_tools_registry.register(
(
preload(
"res://addons/escoria-ui-return-monkey-island/tools/dev/global_inspector.tscn"
)
. instantiate()
)
)
gymkhana.dev_tools_registry.register(
(
preload(
"res://addons/escoria-ui-return-monkey-island/tools/dev/globals_watcher.tscn"
)
. instantiate()
)
)
gymkhana.dev_tools_registry.register(
(
preload("res://addons/escoria-ui-return-monkey-island/tools/dev/hover_stack.tscn")
. instantiate()
)
)
gymkhana.dev_tools_registry.register(
(
preload(
"res://addons/escoria-ui-return-monkey-island/tools/dev/current_target.tscn"
)
. instantiate()
)
)
(
gymkhana
. dev_tools_registry
. register(
(
preload(
"res://addons/escoria-ui-return-monkey-island/achievements/rtmi_achievements_dev_tool.tscn"
)
. instantiate()
)
)
)
func _ready():
# Must call after video player child is ready.
gymkhana.video_manager = RTMIVideoManager.new(video_player)
# Must call after escoria music player child is ready.
var esc_music_player = escoria.object_manager.get_object("_music").node
gymkhana.music_manager.esc_music_player = esc_music_player
gymkhana.score_manager = RTMIScoreManager.new(get_node(pause_menu))
tooltip_node = rtmi_tooltip_node
# We need a slightly modified version of Action Manager to combine items with different actions.
escoria.action_manager = ESCActionManagerMonkey.new()
# We need to connect inside the scene_tree. Cursor manager is in the singelton.
escoria.inputs_manager.input_mode_changed.connect(_on_input_mode_changed)
#escoria.di = RTMIDependencyInjector.new()
if tooltip_node.connect("tooltip_size_updated", Callable(self, "update_tooltip_following_mouse_position").bind(tooltip_node)) != 0:
escoria.logger.error(self, "Error connecting tooltip_size_updated with update_tooltip_following_mouse_position")
# Show inventory when video player finishes playing a video (inventory is hidden when a video starts)
get_video_player().connect("finished", Callable(self, "show_ui"))
if (
tooltip_node.connect(
"tooltip_size_updated",
Callable(self, "update_tooltip_following_mouse_position").bind(tooltip_node)
)
!= 0
):
escoria.logger.error(
self,
"Error connecting tooltip_size_updated with update_tooltip_following_mouse_position"
)
escoria.dialog_player.connect("say_finished", _on_say_finished)
func _enter_tree():
# We get current day and month
var time = Time.get_datetime_dict_from_system()
var day = time["day"]
var month = time["month"]
escoria.globals_manager.set_global('zorionak_eneko', day == 8 and month == 2)
escoria.globals_manager.set_global("zorionak_eneko", day == 8 and month == 2)
func _exit_tree():
escoria.inputs_manager.register_custom_input_handler(null)
@@ -106,36 +184,42 @@ func _exit_tree():
func toggle_room_selector_visibility():
var room_selector_parent = dev_tools_node
var room_selector = room_selector_parent.get_node_or_null("room_select")
if(room_selector != null):
if room_selector != null:
room_selector.visible = !room_selector.visible
func _input(event: InputEvent) -> void:
if escoria.inputs_manager.input_mode == escoria.inputs_manager.INPUT_NONE:
return
if event.is_action_pressed("ui_cancel") && escoria.current_state == escoria.GAME_STATE.DEFAULT:
request_pause_menu.emit()
if event is InputEventMouseMotion:
_current_mouse_pos = get_viewport().get_mouse_position()
update_tooltip_following_mouse_position(tooltip_node)
if event.is_action_pressed("ui_dev_tools"):
dev_tools_node.visible = !dev_tools_node.visible
if event.is_action("ui_show_hints"):
gymkhana.is_hint_active = event.pressed
update_highlights()
## BACKGROUND ##
func click_on_bg(position: Vector2) -> void:
var current_state = escoria.action_manager.action_state
if escoria.action_manager.action_state == ESCActionManager.ACTION_INPUT_STATE.AWAITING_VERB_OR_ITEM:
if (
escoria.action_manager.action_state
== ESCActionManager.ACTION_INPUT_STATE.AWAITING_VERB_OR_ITEM
):
gymkhana.cursor_manager.clear_cursor()
# If we are using an inventory item reset mouse cursor and cancel action
if escoria.action_manager.action_state == ESCActionManager.ACTION_INPUT_STATE.AWAITING_TARGET_ITEM:
gymkhana.cursor_manager.clear_cursor()
if (
escoria.action_manager.action_state
== ESCActionManager.ACTION_INPUT_STATE.AWAITING_TARGET_ITEM
):
escoria.action_manager.clear_current_tool()
gymkhana.cursor_manager.clear_cursor()
if escoria.main.current_scene.player:
escoria.action_manager.do(
@@ -143,13 +227,17 @@ func click_on_bg(position: Vector2) -> void:
[escoria.main.current_scene.player.global_id, position],
true
)
update_highlights()
func left_click_on_bg(position: Vector2) -> void:
click_on_bg(position)
func right_click_on_bg(position: Vector2) -> void:
click_on_bg(position)
func left_double_click_on_bg(position: Vector2) -> void:
if escoria.main.current_scene.player:
escoria.action_manager.do(
@@ -157,115 +245,160 @@ func left_double_click_on_bg(position: Vector2) -> void:
[escoria.main.current_scene.player.global_id, position, true],
true
)
update_highlights()
func mousewheel_action(direction: int) -> void:
#var container = get_node(inventory_ui.inventory_ui_container) as RTMIInventoryContainer
inventory_ui.handle_mouse_wheel(direction)
## ITEM/HOTSPOT FOCUS ##
func element_focused(element_id: String) -> void:
if escoria.current_state != escoria.GAME_STATE.DEFAULT:
return
if not _is_input_all():
return
var target_obj = escoria.object_manager.get_object(element_id).node
if target_obj is ESCItem or ESCItemWithTooltip:
tooltip_node.set_target(target_obj.tooltip_name)
tooltip_node.set_target_object(target_obj)
if is_instance_valid(last_target):
last_target.get_component('outline').highlight(false)
if escoria.action_manager.has_actions(target_obj):
if target_obj is ESCItemWithTooltip:
target_obj.get_component('outline').highlight(true)
last_target = target_obj
if target_obj.is_interactive:
gymkhana.cursor_manager.handle_item_cursor(target_obj)
update_highlights()
func element_unfocused() -> void:
if not _is_input_all():
return
gymkhana.cursor_manager.clear_cursor()
tooltip_node.set_target("")
tooltip_node.set_target_object(null)
if(last_target != null):
last_target.get_component('outline').highlight(false)
last_target = null
update_highlights()
## ITEMS ##
func click_on_item(item_global_id: String, event: InputEvent, action: String) -> void:
# If we are using an inventory item reset mouse cursor and use inventory actions (change action1 for action3 and action2 for action4)
if escoria.action_manager.action_state == ESCActionManager.ACTION_INPUT_STATE.AWAITING_TARGET_ITEM:
if (
escoria.action_manager.action_state
== ESCActionManager.ACTION_INPUT_STATE.AWAITING_TARGET_ITEM
):
gymkhana.cursor_manager.clear_cursor()
action = ACTION3 if action == ACTION1 else ACTION4
# Ensure that the targeted object has an event + tool
if !_item_has_event_and_target(item_global_id, action):
# Clear action manager variables
escoria.action_manager.clear_current_action()
escoria.action_manager.clear_current_tool()
# Interrupt current action
escoria.event_manager.interrupt([], false)
# Manually focus to update tooltips
element_focused(item_global_id)
return
escoria.action_manager.set_current_action(action)
escoria.action_manager.do(
escoria.action_manager.ACTION.ITEM_LEFT_CLICK,
[item_global_id, event],
true
escoria.action_manager.ACTION.ITEM_LEFT_CLICK, [item_global_id, event], true
)
func left_click_on_item(item_global_id: String, event: InputEvent) -> void:
click_on_item(item_global_id, event, ACTION1)
func right_click_on_item(item_global_id: String, event: InputEvent) -> void:
click_on_item(item_global_id, event, ACTION2)
func left_double_click_on_item(item_global_id: String, event: InputEvent) -> void:
escoria.action_manager.do(
escoria.action_manager.ACTION.ITEM_LEFT_CLICK,
[item_global_id, event],
true
escoria.action_manager.ACTION.ITEM_LEFT_CLICK, [item_global_id, event], true
)
## INVENTORY ##
func click_on_inventory_item(item_global_id: String, event: InputEvent, action: String) -> void:
if not _is_input_all():
return
# Skip inventory clicks when eneko_catando
if _check_eneko_catando():
return
clear_highlights()
# If we are using an inventory item reset mouse cursor
if escoria.action_manager.action_state == null:
gymkhana.cursor_manager.clear_cursor()
if escoria.action_manager.action_state == ESCActionManager.ACTION_INPUT_STATE.AWAITING_TARGET_ITEM:
if (
escoria.action_manager.action_state
== ESCActionManager.ACTION_INPUT_STATE.AWAITING_TARGET_ITEM
):
gymkhana.cursor_manager.clear_cursor()
escoria.action_manager.set_current_action(action)
var target_obj = escoria.object_manager.get_object(item_global_id).node
# If item needs combination with this action, use the item texture as mouse cursor
if action in target_obj.combine_when_selected_action_is_in:
var texture = target_obj.inventory_texture
gymkhana.cursor_manager.set_cursor(texture)
if (
action in target_obj.combine_when_selected_action_is_in
and escoria.action_manager.current_tool == null
):
gymkhana.cursor_manager.set_texture_cursor(target_obj.inventory_texture)
escoria.action_manager.do(
escoria.action_manager.ACTION.ITEM_LEFT_CLICK,
[item_global_id, event],
true
escoria.action_manager.ACTION.ITEM_LEFT_CLICK, [item_global_id, event], true
)
update_highlights()
# Hide tooltip if some action is being performed
# Disabled: leaves the tooltips hidden. ToDo: check if has other implications.
#if escoria.action_manager.action_state == ESCActionManager.ACTION_INPUT_STATE.COMPLETED:
# $tooltip_layer/tooltip.setHidden()
func left_click_on_inventory_item(inventory_item_global_id: String, event: InputEvent) -> void:
click_on_inventory_item(inventory_item_global_id, event, ACTION3)
func right_click_on_inventory_item(inventory_item_global_id: String, event: InputEvent) -> void:
click_on_inventory_item(inventory_item_global_id, event, ACTION4)
func inventory_item_focused(inventory_item_global_id: String) -> void:
var target_obj = escoria.object_manager.get_object(inventory_item_global_id).node
if target_obj is ESCItemWithTooltip:
tooltip_node.set_target_object(target_obj)
func inventory_item_unfocused() -> void:
element_unfocused()
func open_inventory():
pass
func close_inventory():
pass
func hide_tooltips():
$game_layer/tooltip_layer.hide()
func show_tooltips():
$game_layer/tooltip_layer.show()
@@ -275,20 +408,21 @@ func hide_ui():
$game_layer/dialog_layer.hide()
$game_layer/tooltip_layer.hide()
func show_ui():
if escoria.room_manager.GLOBAL_CURRENT_SCENE != "turno_cocina_creditos":
if not _in_credits_room():
$game_layer/ui_layer.show()
$game_layer/dialog_layer.show()
$game_layer/tooltip_layer.show()
func hide_main_menu():
escoria.current_state = escoria.GAME_STATE.DEFAULT
if get_node(main_menu).visible:
get_node(main_menu).hide()
show_ui()
func show_main_menu():
if escoria.current_state == escoria.GAME_STATE.PAUSED:
return
@@ -299,6 +433,7 @@ func show_main_menu():
get_node(main_menu).show()
hide_ui()
func unpause_game():
escoria.current_state = escoria.GAME_STATE.DEFAULT
if get_node(pause_menu).visible:
@@ -307,13 +442,16 @@ func unpause_game():
escoria.main.current_scene.game.show_ui()
escoria.main.current_scene.show()
escoria.set_game_paused(false)
gymkhana.music_manager.play_game()
gymkhana.music_manager.resume()
gymkhana.achievement_manager.resume_tracking_time()
func pause_game():
if escoria.current_state == escoria.GAME_STATE.PAUSED:
return
if get_video_player().is_playing():
get_video_player().skip()
if gymkhana.video_manager.is_playing:
gymkhana.video_manager.skip()
return
if not get_node(pause_menu).visible and not get_node(main_menu).visible:
escoria.current_state = escoria.GAME_STATE.PAUSED
@@ -325,51 +463,77 @@ func pause_game():
escoria.main.current_scene.game.hide_ui()
escoria.main.current_scene.hide()
escoria.set_game_paused(true)
gymkhana.music_manager.play_menu()
gymkhana.music_manager.play_menu(false)
gymkhana.achievement_manager.pause_tracking_time()
func get_custom_data() -> Dictionary:
return {
"ui_type": "rtmi-ui"
}
return {"ui_type": "rtmi-ui"}
func apply_custom_settings(custom_settings: Dictionary):
if custom_settings.has(RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY_KEY):
escoria.logger.info(
self,
"Custom setting value loaded CLEAR_TEXT_BY_CLICK_ONLY: %s."
% str(custom_settings[RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY_KEY])
(
"Custom setting value loaded CLEAR_TEXT_BY_CLICK_ONLY: %s."
% str(custom_settings[RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY_KEY])
)
)
escoria.settings_manager.set(
RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY,
custom_settings[RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY_KEY]
)
escoria.settings_manager.set(RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY, custom_settings[RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY_KEY] )
if custom_settings.has(RTMISimpleDialogSettings.SLOW_TEXT_MODE_KEY):
escoria.logger.info(
self,
(
"Custom setting value loaded SLOW_TEXT_MODE: %s."
% str(custom_settings[RTMISimpleDialogSettings.SLOW_TEXT_MODE_KEY])
)
)
escoria.settings_manager.set(
RTMISimpleDialogSettings.SLOW_TEXT_MODE,
custom_settings[RTMISimpleDialogSettings.SLOW_TEXT_MODE_KEY]
)
# Update the tooltip position
func update_tooltip_following_mouse_position(tooltip: RTMIRichTooltip):
if tooltip == null:
return
if(escoria.action_manager.current_tool == null):
set_tooltip_position("tooltip1", tooltip, tooltip.get_tooltip1_size(), tooltip.offset_from_cursor_action1)
set_tooltip_position("tooltip2", tooltip, tooltip.get_tooltip2_size(), tooltip.offset_from_cursor_action2)
if escoria.action_manager.current_tool == null:
set_tooltip_position(
"tooltip1", tooltip, tooltip.get_tooltip1_size(), tooltip.offset_from_cursor_action1
)
set_tooltip_position(
"tooltip2", tooltip, tooltip.get_tooltip2_size(), tooltip.offset_from_cursor_action2
)
return
set_tooltip_position("tooltip1", tooltip, tooltip.get_tooltip1_size(), tooltip.offset_from_cursor_action3)
set_tooltip_position("tooltip2", tooltip, tooltip.get_tooltip2_size(), tooltip.offset_from_cursor_action4)
set_tooltip_position(
"tooltip1", tooltip, tooltip.get_tooltip1_size(), tooltip.offset_from_cursor_action3
)
set_tooltip_position(
"tooltip2", tooltip, tooltip.get_tooltip2_size(), tooltip.offset_from_cursor_action4
)
func set_tooltip_position(nodeId: String, tooltip: RTMIRichTooltip, size: Vector2, offset: Vector2):
var mouse_position = calculateMousePosition(size)
var corrected_position = correctPosition(tooltip, size, mouse_position, offset)
tooltip.get_node(nodeId).position = corrected_position
func set_tooltip_position(
node_id: String, tooltip: RTMIRichTooltip, size: Vector2, offset: Vector2
):
var mouse_position = calculate_mouse_position(size)
var corrected_position = correct_position(tooltip, size, mouse_position, offset)
tooltip.get_node(node_id).position = corrected_position
func calculateMousePosition(size: Vector2):
size.x / 2
size.y / 2
func calculate_mouse_position(_size: Vector2):
return _current_mouse_pos
func correctPosition(tooltip: RTMIRichTooltip, size: Vector2, mouse_position: Vector2, offset: Vector2):
func correct_position(
tooltip: RTMIRichTooltip, size: Vector2, mouse_position: Vector2, offset: Vector2
):
# clamp TOP
if tooltip.tooltip_distance_to_edge_top(_current_mouse_pos) <= mouse_tooltip_margin:
mouse_position.y = mouse_tooltip_margin
@@ -379,37 +543,30 @@ func correctPosition(tooltip: RTMIRichTooltip, size: Vector2, mouse_position: Ve
mouse_position.y = escoria.game_size.y - mouse_tooltip_margin - size.y
# clamp LEFT
if tooltip.tooltip_distance_to_edge_left(_current_mouse_pos - size/2) <= mouse_tooltip_margin:
if tooltip.tooltip_distance_to_edge_left(_current_mouse_pos - size / 2) <= mouse_tooltip_margin:
mouse_position.x = mouse_tooltip_margin
# clamp RIGHT
if tooltip.tooltip_distance_to_edge_right(_current_mouse_pos + size/2) <= mouse_tooltip_margin:
if (
tooltip.tooltip_distance_to_edge_right(_current_mouse_pos + size / 2)
<= mouse_tooltip_margin
):
mouse_position.x = escoria.game_size.x - mouse_tooltip_margin - size.x
return mouse_position - offset
func _on_event_done(return_code: int, _event_name: String):
escoria.logger.info(self, "EVENT DONE! code= %s" % [return_code])
# Reset mouse cursor (should be not needed, but avoids not resetting the cursor on bugs)
Input.set_custom_mouse_cursor(null)
# Show tooltips, they were hidden while performing action
tooltip_node.show()
update_highlights()
func _on_MenuButton_pressed() -> void:
pause_game()
func get_video_player() -> Node:
return $menu_layer/video_player
func play_video(video_file: String) -> void:
hide_ui()
clear_tooltip()
get_video_player().visible = true
get_video_player().play(video_file)
# Clears the tooltip content (if an ESCTooltip node exists in UI)
# MODIFIED FOR RTMIUI
@@ -417,8 +574,99 @@ func clear_tooltip():
if tooltip_node != null:
(tooltip_node as RTMIRichTooltip).clear()
func _on_MusicButton_pressed():
gymkhana.music_manager.toggle()
# MODIFIED FOR RTMIUI
func _on_say_finished() -> void:
show_tooltips()
var current_target_object = tooltip_node.current_target_object
if tooltip_node.current_target_object != null:
var button: RTMIInventoryButton = (
inventory_ui
. get_node(inventory_ui.inventory_ui_container)
. get_inventory_button_by_id(current_target_object.global_id)
)
if button != null:
await get_tree().create_timer(0.01).timeout # Delay a bit so state adjust, needed for tooltip
button._on_inventory_item_mouse_enter()
_current_mouse_pos = get_viewport().get_mouse_position()
update_tooltip_following_mouse_position(tooltip_node)
# If mouse cursor is above an item execute mouse_entered() on it.
var physics2d_dss: PhysicsDirectSpaceState2D = get_world_2d().direct_space_state
var params := PhysicsPointQueryParameters2D.new()
params.position = escoria.main.current_scene.game.get_global_mouse_position()
params.collision_mask = 0x7FFFFFFF
params.collide_with_areas = true
var colliding: Array = physics2d_dss.intersect_point(params)
var colliding_nodes = []
for c in colliding:
if c.collider is ESCItemWithTooltip:
await get_tree().create_timer(0.01).timeout # Delay a bit so state adjust, needed for tooltip
c.collider.mouse_entered()
_current_mouse_pos = get_viewport().get_mouse_position()
update_tooltip_following_mouse_position(tooltip_node)
await get_tree().create_timer(0.01).timeout
update_highlights()
func _is_input_all():
return escoria.inputs_manager.input_mode == ESCInputsManager.INPUT_ALL
func _check_eneko_catando() -> bool:
if escoria.globals_manager.has("cocina_delante_catando"):
return escoria.globals_manager.get_global("cocina_delante_catando")
return false
func _in_credits_room() -> bool:
return escoria.object_manager.current_room_key.room_global_id == "turno_cocina_creditos"
func show_language_selector() -> void:
language_selector.show()
func show_highscores() -> void:
%highscores.show()
%highscores.refresh()
func _item_has_event_and_target(item_global_id: String, action: String) -> bool:
var target_object = escoria.object_manager.get_object(item_global_id)
var event_name: String = action
if escoria.action_manager.current_tool != null:
event_name += " %s" % escoria.action_manager.current_tool.global_id
return target_object.events.has(event_name)
func _on_input_mode_changed(new_mode):
gymkhana.cursor_manager.handle_input_mode_change(new_mode)
update_highlights()
func clear_highlights():
for child in escoria.main.get_children():
if child is ESCRoom:
for room_child in child.get_children():
if room_child is ESCItemWithTooltip:
room_child.get_component("outline").highlight(false)
func update_highlights():
for child in inventory_ui.get_node(inventory_ui.inventory_ui_container).get_children():
child.update_highlight()
for child in escoria.main.get_children():
if child is ESCRoom:
for room_child in child.get_children():
if room_child is ESCItemWithTooltip:
room_child.get_component("outline").update_highlight()
func launch_confetti():
confetti.launch()

View File

@@ -1,11 +1,12 @@
[gd_scene load_steps=24 format=3 uid="uid://cabos3cse6b71"]
[gd_scene load_steps=32 format=3 uid="uid://cabos3cse6b71"]
[ext_resource type="PackedScene" uid="uid://bl50queikqfjc" path="res://addons/escoria-ui-return-monkey-island/inventory/inventory_ui.tscn" id="1"]
[ext_resource type="Script" uid="uid://dfl7khtlretr7" path="res://addons/escoria-core/game/scenes/dialogs/esc_dialog_player.gd" id="2"]
[ext_resource type="Script" path="res://addons/escoria-core/game/scenes/dialogs/esc_dialog_player.gd" id="2"]
[ext_resource type="Script" uid="uid://cyg3662v0vtcl" path="res://addons/escoria-ui-return-monkey-island/shaders/black_and_white_shader.gd" id="2_o34rc"]
[ext_resource type="Shader" uid="uid://bgopfs5nlgkcu" path="res://addons/escoria-ui-return-monkey-island/shaders/black_and_white.gdshader" id="2_ssxmx"]
[ext_resource type="PackedScene" uid="uid://dmw5gicuenj53" path="res://addons/escoria-core/game/scenes/camera_player/camera.tscn" id="3"]
[ext_resource type="PackedScene" uid="uid://d2kogebvoxy51" path="res://addons/escoria-ui-return-monkey-island/rtmi_rich_tooltip.tscn" id="4"]
[ext_resource type="PackedScene" uid="uid://c7mjom1gqkjwv" path="res://addons/escoria-ui-return-monkey-island/ui/confetti.tscn" id="4_ixq7a"]
[ext_resource type="Script" uid="uid://lkc4isk3g0rj" path="res://addons/escoria-ui-return-monkey-island/game.gd" id="5"]
[ext_resource type="Texture2D" uid="uid://ce2rx8nm1s6gh" path="res://addons/escoria-ui-return-monkey-island/icons/music-double-note.svg" id="6"]
[ext_resource type="PackedScene" uid="uid://d3wdxi18u52c5" path="res://addons/escoria-ui-return-monkey-island/menus/main_menu/main_menu.tscn" id="7"]
@@ -13,14 +14,21 @@
[ext_resource type="PackedScene" uid="uid://dl7w8oqk1rmhw" path="res://addons/escoria-ui-return-monkey-island/menus/pause_menu/pause_menu.tscn" id="8"]
[ext_resource type="Theme" uid="uid://bf2eet52fueam" path="res://addons/escoria-ui-return-monkey-island/theme/ui.tres" id="9"]
[ext_resource type="PackedScene" uid="uid://ctg3fukoficqk" path="res://addons/escoria-ui-return-monkey-island/video_player/video_player.tscn" id="12"]
[ext_resource type="Texture2D" uid="uid://cy3eeo64v6ddw" path="res://addons/escoria-ui-return-monkey-island/icons/fullscreen_hover.svg" id="12_te176"]
[ext_resource type="Texture2D" uid="uid://dghklsdy5nmcg" path="res://addons/escoria-ui-return-monkey-island/icons/music-double-note-hover.svg" id="13"]
[ext_resource type="Script" uid="uid://do70qpvafu5my" path="res://addons/escoria-ui-return-monkey-island/ui/full_screen_button.gd" id="13_6rlck"]
[ext_resource type="Texture2D" uid="uid://b35fk7ltvp1hc" path="res://addons/escoria-ui-return-monkey-island/icons/menu.svg" id="13_we0hb"]
[ext_resource type="Script" uid="uid://chas0xyx88njl" path="res://addons/escoria-ui-return-monkey-island/buttons/music_button.gd" id="14"]
[ext_resource type="Texture2D" uid="uid://d0fbiaksfmg7j" path="res://addons/escoria-ui-return-monkey-island/icons/exit_fullscreen.svg" id="14_c6byj"]
[ext_resource type="Texture2D" uid="uid://c6hw4fs6aoydo" path="res://addons/escoria-ui-return-monkey-island/icons/menu_hover.svg" id="14_parhr"]
[ext_resource type="Texture2D" uid="uid://d2sehci16hioi" path="res://addons/escoria-ui-return-monkey-island/icons/music-double-note-hover-disabled.svg" id="15"]
[ext_resource type="Texture2D" uid="uid://y2hfekr163su" path="res://addons/escoria-ui-return-monkey-island/icons/exit_fullscreen_hover.svg" id="15_j7gr8"]
[ext_resource type="Texture2D" uid="uid://e2xk0aimdte" path="res://addons/escoria-ui-return-monkey-island/icons/music-double-note-disabled.svg" id="16"]
[ext_resource type="Texture2D" uid="uid://nsthsaybnd71" path="res://addons/escoria-ui-return-monkey-island/icons/fullscreen.svg" id="18_ixq7a"]
[ext_resource type="PackedScene" uid="uid://d3kgkl2r5xe4d" path="res://addons/escoria-ui-return-monkey-island/achievements/rtmi_achievement_notification_container.tscn" id="18_ssxmx"]
[ext_resource type="PackedScene" uid="uid://c0066wpl3qky4" path="res://addons/escoria-ui-return-monkey-island/menus/language_selector/language_selector.tscn" id="19_we0hb"]
[ext_resource type="Shader" uid="uid://iehp1eakxyak" path="res://addons/escoria-ui-return-monkey-island/shaders/vignette.gdshader" id="20_parhr"]
[ext_resource type="PackedScene" uid="uid://cqgluci3f3v3n" path="res://addons/escoria-ui-return-monkey-island/achievements/scoreboard/rtmi_scoreboard.tscn" id="23_p0ek8"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_p0ek8"]
shader = ExtResource("2_ssxmx")
@@ -33,15 +41,19 @@ shader_parameter/vignette_strength = 0.9
shader_parameter/dither_strength = 0.03
shader_parameter/vignette_color = Color(0, 0, 0, 1)
[node name="game" type="Node2D" node_paths=PackedStringArray("inventory_ui", "rtmi_tooltip_node", "dev_tools_node")]
[node name="game" type="Node2D" node_paths=PackedStringArray("inventory_ui", "rtmi_tooltip_node", "dev_tools_node", "video_player", "language_selector", "confetti")]
script = ExtResource("5")
inventory_ui = NodePath("game_layer/ui_layer/Inventory")
rtmi_tooltip_node = NodePath("game_layer/tooltip_layer/tooltip")
dev_tools_node = NodePath("game_layer/ui_layer/DevTools")
video_player = NodePath("menu_layer/video_player")
language_selector = NodePath("menu_layer/language_selector")
confetti = NodePath("CanvasLayer/Confetti")
main_menu = NodePath("menu_layer/main_menu")
pause_menu = NodePath("menu_layer/pause_menu")
mouse_tooltip_margin = 70.0
editor_debug_mode = 1
ui_parent_control_node = NodePath("game_layer/ui_layer/Tools")
[node name="black_and_white_shader" type="CanvasLayer" parent="."]
unique_name_in_owner = true
@@ -56,6 +68,10 @@ anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="CanvasLayer" type="CanvasLayer" parent="."]
[node name="Confetti" parent="CanvasLayer" instance=ExtResource("4_ixq7a")]
[node name="Vignette" type="CanvasLayer" parent="."]
process_mode = 4
@@ -110,6 +126,17 @@ layout_mode = 2
layout_mode = 2
alignment = 2
[node name="FullScreenButton" type="TextureButton" parent="game_layer/ui_layer/Tools/MarginContainer/HBoxContainer2"]
process_mode = 3
layout_mode = 2
texture_normal = ExtResource("18_ixq7a")
texture_hover = ExtResource("12_te176")
script = ExtResource("13_6rlck")
fullscreen_active_texture = ExtResource("14_c6byj")
fullscreen_active_hover_texture = ExtResource("15_j7gr8")
fullscreen_default_texture = ExtResource("18_ixq7a")
fullscreen_default_hover_texture = ExtResource("12_te176")
[node name="MusicButton" type="TextureButton" parent="game_layer/ui_layer/Tools/MarginContainer/HBoxContainer2"]
custom_minimum_size = Vector2(64, 0)
layout_mode = 2
@@ -129,12 +156,14 @@ anchors_preset = 7
anchor_top = 1.0
anchor_bottom = 1.0
offset_left = -640.0
offset_top = -166.0
offset_top = -135.0
offset_right = 640.0
offset_bottom = 0.0
grow_vertical = 0
pivot_offset = Vector2(845, 116)
[node name="AchievementNotifications" parent="game_layer/ui_layer" instance=ExtResource("18_ssxmx")]
[node name="menu_layer" type="CanvasLayer" parent="."]
layer = 2
@@ -148,6 +177,12 @@ visible = false
visible = false
[node name="language_selector" parent="menu_layer" instance=ExtResource("19_we0hb")]
visible = false
[node name="highscores" parent="menu_layer" instance=ExtResource("23_p0ek8")]
unique_name_in_owner = true
visible = false
[connection signal="button_down" from="game_layer/ui_layer/Tools/MarginContainer/HBoxContainer2/FullScreenButton" to="game_layer/ui_layer/Tools/MarginContainer/HBoxContainer2/FullScreenButton" method="_on_button_down"]
[connection signal="pressed" from="game_layer/ui_layer/Tools/MarginContainer/HBoxContainer2/MusicButton" to="." method="_on_MusicButton_pressed"]
[connection signal="pressed" from="game_layer/ui_layer/Tools/MarginContainer/HBoxContainer2/MenuButton" to="." method="_on_MenuButton_pressed"]

View File

@@ -16,19 +16,96 @@ var language_manager: RTMILanguageManager = RTMILanguageManager.new(csv_parser)
var music_manager: RTMIMusicManager = RTMIMusicManager.new()
var video_manager: RTMIVideoManager
var achievement_manager: RTMIAchievementManager = RTMIAchievementManager.new()
var score_manager: RTMIScoreManager
var fullscreen_manager: RTMIFullscreenManager = RTMIFullscreenManager.new()
var version: GymnkhanaVersion = GymnkhanaVersion.new()
var is_hint_active: bool = false
var _debug_time_start: float
func get_item(global_id: String) -> ESCItem:
var object = escoria.object_manager.get_object(global_id)
if !object:
return null
var node = object.node
if not node is ESCItem:
escoria.logger.error(
self,
"Object is not an ESCItem"
)
escoria.logger.error(self, "Object is not an ESCItem")
return null
return node
func start_time() -> void:
_debug_time_start = Time.get_unix_time_from_system()
func stop_time(custom_source: String = "") -> void:
var elapsed = Time.get_unix_time_from_system() - _debug_time_start
var source = (
custom_source
if custom_source != ""
else escoria.object_manager.current_room_key.room_global_id
)
print('RTMI_DEBUG: "%s" loading time: %s' % [source, elapsed])
func is_item_under_mouse(global_id: String):
var physics2d_dss: PhysicsDirectSpaceState2D = (
escoria.game_scene.get_world_2d().direct_space_state
)
var params := PhysicsPointQueryParameters2D.new()
params.position = escoria.main.current_scene.game.get_global_mouse_position()
params.collision_mask = 0x7FFFFFFF
params.collide_with_areas = true
var colliding: Array = physics2d_dss.intersect_point(params)
var colliding_nodes = []
for c in colliding:
if c.collider is not ESCItemWithTooltip:
continue
if (c.collider as ESCItemWithTooltip).global_id == global_id:
return true
return false
func has_combination_with_current_tool(global_id: String):
if escoria.action_manager.current_tool == null:
return false
var current_object = escoria.object_manager.get_object(global_id)
return (
current_object.events.has("action3 %s" % escoria.action_manager.current_tool.global_id)
or current_object.events.has("action4 %s" % escoria.action_manager.current_tool.global_id)
)
func warm_esc_cache() -> void:
# Instance analizer
var ashes_analyzer = ESCAshesAnalyzer.new()
# From ESCAshesAnalyzer
var files: Array[String] = ashes_analyzer._get_script_files_recursive(
ESCAshesAnalyzer.BASE_PROJECT_DIR
)
files.sort()
for file in files:
# We need to use the compiler from the escoria singelton for the cache to work.
escoria.esc_compiler.load_esc_file(file)
func toogle_fullscreen():
pass
func set_fullscreen(value: bool):
pass

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="64"
height="64"
stroke-width="1.5"
viewBox="0 0 64 64"
fill="none"
color="#000000"
version="1.1"
id="svg3"
sodipodi:docname="exit_fullscreen.svg"
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs3" />
<sodipodi:namedview
id="namedview3"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="7.5520836"
inkscape:cx="21.914482"
inkscape:cy="41.114481"
inkscape:window-width="1680"
inkscape:window-height="941"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="g1" />
<rect
style="fill:#ffffff;fill-opacity:0.330383;stroke:none;stroke-width:3.41;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;paint-order:normal"
id="rect1"
width="64"
height="64"
x="0"
y="0"
ry="11.032078" />
<g
id="g3"
transform="matrix(0.72808748,0,0,0.72808748,8.7012004,8.7012005)"
style="stroke-width:6.24650214;stroke-dasharray:none">
<g
id="g1">
<path
style="fill:none;stroke:#000000;stroke-width:6.2465;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 5.7411847,39.334608 H 24.137035 l -0.05328,18.906603"
id="path1"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#000000;stroke-width:6.2465;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 58.258814,39.334609 H 39.862965 l 0.05328,18.906602"
id="path1-3"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#000000;stroke-width:6.2465;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 5.741185,24.665391 H 24.137034 L 24.083754,5.7587889"
id="path2"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#000000;stroke-width:6.2465;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 58.258814,24.665391 H 39.862965 l 0.05328,-18.9066019"
id="path3"
sodipodi:nodetypes="ccc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="64"
height="64"
stroke-width="1.5"
viewBox="0 0 64 64"
fill="none"
color="#000000"
version="1.1"
id="svg3"
sodipodi:docname="exit_fullscreen_hover.svg"
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs3" />
<sodipodi:namedview
id="namedview3"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="7.5520836"
inkscape:cx="24.827585"
inkscape:cy="29.859309"
inkscape:window-width="1680"
inkscape:window-height="941"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg3" />
<rect
style="fill:#ffffff;fill-opacity:0.546763;stroke:#ffffff;stroke-width:0.666668;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
id="rect1"
width="64"
height="64"
x="0"
y="0"
ry="11.032078" />
<g
id="g2"
style="stroke-width:6.2465;stroke-dasharray:none"
transform="matrix(0.72808748,0,0,0.72808748,8.7012011,8.7012006)">
<path
style="fill:none;stroke:#000000;stroke-width:6.2465;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 5.7411851,39.334609 H 24.137034 l -0.05328,18.906602"
id="path1"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#000000;stroke-width:6.2465;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 58.258814,39.334609 H 39.862965 l 0.05328,18.906602"
id="path1-3"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#000000;stroke-width:6.2465;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 5.741185,24.665391 H 24.137034 L 24.083754,5.7587889"
id="path2"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#000000;stroke-width:6.2465;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 58.258814,24.665391 H 39.862965 l 0.05328,-18.9066019"
id="path3"
sodipodi:nodetypes="ccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="64"
height="64"
stroke-width="1.5"
viewBox="0 0 64 64"
fill="none"
color="#000000"
version="1.1"
id="svg3"
sodipodi:docname="fullscreen.svg"
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs3" />
<sodipodi:namedview
id="namedview3"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="7.5520836"
inkscape:cx="21.914482"
inkscape:cy="41.114481"
inkscape:window-width="1680"
inkscape:window-height="941"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="g3" />
<rect
style="fill:#ffffff;fill-opacity:0.330383;stroke:none;stroke-width:3.41;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;paint-order:normal"
id="rect1"
width="64"
height="64"
x="0"
y="0"
ry="11.032078" />
<g
id="g3"
transform="matrix(0.72808748,0,0,0.72808748,8.7012004,8.7012005)"
style="stroke-width:6.24650214;stroke-dasharray:none">
<g
id="g1">
<path
style="fill:none;stroke:#000000;stroke-width:6.2465;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 24.145849,58.25 H 5.7499995 l 0.053284,-18.906602"
id="path1"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#000000;stroke-width:6.2465;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 39.854151,58.25 H 58.25 L 58.19672,39.343398"
id="path1-3"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#000000;stroke-width:6.2465;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 24.145849,5.75 H 5.7499995 l 0.053284,18.906602"
id="path2"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#000000;stroke-width:6.2465;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 39.854151,5.75 H 58.25 l -0.05328,18.906602"
id="path3"
sodipodi:nodetypes="ccc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="64"
height="64"
stroke-width="1.5"
viewBox="0 0 64 64"
fill="none"
color="#000000"
version="1.1"
id="svg3"
sodipodi:docname="fullscreen_hover.svg"
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs3" />
<sodipodi:namedview
id="namedview3"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="7.5520836"
inkscape:cx="24.827585"
inkscape:cy="29.859309"
inkscape:window-width="1680"
inkscape:window-height="941"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg3" />
<rect
style="fill:#ffffff;fill-opacity:0.546763;stroke:#ffffff;stroke-width:0.666668;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
id="rect1"
width="64"
height="64"
x="0"
y="0"
ry="11.032078" />
<g
id="g2"
style="stroke-width:6.2465;stroke-dasharray:none"
transform="matrix(0.72808748,0,0,0.72808748,8.7012011,8.7012006)">
<path
style="fill:none;stroke:#000000;stroke-width:6.2465;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 24.145849,58.25 H 5.7499995 l 0.053284,-18.906602"
id="path1"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#000000;stroke-width:6.2465;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 39.854151,58.25 H 58.25 L 58.19672,39.343398"
id="path1-3"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#000000;stroke-width:6.2465;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 24.145849,5.75 H 5.7499995 l 0.053284,18.906602"
id="path2"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#000000;stroke-width:6.2465;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 39.854151,5.75 H 58.25 l -0.05328,18.906602"
id="path3"
sodipodi:nodetypes="ccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="32"
height="32"
viewBox="0 0 8.4666665 8.4666667"
version="1.1"
id="svg1"
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
sodipodi:docname="confetti.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="9.9062851"
inkscape:cx="15.192375"
inkscape:cy="18.422648"
inkscape:window-width="1680"
inkscape:window-height="941"
inkscape:window-x="1920"
inkscape:window-y="15"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs1" />
<g
inkscape:label="Capa 1"
inkscape:groupmode="layer"
id="layer1">
<circle
style="fill:#ffffff;stroke:#f2f2f2;stroke-width:0.0312208;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1"
id="path1"
cx="4.2333331"
cy="4.2333331"
r="4.2333331" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -22,4 +22,4 @@ func get_inventory_button_by_id(item_id: String) -> ESCInventoryButton:
if c.global_id == item_id:
inventory_button = c
break
return inventory_button
return inventory_button

View File

@@ -1,5 +1,8 @@
extends ESCInventory
# Scroll step for mouse wheel
var MOUSE_SCROLL_STEP: int = 20
func show_ui():
self.show()
@@ -15,3 +18,6 @@ func hide_inventory():
func set_item_texture_by_id(item_id: String, texture: Texture):
var button: RTMIInventoryButton = get_node(inventory_ui_container).get_inventory_button_by_id(item_id)
button.set_texture(texture)
func handle_mouse_wheel(direction: int) -> void:
%ScrollContainer.scroll_horizontal += -direction * MOUSE_SCROLL_STEP

View File

@@ -5,7 +5,7 @@
[ext_resource type="Script" uid="uid://245b34c8nyex" path="res://addons/escoria-ui-return-monkey-island/inventory/inventory_container.gd" id="3_a1nc4"]
[node name="Inventory" type="PanelContainer"]
custom_minimum_size = Vector2(1280, 160)
custom_minimum_size = Vector2(1280, 142)
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
@@ -14,7 +14,7 @@ anchor_bottom = 0.5
offset_left = -1265.0
offset_top = -360.0
offset_right = 15.0
offset_bottom = -194.0
offset_bottom = -210.0
grow_horizontal = 2
grow_vertical = 2
pivot_offset = Vector2(1726, 214)
@@ -28,6 +28,7 @@ layout_mode = 2
size_flags_vertical = 4
[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer"]
unique_name_in_owner = true
clip_contents = false
layout_mode = 2
size_flags_vertical = 4

View File

@@ -1,47 +1,97 @@
# The inventory representation of an ESC item if pickable (only used by
# the inventory components)
extends ESCInventoryButton
class_name RTMIInventoryButton
extends ESCInventoryButton
const RESIZE_RATIO: float = 0.9
var shader_material = preload(
"res://addons/escoria-ui-return-monkey-island/shaders/shadermaterial_outline_green5px.tres"
)
var first_time: bool = true
var shaderMaterial = preload("res://addons/escoria-ui-return-monkey-island/shaders/shadermaterial_outline_green5px.tres")
var _is_hovered: bool = false
var firstTime: bool = true
func _init(p_item: ESCInventoryItem) -> void:
super(p_item)
var image_normal = texture_normal.get_image()
image_normal.resize(image_normal.get_width() * RESIZE_RATIO, image_normal.get_height() * RESIZE_RATIO)
var image_hover = texture_hover.get_image()
image_hover.resize(image_hover.get_width() * RESIZE_RATIO, image_hover.get_height() * RESIZE_RATIO)
ignore_texture_size = true
stretch_mode = TextureButton.STRETCH_KEEP_CENTERED
func _enter_tree():
pivot_offset = size / 2
if firstTime:
scale = Vector2(0.5,0.5)
if first_time:
scale = Vector2(0.5, 0.5)
var tween: Tween = create_tween().set_loops(1)
tween.tween_property(self,"scale",Vector2.ONE,0.2).set_trans(Tween.TRANS_SPRING).from(Vector2(0.9,0.9))
tween.parallel().tween_property(self, "modulate:a",1.0,0.3).from(0.0).set_trans(Tween.TRANS_SINE)
firstTime = false
tween.tween_property(self, "scale", Vector2.ONE, 0.2).set_trans(Tween.TRANS_SPRING).from(
Vector2(0.9, 0.9)
)
tween.parallel().tween_property(self, "modulate:a", 1.0, 0.3).from(0.0).set_trans(
Tween.TRANS_SINE
)
first_time = false
# Handle mouse entering the item and send the respecitve signal
func _on_inventory_item_mouse_enter():
super._on_inventory_item_mouse_enter()
_is_hovered = true
if escoria.current_state != escoria.GAME_STATE.DEFAULT:
return
self.material = shaderMaterial
update_highlight()
# Handle mouse leaving the item and send the respecitve signal
func _on_inventory_item_mouse_exit():
super._on_inventory_item_mouse_exit()
self.material = null
_is_hovered = false
update_highlight()
func set_texture(texture: Texture):
self.texture_normal = texture
self.texture_hover = texture
func update_highlight():
if (
escoria.action_manager.action_state
!= escoria.action_manager.ACTION_INPUT_STATE.AWAITING_TARGET_ITEM
):
highlight(_is_hovered)
return
if gymkhana.has_combination_with_current_tool(global_id):
highlight(gymkhana.is_hint_active)
func highlight(value: bool) -> void:
self.material = shader_material if value else null
## Handles the gui input and emits the respective signals.[br]
## [br]
## #### Parameters[br]
## [br]
## - event: The event received.
func _on_inventory_item_gui_input(event: InputEvent):
if event is InputEventMouseButton and event.is_released():
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
escoria.inputs_manager._on_mousewheel_action(-1)
get_viewport().set_input_as_handled()
elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
escoria.inputs_manager._on_mousewheel_action(1)
get_viewport().set_input_as_handled()
elif event.double_click:
if event.button_index == MOUSE_BUTTON_LEFT:
mouse_double_left_inventory_item.emit(global_id, event)
# Make sure fast right clicks in the inventory aren't ignored
elif event.button_index == MOUSE_BUTTON_RIGHT:
mouse_right_inventory_item.emit(global_id, event)
else:
if event.button_index == MOUSE_BUTTON_LEFT:
mouse_left_inventory_item.emit(global_id, event)
if event.button_index == MOUSE_BUTTON_RIGHT:
mouse_right_inventory_item.emit(global_id, event)

Some files were not shown because too many files have changed in this diff Show More