Compare commits

...

241 Commits

Author SHA1 Message Date
jonathan 49fa5d08de Added fun button 2025-08-14 20:21:13 +02:00
jonathan 1ee9dea9f6 Fixes in project 2025-08-14 06:30:38 +02:00
jonathan d5fa2f88be Created LanguageTool Plugin 2025-08-14 06:30:17 +02:00
jonathan 8676bbb2f6 Fix spelling 2025-08-13 17:13:33 +02:00
jonathan 6e998810b6 Completed first demo quest line 2025-08-13 03:23:45 +02:00
jonathan c96be7467e Added Quest field 2025-08-11 19:15:12 +02:00
Jonathan 6aa7530502 Added speed hack for vesna 2025-08-06 21:25:28 +02:00
Jonathan d7ac1c6c22 Fixed retrigger yeli dialog 2025-08-06 20:04:24 +02:00
Jonathan 0170a53b5a Added more quest stuff including dialogic quest condition 2025-08-06 18:20:38 +02:00
cblech abc33fd06c Added first quests 2025-08-06 18:19:52 +02:00
cblech 2fbeb93018 Dialogic quest addition and plugin fix 2025-08-06 18:19:08 +02:00
Jonathan 9253a78a06 Merge pull request 'feature/showcase_bugfixing_kathi' (#14) from feature/showcase_bugfixing_kathi into develop
Reviewed-on: #14
2025-08-06 18:16:53 +02:00
kziolkowski 0008b16d48 Adjusted moving values and animations to make vesna not slide any more 2025-08-02 15:32:13 +02:00
kziolkowski 8e0dced918 Vesna can walk diagonally now 2025-08-02 15:08:38 +02:00
kziolkowski 2e21fb7e98 Made sure splash screen features logo 2025-08-02 13:55:11 +02:00
kziolkowski b69191e7f7 fixed pickup layering 2025-08-02 13:46:01 +02:00
kziolkowski 8f75b5b644 Added secondary outline mat and assigned it to inventory items 2025-08-02 13:38:07 +02:00
kziolkowski 6275bea52c MAde Vesna and Yeli disappear on dialogic start 2025-07-31 23:30:12 +02:00
kziolkowski 279cac22ee Fixed dialogic settings 2025-07-31 23:25:43 +02:00
kziolkowski e88ba2e1ef Updated interaction area setups to avoid nullrefs 2025-07-31 23:08:10 +02:00
kziolkowski f01143e887 cleaned up dialogue structure and removed vesna2 from dialogues 2025-07-31 22:09:37 +02:00
kziolkowski 18711776bb Fixed output error ERROR: Script class can only be set together with base class name 2025-07-31 21:45:22 +02:00
kziolkowski 0f246825fc Added Wellbehaviour and fixed door interaction to offer outlines 2025-07-31 20:36:17 +02:00
kziolkowski 19e30dd0b8 Removed disclaimer reference from bootstrap 2025-07-31 20:35:49 +02:00
kziolkowski 730c4999d7 Extracted FightAttack Enum in the hopes of fixing errors 2025-07-31 20:35:24 +02:00
kziolkowski cfe604d3b7 set duck body scale to 1,1 2025-07-31 18:55:06 +02:00
kziolkowski ad16b86171 wip exchanging interaction label with outline 2025-07-27 13:17:34 +02:00
kziolkowski 5ee295256b Fixed Yeli Layering issue in indoor scene 2025-07-26 17:05:17 +02:00
kziolkowski ab23d41496 Fixed ysorting on ducks and trash 2025-07-26 16:51:05 +02:00
Jonathan ae0944fe00 Merge pull request 'feature/showcase_kathi' (#12) from feature/showcase_kathi into develop
Reviewed-on: #12
2025-07-23 12:37:47 +02:00
kziolkowski 486cfb5546 WIP trying to fix the last plant stage bug on repeated farming rounds 2025-07-17 22:10:08 +02:00
kziolkowski b92eb909ad Removed no longer needed print statements 2025-07-17 20:47:34 +02:00
kziolkowski d2c7302ab2 Fixed farming (the way it was before) 2025-07-17 20:44:28 +02:00
kziolkowski 5affc48dc5 Added scene transitions between fighting scene, credits, and start 2025-07-11 04:12:42 +02:00
kziolkowski cdb6b83124 Merge remote-tracking branch 'origin/feature/fight_system' into feature/showcase_kathi 2025-07-11 03:55:56 +02:00
kziolkowski a4f9511892 WIP fixing farming mechanic again 2025-07-11 03:55:36 +02:00
cblech cc7e8c5c4b Added Credits 2025-07-11 03:49:09 +02:00
kziolkowski 7a3e96d679 Merge remote-tracking branch 'origin/feature/fight_system' into feature/showcase_kathi 2025-07-11 03:13:08 +02:00
kziolkowski e38c391e1c Reworked flow to make it playable somehow 2025-07-11 03:12:29 +02:00
cblech c0e002f783 made you win waiting time shorter 2025-07-11 03:01:49 +02:00
cblech e8850ca7c5 Added chuga dialog to fight scene 2025-07-11 03:00:47 +02:00
kziolkowski eaedf8c396 WIP Beetroot 2025-07-11 03:00:43 +02:00
kziolkowski ffa20bbdf8 Added trash to first outdoor scene 2025-07-11 00:56:51 +02:00
kziolkowski b77b6e3a52 Added second outdoor scene after tutorial 2025-07-11 00:17:31 +02:00
cblech 69cb63ad89 merge auto fixes 2025-07-11 00:15:28 +02:00
cblech 11790434f5 Merge remote-tracking branch 'origin/feature/showcase_kathi' into feature/fight_system 2025-07-11 00:11:33 +02:00
kziolkowski c7d56301fc Added counter script to count ducks (and other things) 2025-07-10 23:58:33 +02:00
cblech 8bd2b09232 Added healing 2025-07-10 23:32:16 +02:00
kziolkowski 480d149ede SceneTransition Rework completed 2025-07-10 23:23:20 +02:00
cblech c6fc400994 Added second fight with mavkha 2025-07-10 19:30:57 +02:00
kziolkowski 16251db248 WIP new SceneTransition system 2025-07-10 19:07:46 +02:00
cblech 4752002caf Added action per round 2025-07-10 18:29:18 +02:00
cblech 0e028a2cb9 Renamed signal 2025-07-10 16:12:47 +02:00
cblech 01a281c2aa Fixed camera bounds 2025-07-10 16:04:12 +02:00
cblech 2a46d363e9 Changed music to forrest 2025-07-10 15:43:36 +02:00
cblech 92c3f5e054 Target only alive enemies 2025-07-10 15:25:11 +02:00
cblech 6727339e9a Added audio to fight 2025-07-10 04:39:33 +02:00
cblech e3d67722de Merge remote-tracking branch 'origin/Nao's-Sounds' into feature/fight_system 2025-07-10 03:47:40 +02:00
cblech b6fd6292e3 Basic fighting system 2025-07-10 03:38:48 +02:00
kziolkowski e8c24e18be Added indoor bedroom scene 2025-07-10 01:25:52 +02:00
kziolkowski 199d0873c8 Set up beetroot quest and added cat to indoor scene. 2025-07-10 01:19:00 +02:00
kziolkowski e84ef716f6 Merge remote-tracking branch 'origin/feature_sanel-dialogic' into feature/showcase_kathi
# Conflicts:
#	project.godot
2025-07-09 23:53:40 +02:00
kziolkowski 135ba0d198 Reworked Domovoi kitchen animation and added AnimationStarter script 2025-07-09 23:50:43 +02:00
Sanelschnitte 2940475062 Added dialog in Dialogic
basic char, text, choice - eventually needs more events and functions to work properly
2025-07-09 23:43:02 +02:00
kziolkowski 202f8809aa Fixed plant layering issue 2025-07-09 23:03:56 +02:00
kziolkowski 28bb81c0b0 Added fence gates and fixed dialogic toggle for inventory 2025-07-09 22:58:36 +02:00
kziolkowski b9c5de6dc3 Made labels visible on ducks 2025-07-09 22:49:07 +02:00
kziolkowski 8c18688a69 MVP duck setup 2025-07-09 22:40:03 +02:00
kziolkowski 2429958741 Added Disclaimer scene 2025-07-09 21:40:02 +02:00
kziolkowski 6b5a8ee126 WIP duck behaviour 2025-07-09 20:52:43 +02:00
kziolkowski 8d40529349 Changed StartScreen layout and added Quit button 2025-07-09 20:52:33 +02:00
kziolkowski 9e97cc3b80 WIP duck pushing behaviour 2025-07-08 23:53:50 +02:00
kziolkowski ebc3ee9cf9 Implemented basic duck running away from vesna mechanic 2025-07-08 22:23:28 +02:00
kziolkowski a1bbe44105 Merge remote-tracking branch 'origin/Nao's-Sounds' into feature/showcase_kathi 2025-07-08 21:33:59 +02:00
kziolkowski 3ce10c8ba9 Merge remote-tracking branch 'origin/Nao's-Sounds' into feature/showcase_kathi 2025-07-08 21:33:37 +02:00
kziolkowski 7e6163ed68 updated project.godot 2025-07-07 21:16:36 +02:00
kziolkowski 55d6222698 Added Camera to Indoor Common Room scene and renamend scene asset 2025-07-07 16:37:10 +02:00
kziolkowski d7ad2ba072 reverted / recreated inventory changes 2025-07-07 16:14:07 +02:00
kziolkowski 9c50a63dc3 Merge branch 'develop' into feature/showcase_kathi 2025-07-07 15:34:53 +02:00
kziolkowski 746ac58329 Merge pull request 'Feature: Quest system' (#11) from feature/quest_system into develop
Reviewed-on: #11
2025-07-07 15:24:28 +02:00
cblech a9cb20c8bc Fixed journal references 2025-07-07 04:51:35 +02:00
cblech 32249fde86 Made quest visuals 2025-07-07 04:41:14 +02:00
cblech 27e137bc02 Made quest usable 2025-07-07 04:41:03 +02:00
cblech 01daddee3b Made basic quest setup 2025-07-07 04:40:40 +02:00
Jonathan ba512508f8 Merge pull request 'feature/farm_scene_rework' (#10) from feature/farm_scene_rework into develop
Reviewed-on: #10
2025-07-07 03:46:51 +02:00
kziolkowski ec653aa847 readded camera ref to farming behaviour 2025-07-07 01:17:41 +02:00
kziolkowski 9acea54f28 Added duck sprite 2025-07-07 00:46:57 +02:00
kziolkowski 2f5296e05a Diversified field shapes 2025-07-06 23:48:01 +02:00
kziolkowski e8a58655ad Added grass textures and field borders 2025-07-06 23:28:02 +02:00
kziolkowski aa3789566c Duplicated sunflower field parallaxe layer to ensure seamlessness on big screens 2025-07-06 22:00:39 +02:00
kziolkowski 9c7ae20c18 Reworked Camera controls outside scene 2025-07-06 21:56:15 +02:00
Nao 9f04c8819f SFX for Mavkas (Voices but more "ghostly") Added 2025-07-06 20:20:03 +02:00
Nao 6cd7be196b SFX Wolf + Mavka Voices (when hit in battle) Added 2025-07-06 20:11:50 +02:00
kziolkowski ab2cf3f497 wateringcanstate uid? 2025-07-06 12:26:07 +02:00
kziolkowski bf096aa716 visual improvements on farm scene 2025-07-06 12:25:44 +02:00
kziolkowski 09ef508f49 Fixed field creation bug 2025-07-06 10:57:38 +02:00
Nao 6de8368414 Farm Atmos Added 2025-07-05 23:23:39 +02:00
Nao d20085a67c SFX Water Attack Added (Vesna + Slimes) 2025-07-05 23:17:58 +02:00
kziolkowski a54003c658 Made ground noise texture more seamless 2025-07-05 23:10:23 +02:00
Nao 648ae8395b SFX added for Root Attack, Mavka + Vesna 2025-07-05 23:01:43 +02:00
kziolkowski fbad33213c Finalized new watering can mechanic with vfx and ui 2025-07-05 22:54:52 +02:00
Nao b68eb0953e SFX Duck Flügelflattern "Wings" + Schlappentornado Added 2025-07-05 21:51:19 +02:00
kziolkowski 35c7e9a25e WIP Wasserstand UI 2025-07-05 17:34:03 +02:00
kziolkowski 57896e37df Fixed background music loop and added audio mixers 2025-07-05 15:08:23 +02:00
kziolkowski 242879159a Fixed sfx binding in farming scene 2025-07-05 13:57:14 +02:00
kziolkowski 7ef9fe53b2 Added SignalVisualizer plugin 2025-07-05 13:56:59 +02:00
kziolkowski 600d9cfca1 Made items activate directly when picked up 2025-07-05 13:18:19 +02:00
kziolkowski 48796de1ba Changed dialogic background color to black and opacity to 168 sothat there is a visible dark overlay during dialogues 2025-07-05 12:37:39 +02:00
kziolkowski 4a0b2cd550 Improved Inventory UI (more in the middle, adapt to viewport size, new selector image) 2025-07-05 12:18:28 +02:00
kziolkowski ba429d7b84 wip improving inventory layout 2025-07-04 23:41:15 +02:00
kziolkowski e33776daeb ESC closes inventory now. 2025-07-04 23:15:45 +02:00
kziolkowski 9cfd3bd6f4 Improving farm outside scene performance 2025-07-02 21:36:12 +02:00
Nao 7eb18caaaf Added SFX for Healing magic 2025-07-02 21:24:21 +02:00
Nao e65e82f421 Added SFX Duck & Combat, moved Cat SFX to folder "animals" 2025-07-02 21:23:36 +02:00
kziolkowski c36d0b5866 reduced VRAM load by more than 50% 2025-07-02 17:54:23 +02:00
kziolkowski bcdba7b812 Fixed Vesna sliding issue 2025-07-02 15:48:39 +02:00
kziolkowski 7467ec56d9 Fixed ordering issues in indoor scene 2025-06-28 17:37:39 +02:00
kziolkowski 990494e8b0 Adjusted indoor speed 2025-06-28 17:19:41 +02:00
kziolkowski c6e0cfe4d9 Fixed Button layout behaviour 2025-06-28 17:17:26 +02:00
Nao 691e613a5c Added SFX for Combat 2025-06-28 17:04:20 +02:00
kziolkowski 4e010220bf Improved performance of the first indoor scene 2025-06-28 16:13:06 +02:00
kziolkowski ccc4eb759e Added new house image to farming scene 2025-06-21 16:09:35 +02:00
Nao 250f0d07ca SFX Slime Hit Variations (Pitch) Added 2025-06-17 15:43:33 +02:00
Nao f481f5bea7 SFX Added: UI (Dialog + Confirmation), Slime Hit 2025-06-17 15:39:02 +02:00
Jonathan 58c65fc928 Merge pull request 'First intro sequence with Yeli' (#9) from feature/yeli_intro into develop
Reviewed-on: #9
2025-06-17 02:40:12 +02:00
cblech 937e54e47a Merge branch 'feature/farming_visuals' into develop 2025-06-16 21:03:02 +02:00
kziolkowski 83c8a15e5a Added art for updated startscreen to project (but not yet to start menu scene) 2025-06-16 20:56:01 +02:00
kziolkowski 1fcddb7349 changed export presets for new builds 2025-06-16 20:56:01 +02:00
kziolkowski 26cae9b0f8 fixed missing ready plants 2025-06-16 20:56:01 +02:00
kziolkowski 0ebd0c46a0 Added indoor ending 2025-06-16 20:56:01 +02:00
kziolkowski 2226b859df Added WateringCan SFX 2025-06-16 20:56:00 +02:00
kziolkowski 07bcab4454 Added Farming SFX 2025-06-16 20:56:00 +02:00
kziolkowski 4c6d5350b2 Added Background music 2025-06-16 20:56:00 +02:00
kziolkowski f2c492de54 changed label settings for InteractionArea 2025-06-16 20:56:00 +02:00
kziolkowski e269b3ab44 WIP trying to toggle interactable colliders at runtime for fields 2025-06-16 20:56:00 +02:00
kziolkowski 89ae347a91 Added last farming timelines and fixed some minor issues 2025-06-16 20:56:00 +02:00
kziolkowski ddb5547b42 Updated Startscreen and added second tutorial step 2025-06-16 20:56:00 +02:00
kziolkowski afa06d3ee2 Fixed Yeli Y sorting issue and made fields rounded 2025-06-16 20:56:00 +02:00
kziolkowski dd656d5f5f Extended dialogic toggle 2025-06-16 20:56:00 +02:00
kziolkowski cdb62f3c2f Added Cozy Raven Splashscreen 2025-06-16 20:56:00 +02:00
kziolkowski b0f4592fdd Added first working timeline for yelis intro to farming scene 2025-06-16 20:56:00 +02:00
kziolkowski 406c11b581 import statements 2025-06-16 20:56:00 +02:00
kziolkowski 9812006234 Added Yeli sprites and dialogic test timeline as well as prefab 2025-06-16 20:56:00 +02:00
kziolkowski b8e456f7ef moved player2D prefab 2025-06-16 20:55:59 +02:00
Felix Paul 97e5485ef1 Added Yeli Idle and Talk animations 2025-06-16 20:55:59 +02:00
Felix Paul c77563d38e Rerender Harvesting and added Watering animations 2025-06-16 20:55:59 +02:00
Nao c322f7667a Placeholder for Quest Fail added 2025-06-16 20:55:59 +02:00
Nao 68be479a09 New SFX for Door added 2025-06-16 20:55:58 +02:00
Nao dc52d80a92 SFX Quest Complete Placeholder added (need more time) 2025-06-16 20:55:58 +02:00
Nao a84ca9c32c Farm Atmos Nighttime added 2025-06-16 20:55:58 +02:00
Nao 6b1dd04dd5 New SFX and Forest Atmos Nighttime added 2025-06-16 20:55:58 +02:00
kziolkowski 523624756e missing import files 2025-06-16 20:55:57 +02:00
Nao 72593ff7c7 SFX for kitchen added (cutlery, plates, etc) and a few renamed 2025-06-16 20:55:57 +02:00
kziolkowski d7dfd03241 Deleted unused material folder 2025-06-16 20:55:57 +02:00
Nao eac135508c SFX Snoring Added 2025-06-16 20:55:57 +02:00
ascheck 90cadbea07 ui elemente hinzugefügt für dialog 2025-06-16 20:55:57 +02:00
Nao 72c3454728 SFX Door Open and Close added 2025-06-16 20:55:57 +02:00
kziolkowski 83e25f44cd Fixed background parallaxe effect in outdoor scene 2025-06-16 20:55:57 +02:00
kziolkowski 31f19ad139 Code cleanup part 2 2025-06-16 20:55:57 +02:00
kziolkowski c6ec99e87a Project cleanup: Removed 3D scripts and scenes from project. Also renamed and moved some minor stuff. 2025-06-16 20:55:57 +02:00
Nao b8cb60aec9 Placeholder for Quest Fail added 2025-06-02 16:06:52 +02:00
Nao 55a3e56791 New SFX for Door added 2025-06-02 15:56:36 +02:00
kziolkowski 1f17cca62d changes from build process 2025-05-28 15:37:04 +02:00
ascheck 1629862759 Merge pull request 'ui elemente hinzugefügt für dialog' (#4) from feature/ui-elements into develop
Reviewed-on: #4
2025-05-27 21:23:34 +02:00
ascheck a53b4c4010 ui elemente hinzugefügt für dialog 2025-05-27 21:11:15 +02:00
kziolkowski 3e135afecb Added StartScreen and Scene Transition script 2025-05-24 23:50:06 +02:00
kziolkowski 25d8f217ff basic harvesting implemented 2025-05-24 23:16:41 +02:00
kziolkowski a477f9ef4f Implemented field creation and wateringcan fill up animation 2025-05-24 21:47:25 +02:00
kziolkowski b917fb5fbd changed player window size 2025-05-24 21:46:28 +02:00
kziolkowski 47a1326292 state after magic clip done 2025-05-21 02:10:50 +02:00
kziolkowski 708aa8cca4 State after inventory clip (farming mechanic still WIP) 2025-05-21 00:13:58 +02:00
kziolkowski 83f4144b43 Reworked farming tools pickup animations 2025-05-20 23:05:26 +02:00
kziolkowski 2c677a8cda Inventory resource rework and slot aspect fix 2025-05-20 22:27:48 +02:00
cblech ec5d42068e fixed generic item on ground and added icon 2025-05-20 20:42:32 +02:00
cblech 8fdb395ae8 Added icon to slot 2025-05-20 19:49:37 +02:00
kziolkowski 60928c520c Inventory implemented 2025-05-20 18:27:50 +02:00
kziolkowski f3ed5e0ad0 Changes to ItemOnGround 2025-05-20 18:27:40 +02:00
kziolkowski ee897db52b added swaying plants shader 2025-05-20 18:27:20 +02:00
kziolkowski 41201d7406 Indoor room sprites added 2025-05-20 18:27:09 +02:00
kziolkowski 267172d026 WIP adding the inventory, also state after first clip 2025-05-20 01:00:13 +02:00
kziolkowski 917e6a5f7e Merge remote-tracking branch 'origin/inventory' into feature/farming_visuals
# Conflicts:
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0001.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0002.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0003.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0004.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0005.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0006.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0007.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0008.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0009.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0010.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0011.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0012.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0013.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0014.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0015.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0016.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0017.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0018.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0019.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Gießkanne/0020.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0001.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0002.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0003.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0004.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0005.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0006.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0007.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0008.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0009.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0010.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0011.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0012.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0013.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0014.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0015.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0016.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0017.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0018.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0019.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B01-Idle-Harke/0020.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0001.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0002.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0003.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0004.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0005.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0006.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0007.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0008.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0009.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0010.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0011.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0012.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0013.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0014.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0015.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0016.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0017.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0018.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0019.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Gießkanne/0020.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0001.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0002.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0003.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0004.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0005.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0006.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0007.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0008.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0009.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0010.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0011.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0012.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0013.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0014.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0015.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0016.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0017.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0018.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0019.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/B02-Walk-Harke/0020.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0001.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0002.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0003.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0004.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0005.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0006.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0007.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0008.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0009.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0010.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0011.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0012.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0013.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0014.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0015.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0016.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0017.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0018.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0019.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Gießkanne/0020.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0001.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0002.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0003.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0004.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0005.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0006.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0007.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0008.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0009.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0010.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0011.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0012.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0013.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0014.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0015.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0016.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0017.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0018.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0019.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/D01-Idle-Harke/0020.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0001.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0002.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0003.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0004.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0005.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0006.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0007.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0008.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0009.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0010.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0011.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0012.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0013.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0014.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0015.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0016.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0017.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0018.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0019.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Gießkanne/0020.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0001.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0002.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0003.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0004.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0005.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0006.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0007.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0008.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0009.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0010.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0011.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0012.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0013.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0014.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0015.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0016.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0017.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0018.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0019.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F01-Idle-Harke/0020.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0001.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0002.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0003.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0004.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0005.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0006.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0007.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0008.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0009.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0010.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0011.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0012.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0013.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0014.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0015.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0016.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0017.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0018.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0019.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Gießkanne/0020.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0001.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0002.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0003.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0004.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0005.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0006.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0007.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0008.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0009.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0010.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0011.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0012.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0013.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0014.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0015.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0016.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0017.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0018.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0019.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/F02-Walk-Harke/0020.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0001.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0002.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0003.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0004.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0005.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0006.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0007.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0008.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0009.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0010.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0011.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0012.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0013.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0014.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0015.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0016.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0017.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0018.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0019.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Gießkanne/0020.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0001.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0002.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0003.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0004.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0005.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0006.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0007.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0008.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0009.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0010.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0011.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0012.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0013.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0014.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0015.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0016.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0017.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0018.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0019.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S01-Idle-Harke/0020.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0001.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0002.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0003.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0004.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0005.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0006.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0007.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0008.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0009.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0010.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0011.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0012.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0013.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0014.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0015.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0016.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0017.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0018.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0019.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Gießkanne/0020.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0001.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0002.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0003.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0004.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0005.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0006.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0007.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0008.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0009.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0010.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0011.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0012.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0013.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0014.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0015.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0016.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0017.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0018.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0019.png.import
#	art/animation/Vesna2D/Vesna Anims Tools/S02-Walk-Harke/0020.png.import
#	prefabs/UI/Inventory/Inventory.tscn
#	scenes/Babushka_scene_farm_outside_2d.tscn
2025-05-20 00:19:42 +02:00
kziolkowski 23ef4e9a63 changed visibility order for plants 2025-05-20 00:18:49 +02:00
kziolkowski fa7cc66748 added farming animation mechanic 2025-05-19 23:49:00 +02:00
cblech 7b006d19ef Changed slot visuals 2025-05-19 23:36:45 +02:00
kziolkowski ad070514d7 Added item and interact animations 2025-05-19 22:50:28 +02:00
kziolkowski 80c48ea3df added pickup animation 2025-05-19 22:39:30 +02:00
cblech d76218f88f Moved Bar slot selection handling to inventory manager 2025-05-19 22:07:55 +02:00
kziolkowski 7276bdda38 Watering can animation plays when watering 2025-05-19 22:06:40 +02:00
kziolkowski 73dc3063c0 removed unnecessary icons from farming controls 2025-05-19 21:42:56 +02:00
cblech ae4f7d9c58 added missing imports 2025-05-19 21:36:10 +02:00
cblech 9a5caef52f Added inventory background and fixes 2025-05-19 21:35:55 +02:00
kziolkowski 15c2a84ecd Added babushka icon to project settings 2025-05-19 21:18:24 +02:00
kziolkowski 1094fb2142 Added tool animations to player 2025-05-19 21:17:50 +02:00
cblech 2ab1c38de9 cleaned Inventory ui 2025-05-19 17:17:01 +02:00
Nao 4261789f13 SFX Quest Complete Placeholder added (need more time) 2025-05-18 20:34:00 +02:00
Nao ce18c89c09 Farm Atmos Nighttime added 2025-05-18 19:21:51 +02:00
Nao 7643cccebf New SFX and Forest Atmos Nighttime added 2025-05-18 19:04:02 +02:00
Nao 7e4d733d7c SFX for kitchen added (cutlery, plates, etc) and a few renamed 2025-05-18 17:52:59 +02:00
Nao 1dcd900737 SFX Snoring Added 2025-05-18 15:33:02 +02:00
Nao 74c3540c96 SFX Door Open and Close added 2025-05-18 15:10:08 +02:00
kziolkowski 6d80253d9c import updates to shaders and animations 2025-05-18 13:05:35 +02:00
kziolkowski 1b7c35879c Merge remote-tracking branch 'origin/Animations' into farming_mechanic 2025-05-18 12:34:21 +02:00
kziolkowski ff426b0494 Initial Farming setup complete 2025-05-18 12:32:56 +02:00
kziolkowski 90616537bc Watering fields 2025-05-18 11:44:33 +02:00
kziolkowski 0f8eb244e9 planting / growth works again 2025-05-17 19:04:46 +02:00
kziolkowski 38fdad7690 removed print statements 2025-05-17 18:24:15 +02:00
kziolkowski 0de6bc0c04 the most beautiful grid of fields you can imagine 2025-05-17 18:23:35 +02:00
Felix Paul fc2d6592a2 Added Vesna animations with tools 2025-05-17 17:47:52 +02:00
kziolkowski 222c10fe0a limited field creation to specified shape 2025-05-17 17:40:15 +02:00
kziolkowski 8af825bc18 InteractionAreas are now bound to SpriteSwitchers and farming tool interaction works 2025-05-17 16:38:32 +02:00
kziolkowski f7684b6c2a Deleted unused kenney assets 2025-05-17 14:02:20 +02:00
kziolkowski f9a3a8e389 generated import files for art assets 2025-05-17 13:49:07 +02:00
kziolkowski 6ad8fb00bd imported various art assets from owncloud 2025-05-17 13:47:54 +02:00
kziolkowski c4dbc104d4 music files added 2025-05-17 13:41:42 +02:00
kziolkowski 77c0babdca minor changes after merge 2025-05-17 13:37:56 +02:00
kziolkowski aa5a3483bb Merge remote-tracking branch 'origin/Nao's-Sounds' into farming_mechanic 2025-05-17 13:31:21 +02:00
kziolkowski 68b6031da1 Merge remote-tracking branch 'origin/Animations' into farming_mechanic 2025-05-17 13:30:58 +02:00
kziolkowski 4afb02440c Reworking 2D interactions 2025-05-16 23:16:27 +02:00
Nao de5657a9cd More SFX Added 2025-05-15 19:06:27 +02:00
kziolkowski ff85b67087 Made interaction area 2d work - and farming/growing work again. 2025-05-14 23:12:14 +02:00
Nao 6f3d843818 SFX and Atmos added (with variations) 2025-05-14 19:58:03 +02:00
Felix Paul 20f8eaaebd Added Vesna 2D image sequences 2025-05-14 12:48:37 +02:00
Felix Paul 69848e77c9 Added PickUp and Interact (Back) animations 2025-05-12 17:57:12 +02:00
kziolkowski 366923699c WIP 2D rework 2025-05-12 00:16:13 +02:00
kziolkowski 2a7f39e3fe Adjusted movement and included collider collisions as a constraint to the player 2025-05-11 23:20:35 +02:00
kziolkowski 296fed6e08 Added fields 2025-05-10 16:33:35 +02:00
kziolkowski 1af04631c5 Added 2d outdoor scene with parallaxe and mockup background 2025-05-10 16:29:23 +02:00
Felix Paul 9ec1bcab97 Added 2 animations
Added Fill Watercan and Hold Item animations
2025-05-05 20:24:26 +02:00
kziolkowski d11fc9f1f2 Cleaned up house mockup outline and removed spammy debug log 2025-04-30 18:49:46 +02:00
kziolkowski 16a65f7155 added flat indoor test and skybox to 3d test 2025-04-30 18:43:18 +02:00
kziolkowski 0fcc425ace built first 2d indoor scene + added kitchen 2025-04-30 17:36:38 +02:00
Felix Paul 21685d60d5 Added Vesna animations 2025-04-28 20:15:39 +02:00
kziolkowski 752cdb1502 Added new how sprite 2025-04-27 10:09:11 +02:00
kziolkowski 8299998a0f Added fence to the left part of the farm 2025-04-26 15:15:38 +02:00
kziolkowski 5ea6431216 Added tree prefabs and a forest border around the farm 2025-04-26 14:51:56 +02:00
Felix Paul 7cccd40290 Test
Einige animationen in 3D
2025-04-25 21:19:04 +02:00
kziolkowski 762a694be3 Spawning and watering is now bound to the cursor position (kinda) 2025-04-25 00:13:50 +02:00
kziolkowski 339428c312 Basic watering functionality implemented 2025-04-24 23:36:23 +02:00
kziolkowski 7e19268847 Merge remote-tracking branch 'origin/main' into c_sharp_setup
# Conflicts:
#	scripts/CSharp/Common/CharacterControls/VesnaBehaviour.cs.uid
#	scripts/CSharp/Common/Farming/FieldService.cs.uid
2025-04-24 21:22:56 +02:00
kziolkowski 20b37de108 generated files 2025-04-24 21:22:14 +02:00
kziolkowski c73d3ff370 Reworked the fieldservice 2025-04-14 18:00:10 +02:00
2496 changed files with 240538 additions and 4132 deletions
+6 -1
View File
@@ -2,8 +2,13 @@
.godot/
/android/
/builds/
/_builds/
/_clips/
# temporary files
**/*.tmp
**/*.translation
**/*~lock~
**/*~lock~
# override config can be used by developers to override the settings without pushing changes to the repository
override.cfg
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidProjectSystem">
<option name="providerId" value="RiderAndroidProjectSystem" />
</component>
</project>
+10
View File
@@ -0,0 +1,10 @@
<component name="libraryTable">
<library name="GdSdk Master" type="GdScript">
<properties path="$USER_HOME$/.cache/JetBrains/Rider2025.1/projects/.idea.babushka.a4de4632/sdk/GdSdk Master" version="Master" date="2024-06-01T15:14:16.000+02:00" />
<CLASSES />
<JAVADOC />
<SOURCES>
<root url="file://$USER_HOME$/.cache/JetBrains/Rider2025.1/projects/.idea.babushka.a4de4632/sdk/GdSdk Master" />
</SOURCES>
</library>
</component>
+4
View File
@@ -2,5 +2,9 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Folder Include="prefabs\UI\Inventory\" />
</ItemGroup>
</Project>
+5
View File
@@ -0,0 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=0B2502BD29F5EC4798EEFD2950AA7E06/Description/@EntryValue">Godot Signal</s:String>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=0B2502BD29F5EC4798EEFD2950AA7E06/Text/@EntryValue">[Signal]
public delegate void $SignalName$EventHandler($END$);</s:String>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=0B2502BD29F5EC4798EEFD2950AA7E06/Field/=SignalName/Expression/@EntryValue">suggestVariableName()</s:String></wpf:ResourceDictionary>
+11 -1
View File
@@ -1,2 +1,12 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AArea3D_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F8a54226fa2e1c9371a8091f24cfd744aef11fe6869527dc23b9b837623a29b9_003FArea3D_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AArea3D_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F8a54226fa2e1c9371a8091f24cfd744aef11fe6869527dc23b9b837623a29b9_003FArea3D_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAudioStreamPlayer2D_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F848324b1c23114c3f5e8bbb5a42c4ade394c59a7a7a133a66b76581ca571_003FAudioStreamPlayer2D_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ABabushka_002Escripts_002ECSharp_002ECommon_002EFarming_002EVesnaBehaviour2D_005FScriptProperties_002Egenerated_002Ecs_002Fl_003AC_0021_003FUsers_003FJonathan_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F4298b0f293f987511fc1b7956ee691fd778f8378_003FBabushka_002Escripts_002ECSharp_002ECommon_002EFarming_002EVesnaBehaviour2D_005FScriptProperties_002Egenerated_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ABabushka_002Escripts_002ECSharp_002ECommon_002EQuest_002EQuestListItemUi_005FScriptMethods_002Egenerated_002Ecs_002Fl_003AC_0021_003FUsers_003FJonathan_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F48fad7e7f3c9e292b3fdbddf9d363f0d1752aa_003FBabushka_002Escripts_002ECSharp_002ECommon_002EQuest_002EQuestListItemUi_005FScriptMethods_002Egenerated_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACastHelpers_002Ecs_002Fl_003AC_0021_003FUsers_003FJonathan_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F3c92637ae2e83da0a63791071c41eae291d594156062866d8621b7ed7245c_003FCastHelpers_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACastHelpers_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fd111abf504bf42b5968a609b168fd093b2e200_003Fbb_003F1c116fcd_003FCastHelpers_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACharacterBody2D_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fbba0bbd7a98ee58286e9484fbe86e01afff6232283f6efd3556eb7116453_003FCharacterBody2D_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ADictionary_00602_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003Fhome_003Fjonathan_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe37dc1faf08a4d5ea030ad59bdf77522523400_003Fd4_003Fbd338aeb_003FDictionary_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Ff1d69ec2da76ccf9bc8a75c8e0fdca9a7ba1adf8c8c9d5047e2fa5991c02eca_003FNode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AResourceLoader_002Ecs_002Fl_003AC_0021_003FUsers_003FJonathan_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F9f4e8eb124d11f8219cb513a19bed22b2120ed29f9d6785ba56e3367b48d581_003FResourceLoader_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003AC_0021_003FUsers_003FJonathan_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fc7102cd0ffb8973777e61b1942c3fffac7e14016a511d055c3adf73ff91748_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
+1
View File
@@ -0,0 +1 @@
<svg height="24" viewBox="0 0 16 16" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a1 1 0 0 0 -1 1v5h-2c-1.108 0-2 .892-2 2v1h10v-1c0-1.108-.892-2-2-2h-2v-5a1 1 0 0 0 -1-1zm-5 10v4l10-1v-3z" fill="#e0e0e0"/></svg>

After

Width:  |  Height:  |  Size: 227 B

+37
View File
@@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bmnff63evbdhv"
path="res://.godot/imported/Clear.svg-d661617e27b91e3580171e3447fde514.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/SignalVisualizer/Clear.svg"
dest_files=["res://.godot/imported/Clear.svg-d661617e27b91e3580171e3447fde514.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
@@ -0,0 +1,58 @@
class_name SignalConnection extends Object
# Properties
# |===================================|
# |===================================|
# |===================================|
var signal_id: int
var source_node_name: String
var destination_node_name: String
var method_signature: String
var description: String :
get:
return "ID: {signal_id} Source: {source_node_name} Destination: {destination_node_name} Method: {method_signature}".format({
"signal_id": signal_id,
"source_node_name": source_node_name,
"destination_node_name": destination_node_name,
"method_signature": method_signature,
})
var dictionary_key: String :
get:
return "{signal_id}__{source_node_name}__{destination_node_name}__{method_signature}".format({ "signal_id": signal_id, "source_node_name": source_node_name, "destination_node_name": destination_node_name, "method_signature": method_signature.replace("::", "_") })
var dictionary_representation: Dictionary :
get:
return {
"signal_id": signal_id,
"source_node_name": source_node_name,
"destination_node_name": destination_node_name,
"method_signature": method_signature,
}
# Lifecycle
# |===================================|
# |===================================|
# |===================================|
func _init(signal_id: int, source_node_name: String, destination_node_name: String, method_signature: String):
self.signal_id = signal_id
self.source_node_name = source_node_name
self.destination_node_name = destination_node_name
self.method_signature = method_signature
# Signals
# |===================================|
# |===================================|
# |===================================|
# Methods
# |===================================|
# |===================================|
# |===================================|
@@ -0,0 +1 @@
uid://dm613ct57qfwa
@@ -0,0 +1,56 @@
class_name SignalDescription extends Object
# Properties
# |===================================|
# |===================================|
# |===================================|
var id: int:
get:
if _source_id != null:
return _source_id
return get_instance_id()
var node_name: String
var signal_name: String
var description: String :
get:
return "ID: {id} Node: {node_name} Signal: {signal_name}".format({
"id": id,
"node_name": node_name,
"signal_name": signal_name,
})
var dictionary_representation: Dictionary :
get:
return {
"id": id,
"node_name": node_name,
"signal_name": signal_name,
}
var _source_id = null
# Lifecycle
# |===================================|
# |===================================|
# |===================================|
func _init(node_name: String, signal_name: String):
self.node_name = node_name
self.signal_name = signal_name
# Signals
# |===================================|
# |===================================|
# |===================================|
# Methods
# |===================================|
# |===================================|
# |===================================|
@@ -0,0 +1 @@
uid://dvgsocxisw3ae
@@ -0,0 +1,53 @@
class_name SignalGraph extends Object
# Properties
# |===================================|
# |===================================|
# |===================================|
var name: String
var signals: Array[SignalDescription]
var edges: Array[SignalConnection]
var description: String :
get:
return "Signals: {signals}\nEdges: {edges}".format({
"signals": signals.map(func (item): return item.description),
"edges": edges.map(func (item): return item.description),
})
var dictionary_representation: Dictionary :
get:
return {
"name": name,
"signals": signals.map(func (element): return element.dictionary_representation),
"edges": edges.map(func (element): return element.dictionary_representation),
}
# Lifecycle
# |===================================|
# |===================================|
# |===================================|
func _init(name: String, signals: Array[SignalDescription] = [], edges: Array[SignalConnection] = []):
self.name = name
self.signals = signals
self.edges = edges
# Signals
# |===================================|
# |===================================|
# |===================================|
# Methods
# |===================================|
# |===================================|
# |===================================|
func get_source_signal_for_edge(edge: SignalConnection) -> SignalDescription:
var result = signals.filter(func (item): return item.id == edge.signal_id)
if result.size() > 0:
return result[0]
return null
@@ -0,0 +1 @@
uid://2qj81iy1le0a
@@ -0,0 +1,170 @@
@tool
class_name SignalGraphUtility
static var SignalGraphNode = preload("res://addons/SignalVisualizer/Visualizer/signal_graph_node.tscn")
static var GraphNodeItem = preload("res://addons/SignalVisualizer/Visualizer/signal_graph_node_item.tscn")
const SOURCE_COLOR: Color = Color.SKY_BLUE
const DESTINATION_COLOR: Color = Color.CORAL
const CONNECTION_TYPE: int = 0
#region Methods
static func create_signal_graph(name: String, signals: Array, edges: Array) -> SignalGraph:
var signal_graph = SignalGraph.new(name)
for signal_item in signals:
var new_signal_description = SignalDescription.new(signal_item.node_name, signal_item.signal_name)
new_signal_description._source_id = signal_item.id
signal_graph.signals.append(new_signal_description)
for connection in edges:
var new_edge = SignalConnection.new(connection.signal_id, connection.source_node_name, connection.destination_node_name, connection.method_signature)
signal_graph.edges.append(new_edge)
return signal_graph
static func create_signal_graph_from_node(root_node: Node, is_persistent_only: bool = false):
var signal_graph = SignalGraph.new(root_node.scene_file_path)
var all_nodes: Array[Node] = _gather_nodes_from_node(root_node)
var signals: Array[SignalDescription] = []
var edges: Array[SignalConnection] = []
for node in all_nodes:
for signal_item in node.get_signal_list():
var existing_signals = []
var connection_list = node.get_signal_connection_list(signal_item["name"] as String)
if connection_list.size() > 0:
for connection in connection_list:
var enabled_flags = connection["flags"] == CONNECT_PERSIST if is_persistent_only else true
var should_display_connection = "name" in connection["callable"].get_object() and not connection["callable"].get_object().name.begins_with("@") and enabled_flags
if should_display_connection:
var signal_description: SignalDescription
var filtered_signals = existing_signals.filter(func (element): return element.signal_name == signal_item.name and element.node_name == node.name)
if filtered_signals.size() == 1:
signal_description = filtered_signals[0]
else:
signal_description = SignalDescription.new(node.name, signal_item.name)
existing_signals.append(signal_description)
signals.append(signal_description)
var signal_edge = SignalConnection.new(signal_description.id, signal_description.node_name, connection["callable"].get_object().name, connection["callable"].get_method())
if not signal_graph.edges.any(func (element): return element.signal_id == signal_description.id):
edges.append(signal_edge)
var temp_signals = {}
for item in signals:
temp_signals[item.id] = item
var temp_edges = {}
for item in edges:
temp_edges[item.dictionary_key] = item
signal_graph.signals.assign(temp_signals.keys().map(func (key): return temp_signals[key]))
signal_graph.edges.assign(temp_edges.keys().map(func (key): return temp_edges[key]))
return signal_graph
static func generate_signal_graph_nodes(signal_graph: SignalGraph, graph_node: GraphEdit, open_script_callable: Callable):
var graph_nodes: Dictionary = {}
for signal_item in signal_graph.signals:
var current_graph_node: SignalGraphNode
if graph_nodes.has(signal_item.node_name):
current_graph_node = graph_nodes[signal_item.node_name]
if not current_graph_node:
current_graph_node = SignalGraphNode.instantiate()
current_graph_node.title = signal_item.node_name
current_graph_node.name = _get_graph_node_name(signal_item.node_name)
graph_node.add_child(current_graph_node)
graph_nodes[signal_item.node_name] = current_graph_node
for edge in signal_graph.edges:
var destination_graph_node: SignalGraphNode
if graph_nodes.has(edge.destination_node_name):
destination_graph_node = graph_nodes[edge.destination_node_name]
else:
destination_graph_node = SignalGraphNode.instantiate()
destination_graph_node.title = edge.destination_node_name
destination_graph_node.name = _get_graph_node_name(edge.destination_node_name)
graph_node.add_child(destination_graph_node)
graph_nodes[edge.destination_node_name] = destination_graph_node
var source_signal = signal_graph.get_source_signal_for_edge(edge)
if source_signal != null:
var source_graph_node: SignalGraphNode = graph_nodes[edge.source_node_name] as SignalGraphNode
if not source_graph_node.has_source_signal_description(source_signal.signal_name, edge.destination_node_name):
var source_signal_label = Label.new()
source_signal_label.text = source_signal.signal_name
source_signal_label.name = "source_" + source_signal.signal_name + "_" + edge.destination_node_name
source_graph_node.add_child(source_signal_label)
var destination_signal_name = "destination_" + source_signal.signal_name + "_" + edge.method_signature.replace("::", "__")
var has_destination = destination_graph_node.has_destination_signal_description(source_signal.signal_name, edge.method_signature)
if not has_destination:
var destination_signal_item = GraphNodeItem.instantiate()
destination_signal_item.signal_data = SignalGraphNodeItem.Metadata.new(source_signal.signal_name, edge.method_signature, edge.destination_node_name)
destination_signal_item.text = edge.method_signature
destination_signal_item.name = destination_signal_name
destination_signal_item.open_script.connect(open_script_callable)
destination_graph_node.add_child(destination_signal_item)
for edge in signal_graph.edges:
var source_signal = signal_graph.get_source_signal_for_edge(edge)
if source_signal != null:
var source_graph_node: SignalGraphNode = graph_nodes[edge.source_node_name] as SignalGraphNode
var destination_graph_node: SignalGraphNode = graph_nodes[edge.destination_node_name] as SignalGraphNode
var from_port = source_graph_node.get_source_slot(source_signal.signal_name, edge.destination_node_name)
var to_port = destination_graph_node.get_destination_slot(source_signal.signal_name, edge.method_signature)
source_graph_node.set_slot(from_port, false, CONNECTION_TYPE, Color.BLACK, true, CONNECTION_TYPE, SOURCE_COLOR)
destination_graph_node.set_slot(to_port, true, CONNECTION_TYPE, DESTINATION_COLOR, false, CONNECTION_TYPE, Color.BLACK)
var from_slot_index = source_graph_node.get_next_source_slot(source_signal.signal_name, edge.destination_node_name)
var to_slot_index = destination_graph_node.get_next_destination_slot(source_signal.signal_name, edge.method_signature)
if from_port >= 0 and to_port >= 0:
graph_node.connect_node(source_graph_node.name, from_slot_index, destination_graph_node.name, to_slot_index)
else:
print(">>> Invalid Connection Request")
static func generate_signal_graph_tree(signal_graph: SignalGraph, tree_node: Tree):
var root = tree_node.create_item()
root.set_text(0, signal_graph.name)
var tree_items: Dictionary = {}
for signal_item in signal_graph.signals:
var node_tree_item: TreeItem
if tree_items.has(signal_item.node_name):
node_tree_item = tree_items[signal_item.node_name] as TreeItem
else:
node_tree_item = tree_node.create_item(root)
node_tree_item.set_text(0, signal_item.node_name)
tree_items[signal_item.node_name] = node_tree_item
var signal_tree_item = tree_node.create_item(node_tree_item)
signal_tree_item.set_text(0, signal_item.signal_name)
for edge in signal_graph.edges.filter(func (item): return item.signal_id == signal_item.id):
var signal_connection_tree_item = tree_node.create_item(signal_tree_item)
signal_connection_tree_item.set_text(0, edge.destination_node_name + "::" + edge.method_signature)
static func _get_graph_node_name(name: String) -> String:
return "{node_name}_graph_node".format({ "node_name": name })
static func _gather_nodes_from_node(root_node: Node) -> Array[Node]:
var node_list: Array[Node] = [root_node]
return node_list + __gather_nodes_from_node(root_node)
static func __gather_nodes_from_node(node: Node) -> Array[Node]:
var nodes: Array[Node] = []
for child in node.get_children(false):
nodes.append(child)
nodes += __gather_nodes_from_node(child)
return nodes
#endregion
@@ -0,0 +1 @@
uid://csw8uccbs0vuk
@@ -0,0 +1,146 @@
extends Node
# Properties
# |===================================|
# |===================================|
# |===================================|
var _signal_graph: SignalGraph
var _lambda_map: Dictionary = {}
# Lifecycle
# |===================================|
# |===================================|
# |===================================|
func _ready():
if OS.is_debug_build():
EngineDebugger.register_message_capture("signal_debugger", _on_signal_debugger_message_capture)
# Signals
# |===================================|
# |===================================|
# |===================================|
func _on_signal_debugger_message_capture(message: String, data: Array) -> bool:
if message == "start":
_signal_graph = generate_signal_graph()
for signal_item in _signal_graph.signals:
_connect_to_signal(signal_item)
EngineDebugger.send_message(
"signal_debugger:generated_graph",
[[_signal_graph.signals.map(func (item): return item.dictionary_representation), _signal_graph.edges.map(func (item): return item.dictionary_representation)]]
)
if message == "stop" and _signal_graph:
for signal_item in _signal_graph.signals:
_disconnect_from_signal(signal_item)
if message == "invoke_signal" and data.size() == 2:
var node_name = data[0]
var signal_name = data[1]
var root_node = get_tree().current_scene
var node = root_node if root_node.name == node_name else root_node.find_child(node_name)
if node:
var connection_list = node.get_signal_connection_list(signal_name)
for connection in connection_list:
var callable = connection["callable"]
var bound_args = callable.get_bound_arguments()
var bound_args_count = callable.get_bound_arguments_count()
var method = callable.get_method()
callable.callv([node])
return true
func _on_signal_execution(signal_name: String, node_name: String, args):
EngineDebugger.send_message(
"signal_debugger:signal_executed",
[Time.get_datetime_string_from_system(), node_name, signal_name]
)
# Methods
# |===================================|
# |===================================|
# |===================================|
func generate_signal_graph() -> SignalGraph:
var graph = SignalGraphUtility.create_signal_graph_from_node(get_tree().current_scene)
return graph
#var signal_graph = SignalGraph.new(get_tree().current_scene.name)
#var all_nodes: Array[Node] = _gather_nodes_in_scene()
#var signals: Array[SignalDescription] = []
#var edges: Array[SignalConnection] = []
#
#for node in all_nodes:
#for signal_item in node.get_signal_list():
#var existing_signals = []
#var connection_list = node.get_signal_connection_list(signal_item["name"] as String)
#if connection_list.size() > 0:
#for connection in connection_list:
#var should_display_connection = "name" in connection["callable"].get_object() and not connection["callable"].get_object().name.begins_with("@")
#if should_display_connection:
#var signal_description: SignalDescription
#var filtered_signals = existing_signals.filter(func (element): return element.signal_name == signal_item.name and element.node_name == node.name)
#if filtered_signals.size() == 1:
#signal_description = filtered_signals[0]
#else:
#signal_description = SignalDescription.new(node.name, signal_item.name)
#existing_signals.append(signal_description)
#signals.append(signal_description)
#
#var signal_edge = SignalConnection.new(signal_description.id, signal_description.node_name, connection["callable"].get_object().name, connection["callable"].get_method())
#if not signal_graph.edges.any(func (element): return element.signal_id == signal_description.id):
#edges.append(signal_edge)
#
#var temp_signals = {}
#for item in signals:
#temp_signals[item.id] = item
#
#var temp_edges = {}
#for item in edges:
#temp_edges[item.dictionary_key] = item
#
#signal_graph.signals.assign(temp_signals.keys().map(func (key): return temp_signals[key]))
#signal_graph.edges.assign(temp_edges.keys().map(func (key): return temp_edges[key]))
#
#return signal_graph
#func _gather_nodes_in_scene() -> Array[Node]:
#var scene_root = get_tree().current_scene
#var node_list: Array[Node] = [scene_root]
#return node_list + _gather_nodes_from_node(scene_root)
#
#func _gather_nodes_from_node(node: Node) -> Array[Node]:
#var nodes: Array[Node] = []
#for child in node.get_children(false):
#nodes.append(child)
#nodes += _gather_nodes_from_node(child)
#
#return nodes
func _connect_to_signal(signal_item: SignalDescription):
var root_node = get_tree().current_scene
var _execute: Callable = func (args = []): _on_signal_execution(signal_item.signal_name, signal_item.node_name, args)
if root_node.name == signal_item.node_name:
root_node.connect(signal_item.signal_name, _execute)
_lambda_map[signal_item] = _execute
else:
var child = root_node.find_child(signal_item.node_name)
if child:
child.connect(signal_item.signal_name, _execute)
_lambda_map[signal_item] = _execute
func _disconnect_from_signal(signal_item: SignalDescription):
var root_node = get_tree().current_scene
if root_node.name == signal_item.node_name:
var callable = _lambda_map[signal_item]
if callable:
root_node.disconnect(signal_item.signal_name, callable)
_lambda_map.erase(signal_item)
else:
var child = root_node.find_child(signal_item.node_name)
if child:
var callable = _lambda_map[signal_item]
if callable:
child.disconnect(signal_item.signal_name, callable)
_lambda_map.erase(signal_item)
@@ -0,0 +1 @@
uid://bmsqdh2cnmgw8
@@ -0,0 +1,97 @@
[gd_scene load_steps=5 format=3 uid="uid://cbsmvov8u78q"]
[ext_resource type="Script" path="res://addons/SignalVisualizer/Debugger/signal_debugger_panel.gd" id="1_66cpc"]
[ext_resource type="Texture2D" uid="uid://be3nwoioa311t" path="res://addons/SignalVisualizer/Play.svg" id="2_2wkuv"]
[ext_resource type="Texture2D" uid="uid://oo1oq2colx5b" path="res://addons/SignalVisualizer/Stop.svg" id="3_bg5eu"]
[ext_resource type="Texture2D" uid="uid://bmnff63evbdhv" path="res://addons/SignalVisualizer/Clear.svg" id="4_vg63r"]
[node name="SignalDebugger" type="Control"]
clip_contents = true
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_66cpc")
start_icon = ExtResource("2_2wkuv")
stop_icon = ExtResource("3_bg5eu")
[node name="VBoxContainer" type="VBoxContainer" parent="."]
clip_contents = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"]
custom_minimum_size = Vector2(2.08165e-12, 50)
layout_mode = 2
theme_override_constants/separation = 8
[node name="ActionButton" type="Button" parent="VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
disabled = true
text = "Start"
icon = ExtResource("2_2wkuv")
[node name="ClearAllButton" type="Button" parent="VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Clear All"
icon = ExtResource("4_vg63r")
[node name="Spacer" type="Control" parent="VBoxContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="ClearLogsButton" type="Button" parent="VBoxContainer/HBoxContainer"]
layout_mode = 2
text = "Clear Logs"
icon = ExtResource("4_vg63r")
[node name="HSplitContainer" type="HSplitContainer" parent="VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
[node name="SignalTree" type="Tree" parent="VBoxContainer/HSplitContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(250, 2.08165e-12)
layout_mode = 2
columns = 2
allow_reselect = true
allow_rmb_select = true
hide_root = true
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/HSplitContainer"]
layout_mode = 2
[node name="TabBar" type="TabBar" parent="VBoxContainer/HSplitContainer/VBoxContainer"]
layout_mode = 2
tab_count = 2
tab_0/title = "Signal Log"
tab_1/title = "Signal Graph"
[node name="LogLabel" type="RichTextLabel" parent="VBoxContainer/HSplitContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_colors/default_color = Color(0.690196, 0.690196, 0.690196, 1)
bbcode_enabled = true
scroll_following = true
[node name="Graph" type="GraphEdit" parent="VBoxContainer/HSplitContainer/VBoxContainer"]
unique_name_in_owner = true
visible = false
layout_mode = 2
size_flags_vertical = 3
[connection signal="pressed" from="VBoxContainer/HBoxContainer/ActionButton" to="." method="_on_action_button_pressed"]
[connection signal="pressed" from="VBoxContainer/HBoxContainer/ClearAllButton" to="." method="_on_clear_all_button_pressed"]
[connection signal="pressed" from="VBoxContainer/HBoxContainer/ClearLogsButton" to="." method="_on_clear_logs_button_pressed"]
[connection signal="item_selected" from="VBoxContainer/HSplitContainer/SignalTree" to="." method="_on_signal_tree_item_selected"]
[connection signal="tab_changed" from="VBoxContainer/HSplitContainer/VBoxContainer/TabBar" to="." method="_on_tab_bar_tab_changed"]
@@ -0,0 +1,192 @@
@tool
class_name SignalDebuggerPanel extends Control
signal open_script(node_name: String, method_signature: String)
signal start_signal_debugging
signal stop_signal_debugging
var SignalGraphNode = preload("res://addons/SignalVisualizer/Visualizer/signal_graph_node.tscn")
var GraphNodeItem = preload("res://addons/SignalVisualizer/Visualizer/signal_graph_node_item.tscn")
const SOURCE_COLOR: Color = Color.SKY_BLUE
const DESTINATION_COLOR: Color = Color.CORAL
const CONNECTION_TYPE: int = 0
enum Tabs {
LOG,
GRAPH
}
# Properties
# |===================================|
# |===================================|
# |===================================|
@export var start_icon: Texture2D
@export var stop_icon: Texture2D
@onready var action_button: Button = %ActionButton
@onready var clear_all_button: Button = %ClearAllButton
@onready var signal_tree: Tree = %SignalTree
@onready var log_label: RichTextLabel = %LogLabel
@onready var graph_node: GraphEdit = %Graph
var is_started: bool = false :
get: return is_started
set(new_value):
is_started = new_value
_update_action_button()
var _signals: Array = []
var _signal_filter: Array = []
var _is_stack_trace_enabled: bool = false
var _debugger_tab_state: Tabs = Tabs.LOG
var _graph: SignalGraph
# Lifecycle
# |===================================|
# |===================================|
# |===================================|
func _ready():
disable()
_handle_tab_update(0)
# Signals
# |===================================|
# |===================================|
# |===================================|
func _on_action_button_pressed():
if is_started:
stop()
else:
start()
func _on_clear_all_button_pressed():
log_label.clear()
signal_tree.clear()
graph_node.clear_connections()
for child in graph_node.get_children():
if child is SignalGraphNode:
child.queue_free()
func _on_clear_logs_button_pressed():
log_label.clear()
func _on_signal_tree_item_selected():
# Updates the checkmark button
var selected_item = signal_tree.get_selected()
var is_checked = selected_item.is_checked(1)
selected_item.set_checked(1, (not is_checked))
# Add / Remove signal from filters
var selected_signal = _signals.filter(func (element): return element.signal_name == selected_item.get_text(0))[0]
if _signal_filter.has(selected_signal.signal_name):
var selected_index = _signal_filter.find(selected_signal.signal_name)
_signal_filter.remove_at(selected_index)
else:
_signal_filter.append(selected_signal.signal_name)
func _on_tab_bar_tab_changed(tab: int):
_handle_tab_update(tab)
func _on_stack_trace_button_pressed():
_is_stack_trace_enabled = not _is_stack_trace_enabled
func _on_open_signal_in_script(data: SignalGraphNodeItem.Metadata):
open_script.emit(data.node_name, data.method_signature)
# Methods
# |===================================|
# |===================================|
# |===================================|
func enable():
action_button.disabled = false
func disable():
action_button.disabled = true
func start():
if not is_started:
is_started = true
action_button.icon = stop_icon
start_signal_debugging.emit()
log_label.append_text("[color=#B0B0B0]Signal Debugging Started...[/color]")
log_label.newline()
log_label.newline()
func stop():
if is_started:
is_started = false
action_button.icon = start_icon
stop_signal_debugging.emit()
log_label.newline()
log_label.append_text("[color=#B0B0B0]Signal Debugging Stopped[/color]")
log_label.newline()
log_label.newline()
func create_tree_from_signals(signals: Array):
_signals = signals
var root = signal_tree.create_item()
root.set_text(0, "Signals")
var tree_items: Dictionary = {}
for signal_item in signals:
var node_tree_item: TreeItem
if tree_items.has(signal_item.node_name):
node_tree_item = tree_items[signal_item.node_name] as TreeItem
else:
node_tree_item = signal_tree.create_item(root)
node_tree_item.set_text(0, signal_item.node_name)
node_tree_item.set_selectable(0, false)
node_tree_item.set_selectable(1, false)
tree_items[signal_item.node_name] = node_tree_item
var signal_tree_item = signal_tree.create_item(node_tree_item)
signal_tree_item.set_text(0, signal_item.signal_name)
signal_tree_item.set_cell_mode(1, TreeItem.CELL_MODE_CHECK)
signal_tree_item.set_checked(1, true)
signal_tree_item.set_selectable(0, false)
signal_tree_item.set_selectable(1, true)
func create_signal_graph(signals: Array, edges: Array):
_graph = SignalGraphUtility.create_signal_graph(get_tree().edited_scene_root.scene_file_path, signals, edges)
SignalGraphUtility.generate_signal_graph_nodes(_graph, graph_node, _on_open_signal_in_script)
func log_signal_execution(time: String, node_name: String, signal_name: String):
if _signal_filter != null and _signal_filter.has(signal_name):
return
if not log_label.text.is_empty():
log_label.newline()
log_label.append_text(
"[color=#FFCC00]{time}[/color]\t\t{node_name}\t\t{signal_name}".format({ "time": time, "node_name": node_name, "signal_name": signal_name })
)
log_label.newline()
func _handle_tab_update(selected_tab_index: int):
match selected_tab_index:
1:
_debugger_tab_state = Tabs.GRAPH
_:
_debugger_tab_state = Tabs.LOG
match _debugger_tab_state:
Tabs.LOG:
log_label.show()
graph_node.hide()
Tabs.GRAPH:
log_label.hide()
graph_node.show()
func _update_action_button():
if is_started:
action_button.text = "Stop"
action_button.modulate = Color("#ff3b30")
else:
action_button.text = "Start"
action_button.modulate = Color.WHITE
@@ -0,0 +1 @@
uid://yg8cqm6f1prd
+1
View File
@@ -0,0 +1 @@
<svg height="24" width="24" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M11 1a1 1 0 0 0-1 1v3a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1zM6.732 5A2 2 0 0 1 7 6v1.117L9.268 6A2 2 0 0 1 9 5V3.883zM2 5a1 1 0 0 0-1 1v4a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1zm5 3.883V10a2 2 0 0 1-.268 1L9 12.117V11a2 2 0 0 1 .268-1zM11 10a1 1 0 0 0-1 1v3a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-3a1 1 0 0 0-1-1z" fill="#8eef97"/></svg>

After

Width:  |  Height:  |  Size: 437 B

@@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bxj8ep08wbnm6"
path="res://.godot/imported/GraphEdit.svg-90dae61e8e0b157ab8eff95fe4b91e53.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/SignalVisualizer/GraphEdit.svg"
dest_files=["res://.godot/imported/GraphEdit.svg-90dae61e8e0b157ab8eff95fe4b91e53.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
+1
View File
@@ -0,0 +1 @@
<svg height="24" viewBox="0 0 16 16" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M4 12a1 1 0 0 0 1.555.832l6-4a1 1 0 0 0 0-1.664l-6-4A1 1 0 0 0 4 4z" fill="#e0e0e0"/></svg>

After

Width:  |  Height:  |  Size: 184 B

+37
View File
@@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://be3nwoioa311t"
path="res://.godot/imported/Play.svg-a446691ffcef211028bb160b5a2d6ff1.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/SignalVisualizer/Play.svg"
dest_files=["res://.godot/imported/Play.svg-a446691ffcef211028bb160b5a2d6ff1.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
+162
View File
@@ -0,0 +1,162 @@
@tool
extends EditorPlugin
class SignalDebuggerPlugin extends EditorDebuggerPlugin:
var SignalDebuggerPanelScene = preload("res://addons/SignalVisualizer/Debugger/SignalDebugger.tscn")
signal open_script
signal start_signal_debugging
signal stop_signal_debugging
var debugger_panel
func _has_capture(prefix) -> bool:
return prefix == "signal_debugger"
func _capture(message, data, session_id) -> bool:
if message == "signal_debugger:signal_executed":
if data.size() == 3:
var time = data[0]
var node_name = data[1]
var signal_name = data[2]
debugger_panel.log_signal_execution(time, node_name, signal_name)
return true
if message == "signal_debugger:generated_graph":
if data.size() == 1:
var signals = data[0][0] as Array
var edges = data[0][1] as Array
debugger_panel.create_tree_from_signals(signals)
debugger_panel.create_signal_graph(signals, edges)
return true
return false
func _setup_session(session_id):
debugger_panel = SignalDebuggerPanelScene.instantiate()
var session = get_session(session_id)
debugger_panel.name = "Signal Debugger"
debugger_panel.open_script.connect(func (arg1, arg2): open_script.emit(arg1, arg2))
debugger_panel.start_signal_debugging.connect(func (): start_signal_debugging.emit())
debugger_panel.stop_signal_debugging.connect(func (): stop_signal_debugging.emit())
session.started.connect(
func ():
debugger_panel.enable()
)
session.stopped.connect(
func ():
debugger_panel.stop()
debugger_panel.disable()
stop_signal_debugging.emit()
)
session.add_session_tab(debugger_panel)
var SignalVisualizerDockScene = preload("res://addons/SignalVisualizer/Visualizer/signal_visualizer_dock.tscn")
class ScriptMethodReference:
var script_reference: Script
var line_number: int
# Properties
# |===================================|
# |===================================|
# |===================================|
var dock: Control
var debugger: SignalDebuggerPlugin
# Lifecycle
# |===================================|
# |===================================|
# |===================================|
func _enter_tree():
dock = SignalVisualizerDockScene.instantiate()
debugger = SignalDebuggerPlugin.new()
dock.open_script.connect(_on_open_signal_in_script)
add_control_to_bottom_panel(dock, "Signal Visualizer")
debugger.start_signal_debugging.connect(_on_debugger_start_signal_debugging)
debugger.stop_signal_debugging.connect(_on_debugger_stop_signal_debugging)
debugger.open_script.connect(_on_open_signal_in_script)
add_debugger_plugin(debugger)
if not ProjectSettings.has_setting("autoload/Signal_Debugger"):
add_autoload_singleton("Signal_Debugger", "res://addons/SignalVisualizer/Debugger/SignalDebugger.gd")
func _exit_tree():
remove_control_from_bottom_panel(dock)
dock.free()
remove_debugger_plugin(debugger)
remove_autoload_singleton("Signal_Debugger")
# Signals
# |===================================|
# |===================================|
# |===================================|
func _on_open_signal_in_script(node_name: String, method_signature: String):
var node: Node
if get_tree().edited_scene_root.name == node_name:
node = get_tree().edited_scene_root
else:
node = get_tree().edited_scene_root.find_child(node_name)
if node != null:
var script: Script = node.get_script()
if script != null:
var editor = get_editor_interface()
var method_reference = _find_method_reference_in_script(script, method_signature)
if method_reference != null:
editor.edit_script(method_reference.script_reference, method_reference.line_number, 0)
editor.set_main_screen_editor("Script")
else:
push_warning("Requested method in script ({script}) for node ({name}) is not available.".format({ "name": node_name, "script": script.name }))
else:
push_warning("Requested script for node ({name}) is not available.".format({ "name": node_name }))
else:
push_warning("Requested script for node ({name}) is not available.".format({ "name": node_name }))
func _on_debugger_start_signal_debugging():
for session in debugger.get_sessions():
session.send_message("signal_debugger:start", [])
func _on_debugger_stop_signal_debugging():
for session in debugger.get_sessions():
session.send_message("signal_debugger:stop", [])
# Methods
# |===================================|
# |===================================|
# |===================================|
func _find_method_reference_in_script(script: Script, method_signature: String) -> ScriptMethodReference:
var line_number = __find_method_line_number_in_script(script, method_signature)
if line_number == -1:
var base_script = script.get_base_script()
if base_script:
return _find_method_reference_in_script(base_script, method_signature)
var reference = ScriptMethodReference.new()
reference.script_reference = script
reference.line_number = line_number
return reference
func __find_method_line_number_in_script(script: Script, method_signature: String) -> int:
var line_number = 0
var found = false
for line in script.source_code.split("\n", true):
line_number += 1
if line.contains(method_signature):
found = true
return line_number
return -1
@@ -0,0 +1 @@
uid://43lcsn3nt3ri
+1
View File
@@ -0,0 +1 @@
<svg height="24" viewBox="0 0 16 16" width="24" xmlns="http://www.w3.org/2000/svg"><rect x="3" y="3" height="10" width="10" rx="1" fill="#e0e0e0"/></svg>

After

Width:  |  Height:  |  Size: 154 B

+37
View File
@@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://oo1oq2colx5b"
path="res://.godot/imported/Stop.svg-e085086fb31c334bc2f02ca2bffba522.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/SignalVisualizer/Stop.svg"
dest_files=["res://.godot/imported/Stop.svg-e085086fb31c334bc2f02ca2bffba522.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
@@ -0,0 +1,31 @@
@tool
extends Label
# Properties
# |===================================|
# |===================================|
# |===================================|
# Lifecycle
# |===================================|
# |===================================|
# |===================================|
# Signals
# |===================================|
# |===================================|
# |===================================|
# Methods
# |===================================|
# |===================================|
# |===================================|
func get_text_size() -> Vector2:
return get_theme_default_font().get_string_size(text)
@@ -0,0 +1 @@
uid://d3lyqancfvwup
@@ -0,0 +1,94 @@
@tool
class_name SignalGraphNode extends GraphNode
# Properties
# |===================================|
# |===================================|
# |===================================|
var connections: Array = [] :
get: return connections
set(new_value):
connections = new_value
# Lifecycle
# |===================================|
# |===================================|
# |===================================|
func _ready():
selectable = true
resizable = true
draggable = true
# Signals
# |===================================|
# |===================================|
# |===================================|
func _on_resize_request(new_minsize):
size = new_minsize
# Methods
# |===================================|
# |===================================|
# |===================================|
func has_source_signal_description(signal_name: String, destination_node_name: String) -> bool:
for child in get_children():
if child.name == "source_" + signal_name + "_" + destination_node_name:
return true
return false
func get_source_slot(signal_name: String, destination_node_name: String) -> int:
var index = 0
for child in get_children():
if child.name == "source_" + signal_name + "_" + destination_node_name:
return index
index += 1
return -1
func get_next_source_slot(signal_name: String, destination_node_name: String) -> int:
var index = 0
for child in get_children():
if child.name.begins_with("source_"):
if child.name == "source_" + signal_name + "_" + destination_node_name:
return index
index += 1
return -1
func has_destination_signal_description(signal_name: String, method_signature: String) -> bool:
for child in get_children():
if child.name == "destination_" + signal_name + "_" + _sanitize_method_signature(method_signature):
return true
return false
func get_destination_slot(signal_name: String, method_signature: String) -> int:
var index = 0
for child in get_children():
if child.name == "destination_" + signal_name + "_" + _sanitize_method_signature(method_signature):
return index
index += 1
return -1
func get_next_destination_slot(signal_name: String, method_signature: String) -> int:
var index = 0
for child in get_children():
if child.name.begins_with("destination_"):
if child.name == "destination_" + signal_name + "_" + _sanitize_method_signature(method_signature):
return index
index += 1
return -1
func _sanitize_method_signature(signature: String) -> String:
return signature.replace("::", "__")
@@ -0,0 +1 @@
uid://bdwkkgkhgfrtk
@@ -0,0 +1,12 @@
[gd_scene load_steps=2 format=3 uid="uid://cq10iaub18e54"]
[ext_resource type="Script" path="res://addons/SignalVisualizer/Visualizer/signal_graph_node.gd" id="1_ovklj"]
[node name="SignalGraphNode" type="GraphNode"]
custom_minimum_size = Vector2(100, 50)
offset_right = 232.0
offset_bottom = 54.0
resizable = true
script = ExtResource("1_ovklj")
[connection signal="resize_request" from="." to="." method="_on_resize_request"]
@@ -0,0 +1,57 @@
@tool
class_name SignalGraphNodeItem extends Control
signal open_script(metadata: SignalGraphNodeItem.Metadata)
class Metadata:
var signal_name: String
var method_signature: String
var node_name: String
func _init(signal_name: String, method_signature: String, node_name: String):
self.signal_name = signal_name
self.method_signature = method_signature
self.node_name = node_name
# Properties
# |===================================|
# |===================================|
# |===================================|
@onready var label: Label = %DescriptionLabel
var signal_data: Metadata = null
var text: String = "" :
get: return text
set(new_value):
text = new_value
if label:
label.text = text
# Lifecycle
# |===================================|
# |===================================|
# |===================================|
func _ready():
_update()
# Signals
# |===================================|
# |===================================|
# |===================================|
func _on_open_signal_in_script_button_pressed():
open_script.emit(signal_data)
# Methods
# |===================================|
# |===================================|
# |===================================|
func _update():
label.text = text
var text_size = label.get_text_size()
custom_minimum_size = Vector2((text_size.x * 2) + 50, text_size.y * 3)
@@ -0,0 +1 @@
uid://c0n3sifmbiih0
@@ -0,0 +1,43 @@
[gd_scene load_steps=3 format=3 uid="uid://b2lwtwp6kpwtb"]
[ext_resource type="Script" path="res://addons/SignalVisualizer/Visualizer/signal_graph_node_item.gd" id="1_jrd34"]
[ext_resource type="Script" path="res://addons/SignalVisualizer/Visualizer/resizable_label.gd" id="2_4wwd5"]
[node name="SignalItem" type="Control"]
clip_contents = true
custom_minimum_size = Vector2(51, 23)
layout_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
script = ExtResource("1_jrd34")
[node name="HBoxContainer" type="HBoxContainer" parent="."]
custom_minimum_size = Vector2(100, 50)
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="DescriptionLabel" type="Label" parent="HBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(100, 50)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 1
vertical_alignment = 1
clip_text = true
script = ExtResource("2_4wwd5")
[node name="OpenSignalInScriptButton" type="Button" parent="HBoxContainer"]
layout_mode = 2
text = "Open"
flat = true
[connection signal="pressed" from="HBoxContainer/OpenSignalInScriptButton" to="." method="_on_open_signal_in_script_button_pressed"]
@@ -0,0 +1,67 @@
@tool
extends Control
signal open_script(node_name: String, method_signature: String)
var SignalGraphNode = preload("res://addons/SignalVisualizer/Visualizer/signal_graph_node.tscn")
var GraphNodeItem = preload("res://addons/SignalVisualizer/Visualizer/signal_graph_node_item.tscn")
# Properties
# |===================================|
# |===================================|
# |===================================|
const SOURCE_COLOR: Color = Color.SKY_BLUE
const DESTINATION_COLOR: Color = Color.CORAL
const CONNECTION_TYPE: int = 0
@onready var arrange_nodes_checkbox: CheckBox = %ArrangeNodesCheckBox
@onready var signal_details_checkbox: CheckBox = %SignalDetailsCheckBox
@onready var signal_tree: Tree = %SignalTree
@onready var graph: GraphEdit = %Graph
# Lifecycle
# |===================================|
# |===================================|
# |===================================|
# Signals
# |===================================|
# |===================================|
# |===================================|
func _on_clear_graph_button_pressed():
clear()
func _on_generate_graph_button_pressed():
clear()
var scene_signal_graph = SignalGraphUtility.create_signal_graph_from_node(get_tree().edited_scene_root, true)
SignalGraphUtility.generate_signal_graph_nodes(scene_signal_graph, graph, _on_open_signal_in_script)
SignalGraphUtility.generate_signal_graph_tree(scene_signal_graph, signal_tree)
if arrange_nodes_checkbox.button_pressed:
graph.arrange_nodes()
func _on_open_signal_in_script(data: SignalGraphNodeItem.Metadata):
open_script.emit(data.node_name, data.method_signature)
# Methods
# |===================================|
# |===================================|
# |===================================|
func clear():
_clear_graph_nodes()
_clear_tree()
func _clear_graph_nodes():
graph.clear_connections()
for child in graph.get_children():
if child is SignalGraphNode:
child.queue_free()
func _clear_tree():
signal_tree.clear()
@@ -0,0 +1 @@
uid://bbd48wbihmuos
@@ -0,0 +1,78 @@
[gd_scene load_steps=5 format=3 uid="uid://dppfamjc0ji40"]
[ext_resource type="Script" path="res://addons/SignalVisualizer/Visualizer/signal_visualizer_dock.gd" id="1_akar5"]
[ext_resource type="Texture2D" uid="uid://bmnff63evbdhv" path="res://addons/SignalVisualizer/Clear.svg" id="2_m8bsv"]
[ext_resource type="Texture2D" uid="uid://bxj8ep08wbnm6" path="res://addons/SignalVisualizer/GraphEdit.svg" id="3_dtmqs"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ae0jg"]
[node name="SignalVisualizerDock" type="Control"]
clip_contents = true
custom_minimum_size = Vector2(2.08165e-12, 200)
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_akar5")
[node name="VBoxContainer" type="VBoxContainer" parent="."]
clip_contents = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"]
clip_contents = true
custom_minimum_size = Vector2(2.08165e-12, 50)
layout_mode = 2
theme_override_constants/separation = 8
alignment = 2
[node name="ArrangeNodesCheckBox" type="CheckBox" parent="VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Arrange Nodes"
[node name="SignalDetailsCheckBox" type="CheckBox" parent="VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Signal Details"
[node name="Panel" type="Panel" parent="VBoxContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_styles/panel = SubResource("StyleBoxEmpty_ae0jg")
[node name="ClearGraphButton" type="Button" parent="VBoxContainer/HBoxContainer"]
layout_mode = 2
text = "Clear Graph"
icon = ExtResource("2_m8bsv")
[node name="GenerateGraphButton" type="Button" parent="VBoxContainer/HBoxContainer"]
layout_mode = 2
text = "Generate Graph"
icon = ExtResource("3_dtmqs")
[node name="HSplitContainer" type="HSplitContainer" parent="VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
[node name="SignalTree" type="Tree" parent="VBoxContainer/HSplitContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(200, 2.08165e-12)
layout_mode = 2
column_titles_visible = true
[node name="Graph" type="GraphEdit" parent="VBoxContainer/HSplitContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
[connection signal="pressed" from="VBoxContainer/HBoxContainer/ClearGraphButton" to="." method="_on_clear_graph_button_pressed"]
[connection signal="pressed" from="VBoxContainer/HBoxContainer/GenerateGraphButton" to="." method="_on_generate_graph_button_pressed"]
+7
View File
@@ -0,0 +1,7 @@
[plugin]
name="SignalVisualizer"
description="Visual the current scene's signal connections as a graph. Debug the current running scene's signals with automatic logging in a new debugger panel."
author="MiniGameDev"
version="1.7.0"
script="SignalVisualizer.gd"
+22
View File
@@ -0,0 +1,22 @@
@tool
extends EditorPlugin
func _enter_tree() -> void:
if !ProjectSettings.has_setting("babushka/hacks/speed_hack"):
ProjectSettings.set_setting("babushka/hacks/speed_hack",-1)
var property_info = {
"name": "babushka/hacks/speed_hack",
"type": TYPE_FLOAT,
"hint": PROPERTY_HINT_RANGE,
"hint_string": "-1,20,0.5"
}
ProjectSettings.add_property_info(property_info)
ProjectSettings.set_initial_value("babushka/hacks/speed_hack",-1)
func _exit_tree() -> void:
# Clean-up of the plugin goes here.
pass
@@ -0,0 +1 @@
uid://buwfplh0xji8q
+7
View File
@@ -0,0 +1,7 @@
[plugin]
name="BabushkaHelpers"
description=""
author="Cozy Raven"
version=""
script="babushkahelpers.gd"
@@ -21,5 +21,5 @@ anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
color = Color(1, 1, 1, 0)
color = Color(0, 0, 0, 0.658824)
script = ExtResource("2_ghan2")
@@ -10,3 +10,4 @@ corner_radius_top_left = 5
corner_radius_top_right = 5
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
shadow_color = Color(0, 0, 0, 0.772549)
+19
View File
@@ -0,0 +1,19 @@
[gd_resource type="Resource" script_class="DialogicStyle" load_steps=4 format=3 uid="uid://d0w0cnruamnn1"]
[ext_resource type="Script" uid="uid://dfx2htp24tuvm" path="res://addons/dialogic/Resources/dialogic_style_layer.gd" id="1_tjdw8"]
[ext_resource type="Script" uid="uid://b14h380mah4av" path="res://addons/dialogic/Resources/dialogic_style.gd" id="2_ae84x"]
[sub_resource type="Resource" id="Resource_qrxdt"]
script = ExtResource("1_tjdw8")
overrides = {}
[resource]
script = ExtResource("2_ae84x")
name = "New_File"
layer_list = Array[String]([])
layer_info = {
"": SubResource("Resource_qrxdt")
}
base_overrides = {}
layers = Array[ExtResource("1_tjdw8")]([])
metadata/_latest_layer = ""
+2
View File
@@ -95,6 +95,8 @@ func _make_visible(visible:bool) -> void:
func _save_external_data() -> void:
if _editor_view_and_manager_exist():
editor_view.editors_manager.save_current_resource()
DialogicResourceUtil.update_directory('.tres')
func _get_unsaved_status(for_scene:String) -> String:
@@ -0,0 +1,55 @@
@tool
extends DialogicEvent
class_name DialogicQuestActivateEvent
# Define properties of the event here
var quest_resource: String
func _execute() -> void:
var resource = ResourceLoader.load(quest_resource)
QuestManager.ChangeQuestStatus(resource,QuestEventUtils.QuestStatus.AVAILABLE)
QuestManager.SetFollowQuest(resource)
finish() # called to continue with the next event
#region INITIALIZE
################################################################################
# Set fixed settings of this event
func _init() -> void:
event_name = "Activate Quest"
event_category = "Quest"
#endregion
#region SAVING/LOADING
################################################################################
func get_shortcode() -> String:
return "quest_activate"
func get_shortcode_parameters() -> Dictionary:
return {
#param_name : property_info
"quest_resource" : {"property": "quest_resource", "default": ""},
}
# You can alternatively overwrite these 3 functions: to_text(), from_text(), is_valid_event()
#endregion
#region EDITOR REPRESENTATION
################################################################################
func build_event_editor() -> void:
add_header_label("Activate Quest")
add_header_edit(
"quest_resource",
ValueType.DYNAMIC_OPTIONS,
{
"mode":2,
"suggestions_func":QuestEventUtils.quest_resource_suggestrions
})
#endregion
@@ -0,0 +1 @@
uid://br3a7napsjmg3
@@ -0,0 +1,55 @@
@tool
extends DialogicEvent
class_name DialogicQuestCompleteEvent
# Define properties of the event here
var quest_resource: String
func _execute() -> void:
var resource = ResourceLoader.load(quest_resource)
QuestManager.ChangeQuestStatus(resource,QuestEventUtils.QuestStatus.DONE)
QuestManager.SetFollowQuest(null)
finish() # called to continue with the next event
#region INITIALIZE
################################################################################
# Set fixed settings of this event
func _init() -> void:
event_name = "Complete Quest"
event_category = "Quest"
#endregion
#region SAVING/LOADING
################################################################################
func get_shortcode() -> String:
return "quest_complete"
func get_shortcode_parameters() -> Dictionary:
return {
#param_name : property_info
"quest_resource" : {"property": "quest_resource", "default": ""},
}
# You can alternatively overwrite these 3 functions: to_text(), from_text(), is_valid_event()
#endregion
#region EDITOR REPRESENTATION
################################################################################
func build_event_editor() -> void:
add_header_label("Complete Quest")
add_header_edit(
"quest_resource",
ValueType.DYNAMIC_OPTIONS,
{
"mode":2,
"suggestions_func":QuestEventUtils.quest_resource_suggestrions
})
#endregion
@@ -0,0 +1 @@
uid://c8mtjwpe7c0h
@@ -0,0 +1,163 @@
@tool
extends DialogicEvent
class_name DialogicQuestConditionEvent
## Event that allows branching a timeline based on a condition.
#enum ConditionTypes {IF, ELIF, ELSE}
### Settings
## condition type (see [ConditionTypes]). Defaults to if.
#var condition_type := ConditionTypes.IF
## The condition as a string. Will be executed as an Expression.
#var condition := ""
var quest_resource: String
var compare_status: QuestEventUtils.QuestStatusOrActive
################################################################################
## EXECUTE
################################################################################
func _execute() -> void:
var resource = ResourceLoader.load(quest_resource)
var result: bool
if compare_status == QuestEventUtils.QuestStatusOrActive.ACTIVE:
result = QuestManager.GetFollowQuest() == resource
elif compare_status == QuestEventUtils.QuestStatusOrActive.NOT_ACTIVE:
result = QuestManager.GetFollowQuest() != resource
else:
result = QuestManager.GetQuestStatus(resource).status == compare_status
if not result:
var idx: int = dialogic.current_event_idx
var ignore := 1
while true:
idx += 1
if not dialogic.current_timeline.get_event(idx) or ignore == 0:
break
elif dialogic.current_timeline.get_event(idx).can_contain_events:
ignore += 1
elif dialogic.current_timeline.get_event(idx) is DialogicEndBranchEvent:
ignore -= 1
dialogic.current_event_idx = idx-1
finish()
## only called if the previous event was an end-branch event
## return true if this event should be executed if the previous event was an end-branch event
func should_execute_this_branch() -> bool:
return true
################################################################################
## INITIALIZE
################################################################################
func _init() -> void:
event_name = "Quest Condition"
set_default_color('Color3')
event_category = "Quest"
event_sorting_index = 1
can_contain_events = true
# return a control node that should show on the END BRANCH node
func get_end_branch_control() -> Control:
return load(get_script().resource_path.get_base_dir().path_join('ui_quest_condition_end.tscn')).instantiate()
################################################################################
## SAVING/LOADING
################################################################################
func to_text() -> String:
return 'ifquest ' + quest_resource + ', ' + str(compare_status) + ':'
func from_text(string:String) -> void:
#if string.strip_edges().begins_with('if'):
# condition = string.strip_edges().trim_prefix('if ').trim_suffix(':').strip_edges()
# condition_type = ConditionTypes.IF
var strings:Array[String]
strings.assign(string.strip_edges().trim_prefix('ifquest ').trim_suffix(':').strip_edges().split(','))
quest_resource = strings[0].strip_edges()
var compare_string: String = strings[1].strip_edges()
if compare_string.is_valid_int():
compare_status = compare_string.to_int()
else:
compare_status = QuestEventUtils.QuestStatusOrActive.get(compare_string)
func is_valid_event(string:String) -> bool:
if string.strip_edges().begins_with('ifquest '):
return true
return false
################################################################################
## EDITOR REPRESENTATION
################################################################################
func build_event_editor() -> void:
add_header_label("IF")
add_header_edit(
"quest_resource",
ValueType.DYNAMIC_OPTIONS,
{
"mode":2,
"suggestions_func":QuestEventUtils.quest_resource_suggestrions
})
add_header_label("IS")
add_header_edit("compare_status",ValueType.FIXED_OPTIONS,{
'options': [
{
'label': 'HIDDEN',
'value': QuestEventUtils.QuestStatusOrActive.HIDDEN,
},
{
'label': 'AVAILABLE',
'value': QuestEventUtils.QuestStatusOrActive.AVAILABLE,
},
{
'label': 'DONE',
'value': QuestEventUtils.QuestStatusOrActive.DONE,
},
{
'label': 'CANCLED',
'value': QuestEventUtils.QuestStatusOrActive.CANCLED,
},
{
'label': 'ACTIVE',
'value': QuestEventUtils.QuestStatusOrActive.ACTIVE,
},
{
'label': 'NOT_ACTIVE',
'value': QuestEventUtils.QuestStatusOrActive.NOT_ACTIVE,
}
]})
func _get_icon() -> Resource:
return load("res://addons/dialogic/Modules/Condition/icon.svg")
####################### CODE COMPLETION ########################################
################################################################################
func _get_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit, line:String, _word:String, symbol:String) -> void:
pass
func _get_start_code_completion(_CodeCompletionHelper:Node, TextNode:TextEdit) -> void:
TextNode.add_code_completion_option(CodeEdit.KIND_PLAIN_TEXT, 'ifquest', 'ifquest ', TextNode.syntax_highlighter.code_flow_color)
#################### SYNTAX HIGHLIGHTING #######################################
################################################################################
func _get_syntax_highlighting(Highlighter:SyntaxHighlighter, dict:Dictionary, line:String) -> Dictionary:
var word := line.get_slice(' ', 0)
dict[line.find(word)] = {"color":Highlighter.code_flow_color}
dict[line.find(word)+len(word)] = {"color":Highlighter.normal_color}
dict = Highlighter.color_condition(dict, line)
return dict
@@ -0,0 +1 @@
uid://b2ggc2f5kh61j
@@ -0,0 +1,43 @@
@tool
class_name QuestEventUtils
enum QuestStatus{
HIDDEN = 0,
AVAILABLE = 1,
DONE = 2,
CANCLED = 3
}
enum QuestStatusOrActive{
HIDDEN = 0,
AVAILABLE = 1,
DONE = 2,
CANCLED = 3,
ACTIVE = 4,
NOT_ACTIVE = 5
}
static func quest_resource_suggestrions(search_text:String) -> Dictionary:
var ret_val = {}
var quest_paths = get_all_file_paths("res://resources/quests")
for path in quest_paths:
var res = ResourceLoader.load(path)
ret_val[res.id]= {"value":path, "tooltip":res.title + "\n\n" + res.description}
return ret_val
static func get_all_file_paths(path: String) -> Array[String]:
var file_paths: Array[String] = []
var dir = DirAccess.open(path)
dir.list_dir_begin()
var file_name = dir.get_next()
while file_name != "":
var file_path = path + "/" + file_name
if dir.current_is_dir():
file_paths += get_all_file_paths(file_path)
else:
file_paths.append(file_path)
file_name = dir.get_next()
return file_paths
@@ -0,0 +1 @@
uid://d1x2343wpkdku
+9
View File
@@ -0,0 +1,9 @@
@tool
extends DialogicIndexer
func _get_events() -> Array:
return [
this_folder.path_join('event_quest_activate.gd'),
this_folder.path_join('event_quest_complete.gd'),
this_folder.path_join('event_quest_condition.gd')
]
@@ -0,0 +1 @@
uid://wup1fvm05rqv
@@ -0,0 +1,51 @@
@tool
extends HBoxContainer
var parent_resource: DialogicEvent = null
func _ready() -> void:
$AddElif.button_up.connect(add_elif)
$AddElse.button_up.connect(add_else)
func refresh() -> void:
if parent_resource is DialogicQuestConditionEvent:
# hide add elif and add else button on ELSE event
$AddElif.visible = false# parent_resource.condition_type != DialogicConditionEvent.ConditionTypes.ELSE
$AddElse.visible = true# parent_resource.condition_type != DialogicConditionEvent.ConditionTypes.ELSE
$Label.text = "End of If Quest" #"End of "+["IF", "ELIF", "ELSE"][parent_resource.condition_type]+" ("+parent_resource.condition+")"
# hide add add else button if followed by ELIF or ELSE event
var timeline_editor := find_parent('VisualEditor')
if timeline_editor:
var next_event: DialogicEvent = null
if timeline_editor.get_block_below(get_parent()):
next_event = timeline_editor.get_block_below(get_parent()).resource
if next_event is DialogicConditionEvent:
if next_event.condition_type != DialogicConditionEvent.ConditionTypes.IF:
$AddElse.hide()
#if parent_resource.condition_type == DialogicConditionEvent.ConditionTypes.ELSE:
# $Label.text = "End of ELSE"
else:
hide()
func add_elif() -> void:
var timeline := find_parent('VisualEditor')
if timeline:
var resource := DialogicConditionEvent.new()
resource.condition_type = DialogicConditionEvent.ConditionTypes.ELIF
timeline.add_event_undoable(resource, get_parent().get_index()+1)
timeline.indent_events()
timeline.something_changed()
func add_else() -> void:
var timeline := find_parent('VisualEditor')
if timeline:
var resource := DialogicConditionEvent.new()
resource.condition_type = DialogicConditionEvent.ConditionTypes.ELSE
timeline.add_event_undoable(resource, get_parent().get_index()+1)
timeline.indent_events()
timeline.something_changed()
@@ -0,0 +1 @@
uid://dlrnhnnonum4o
@@ -0,0 +1,20 @@
[gd_scene load_steps=2 format=3 uid="uid://dnrpcgjkyoiau"]
[ext_resource type="Script" uid="uid://dlrnhnnonum4o" path="res://addons/dialogic_additions/Quest/ui_condition_end.gd" id="1_f3miq"]
[node name="Condition_End" type="HBoxContainer"]
offset_right = 90.0
offset_bottom = 23.0
script = ExtResource("1_f3miq")
[node name="Label" type="Label" parent="."]
layout_mode = 2
text = "End of condition X"
[node name="AddElif" type="Button" parent="."]
layout_mode = 2
text = "Add Elif"
[node name="AddElse" type="Button" parent="."]
layout_mode = 2
text = "Add Else"
@@ -0,0 +1,510 @@
{
"swagger": "2.0",
"info": {
"title": "LanguageTool API",
"description": "Check texts for style and grammar issues with <a href='https://languagetool.org'>LanguageTool</a>. Please consider the following default limitations:<ul><li>your daily request limit depending on <a href='https://languagetool.org/editor/settings/access-tokens'>your plan</a> <li>maximum number of requests per minute: 20 (free) / 80 (Premium) <li>maximum number of characters per minute: 75,000 (free) / 300,000 (Premium) <li>maximum number of characters per request: 20,000 (free) / 60,000 (Premium) <li>for the free version, also consider the <a href='https://dev.languagetool.org/public-http-api'>limitations documented here</a> <li><b>Note:</b> any parameters or outputs not part of this documentation are internal and must not be relied on</ul> Need more generous limits? Just <a href='https://languagetool.org/proofreading-api'>contact us</a>.",
"version": "1.1.2"
},
"host": "api.languagetoolplus.com",
"schemes": [
"https"
],
"basePath": "/v2",
"produces": [
"application/json"
],
"paths": {
"/check": {
"post": {
"summary": "Check a text",
"description": "The main feature - check a text with LanguageTool for possible style and grammar issues.",
"parameters": [
{
"name": "text",
"in": "formData",
"type": "string",
"description": "The text to be checked. This or 'data' is required.",
"required": false
},
{
"name": "data",
"in": "formData",
"type": "string",
"description": "The text to be checked, given as a JSON document that specifies what's text and what's markup. This or 'text' is required. Markup will be ignored when looking for errors. Example text: <pre>A &lt;b>test&lt;/b></pre>JSON for the example text: <pre>{\"annotation\":[\n {\"text\": \"A \"},\n {\"markup\": \"&lt;b>\"},\n {\"text\": \"test\"},\n {\"markup\": \"&lt;/b>\"}\n]}</pre> <p>If you have markup that should be interpreted as whitespace, like <tt>&lt;p&gt;</tt> in HTML, you can have it interpreted like this: <pre>{\"markup\": \"&lt;p&gt;\", \"interpretAs\": \"\\n\\n\"}</pre><p>The 'data' feature is not limited to HTML or XML, it can be used for any kind of markup. Entities will need to be expanded in this input.",
"required": false
},
{
"name": "language",
"in": "formData",
"type": "string",
"description": "A language code like `en-US`, `de-DE`, `fr`, or `auto` to guess the language automatically (see `preferredVariants` below). For languages with variants (English, German, Portuguese) spell checking will only be activated when you specify the variant, e.g. `en-GB` instead of just `en`.",
"required": true
},
{
"name": "username",
"in": "formData",
"type": "string",
"description": "Set to get Premium API access: Your username/email as used to log in at languagetool.org."
},
{
"name": "apiKey",
"in": "formData",
"type": "string",
"format": "password",
"description": "Set to get Premium API access: <a target='_blank' href='https://languagetool.org/editor/settings/access-tokens'>your API key</a>"
},
{
"name": "dicts",
"in": "formData",
"type": "string",
"description": "Comma-separated list of dictionaries to include words from; uses special default dictionary if this is unset"
},
{
"name": "motherTongue",
"in": "formData",
"type": "string",
"description": "A language code of the user's native language, enabling false friends checks for some language pairs."
},
{
"name": "preferredVariants",
"in": "formData",
"type": "string",
"description": "Comma-separated list of preferred language variants. The language detector used with `language=auto` can detect e.g. English, but it cannot decide whether British English or American English is used. Thus this parameter can be used to specify the preferred variants like `en-GB` and `de-AT`. Only available with `language=auto`. You should set variants for at least German and English, as otherwise the spell checking will not work for those, as no spelling dictionary can be selected for just `en` or `de`."
},
{
"name": "enabledRules",
"in": "formData",
"type": "string",
"description": "IDs of rules to be enabled, comma-separated. Note that 'level' still applies, so the rule won't run unless 'level' is set to a level that activates the rule."
},
{
"name": "disabledRules",
"in": "formData",
"type": "string",
"description": "IDs of rules to be disabled, comma-separated"
},
{
"name": "enabledCategories",
"in": "formData",
"type": "string",
"description": "IDs of categories to be enabled, comma-separated"
},
{
"name": "disabledCategories",
"in": "formData",
"type": "string",
"description": "IDs of categories to be disabled, comma-separated"
},
{
"name": "enabledOnly",
"in": "formData",
"type": "boolean",
"default": false,
"description": "If true, only the rules and categories whose IDs are specified with `enabledRules` or `enabledCategories` are enabled."
},
{
"name": "level",
"in": "formData",
"type": "string",
"enum": ["default", "picky"],
"description": "If set to `picky`, additional rules will be activated, i.e. rules that you might only find useful when checking formal text."
}
],
"responses": {
"200": {
"description": "the result of checking the text",
"schema": {
"properties": {
"software": {
"type": "object",
"required": [
"name",
"version",
"buildDate",
"apiVersion"
],
"properties": {
"name": {
"type": "string",
"description": "Usually 'LanguageTool'."
},
"version": {
"type": "string",
"description": "A version string like '3.3' or '3.4-SNAPSHOT'."
},
"buildDate": {
"type": "string",
"description": "Date when the software was built, e.g. '2016-05-25'."
},
"apiVersion": {
"type": "integer",
"description": "Version of this API response. We don't expect to make incompatible changes, so this can also be increased for newly added fields."
},
"status": {
"type": "string",
"description": "An optional warning, e.g. when the API format is not stable."
},
"premium": {
"type": "boolean",
"description": "true if you're using a Premium account with all the premium text checks (since LanguageTool 4.2)"
}
}
},
"language": {
"type": "object",
"description": "The language used for checking the text.",
"required": [
"name",
"code",
"detectedLanguage"
],
"properties": {
"name": {
"type": "string",
"description": "Language name like 'French' or 'English (US)'."
},
"code": {
"type": "string",
"description": "ISO 639-1 code like 'en', 'en-US', or 'ca-ES-valencia'"
},
"detectedLanguage": {
"type": "object",
"description": "The automatically detected text language (might be different from the language actually used for checking).",
"required": [
"name",
"code"
],
"properties": {
"name": {
"type": "string",
"description": "Language name like 'French' or 'English (US)'."
},
"code": {
"type": "string",
"description": "ISO 639-1 code like 'en', 'en-US', or 'ca-ES-valencia'."
}
}
}
}
},
"matches": {
"type": "array",
"items": {
"type": "object",
"required": [
"message",
"offset",
"length",
"replacements",
"context",
"sentence"
],
"properties": {
"message": {
"type": "string",
"description": "Message about the error displayed to the user."
},
"shortMessage": {
"type": "string",
"description": "An optional shorter version of 'message'."
},
"offset": {
"type": "integer",
"description": "The 0-based character offset of the error in the text."
},
"length": {
"type": "integer",
"description": "The length of the error in characters."
},
"replacements": {
"type": "array",
"description": "Replacements that might correct the error. The array can be empty, in this case there is no suggested replacement.",
"items": {
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "the replacement string"
}
}
}
},
"context": {
"type": "object",
"required": [
"text",
"offset",
"length"
],
"properties": {
"text": {
"type": "string",
"description": "Context of the error, i.e. the error and some text to the left and to the left."
},
"offset": {
"type": "integer",
"description": "The 0-based character offset of the error in the context text."
},
"length": {
"type": "integer",
"description": "The length of the error in characters in the context."
}
}
},
"sentence": {
"type": "string",
"description": "The sentence the error occurred in (since LanguageTool 4.0 or later)"
},
"rule": {
"type": "object",
"required": [
"id",
"description",
"category"
],
"properties": {
"id": {
"type": "string",
"description": "An rule's identifier that's unique for this language."
},
"subId": {
"type": "string",
"description": "An optional sub identifier of the rule, used when several rules are grouped."
},
"description": {
"type": "string"
},
"urls": {
"type": "array",
"description": "An optional array of URLs with a more detailed description of the error.",
"items": {
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "the URL"
}
}
}
},
"issueType": {
"type": "string",
"description": "The <a href=\"http://www.w3.org/International/multilingualweb/lt/drafts/its20/its20.html#lqissue-typevalues\">Localization Quality Issue Type</a>. This is not defined for all languages, in which case it will always be 'Uncategorized'."
},
"category": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "A category's identifier that's unique for this language."
},
"name": {
"type": "string",
"description": "A short description of the category."
}
}
}
}
}
}
}
}
}
}
}
}
}
},
"/languages": {
"get": {
"summary": "Get a list of supported languages.",
"responses": {
"200": {
"description": "An array of language objects.",
"schema": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"code",
"longCode"
],
"properties": {
"name": {
"type": "string",
"description": "a language name like 'French' or 'English (Australia)'"
},
"code": {
"type": "string",
"description": "a language code like 'en'"
},
"longCode": {
"type": "string",
"description": "a language code like 'en-US' or 'ca-ES-valencia'"
}
}
}
}
}
}
}
},
"/words": {
"get": {
"summary": "List words in dictionaries",
"description": "List words in the user's personal dictionaries.",
"parameters": [
{
"name": "offset",
"in": "query",
"type": "integer",
"description": "Offset of where to start in the list of words. Defaults to 0."
},
{
"name": "limit",
"in": "query",
"type": "integer",
"description": "Maximum number of words to return. Defaults to 10."
},
{
"name": "username",
"in": "query",
"type": "string",
"description": "Your username as used to log in at languagetool.org.",
"required": true
},
{
"name": "apiKey",
"in": "query",
"type": "string",
"format": "password",
"description": "<a target='_blank' href='https://languagetool.org/editor/settings/access-tokens'>Your API key</a>",
"required": true
},
{
"name": "dicts",
"in": "query",
"type": "string",
"description": "Comma-separated list of dictionaries to include words from; uses special default dictionary if this is unset"
}
],
"responses": {
"200": {
"description": "the user's words from the given user dictionaries",
"schema": {
"properties": {
"words": {
"type": "array",
"description": "array of words",
"items": {
"type": "string"
}
}
}
}
}
}
}
},
"/words/add": {
"post": {
"summary": "Add word to a dictionary",
"description": "Add a word to one of the user's personal dictionaries. Please note that this feature is considered to be used for personal dictionaries which must not contain more than 500 words. If this is an issue for you, please contact us.",
"parameters": [
{
"name": "word",
"in": "formData",
"type": "string",
"description": "The word to be added. Must not be a phrase, i.e. cannot contain white space. The word is added to a global dictionary that applies to all languages.",
"required": true
},
{
"name": "username",
"in": "formData",
"type": "string",
"description": "Your username as used to log in at languagetool.org.",
"required": true
},
{
"name": "apiKey",
"in": "formData",
"type": "string",
"format": "password",
"description": "<a target='_blank' href='https://languagetool.org/editor/settings/access-tokens'>Your API key</a>",
"required": true
},
{
"name": "dict",
"in": "formData",
"type": "string",
"description": "Name of the dictionary to add the word to; non-existent dictionaries are created after calling this; if unset, adds to special default dictionary"
}
],
"responses": {
"200": {
"description": "the result of adding the word",
"schema": {
"properties": {
"added": {
"type": "boolean",
"description": "true if the word has been added. false means the word hasn't been added because it had been added before."
}
}
}
}
}
}
},
"/words/delete": {
"post": {
"summary": "Remove word from a dictionary",
"description": "Remove a word from one of the user's personal dictionaries.",
"parameters": [
{
"name": "word",
"in": "formData",
"type": "string",
"description": "The word to be removed.",
"required": true
},
{
"name": "username",
"in": "formData",
"type": "string",
"description": "Your username as used to log in at languagetool.org.",
"required": true
},
{
"name": "apiKey",
"in": "formData",
"type": "string",
"format": "password",
"description": "<a target='_blank' href='https://languagetool.org/editor/settings/access-tokens'>Your API key</a>",
"required": true
},
{
"name": "dict",
"in": "formData",
"type": "string",
"description": "Name of the dictionary to remove the word from; if the dictionary is empty upon calling this, it is deleted; if unset, removes from special default dictionary"
}
],
"responses": {
"200": {
"description": "the result of removing the word",
"schema": {
"properties": {
"deleted": {
"type": "boolean",
"description": "true if the word has been removed. false means the word hasn't been removed because it was not in the dictionary."
}
}
}
}
}
}
}
}
}
+18
View File
@@ -0,0 +1,18 @@
@tool
extends EditorPlugin
var plugin: LanguagetToolPlugin
func _enter_tree() -> void:
plugin = LanguagetToolPlugin.new()
add_child(plugin)
EditorInterface.get_inspector().edited_object_changed.connect(_inspector_edited_object_changed)
func _inspector_edited_object_changed():
plugin.check_new_inspector();
func _exit_tree() -> void:
pass
+1
View File
@@ -0,0 +1 @@
uid://fm32qkudo8sp
+7
View File
@@ -0,0 +1,7 @@
[plugin]
name="LanguageTool"
description="Check texts for style and grammar issues with LanguageTool. "
author="Jonathan @ Cozy Raven Interactive"
version=""
script="languagetool.gd"
@@ -0,0 +1,110 @@
[gd_scene load_steps=3 format=3 uid="uid://dxalawvo2ji7p"]
[ext_resource type="Script" uid="uid://dkyiuvuc2w2xc" path="res://addons/languagetool/scripts/language_tool_correction_overlay_references.gd" id="1_rh5c2"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_hdqxg"]
bg_color = Color(0.145098, 0.145098, 0.145098, 1)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.0784314, 0.0784314, 0.0784314, 1)
corner_radius_top_left = 5
corner_radius_top_right = 5
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
[node name="CorrectionOverlay" type="VBoxContainer"]
offset_right = 408.0
offset_bottom = 181.0
size_flags_horizontal = 0
size_flags_vertical = 0
script = ExtResource("1_rh5c2")
[node name="MarginContainer" type="MarginContainer" parent="."]
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="PanelContainer" type="PanelContainer" parent="MarginContainer"]
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_hdqxg")
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/PanelContainer"]
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/PanelContainer/MarginContainer"]
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="CategoryLabel" type="Label" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_font_sizes/font_size = 11
text = "Rechtschreibung"
autowrap_mode = 3
[node name="CloseButton" type="Button" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 11
text = "X"
[node name="Spacer" type="Control" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer"]
custom_minimum_size = Vector2(0, 4)
layout_mode = 2
[node name="DescriptionLabel" type="Label" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_constants/paragraph_spacing = 0
text = "Ensure spelling is correct"
autowrap_mode = 3
[node name="Spacer2" type="Control" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer"]
custom_minimum_size = Vector2(0, 2)
layout_mode = 2
[node name="Replacements" type="HFlowContainer" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="Button" type="Button" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer/Replacements"]
layout_mode = 2
size_flags_horizontal = 0
text = "Test 1"
[node name="Button2" type="Button" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer/Replacements"]
layout_mode = 2
size_flags_horizontal = 0
text = "Test 1"
[node name="Button3" type="Button" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer/Replacements"]
layout_mode = 2
size_flags_horizontal = 0
text = "Test 1"
[node name="Button4" type="Button" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer/Replacements"]
layout_mode = 2
size_flags_horizontal = 0
text = "Hello world!!!"
[node name="Button5" type="Button" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer/Replacements"]
layout_mode = 2
size_flags_horizontal = 0
text = "Test 1"
[node name="Button6" type="Button" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer/Replacements"]
layout_mode = 2
size_flags_horizontal = 0
text = "Test 1"
[node name="Button7" type="Button" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer/Replacements"]
layout_mode = 2
size_flags_horizontal = 0
text = "Test 1"
@@ -0,0 +1,41 @@
@tool
extends Node
class_name LanguageToolCorrectionOverlay
const CORRECTION_OVERLAY = preload("res://addons/languagetool/scenes/correction_overlay.tscn")
var instantiatedOverlay: LanguageToolCorrectionOverlayReferences
func _enter_tree() -> void:
instantiatedOverlay = CORRECTION_OVERLAY.instantiate()
add_child(instantiatedOverlay)
hideOverlay()
func _ready():
instantiatedOverlay.close_button.pressed.connect(hideOverlay)
func _exit_tree() -> void:
pass
func hideOverlay():
instantiatedOverlay.hide()
func showOverlay(position:Vector2, width: float, _match:LanguageToolApiWrapper.LanguageToolCheckResponse.Match, replacement_clicked : Callable):
#print(instantiatedOverlay.test)
instantiatedOverlay.show()
instantiatedOverlay.global_position = position
instantiatedOverlay.size = Vector2(0,0)
instantiatedOverlay.custom_minimum_size = Vector2(width, 0)
instantiatedOverlay.category_label.text = _match.rule.category.name
instantiatedOverlay.description_label.text = _match.message
for c in instantiatedOverlay.replacements.get_children():
c.free()
for r in _match.replacements:
var replacementButton = Button.new()
replacementButton.text = r
replacementButton.size_flags_horizontal = Control.SIZE_EXPAND_FILL
replacementButton.pressed.connect(func():replacement_clicked.call(r))
instantiatedOverlay.replacements.add_child(replacementButton)
@@ -0,0 +1 @@
uid://ct2t8rr000prq
@@ -0,0 +1,9 @@
@tool
extends VBoxContainer
class_name LanguageToolCorrectionOverlayReferences
@onready var category_label: Label = $MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/CategoryLabel
@onready var description_label: Label = $MarginContainer/PanelContainer/MarginContainer/VBoxContainer/DescriptionLabel
@onready var replacements: HFlowContainer = $MarginContainer/PanelContainer/MarginContainer/VBoxContainer/Replacements
@onready var close_button: Button = $MarginContainer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer/CloseButton
@@ -0,0 +1 @@
uid://dkyiuvuc2w2xc
@@ -0,0 +1,32 @@
extends SyntaxHighlighter
class_name LanguageToolErrorSyntaxHighlighter
var check:LanguageToolApiWrapper.LanguageToolCheckResponse
func _init(check:LanguageToolApiWrapper.LanguageToolCheckResponse):
self.check = check
func _get_line_syntax_highlighting(line: int) -> Dictionary:
var normalColor = EditorInterface.get_base_control().get_theme_color("font_color", "Editor")
var errorColor = EditorInterface.get_base_control().get_theme_color("error_color", "Editor")
var warningColor = EditorInterface.get_base_control().get_theme_color("warning_color", "Editor")
var successColor = EditorInterface.get_base_control().get_theme_color("success_color", "Editor")
var retval = {}
for m:LanguageToolApiWrapper.LanguageToolCheckResponse.Match in check.matches:
var row_column = LanguageToolUtils.offset_to_row_column(m.offset,get_text_edit().text)
if row_column[0] != line:
continue
match m.rule.category.id:
"GRAMMAR":
retval[row_column[1]] = {"color":warningColor}
"TYPOS":
retval[row_column[1]] = {"color":errorColor}
_:
retval[row_column[1]] = {"color":successColor}
retval[row_column[1]+m.length] = {"color":normalColor}
return retval
@@ -0,0 +1 @@
uid://csxcr0bsetagc
@@ -0,0 +1,112 @@
extends Node
class_name LanguagetToolPlugin
var api: LanguageToolApiWrapper
var overlay: LanguageToolCorrectionOverlay
var checkDict: Dictionary[String,LanguageToolApiWrapper.LanguageToolCheckResponse] = {}
func _enter_tree() -> void:
api = LanguageToolApiWrapper.new()
add_child(api)
overlay = LanguageToolCorrectionOverlay.new()
add_child(overlay)
func _exit_tree() -> void:
pass
func check_new_inspector():
overlay.hideOverlay()
var textEdits: Array[TextEdit] = _find_multiline_text_edits()
for te: TextEdit in textEdits:
te.text_changed.connect(func():_on_text_changed(te))
te.focus_exited.connect(func():_on_focus_lost(te))
te.caret_changed.connect(func():_on_caret_changed(te))
_check_text(te)
_mark_errors_in_text(te)
func _on_text_changed(textEdit: TextEdit):
_mark_errors_in_text(textEdit)
overlay.hideOverlay()
func _on_focus_lost(textEdit: TextEdit):
_check_text(textEdit)
_mark_errors_in_text(textEdit)
func _on_caret_changed(textEdit: TextEdit):
if(!checkDict.has(textEdit.text)):
return
var check: LanguageToolApiWrapper.LanguageToolCheckResponse = checkDict[textEdit.text]
# find match at caret
var caret_offset:int = LanguageToolUtils.row_column_to_offset(textEdit.get_caret_line(), textEdit.get_caret_column(),textEdit.text)
var _match:LanguageToolApiWrapper.LanguageToolCheckResponse.Match = null
for m in check.matches:
if m.offset <= caret_offset and m.offset + m.length >= caret_offset:
_match = m
break
if _match != null:
var edit_global_rect = textEdit.get_global_rect()
overlay.showOverlay(
edit_global_rect.position + Vector2(0,edit_global_rect.size.y),
edit_global_rect.size.x,
_match,
func(newText):_apply_text_change(textEdit,newText,_match))
else:
overlay.hideOverlay()
pass
func _check_text(textEdit: TextEdit):
if textEdit.text == "":
return
if checkDict.has(textEdit.text):
return
var response = api.check(textEdit.text)
checkDict[textEdit.text] = response
func _mark_errors_in_text(textEdit: TextEdit):
if(!checkDict.has(textEdit.text)):
textEdit.syntax_highlighter=null
return
var check: LanguageToolApiWrapper.LanguageToolCheckResponse = checkDict[textEdit.text]
textEdit.syntax_highlighter = LanguageToolErrorSyntaxHighlighter.new(check)
func _apply_text_change(textEdit:TextEdit, newText: String, _match:LanguageToolApiWrapper.LanguageToolCheckResponse.Match):
var oldText = textEdit.text
var removedOldWord = oldText.erase(_match.offset,_match.length)
var newWordInserted = removedOldWord.insert(_match.offset,newText)
textEdit.text = newWordInserted
textEdit.text_changed.emit()
overlay.hideOverlay()
_check_text(textEdit)
_mark_errors_in_text(textEdit)
func _find_multiline_text_edits()->Array[TextEdit]:
var multilinteTexts:Array[Node] = _find_recursive(
EditorInterface.get_inspector().get_child(0).get_child(2),
"EditorPropertyMultilineText");
var textEditors:Array[TextEdit]
textEditors.assign( multilinteTexts.map(func(c):return c.get_child(0).get_child(0) as TextEdit))
return textEditors
func _find_recursive(node: Node, type: Variant) -> Array[Node]:
if type is String:
if node.get_class() == type:
return [node]
elif is_instance_of(node, type):
return [node]
var retval: Array[Node] = []
for child in node.get_children():
retval.append_array(_find_recursive(child, type))
return retval
@@ -0,0 +1 @@
uid://bi8yv26eglkso
@@ -0,0 +1,32 @@
@tool
extends Object
class_name LanguageToolUtils
static func offset_to_row_column(offset:int, text:String)->Vector2i:
var row:int = 0
var column:int = 0
if offset > text.length():
return Vector2i(-1,-1)
for i in offset:
if text[i] == "\n":
row+=1
column = 0
else:
column+=1
return Vector2i(row, column)
static func row_column_to_offset(row:int, column:int, text:String) -> int:
var current_row:int = 0
var current_column:int = 0
for i in text.length():
if current_row == row and current_column == column:
return i
if text[i] == "\n":
current_row += 1
current_column = 0
else:
current_column += 1
return -1
@@ -0,0 +1 @@
uid://q01v4f8pfgfe
@@ -0,0 +1,211 @@
@tool
class_name LanguageToolApiWrapper
extends Node
const BASE_URL := "https://api.languagetoolplus.com/v2"
func _make_request(endpoint: String, method: HTTPClient.Method = HTTPClient.METHOD_GET, data: Dictionary = {}, headers: Dictionary = {}):
var url = BASE_URL + endpoint
var scheme_split = url.split("://")
var scheme = scheme_split[0]
var rest = scheme_split[1]
var host_and_path = rest.split("/", false, 1)
var host = host_and_path[0]
var path = "/" + host_and_path[1] if host_and_path.size() > 1 else "/"
var port = 443 if scheme == "https" else 80
var client = HTTPClient.new()
var tlsOptions: TLSOptions = (TLSOptions.client() if scheme == "https" else null)
var err = client.connect_to_host(host, port, tlsOptions)
if err != OK:
push_error("Failed to connect to host: " + str(err))
return null
while client.get_status() in [HTTPClient.STATUS_CONNECTING, HTTPClient.STATUS_RESOLVING]:
client.poll()
OS.delay_msec(10)
var header_array = []
for k in headers.keys():
header_array.append(str(k) + ": " + str(headers[k]))
var body = ""
if method == HTTPClient.METHOD_POST:
body = ""
if data.size() > 0:
body = client.query_string_from_dict(data)
header_array.append("Content-Type: application/x-www-form-urlencoded")
header_array.append("Content-Length: " + str(body.length()))
client.request(HTTPClient.METHOD_POST, path, header_array, body)
else:
if data.size() > 0:
path += "?" + client.query_string_from_dict(data)
client.request(HTTPClient.METHOD_GET, path, header_array)
while client.get_status() == HTTPClient.STATUS_REQUESTING:
client.poll()
OS.delay_msec(10)
var response = ""
while client.get_status() == HTTPClient.STATUS_BODY or client.has_response():
client.poll()
var chunk = client.read_response_body_chunk()
if chunk.size() == 0:
break
response += chunk.get_string_from_utf8()
OS.delay_msec(10)
var resp_code = client.get_response_code()
if resp_code != 200:
push_error("HTTP error: " + str(resp_code) + "\\n" + response)
return null
var json = JSON.new()
var json_err = json.parse(response)
if json_err != OK:
push_error("JSON parse error: " + str(json_err) + "\\n" + response)
return null
return json.get_data()
func check(text: String, language: String = "auto", opts: Dictionary = {}) -> LanguageToolCheckResponse:
var data = {
"text": text,
"language": language
}
for k in opts.keys():
data[k] = opts[k]
print("Checking text: "+text)
return LanguageToolCheckResponse.new(_make_request("/check", HTTPClient.METHOD_POST, data))
func get_languages():
return _make_request("/languages", HTTPClient.METHOD_GET)
func list_words(username: String, apiKey: String, offset: int = 0, limit: int = 10, dicts: String = ""):
var data = {
"username": username,
"apiKey": apiKey,
"offset": offset,
"limit": limit
}
if dicts != "":
data["dicts"] = dicts
return _make_request("/words", HTTPClient.METHOD_GET, data)
func add_word(word: String, username: String, apiKey: String, dict: String = ""):
var data = {
"word": word,
"username": username,
"apiKey": apiKey
}
if dict != "":
data["dict"] = dict
return _make_request("/words/add", HTTPClient.METHOD_POST, data)
func delete_word(word: String, username: String, apiKey: String, dict: String = ""):
var data = {
"word": word,
"username": username,
"apiKey": apiKey
}
if dict != "":
data["dict"] = dict
return _make_request("/words/delete", HTTPClient.METHOD_POST, data)
static func percent_encode(text: String) -> String:
return text.uri_encode()
class LanguageToolCheckResponse:
# Software info
var software_name: String
var software_version: String
var software_build_date: String
var software_api_version: int
var software_status: String = ""
var software_premium: bool = false
# Language info
var language_name: String
var language_code: String
var detected_language_name: String
var detected_language_code: String
# Match structure
class Match:
var message: String
var short_message: String = ""
var offset: int
var length: int
var replacements: Array[String] = []
var context_text: String
var context_offset: int
var context_length: int
var sentence: String
class Rule:
var id: String
var sub_id: String = ""
var description: String
var urls: Array[String] = []
var issue_type: String = ""
class Category:
var id: String
var name: String
var category: Category
var rule: Rule
var matches: Array[Match] = []
func _init(response: Variant) -> void:
# Parse software
var sw = response.software if response.has("software") else {}
software_name = sw.name if sw.has("name") else ""
software_version = sw.version if sw.has("version") else ""
software_build_date = sw.buildDate if sw.has("buildDate") else ""
software_api_version = sw.apiVersion if sw.has("apiVersion") else 0
software_status = sw.status if sw.has("status") else ""
software_premium = sw.premium if sw.has("premium") else false
# Parse language
var lang = response.language if response.has("language") else {}
language_name = lang.name if lang.has("name") else ""
language_code = lang.code if lang.has("code") else ""
var det_lang = lang.detectedLanguage if lang.has("detectedLanguage") else {}
detected_language_name = det_lang.name if det_lang.has("name") else ""
detected_language_code = det_lang.code if det_lang.has("code") else ""
# Parse matches
matches = []
var matches_arr = response.matches if response.has("matches") else []
for m in matches_arr:
var _match = Match.new()
_match.message = m.message if m.has("message") else ""
_match.short_message = m.shortMessage if m.has("shortMessage") else ""
_match.offset = m.offset if m.has("offset") else 0
_match.length = m.length if m.has("length") else 0
#_match.replacements = []
var replacements_arr = m.replacements if m.has("replacements") else []
for r in replacements_arr:
_match.replacements.append(r.value if r.has("value") else "")
var ctx = m.context if m.has("context") else {}
_match.context_text = ctx.text if ctx.has("text") else ""
_match.context_offset = ctx.offset if ctx.has("offset") else 0
_match.context_length = ctx.length if ctx.has("length") else 0
_match.sentence = m.sentence if m.has("sentence") else ""
var rule_dict = m.rule if m.has("rule") else {}
var rule = Match.Rule.new()
rule.id = rule_dict.id if rule_dict.has("id") else ""
rule.sub_id = rule_dict.subId if rule_dict.has("subId") else ""
rule.description = rule_dict.description if rule_dict.has("description") else ""
#rule.urls = []
var urls_arr = rule_dict.urls if rule_dict.has("urls") else []
for u in urls_arr:
rule.urls.append(u.value if u.has("value") else "")
rule.issue_type = rule_dict.issueType if rule_dict.has("issueType") else ""
var cat = rule_dict.category if rule_dict.has("category") else {}
var category = Match.Rule.Category.new()
category.id = cat.id if cat.has("id") else ""
category.name = cat.name if cat.has("name") else ""
rule.category = category
_match.rule = rule
matches.append(_match)
@@ -0,0 +1 @@
uid://bkyd022t8ugkw
+8
View File
@@ -0,0 +1,8 @@
@tool
extends EditorScript
func _run():
var api = LanguageToolApiWrapper.new()
EditorInterface.get_base_control().add_child(api)
var result = api.check("Hello this is a santence how are you")
print(result.matches[0])
@@ -0,0 +1 @@
uid://77jt5suj0wdj
@@ -0,0 +1,47 @@
@tool
extends EditorScript
var testButton: Button
func _run():
#var selected: Node = EditorInterface.get_inspector().get_child(0).get_child(2)
#_print_info(selected)
#print((EditorInterface.get_inspector().get_child(0).get_child(2).get_child(-1) as Button).text)
#print((selected as LineEdit).text)
#(selected as LineEdit).insert_text_at_caret("hello")
#(selected as LineEdit).text_changed.emit((selected as LineEdit).text)
#print(selected.get_class())
#print(is_instance_of(selected, EditorPropertyText))
#print(_find_recursive(selected,"EditorPropertyMultilineText")[0].get_child(0).get_child(0).get_class())
#print(_find_recursive(selected,"EditorPropertyText")[0].get_child(0).get_child(0).get_class())
testButton = Button.new()
testButton.text = "Remove this button"
#testButton.global_position = Vector2(1904.0, 305.0)
testButton.pressed.connect(
func():
testButton.get_parent().remove_child(testButton)
testButton.queue_free()
)
EditorInterface.get_base_control().add_child(testButton)
pass
func _print_info(node: Control):
print("Name: "+node.name)
print("Children:")
for child in node.get_children():
print(" - "+child.name)
func _find_recursive(node: Node, type: Variant) -> Array[Node]:
if type is String:
if node.get_class() == type:
return [node]
elif is_instance_of(node, type):
return [node]
var retval: Array[Node] = []
for child in node.get_children():
retval.append_array(_find_recursive(child, type))
return retval
@@ -0,0 +1 @@
uid://t6f7snttaggn
Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

+34
View File
@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://hvchk6t0xe7j"
path="res://.godot/imported/Ente.png-21ead71377d82aa0401b2345b9713a4b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/animals/Ente.png"
dest_files=["res://.godot/imported/Ente.png-21ead71377d82aa0401b2345b9713a4b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

+34
View File
@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c4q12jiligcl7"
path="res://.godot/imported/katze.png-0faf4775b24cd38949e4c4160b5ed047.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/animals/katze.png"
dest_files=["res://.godot/imported/katze.png-0faf4775b24cd38949e4c4160b5ed047.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 672 KiB

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://7jrac5ii3ah3"
path="res://.godot/imported/0001.png-9c6cb663e52b1142937f646500ed09a3.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/animation/Vesna2D/Vesna Anims Sequences/B01-Idle/0001.png"
dest_files=["res://.godot/imported/0001.png-9c6cb663e52b1142937f646500ed09a3.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
Binary file not shown.

After

Width:  |  Height:  |  Size: 672 KiB

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c06b551t2qlo6"
path="res://.godot/imported/0002.png-3c9447de011edd3c49d95cc40900862f.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/animation/Vesna2D/Vesna Anims Sequences/B01-Idle/0002.png"
dest_files=["res://.godot/imported/0002.png-3c9447de011edd3c49d95cc40900862f.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
Binary file not shown.

After

Width:  |  Height:  |  Size: 670 KiB

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://d0dqhq2cbwyus"
path="res://.godot/imported/0003.png-43b2fbee351b3e40cec5c91ac958b6e5.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/animation/Vesna2D/Vesna Anims Sequences/B01-Idle/0003.png"
dest_files=["res://.godot/imported/0003.png-43b2fbee351b3e40cec5c91ac958b6e5.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
Binary file not shown.

After

Width:  |  Height:  |  Size: 668 KiB

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bj2ssu0ixr0p1"
path="res://.godot/imported/0004.png-40cdc6ee34fa9f1165af62d833008a91.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/animation/Vesna2D/Vesna Anims Sequences/B01-Idle/0004.png"
dest_files=["res://.godot/imported/0004.png-40cdc6ee34fa9f1165af62d833008a91.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
Binary file not shown.

After

Width:  |  Height:  |  Size: 665 KiB

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://baho1jt70dj6u"
path="res://.godot/imported/0005.png-51e4d358637a92057728002a1d20bee6.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/animation/Vesna2D/Vesna Anims Sequences/B01-Idle/0005.png"
dest_files=["res://.godot/imported/0005.png-51e4d358637a92057728002a1d20bee6.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
Binary file not shown.

After

Width:  |  Height:  |  Size: 664 KiB

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c4kq6oyxchwae"
path="res://.godot/imported/0006.png-941fa868f0e50a15b299f562e3a4b2ec.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/animation/Vesna2D/Vesna Anims Sequences/B01-Idle/0006.png"
dest_files=["res://.godot/imported/0006.png-941fa868f0e50a15b299f562e3a4b2ec.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

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