diff --git a/godot/cover_art/schatzjaeger.webp b/godot/cover_art/schatzjaeger.webp
new file mode 100644
index 0000000..d1f7e76
Binary files /dev/null and b/godot/cover_art/schatzjaeger.webp differ
diff --git a/godot/cover_art/schatzjaeger.webp.import b/godot/cover_art/schatzjaeger.webp.import
new file mode 100644
index 0000000..fa19e60
--- /dev/null
+++ b/godot/cover_art/schatzjaeger.webp.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dyga5qn124307"
+path="res://.godot/imported/schatzjaeger.webp-78cbd277d58b4174bd8efac086727420.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://cover_art/schatzjaeger.webp"
+dest_files=["res://.godot/imported/schatzjaeger.webp-78cbd277d58b4174bd8efac086727420.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
diff --git a/godot/main.tscn b/godot/main.tscn
new file mode 100644
index 0000000..c09de01
--- /dev/null
+++ b/godot/main.tscn
@@ -0,0 +1,32 @@
+[gd_scene load_steps=3 format=3 uid="uid://cmqfu6cc780h4"]
+
+[ext_resource type="Theme" uid="uid://ks2uyxqg6u4k" path="res://mhjnr/theme.tres" id="1_4qyey"]
+[ext_resource type="Texture2D" uid="uid://dyga5qn124307" path="res://cover_art/schatzjaeger.webp" id="2_f5uhf"]
+
+[node name="main" type="MarginContainer"]
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme = ExtResource("1_4qyey")
+
+[node name="ScrollContainer" type="ScrollContainer" parent="."]
+layout_mode = 2
+
+[node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer"]
+layout_mode = 2
+
+[node name="Label" type="Label" parent="ScrollContainer/VBoxContainer"]
+layout_mode = 2
+theme_override_font_sizes/font_size = 40
+text = "Schatzjäger"
+
+[node name="HBoxContainer" type="HBoxContainer" parent="ScrollContainer/VBoxContainer"]
+layout_mode = 2
+
+[node name="Button" type="Button" parent="ScrollContainer/VBoxContainer/HBoxContainer"]
+layout_mode = 2
+icon = ExtResource("2_f5uhf")
+flat = true
+icon_alignment = 1
diff --git a/godot/mhjnr/level.tscn b/godot/mhjnr/level.tscn
index 42c7325..90f63df 100644
--- a/godot/mhjnr/level.tscn
+++ b/godot/mhjnr/level.tscn
@@ -85,6 +85,7 @@ anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
+theme = ExtResource("3_a2fmg")
theme_override_constants/margin_left = 32
theme_override_constants/margin_top = 32
theme_override_constants/margin_right = 32
diff --git a/godot/mhjnr/menu.tscn b/godot/mhjnr/menu.tscn
new file mode 100644
index 0000000..76430d6
--- /dev/null
+++ b/godot/mhjnr/menu.tscn
@@ -0,0 +1,74 @@
+[gd_scene load_steps=5 format=3 uid="uid://dleusk0maomll"]
+
+[ext_resource type="Theme" uid="uid://ks2uyxqg6u4k" path="res://mhjnr/theme.tres" id="1_o0c21"]
+[ext_resource type="Texture2D" uid="uid://dkeuhlg0ki67o" path="res://remakes/minimize.svg" id="3_qkgqr"]
+[ext_resource type="Texture2D" uid="uid://24kg870sjulo" path="res://remakes/close.svg" id="4_a24a2"]
+
+[sub_resource type="GDScript" id="GDScript_oemh7"]
+script/source = "extends MarginContainer
+
+@export var entry = \"main\"
+
+var menu: Node
+
+func _ready() -> void:
+ set_menu(entry)
+
+func set_menu(name: String) -> void:
+ if menu != null:
+ menu.queue_free()
+ var translations: Translation = load(\"datafile://data/text.csv\")
+ menu = load(\"datafile://data/menu/screens/%s.xml\" % name).instantiate()
+ add_child(menu)
+ move_child(menu, 0)
+
+ for button in menu.find_children(\"*\", \"Button\"):
+ if not button.has_meta(\"action\"):
+ continue
+ var action = button.get_meta(\"action\")
+ var callable = Callable(self, \"_on_action_%s\" % action.name)
+ button.connect(\"pressed\", callable.bindv(action.args))
+
+ for node in menu.find_children(\"*\"):
+ if node.has_method(\"set_text\"):
+ node.text = translations.tr(node.text)
+
+func _on_close_pressed() -> void:
+ get_tree().quit()
+
+func _on_action_SetMenu(name: String) -> void:
+ set_menu(name)
+
+func _on_action_CheckStartGame() -> void:
+ print(\"CheckStartGame\")
+"
+
+[node name="Root" type="MarginContainer"]
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme = ExtResource("1_o0c21")
+script = SubResource("GDScript_oemh7")
+
+[node name="Titlebar" type="HBoxContainer" parent="."]
+layout_mode = 2
+size_flags_horizontal = 8
+size_flags_vertical = 0
+
+[node name="Minimize" type="Button" parent="Titlebar"]
+layout_mode = 2
+focus_mode = 1
+theme_override_colors/icon_hover_color = Color(0.403922, 0.403922, 0.403922, 1)
+icon = ExtResource("3_qkgqr")
+flat = true
+
+[node name="Close" type="Button" parent="Titlebar"]
+layout_mode = 2
+focus_mode = 1
+theme_override_colors/icon_hover_color = Color(0.780392, 0.435294, 0.360784, 1)
+icon = ExtResource("4_a24a2")
+flat = true
+
+[connection signal="pressed" from="Titlebar/Close" to="." method="_on_close_pressed"]
diff --git a/godot/mhjnr/theme.tres b/godot/mhjnr/theme.tres
index a7b34dc..8dfede2 100644
--- a/godot/mhjnr/theme.tres
+++ b/godot/mhjnr/theme.tres
@@ -1,6 +1,17 @@
-[gd_resource type="Theme" format=3 uid="uid://ks2uyxqg6u4k"]
+[gd_resource type="Theme" load_steps=3 format=3 uid="uid://ks2uyxqg6u4k"]
-[ext_resource type="FontFile" path="datafile://data/fonts/menufont.bmp" id="9_6bx8b"]
+[ext_resource type="FontFile" uid="uid://b50bdb32aerbb" path="res://remakes/font/LondrinaSolid-Regular.otf" id="1_1apnt"]
+
+[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_wa7wi"]
[resource]
-/fonts/menufont = ExtResource("9_6bx8b")
+default_font = ExtResource("1_1apnt")
+default_font_size = 29
+Button/colors/font_color = Color(0.572549, 0.517647, 0.411765, 0.929412)
+Button/colors/font_outline_color = Color(0, 0, 0, 0.568627)
+Button/constants/outline_size = 2
+Button/font_sizes/font_size = 39
+Button/styles/focus = SubResource("StyleBoxEmpty_wa7wi")
+Fonts/fonts/large = ExtResource("1_1apnt")
+Label/colors/font_outline_color = Color(0, 0, 0, 1)
+Label/constants/outline_size = 8
diff --git a/godot/project.godot b/godot/project.godot
index c96e96e..3328c69 100644
--- a/godot/project.godot
+++ b/godot/project.godot
@@ -17,6 +17,13 @@ boot_splash/bg_color=Color(0, 0, 0, 1)
boot_splash/image="res://icon.png"
boot_splash/fullsize=false
+[display]
+
+window/size/viewport_width=800
+window/size/viewport_height=600
+window/size/resizable=false
+window/size/borderless=true
+
[input]
"Move Up"={
diff --git a/godot/remakes/close.svg b/godot/remakes/close.svg
new file mode 100644
index 0000000..7ba82bb
--- /dev/null
+++ b/godot/remakes/close.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/godot/remakes/close.svg.import b/godot/remakes/close.svg.import
new file mode 100644
index 0000000..642cbd7
--- /dev/null
+++ b/godot/remakes/close.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://24kg870sjulo"
+path="res://.godot/imported/close.svg-ad90c42e0d2534c8ed6665a43851eb64.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://remakes/close.svg"
+dest_files=["res://.godot/imported/close.svg-ad90c42e0d2534c8ed6665a43851eb64.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
diff --git a/godot/remakes/font/Creative Commons Attribution Share Alike License.txt b/godot/remakes/font/Creative Commons Attribution Share Alike License.txt
new file mode 100644
index 0000000..e27d491
--- /dev/null
+++ b/godot/remakes/font/Creative Commons Attribution Share Alike License.txt
@@ -0,0 +1,359 @@
+Creative Commons Legal Code
+
+Attribution-ShareAlike 3.0 Unported
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
+ DAMAGES RESULTING FROM ITS USE.
+
+License
+
+THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
+COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
+COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
+AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+
+BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
+TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
+BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
+CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
+CONDITIONS.
+
+1. Definitions
+
+ a. "Adaptation" means a work based upon the Work, or upon the Work and
+ other pre-existing works, such as a translation, adaptation,
+ derivative work, arrangement of music or other alterations of a
+ literary or artistic work, or phonogram or performance and includes
+ cinematographic adaptations or any other form in which the Work may be
+ recast, transformed, or adapted including in any form recognizably
+ derived from the original, except that a work that constitutes a
+ Collection will not be considered an Adaptation for the purpose of
+ this License. For the avoidance of doubt, where the Work is a musical
+ work, performance or phonogram, the synchronization of the Work in
+ timed-relation with a moving image ("synching") will be considered an
+ Adaptation for the purpose of this License.
+ b. "Collection" means a collection of literary or artistic works, such as
+ encyclopedias and anthologies, or performances, phonograms or
+ broadcasts, or other works or subject matter other than works listed
+ in Section 1(f) below, which, by reason of the selection and
+ arrangement of their contents, constitute intellectual creations, in
+ which the Work is included in its entirety in unmodified form along
+ with one or more other contributions, each constituting separate and
+ independent works in themselves, which together are assembled into a
+ collective whole. A work that constitutes a Collection will not be
+ considered an Adaptation (as defined below) for the purposes of this
+ License.
+ c. "Creative Commons Compatible License" means a license that is listed
+ at https://creativecommons.org/compatiblelicenses that has been
+ approved by Creative Commons as being essentially equivalent to this
+ License, including, at a minimum, because that license: (i) contains
+ terms that have the same purpose, meaning and effect as the License
+ Elements of this License; and, (ii) explicitly permits the relicensing
+ of adaptations of works made available under that license under this
+ License or a Creative Commons jurisdiction license with the same
+ License Elements as this License.
+ d. "Distribute" means to make available to the public the original and
+ copies of the Work or Adaptation, as appropriate, through sale or
+ other transfer of ownership.
+ e. "License Elements" means the following high-level license attributes
+ as selected by Licensor and indicated in the title of this License:
+ Attribution, ShareAlike.
+ f. "Licensor" means the individual, individuals, entity or entities that
+ offer(s) the Work under the terms of this License.
+ g. "Original Author" means, in the case of a literary or artistic work,
+ the individual, individuals, entity or entities who created the Work
+ or if no individual or entity can be identified, the publisher; and in
+ addition (i) in the case of a performance the actors, singers,
+ musicians, dancers, and other persons who act, sing, deliver, declaim,
+ play in, interpret or otherwise perform literary or artistic works or
+ expressions of folklore; (ii) in the case of a phonogram the producer
+ being the person or legal entity who first fixes the sounds of a
+ performance or other sounds; and, (iii) in the case of broadcasts, the
+ organization that transmits the broadcast.
+ h. "Work" means the literary and/or artistic work offered under the terms
+ of this License including without limitation any production in the
+ literary, scientific and artistic domain, whatever may be the mode or
+ form of its expression including digital form, such as a book,
+ pamphlet and other writing; a lecture, address, sermon or other work
+ of the same nature; a dramatic or dramatico-musical work; a
+ choreographic work or entertainment in dumb show; a musical
+ composition with or without words; a cinematographic work to which are
+ assimilated works expressed by a process analogous to cinematography;
+ a work of drawing, painting, architecture, sculpture, engraving or
+ lithography; a photographic work to which are assimilated works
+ expressed by a process analogous to photography; a work of applied
+ art; an illustration, map, plan, sketch or three-dimensional work
+ relative to geography, topography, architecture or science; a
+ performance; a broadcast; a phonogram; a compilation of data to the
+ extent it is protected as a copyrightable work; or a work performed by
+ a variety or circus performer to the extent it is not otherwise
+ considered a literary or artistic work.
+ i. "You" means an individual or entity exercising rights under this
+ License who has not previously violated the terms of this License with
+ respect to the Work, or who has received express permission from the
+ Licensor to exercise rights under this License despite a previous
+ violation.
+ j. "Publicly Perform" means to perform public recitations of the Work and
+ to communicate to the public those public recitations, by any means or
+ process, including by wire or wireless means or public digital
+ performances; to make available to the public Works in such a way that
+ members of the public may access these Works from a place and at a
+ place individually chosen by them; to perform the Work to the public
+ by any means or process and the communication to the public of the
+ performances of the Work, including by public digital performance; to
+ broadcast and rebroadcast the Work by any means including signs,
+ sounds or images.
+ k. "Reproduce" means to make copies of the Work by any means including
+ without limitation by sound or visual recordings and the right of
+ fixation and reproducing fixations of the Work, including storage of a
+ protected performance or phonogram in digital form or other electronic
+ medium.
+
+2. Fair Dealing Rights. Nothing in this License is intended to reduce,
+limit, or restrict any uses free from copyright or rights arising from
+limitations or exceptions that are provided for in connection with the
+copyright protection under copyright law or other applicable laws.
+
+3. License Grant. Subject to the terms and conditions of this License,
+Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
+perpetual (for the duration of the applicable copyright) license to
+exercise the rights in the Work as stated below:
+
+ a. to Reproduce the Work, to incorporate the Work into one or more
+ Collections, and to Reproduce the Work as incorporated in the
+ Collections;
+ b. to create and Reproduce Adaptations provided that any such Adaptation,
+ including any translation in any medium, takes reasonable steps to
+ clearly label, demarcate or otherwise identify that changes were made
+ to the original Work. For example, a translation could be marked "The
+ original work was translated from English to Spanish," or a
+ modification could indicate "The original work has been modified.";
+ c. to Distribute and Publicly Perform the Work including as incorporated
+ in Collections; and,
+ d. to Distribute and Publicly Perform Adaptations.
+ e. For the avoidance of doubt:
+
+ i. Non-waivable Compulsory License Schemes. In those jurisdictions in
+ which the right to collect royalties through any statutory or
+ compulsory licensing scheme cannot be waived, the Licensor
+ reserves the exclusive right to collect such royalties for any
+ exercise by You of the rights granted under this License;
+ ii. Waivable Compulsory License Schemes. In those jurisdictions in
+ which the right to collect royalties through any statutory or
+ compulsory licensing scheme can be waived, the Licensor waives the
+ exclusive right to collect such royalties for any exercise by You
+ of the rights granted under this License; and,
+ iii. Voluntary License Schemes. The Licensor waives the right to
+ collect royalties, whether individually or, in the event that the
+ Licensor is a member of a collecting society that administers
+ voluntary licensing schemes, via that society, from any exercise
+ by You of the rights granted under this License.
+
+The above rights may be exercised in all media and formats whether now
+known or hereafter devised. The above rights include the right to make
+such modifications as are technically necessary to exercise the rights in
+other media and formats. Subject to Section 8(f), all rights not expressly
+granted by Licensor are hereby reserved.
+
+4. Restrictions. The license granted in Section 3 above is expressly made
+subject to and limited by the following restrictions:
+
+ a. You may Distribute or Publicly Perform the Work only under the terms
+ of this License. You must include a copy of, or the Uniform Resource
+ Identifier (URI) for, this License with every copy of the Work You
+ Distribute or Publicly Perform. You may not offer or impose any terms
+ on the Work that restrict the terms of this License or the ability of
+ the recipient of the Work to exercise the rights granted to that
+ recipient under the terms of the License. You may not sublicense the
+ Work. You must keep intact all notices that refer to this License and
+ to the disclaimer of warranties with every copy of the Work You
+ Distribute or Publicly Perform. When You Distribute or Publicly
+ Perform the Work, You may not impose any effective technological
+ measures on the Work that restrict the ability of a recipient of the
+ Work from You to exercise the rights granted to that recipient under
+ the terms of the License. This Section 4(a) applies to the Work as
+ incorporated in a Collection, but this does not require the Collection
+ apart from the Work itself to be made subject to the terms of this
+ License. If You create a Collection, upon notice from any Licensor You
+ must, to the extent practicable, remove from the Collection any credit
+ as required by Section 4(c), as requested. If You create an
+ Adaptation, upon notice from any Licensor You must, to the extent
+ practicable, remove from the Adaptation any credit as required by
+ Section 4(c), as requested.
+ b. You may Distribute or Publicly Perform an Adaptation only under the
+ terms of: (i) this License; (ii) a later version of this License with
+ the same License Elements as this License; (iii) a Creative Commons
+ jurisdiction license (either this or a later license version) that
+ contains the same License Elements as this License (e.g.,
+ Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible
+ License. If you license the Adaptation under one of the licenses
+ mentioned in (iv), you must comply with the terms of that license. If
+ you license the Adaptation under the terms of any of the licenses
+ mentioned in (i), (ii) or (iii) (the "Applicable License"), you must
+ comply with the terms of the Applicable License generally and the
+ following provisions: (I) You must include a copy of, or the URI for,
+ the Applicable License with every copy of each Adaptation You
+ Distribute or Publicly Perform; (II) You may not offer or impose any
+ terms on the Adaptation that restrict the terms of the Applicable
+ License or the ability of the recipient of the Adaptation to exercise
+ the rights granted to that recipient under the terms of the Applicable
+ License; (III) You must keep intact all notices that refer to the
+ Applicable License and to the disclaimer of warranties with every copy
+ of the Work as included in the Adaptation You Distribute or Publicly
+ Perform; (IV) when You Distribute or Publicly Perform the Adaptation,
+ You may not impose any effective technological measures on the
+ Adaptation that restrict the ability of a recipient of the Adaptation
+ from You to exercise the rights granted to that recipient under the
+ terms of the Applicable License. This Section 4(b) applies to the
+ Adaptation as incorporated in a Collection, but this does not require
+ the Collection apart from the Adaptation itself to be made subject to
+ the terms of the Applicable License.
+ c. If You Distribute, or Publicly Perform the Work or any Adaptations or
+ Collections, You must, unless a request has been made pursuant to
+ Section 4(a), keep intact all copyright notices for the Work and
+ provide, reasonable to the medium or means You are utilizing: (i) the
+ name of the Original Author (or pseudonym, if applicable) if supplied,
+ and/or if the Original Author and/or Licensor designate another party
+ or parties (e.g., a sponsor institute, publishing entity, journal) for
+ attribution ("Attribution Parties") in Licensor's copyright notice,
+ terms of service or by other reasonable means, the name of such party
+ or parties; (ii) the title of the Work if supplied; (iii) to the
+ extent reasonably practicable, the URI, if any, that Licensor
+ specifies to be associated with the Work, unless such URI does not
+ refer to the copyright notice or licensing information for the Work;
+ and (iv) , consistent with Ssection 3(b), in the case of an
+ Adaptation, a credit identifying the use of the Work in the Adaptation
+ (e.g., "French translation of the Work by Original Author," or
+ "Screenplay based on original Work by Original Author"). The credit
+ required by this Section 4(c) may be implemented in any reasonable
+ manner; provided, however, that in the case of a Adaptation or
+ Collection, at a minimum such credit will appear, if a credit for all
+ contributing authors of the Adaptation or Collection appears, then as
+ part of these credits and in a manner at least as prominent as the
+ credits for the other contributing authors. For the avoidance of
+ doubt, You may only use the credit required by this Section for the
+ purpose of attribution in the manner set out above and, by exercising
+ Your rights under this License, You may not implicitly or explicitly
+ assert or imply any connection with, sponsorship or endorsement by the
+ Original Author, Licensor and/or Attribution Parties, as appropriate,
+ of You or Your use of the Work, without the separate, express prior
+ written permission of the Original Author, Licensor and/or Attribution
+ Parties.
+ d. Except as otherwise agreed in writing by the Licensor or as may be
+ otherwise permitted by applicable law, if You Reproduce, Distribute or
+ Publicly Perform the Work either by itself or as part of any
+ Adaptations or Collections, You must not distort, mutilate, modify or
+ take other derogatory action in relation to the Work which would be
+ prejudicial to the Original Author's honor or reputation. Licensor
+ agrees that in those jurisdictions (e.g. Japan), in which any exercise
+ of the right granted in Section 3(b) of this License (the right to
+ make Adaptations) would be deemed to be a distortion, mutilation,
+ modification or other derogatory action prejudicial to the Original
+ Author's honor and reputation, the Licensor will waive or not assert,
+ as appropriate, this Section, to the fullest extent permitted by the
+ applicable national law, to enable You to reasonably exercise Your
+ right under Section 3(b) of this License (right to make Adaptations)
+ but not otherwise.
+
+5. Representations, Warranties and Disclaimer
+
+UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
+OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
+KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
+INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
+FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
+LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
+WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
+OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+
+6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
+LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
+ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
+ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. Termination
+
+ a. This License and the rights granted hereunder will terminate
+ automatically upon any breach by You of the terms of this License.
+ Individuals or entities who have received Adaptations or Collections
+ from You under this License, however, will not have their licenses
+ terminated provided such individuals or entities remain in full
+ compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
+ survive any termination of this License.
+ b. Subject to the above terms and conditions, the license granted here is
+ perpetual (for the duration of the applicable copyright in the Work).
+ Notwithstanding the above, Licensor reserves the right to release the
+ Work under different license terms or to stop distributing the Work at
+ any time; provided, however that any such election will not serve to
+ withdraw this License (or any other license that has been, or is
+ required to be, granted under the terms of this License), and this
+ License will continue in full force and effect unless terminated as
+ stated above.
+
+8. Miscellaneous
+
+ a. Each time You Distribute or Publicly Perform the Work or a Collection,
+ the Licensor offers to the recipient a license to the Work on the same
+ terms and conditions as the license granted to You under this License.
+ b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
+ offers to the recipient a license to the original Work on the same
+ terms and conditions as the license granted to You under this License.
+ c. If any provision of this License is invalid or unenforceable under
+ applicable law, it shall not affect the validity or enforceability of
+ the remainder of the terms of this License, and without further action
+ by the parties to this agreement, such provision shall be reformed to
+ the minimum extent necessary to make such provision valid and
+ enforceable.
+ d. No term or provision of this License shall be deemed waived and no
+ breach consented to unless such waiver or consent shall be in writing
+ and signed by the party to be charged with such waiver or consent.
+ e. This License constitutes the entire agreement between the parties with
+ respect to the Work licensed here. There are no understandings,
+ agreements or representations with respect to the Work not specified
+ here. Licensor shall not be bound by any additional provisions that
+ may appear in any communication from You. This License may not be
+ modified without the mutual written agreement of the Licensor and You.
+ f. The rights granted under, and the subject matter referenced, in this
+ License were drafted utilizing the terminology of the Berne Convention
+ for the Protection of Literary and Artistic Works (as amended on
+ September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
+ Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
+ and the Universal Copyright Convention (as revised on July 24, 1971).
+ These rights and subject matter take effect in the relevant
+ jurisdiction in which the License terms are sought to be enforced
+ according to the corresponding provisions of the implementation of
+ those treaty provisions in the applicable national law. If the
+ standard suite of rights granted under applicable copyright law
+ includes additional rights not granted under this License, such
+ additional rights are deemed to be included in the License; this
+ License is not intended to restrict the license of any rights under
+ applicable law.
+
+
+Creative Commons Notice
+
+ Creative Commons is not a party to this License, and makes no warranty
+ whatsoever in connection with the Work. Creative Commons will not be
+ liable to You or any party on any legal theory for any damages
+ whatsoever, including without limitation any general, special,
+ incidental or consequential damages arising in connection to this
+ license. Notwithstanding the foregoing two (2) sentences, if Creative
+ Commons has expressly identified itself as the Licensor hereunder, it
+ shall have all rights and obligations of Licensor.
+
+ Except for the limited purpose of indicating to the public that the
+ Work is licensed under the CCPL, Creative Commons does not authorize
+ the use by either party of the trademark "Creative Commons" or any
+ related trademark or logo of Creative Commons without the prior
+ written consent of Creative Commons. Any permitted use will be in
+ compliance with Creative Commons' then-current trademark usage
+ guidelines, as may be published on its website or otherwise made
+ available upon request from time to time. For the avoidance of doubt,
+ this trademark restriction does not form part of the License.
+
+ Creative Commons may be contacted at https://creativecommons.org/.
diff --git a/godot/remakes/font/LondrinaSolid-Regular.otf b/godot/remakes/font/LondrinaSolid-Regular.otf
new file mode 100644
index 0000000..02336ee
Binary files /dev/null and b/godot/remakes/font/LondrinaSolid-Regular.otf differ
diff --git a/godot/remakes/font/LondrinaSolid-Regular.otf.import b/godot/remakes/font/LondrinaSolid-Regular.otf.import
new file mode 100644
index 0000000..96c5e01
--- /dev/null
+++ b/godot/remakes/font/LondrinaSolid-Regular.otf.import
@@ -0,0 +1,38 @@
+[remap]
+
+importer="font_data_dynamic"
+type="FontFile"
+uid="uid://b50bdb32aerbb"
+path="res://.godot/imported/LondrinaSolid-Regular.otf-d908676649cd6eb2320758d9884c8ea7.fontdata"
+
+[deps]
+
+source_file="res://remakes/font/LondrinaSolid-Regular.otf"
+dest_files=["res://.godot/imported/LondrinaSolid-Regular.otf-d908676649cd6eb2320758d9884c8ea7.fontdata"]
+
+[params]
+
+Rendering=null
+antialiasing=1
+generate_mipmaps=false
+multichannel_signed_distance_field=false
+msdf_pixel_range=8
+msdf_size=48
+allow_system_fallback=true
+force_autohinter=false
+hinting=1
+subpixel_positioning=1
+oversampling=0.0
+Fallbacks=null
+fallbacks=[]
+Compress=null
+compress=true
+preload=[{
+"chars": [],
+"glyphs": [],
+"name": "New Configuration",
+"size": Vector2i(16, 2)
+}]
+language_support={}
+script_support={}
+opentype_features={}
diff --git a/godot/remakes/minimize.svg b/godot/remakes/minimize.svg
new file mode 100644
index 0000000..66fec9b
--- /dev/null
+++ b/godot/remakes/minimize.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/godot/remakes/minimize.svg.import b/godot/remakes/minimize.svg.import
new file mode 100644
index 0000000..784ad15
--- /dev/null
+++ b/godot/remakes/minimize.svg.import
@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dkeuhlg0ki67o"
+path="res://.godot/imported/minimize.svg-37263805eefa5e71d7973332b8503c4b.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://remakes/minimize.svg"
+dest_files=["res://.godot/imported/minimize.svg-37263805eefa5e71d7973332b8503c4b.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
diff --git a/godot/remakes/titlebar.afdesign b/godot/remakes/titlebar.afdesign
new file mode 100644
index 0000000..9e5c511
Binary files /dev/null and b/godot/remakes/titlebar.afdesign differ
diff --git a/rust/src/formats/mod.rs b/rust/src/formats/mod.rs
index db9b1ae..7fc1c69 100644
--- a/rust/src/formats/mod.rs
+++ b/rust/src/formats/mod.rs
@@ -5,6 +5,8 @@ use crate::formats::sprites::Sprites;
use crate::formats::txt::{decrypt_txt, DecryptError};
use crate::formats::ui_xml::UiTag;
use binrw::BinRead;
+use itertools::Itertools;
+use std::collections::HashMap;
use std::ffi::OsStr;
use std::fmt::Debug;
use std::io::{Cursor, Read, Seek, SeekFrom};
@@ -26,6 +28,7 @@ pub enum DatafileFile {
Vorbis(Vec),
TileCollision(String),
Ui(UiTag),
+ Translations(HashMap>),
}
pub enum Error {
@@ -90,26 +93,20 @@ where
Ok(DatafileFile::Txt(decr))
}
}
- /*Some("rle") => {
- let image: RleImage = RleImage::read(&mut Cursor::new(data)).unwrap();
- let path = Path::new(dat_path).with_file_name("res.gif");
- println!("{:?}", path);
- let mut encoder = GifEncoder::new(
- OpenOptions::new()
- .create(true)
- .write(true)
- .open(path)
- .unwrap(),
- );
- encoder.set_repeat(Repeat::Infinite).unwrap();
- encoder.try_encode_frames(image.into_frames()).unwrap();
- }
- Some("dat") => {
- let image = level_tile_data_to_image(&data).unwrap();
- let path = Path::new(dat_path).with_file_name("res.png");
- println!("{:?}", path);
- image.save_with_format(path, ImageFormat::Png).unwrap();
- }*/
+ "csv" => Ok(DatafileFile::Translations(
+ String::from_utf8(data)
+ .unwrap()
+ .split('\n')
+ .map(|l| l.trim())
+ .filter(|l| !l.is_empty())
+ .map(|l| {
+ l.splitn(2, ';')
+ .map(|s| s.to_string())
+ .collect_tuple::<(String, String)>()
+ .expect("Invalid csv")
+ })
+ .into_group_map(),
+ )),
ext => Err(Error::UnknownFormat(ext.to_string())),
}
}
diff --git a/rust/src/formats/ui_xml.rs b/rust/src/formats/ui_xml.rs
index cab9fb7..3109595 100644
--- a/rust/src/formats/ui_xml.rs
+++ b/rust/src/formats/ui_xml.rs
@@ -16,7 +16,7 @@ pub struct UiMenu {
pub selected: String,
#[serde(rename = "OnBack")]
pub on_back: Option,
- #[serde(rename = "$value")]
+ #[serde(rename = "$value", default)]
pub children: Vec,
}
@@ -45,13 +45,14 @@ pub struct UiTextButton {
pub on_select: String,
}
+/// This sometimes appears completely empty
#[derive(Debug, Deserialize)]
pub struct UiTextArea {
- #[serde(deserialize_with = "deserialize_vec2")]
+ #[serde(deserialize_with = "deserialize_vec2", default)]
pub position: [i32; 2],
- #[serde(deserialize_with = "deserialize_vec2")]
+ #[serde(deserialize_with = "deserialize_vec2", default)]
pub size: [i32; 2],
- #[serde(rename = "$value")]
+ #[serde(rename = "$value", default)]
pub children: Vec,
}
diff --git a/rust/src/godot/datafile.rs b/rust/src/godot/datafile.rs
index 820c8b4..2191a21 100644
--- a/rust/src/godot/datafile.rs
+++ b/rust/src/godot/datafile.rs
@@ -1,6 +1,5 @@
use crate::formats;
use crate::formats::datafile::{Datafile, FileEntry};
-use crate::formats::sprites::{CropMode, RenderMode, SpriteType};
use crate::formats::{load_data, DatafileFile};
use crate::godot::font::load_bitmap_font;
use crate::godot::game_object::parse_game_object;
@@ -10,16 +9,11 @@ use crate::godot::tile_map::{create_tile_map, TileCollision};
use crate::godot::ui::convert_ui;
use binrw::BinRead;
use godot::engine::global::Error;
-use godot::engine::image::Format;
use godot::engine::resource_loader::CacheMode;
use godot::engine::resource_saver::SaverFlags;
-use godot::engine::utilities::{printerr, prints};
-use godot::engine::{
- AtlasTexture, AudioStream, AudioStreamOggVorbis, DirAccess, OggPacketSequence,
- PlaceholderTexture2D, SpriteFrames,
-};
-use godot::engine::{Image, PckPacker};
-use godot::engine::{ImageTexture, ProjectSettings};
+use godot::engine::utilities::printerr;
+use godot::engine::ImageTexture;
+use godot::engine::{AudioStreamOggVorbis, DirAccess, OggPacketSequence, Translation};
use godot::engine::{ResourceFormatLoader, ResourceSaver};
use godot::engine::{ResourceFormatLoaderVirtual, ResourceLoader};
use godot::prelude::*;
@@ -137,12 +131,12 @@ impl ResourceFormatLoaderVirtual for DatafileLoader {
fn load(
&self,
- path: GodotString,
+ virtual_path: GodotString,
_original_path: GodotString,
_use_sub_threads: bool,
_cache_mode: i64,
) -> Variant {
- let datafile_path = convert_path(&path);
+ let datafile_path = convert_path(&virtual_path);
if let Some(resource) = self.retrieve_cache::(format!(
"{}.{}",
datafile_path,
@@ -178,13 +172,25 @@ impl ResourceFormatLoaderVirtual for DatafileLoader {
game_object.to_variant()
}
Ok(DatafileFile::Ui(ui)) => {
- let ui = convert_ui(ui, None);
+ let full_path = virtual_path.to_string();
+ let (_, _, base_path) = full_path
+ .rsplitn(3, '/')
+ .collect_tuple()
+ .expect("Illegal path for UI");
+ let ui = convert_ui(ui, None, base_path);
let mut scene = PackedScene::new();
scene.pack(ui);
self.save_to_cache(scene.share().upcast(), format!("{}.scn", datafile_path));
scene.to_variant()
}
+ Ok(DatafileFile::Translations(translations)) => {
+ let mut translation = Translation::new();
+ for (key, message) in translations {
+ translation.add_message(key.into(), message.join("\n").into(), "".into());
+ }
+ translation.to_variant()
+ }
Ok(DatafileFile::Vorbis(vorbis)) => {
let mut audio = AudioStreamOggVorbis::new();
audio.set_loop(true);
@@ -198,7 +204,7 @@ impl ResourceFormatLoaderVirtual for DatafileLoader {
}
Ok(DatafileFile::RleSprite(rle)) => load_rle_as_sprite_frames(*rle).to_variant(),
Ok(DatafileFile::Sprites(sprites)) => {
- let sprite_frames = load_sprite_frames(sprites, path);
+ let sprite_frames = load_sprite_frames(sprites, virtual_path);
self.save_to_cache(
sprite_frames.share().upcast(),
diff --git a/rust/src/godot/ui.rs b/rust/src/godot/ui.rs
index 3f943f0..62b8531 100644
--- a/rust/src/godot/ui.rs
+++ b/rust/src/godot/ui.rs
@@ -1,85 +1,143 @@
use crate::formats::ui_xml::{HorizontalAlign, UiTag};
-use godot::builtin::{Array, Dictionary, GodotString, Signal, ToVariant, Vector2};
+use godot::builtin::{Array, Dictionary, GodotString, ToVariant, Vector2};
+use godot::engine::control::{LayoutPreset, SizeFlags};
use godot::engine::global::HorizontalAlignment;
use godot::engine::node::InternalMode;
-use godot::engine::{Button, Control, Node, TextureRect};
-use godot::obj::{Gd, Share};
-use godot::sys::GDEXTENSION_VARIANT_TYPE_STRING;
+use godot::engine::{load, Button, Control, Label, Node, SpinBox, TextureRect};
+use godot::obj::{Gd, Inherits, Share};
use itertools::Itertools;
const ACTION_META_NAME: &str = "action";
-pub fn convert_ui(ui: UiTag, owner: Option>) -> Gd {
+pub fn convert_ui(ui: UiTag, owner: Option>, base_path: &str) -> Gd {
match ui {
UiTag::Menu(menu) => {
let mut gd_menu = Control::new_alloc();
- let owner_node = owner.unwrap_or_else(|| gd_menu.share().upcast());
-
- for child in menu.children {
- let mut child = convert_ui(child, Some(owner_node.share()));
- gd_menu.add_child(child.share(), false, InternalMode::INTERNAL_MODE_FRONT);
- child.set_owner(owner_node.share());
- }
+ gd_menu.set_anchors_preset(LayoutPreset::PRESET_FULL_RECT, false);
+ attach_children(&mut gd_menu, owner, menu.children, base_path);
gd_menu.upcast()
}
UiTag::Image(image) => {
let mut gd_image = TextureRect::new_alloc();
+ let texture = load(format!("{}/sprites/{}.bmp", base_path, image.texture));
+
+ gd_image.set_texture(texture);
gd_image.set_name(image.texture.into());
- gd_image.set_position(
- Vector2 {
- x: image.position[0] as f32,
- y: image.position[1] as f32,
- },
- false,
- );
- gd_image.set_size(
- Vector2 {
- x: image.size[0] as f32,
- y: image.size[1] as f32,
- },
- false,
- );
+ gd_image.set_position(to_vec2(image.position), false);
+ gd_image.set_size(to_vec2(image.size), false);
gd_image.upcast()
}
+ UiTag::StaticText(text) => {
+ let mut label = Label::new_alloc();
+ label.set_anchors_preset(LayoutPreset::PRESET_TOP_WIDE, false);
+ label.set_position(to_vec2(text.position), false);
+ label.set_horizontal_alignment(text.horizontal_align.into());
+ label.set_text(text.text.into());
+ label.upcast()
+ }
+ UiTag::TextArea(area) => {
+ let mut text_area = Control::new_alloc();
+ text_area.set_anchors_preset(LayoutPreset::PRESET_FULL_RECT, false);
+ text_area.set_position(to_vec2(area.position), false);
+ text_area.set_size(to_vec2(area.size), false);
+ attach_children(&mut text_area, owner, area.children, base_path);
+ text_area.upcast()
+ }
+ UiTag::ToggleButton(toggle) => {
+ let mut spin_box = SpinBox::new_alloc();
+ spin_box.set_position(to_vec2(toggle.position), false);
+ spin_box.set_min(toggle.min_value as f64);
+ spin_box.set_max(toggle.max_value as f64);
+ spin_box.set_step(toggle.value_step as f64);
+ if let Some(name) = toggle.name {
+ spin_box.set_name(GodotString::from(name));
+ }
+ spin_box.set_meta("text".into(), toggle.text.to_variant());
+ spin_box.set_meta("target".into(), toggle.target.to_variant());
+ spin_box.set_meta(
+ "no_sound".into(),
+ toggle.no_sound.unwrap_or(false).to_variant(),
+ );
+ attach_call_meta(&mut spin_box, toggle.on_change);
+ spin_box.upcast()
+ }
UiTag::TextButton(button) => {
let mut gd_button = Button::new_alloc();
- gd_button.set_position(
- Vector2 {
- x: button.position[0] as f32,
- y: button.position[1] as f32,
- },
- false,
- );
- gd_button.set_text_alignment(match button.horizontal_align {
- HorizontalAlign::Center => HorizontalAlignment::HORIZONTAL_ALIGNMENT_CENTER,
- });
+ gd_button.set_anchors_preset(LayoutPreset::PRESET_TOP_WIDE, false);
+ gd_button.set_flat(true);
+ gd_button.set_position(to_vec2(button.position), false);
+ gd_button.set_text_alignment(button.horizontal_align.into());
if let Some(name) = button.name {
gd_button.set_name(GodotString::from(name));
}
gd_button.set_text(GodotString::from(button.text));
-
- let mut call = button.on_select.split_whitespace().collect_vec();
- if let Some((name,)) = call.drain(..1).collect_tuple() {
- gd_button.set_meta(
- ACTION_META_NAME.into(),
- Dictionary::from([
- (&"name".to_variant(), &name.to_variant()),
- (
- &"args".to_variant(),
- &Array::from(
- call.into_iter()
- .map(GodotString::from)
- .collect::>()
- .as_slice(),
- )
- .to_variant(),
- ),
- ])
- .to_variant(),
- );
- }
-
+ attach_call_meta(&mut gd_button, button.on_select);
gd_button.upcast()
}
}
}
+
+impl Into for HorizontalAlign {
+ fn into(self) -> HorizontalAlignment {
+ match self {
+ HorizontalAlign::Center => HorizontalAlignment::HORIZONTAL_ALIGNMENT_CENTER,
+ HorizontalAlign::Left => HorizontalAlignment::HORIZONTAL_ALIGNMENT_LEFT,
+ HorizontalAlign::Right => HorizontalAlignment::HORIZONTAL_ALIGNMENT_RIGHT,
+ }
+ }
+}
+
+fn attach_children(
+ node: &mut Gd,
+ owner: Option>,
+ children: Vec,
+ base_path: &str,
+) where
+ T: Inherits,
+{
+ let owner_node = owner.unwrap_or_else(|| node.share().upcast());
+
+ for child in children {
+ let mut child = convert_ui(child, Some(owner_node.share()), base_path);
+ node.share()
+ .upcast()
+ .add_child(child.share(), false, InternalMode::INTERNAL_MODE_FRONT);
+ child.set_owner(owner_node.share());
+ }
+}
+
+fn to_vec2(vec: [i32; 2]) -> Vector2 {
+ Vector2 {
+ x: vec[0] as f32,
+ y: vec[1] as f32,
+ }
+}
+
+fn attach_call_meta(button: &mut Gd, call_string: String)
+where
+ T: Inherits,
+{
+ let mut call = call_string.split_whitespace().collect_vec();
+ if call.is_empty() {
+ return;
+ }
+ if let Some((name,)) = call.drain(..1).collect_tuple() {
+ button.share().upcast().set_meta(
+ ACTION_META_NAME.into(),
+ Dictionary::from([
+ (&"name".to_variant(), &name.to_variant()),
+ (
+ &"args".to_variant(),
+ &Array::from(
+ call.into_iter()
+ .map(GodotString::from)
+ .collect::>()
+ .as_slice(),
+ )
+ .to_variant(),
+ ),
+ ])
+ .to_variant(),
+ );
+ }
+}