diff --git a/.gitignore b/.gitignore index 9dd0b5e..1d8ce88 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,9 @@ export.cfg Thumbs.db *~ .import +.vscode +*.exe +*.pck +*.x86_64 + +export_presets.cfg diff --git a/Drawing.gd b/Drawing.gd deleted file mode 100644 index 4380236..0000000 --- a/Drawing.gd +++ /dev/null @@ -1,115 +0,0 @@ -extends Control - -var _pixels = 800 - -var _previous_point = Vector2() -var _image = Image.new() -var _stroke = Image.new() -var _brush = Image.new() - -var _image_tex = ImageTexture.new() -var _stroke_tex = ImageTexture.new() -var _brush_tex = ImageTexture.new() - -var _brush_width -var _brush_height - -var _drawing_stroke = false - -var _color_into_brush = ImageBlender.new() -var _brush_into_stroke = ImageBlender.new() -var _stroke_into_image = ImageBlender.new() - -func _ready(): - _image.create(_pixels, _pixels, false, Image.FORMAT_RGBA8) - _image.fill(Color.white) - - _image_tex.create_from_image(_image) - - _stroke.create(_pixels, _pixels, false, Image.FORMAT_RGBA8) - _stroke.fill(Color.transparent) - - _stroke_tex.create_from_image(_stroke) - - _color_into_brush.set_rgb_src_factor(ImageBlender.FACTOR_ONE) - _color_into_brush.set_rgb_dst_factor(ImageBlender.FACTOR_ZERO) - _color_into_brush.set_alpha_src_factor(ImageBlender.FACTOR_ZERO) - _color_into_brush.set_alpha_dst_factor(ImageBlender.FACTOR_ONE) - - _brush_into_stroke.set_rgb_src_factor(ImageBlender.FACTOR_ONE) - _brush_into_stroke.set_rgb_dst_factor(ImageBlender.FACTOR_ZERO) - _brush_into_stroke.set_alpha_equation(ImageBlender.FUNC_MAX) - - create_brush("./brush.png") - resize_brush(64, 64) - set_brush_color(Color.red) - - _brush_tex.create_from_image(_brush) - -func _draw(): - draw_texture(_image_tex, Vector2.ZERO) - draw_texture(_stroke_tex, Vector2.ZERO) - -func _input(event): - if event is InputEventMouseButton: - if event.get_button_index() == BUTTON_LEFT: - if event.is_pressed(): - start_stroke(event.position) - draw_stroke(event.position) - else: - end_stroke() - elif event is InputEventMouseMotion: - if _drawing_stroke: - draw_stroke(event.position) - -func create_brush(path : String): - _brush.load(path) - _brush.lock() - - _brush_width = _brush.get_size().x - _brush_height = _brush.get_size().y - -func resize_brush(width : int, height : int): - _brush_width = width - _brush_height = height - - _brush.unlock() - _brush.resize(width, height, Image.INTERPOLATE_NEAREST) - _brush.lock() - -func set_brush_color(color : Color): - var color_image = Image.new() - color_image.copy_from(_brush) - color_image.fill(color) - - _color_into_brush.blend_rect(color_image, Rect2(Vector2.ZERO, color_image.get_size()), _brush, Vector2.ZERO) - -func start_stroke(pos : Vector2): - _stroke.lock() - - _previous_point = pos - _drawing_stroke = true - -func draw_stroke(_current_point : Vector2): - _brush_into_stroke.stamp_rect(_brush, Rect2(Vector2.ZERO,_brush.get_size()), _stroke, _previous_point, _current_point, 6.4) - - _previous_point = _current_point - update_stroke() - update() - -func end_stroke(): - _stroke_into_image.blend_rect(_stroke, Rect2(Vector2.ZERO,_stroke.get_size()), _image, Vector2.ZERO) - update_image() - - _stroke.fill(Color.transparent) - update_stroke() - - update() - - _drawing_stroke = false - -func update_image(): - _image_tex.set_data(_image) - -func update_stroke(): - _stroke_tex.set_data(_stroke) diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..95a879c --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2020 Tomás Espejo Gómez + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/MainWindow.gd b/MainWindow.gd new file mode 100644 index 0000000..b3af26d --- /dev/null +++ b/MainWindow.gd @@ -0,0 +1,51 @@ +extends Control + +enum StyleState{ + NONE, + SELECTED, + SELECT_ANOTHER_ONE +} + +var _work_space = preload("res://views/WorkSpace.tscn") +var _style_state = StyleState.NONE + +func _ready(): + OS.set_window_maximized(true) + +func _popup_loadstyle(): + if _style_state == StyleState.NONE: + get_node("LoadStylePopup").popup_centered() + get_node("LoadStylePopup").get_close_button().disabled = true + _loadstyle_resized() + elif _style_state == StyleState.SELECT_ANOTHER_ONE: + get_node("LoadStylePopup").popup_centered() + get_node("LoadStylePopup").get_close_button().disabled = false + _loadstyle_resized() + else: + pass + +func _resized(): + _popup_loadstyle() + +func _loadstyle_resized(): + var height = get_node("LoadStylePopup/LoadStyle").get_size().y + 20 + get_node("LoadStylePopup").set_size(Vector2(700, height)) + +func _style_selected(canvas_conf : Dictionary, style_conf : Dictionary): + _style_state = StyleState.SELECTED + get_node("LoadStylePopup").hide() + + if _style_state == StyleState.SELECT_ANOTHER_ONE: + get_node("WorkSpace").queue_free() + + var work_space = _work_space.instance() + work_space.connect("new", self, "_new") + add_child(work_space) + work_space.init(canvas_conf, style_conf) + + update() + +func _new(): + _style_state = StyleState.SELECT_ANOTHER_ONE + + _popup_loadstyle() diff --git a/MainWindow.tscn b/MainWindow.tscn index b7994fa..47b5125 100644 --- a/MainWindow.tscn +++ b/MainWindow.tscn @@ -1,9 +1,348 @@ -[gd_scene load_steps=2 format=2] +[gd_scene load_steps=26 format=2] -[ext_resource path="res://Drawing.gd" type="Script" id=1] +[ext_resource path="res://MainWindow.gd" type="Script" id=1] +[ext_resource path="res://views/LoadStyle.tscn" type="PackedScene" id=2] +[ext_resource path="res://resources/icons/Slider.png" type="Texture" id=3] + +[sub_resource type="StyleBoxFlat" id=1] +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="StyleBoxFlat" id=2] +bg_color = Color( 0.811765, 0.854902, 1, 1 ) +border_color = Color( 0.811765, 0.854902, 1, 1 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="StyleBoxFlat" id=3] +bg_color = Color( 1, 1, 1, 1 ) +border_width_left = 5 +border_width_top = 5 +border_width_right = 5 +border_width_bottom = 5 +border_color = Color( 1, 1, 1, 1 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="StyleBoxFlat" id=4] +bg_color = Color( 0.592157, 0.835294, 0.886275, 1 ) +border_color = Color( 0.266667, 0.427451, 0.964706, 1 ) + +[sub_resource type="StyleBoxFlat" id=5] +bg_color = Color( 0.509804, 0.752941, 0.8, 1 ) +border_color = Color( 0.266667, 0.427451, 0.964706, 1 ) + +[sub_resource type="StyleBoxFlat" id=6] +bg_color = Color( 1, 1, 1, 1 ) +border_width_top = 5 +border_width_bottom = 5 +border_color = Color( 1, 1, 1, 1 ) + +[sub_resource type="StyleBoxFlat" id=7] +content_margin_left = 5.0 +bg_color = Color( 0.145098, 0.196078, 0.215686, 1 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="StyleBoxFlat" id=8] +bg_color = Color( 0.266667, 0.427451, 0.964706, 1 ) +border_color = Color( 1, 1, 1, 1 ) + +[sub_resource type="DynamicFontData" id=9] +font_path = "res://resources/fonts/Roboto_Mono/RobotoMono-VariableFont_wght.ttf" + +[sub_resource type="DynamicFont" id=10] +font_data = SubResource( 9 ) + +[sub_resource type="StyleBoxFlat" id=11] +content_margin_left = 5.0 +content_margin_right = 5.0 +content_margin_top = 5.0 +content_margin_bottom = 5.0 +bg_color = Color( 0.976471, 0.984314, 0.698039, 1 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="StyleBoxFlat" id=12] +bg_color = Color( 0.266667, 0.427451, 0.964706, 1 ) +border_color = Color( 1, 1, 1, 1 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="StyleBoxFlat" id=13] +bg_color = Color( 0.14902, 0.298039, 0.780392, 1 ) +border_width_left = 5 +border_width_top = 5 +border_width_right = 5 +border_color = Color( 0.14902, 0.298039, 0.780392, 1 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 + +[sub_resource type="StyleBoxFlat" id=14] +border_width_left = 5 +border_width_top = 5 +border_width_right = 5 +border_color = Color( 0.6, 0.6, 0.6, 1 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 + +[sub_resource type="StyleBoxFlat" id=15] +content_margin_left = 5.0 +content_margin_right = 5.0 +content_margin_top = 5.0 +content_margin_bottom = 0.0 +bg_color = Color( 1, 1, 1, 1 ) +border_color = Color( 1, 1, 1, 1 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 + +[sub_resource type="StyleBoxFlat" id=16] +content_margin_left = 5.0 +content_margin_right = 5.0 +content_margin_top = 5.0 +content_margin_bottom = 5.0 +bg_color = Color( 0.6, 0.6, 0.6, 0 ) +border_color = Color( 1, 1, 1, 1 ) + +[sub_resource type="StyleBoxFlat" id=17] +bg_color = Color( 0.976471, 0.984314, 0.698039, 0.490196 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 +expand_margin_left = 5.0 +expand_margin_right = 5.0 +expand_margin_top = 5.0 +expand_margin_bottom = 5.0 + +[sub_resource type="StyleBoxFlat" id=18] +bg_color = Color( 1, 1, 1, 1 ) +border_width_left = 5 +border_width_right = 5 +border_color = Color( 1, 1, 1, 1 ) + +[sub_resource type="StyleBoxFlat" id=19] +bg_color = Color( 0.266667, 0.427451, 0.964706, 1 ) +border_width_left = 2 +border_width_top = 2 +border_width_right = 2 +border_width_bottom = 2 +border_color = Color( 1, 1, 1, 1 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 +shadow_color = Color( 1, 1, 1, 1 ) +shadow_size = 1 +shadow_offset = Vector2( 10, -20 ) + +[sub_resource type="DynamicFontData" id=20] +font_path = "res://resources/fonts/Poppins/Poppins-SemiBold.ttf" + +[sub_resource type="DynamicFont" id=21] +font_data = SubResource( 20 ) + +[sub_resource type="Theme" id=22] +default_font = SubResource( 21 ) +Button/colors/font_color = Color( 0.266667, 0.427451, 0.964706, 1 ) +Button/colors/font_color_disabled = Color( 0.901961, 0.901961, 0.901961, 0.2 ) +Button/colors/font_color_hover = Color( 1, 1, 1, 1 ) +Button/colors/font_color_pressed = Color( 1, 1, 1, 1 ) +Button/constants/hseparation = 2 +Button/fonts/font = null +Button/styles/disabled = SubResource( 1 ) +Button/styles/focus = null +Button/styles/hover = SubResource( 2 ) +Button/styles/normal = SubResource( 3 ) +Button/styles/pressed = SubResource( 2 ) +GridContainer/constants/hseparation = 10 +GridContainer/constants/vseparation = 10 +HScrollBar/icons/decrement = null +HScrollBar/icons/decrement_highlight = null +HScrollBar/icons/increment = null +HScrollBar/icons/increment_highlight = null +HScrollBar/styles/grabber = SubResource( 4 ) +HScrollBar/styles/grabber_highlight = SubResource( 5 ) +HScrollBar/styles/grabber_pressed = SubResource( 5 ) +HScrollBar/styles/scroll = SubResource( 6 ) +HScrollBar/styles/scroll_focus = SubResource( 6 ) +HSlider/icons/grabber = ExtResource( 3 ) +HSlider/icons/grabber_disabled = ExtResource( 3 ) +HSlider/icons/grabber_highlight = ExtResource( 3 ) +HSlider/icons/tick = ExtResource( 3 ) +HSlider/styles/grabber_area = SubResource( 4 ) +HSlider/styles/grabber_area_highlight = SubResource( 5 ) +HSlider/styles/slider = SubResource( 6 ) +LineEdit/colors/clear_button_color = Color( 0.88, 0.88, 0.88, 1 ) +LineEdit/colors/clear_button_color_pressed = Color( 1, 1, 1, 1 ) +LineEdit/colors/cursor_color = Color( 0.94, 0.94, 0.94, 1 ) +LineEdit/colors/font_color = Color( 0.88, 0.88, 0.88, 1 ) +LineEdit/colors/font_color_selected = Color( 0, 0, 0, 1 ) +LineEdit/colors/font_color_uneditable = Color( 0.88, 0.88, 0.88, 0.5 ) +LineEdit/colors/selection_color = Color( 0.49, 0.49, 0.49, 1 ) +LineEdit/constants/minimum_spaces = 12 +LineEdit/fonts/font = null +LineEdit/icons/clear = null +LineEdit/styles/focus = SubResource( 7 ) +LineEdit/styles/normal = SubResource( 7 ) +LineEdit/styles/read_only = SubResource( 7 ) +MarginContainer/constants/margin_bottom = 10 +MarginContainer/constants/margin_left = 10 +MarginContainer/constants/margin_right = 10 +MarginContainer/constants/margin_top = 10 +Panel/styles/panel = SubResource( 7 ) +PanelContainer/styles/panel = SubResource( 8 ) +RichTextLabel/colors/default_color = Color( 0.145098, 0.196078, 0.215686, 1 ) +RichTextLabel/colors/font_color_selected = Color( 0.49, 0.49, 0.49, 1 ) +RichTextLabel/colors/font_color_shadow = Color( 0, 0, 0, 0 ) +RichTextLabel/colors/selection_color = Color( 0.1, 0.1, 1, 0.8 ) +RichTextLabel/constants/line_separation = 1 +RichTextLabel/constants/shadow_as_outline = 0 +RichTextLabel/constants/shadow_offset_x = 1 +RichTextLabel/constants/shadow_offset_y = 1 +RichTextLabel/constants/table_hseparation = 3 +RichTextLabel/constants/table_vseparation = 3 +RichTextLabel/fonts/bold_font = null +RichTextLabel/fonts/bold_italics_font = null +RichTextLabel/fonts/italics_font = null +RichTextLabel/fonts/mono_font = null +RichTextLabel/fonts/normal_font = SubResource( 10 ) +RichTextLabel/styles/focus = SubResource( 11 ) +RichTextLabel/styles/normal = SubResource( 11 ) +TabContainer/colors/font_color_bg = Color( 1, 1, 1, 1 ) +TabContainer/colors/font_color_disabled = Color( 0.901961, 0.901961, 0.901961, 0.780392 ) +TabContainer/colors/font_color_fg = Color( 0.266667, 0.427451, 0.964706, 1 ) +TabContainer/constants/hseparation = 4 +TabContainer/constants/label_valign_bg = 2 +TabContainer/constants/label_valign_fg = 0 +TabContainer/constants/side_margin = 8 +TabContainer/constants/top_margin = 24 +TabContainer/fonts/font = null +TabContainer/icons/decrement = null +TabContainer/icons/decrement_highlight = null +TabContainer/icons/increment = null +TabContainer/icons/increment_highlight = null +TabContainer/icons/menu = null +TabContainer/icons/menu_highlight = null +TabContainer/styles/panel = SubResource( 12 ) +TabContainer/styles/tab_bg = SubResource( 13 ) +TabContainer/styles/tab_disabled = SubResource( 14 ) +TabContainer/styles/tab_fg = SubResource( 15 ) +TextEdit/colors/background_color = Color( 0, 0, 0, 0 ) +TextEdit/colors/bookmark_color = Color( 0.08, 0.49, 0.98, 1 ) +TextEdit/colors/brace_mismatch_color = Color( 1, 0.2, 0.2, 1 ) +TextEdit/colors/breakpoint_color = Color( 0.8, 0.8, 0.4, 0.2 ) +TextEdit/colors/caret_background_color = Color( 0, 0, 0, 1 ) +TextEdit/colors/caret_color = Color( 0.88, 0.88, 0.88, 1 ) +TextEdit/colors/code_folding_color = Color( 0.8, 0.8, 0.8, 0.8 ) +TextEdit/colors/completion_background_color = Color( 0.17, 0.16, 0.2, 1 ) +TextEdit/colors/completion_existing_color = Color( 0.87, 0.87, 0.87, 0.13 ) +TextEdit/colors/completion_font_color = Color( 0.67, 0.67, 0.67, 1 ) +TextEdit/colors/completion_scroll_color = Color( 1, 1, 1, 1 ) +TextEdit/colors/completion_selected_color = Color( 0.26, 0.26, 0.27, 1 ) +TextEdit/colors/current_line_color = Color( 0.25, 0.25, 0.26, 0.8 ) +TextEdit/colors/executing_line_color = Color( 0.2, 0.8, 0.2, 0.4 ) +TextEdit/colors/font_color = Color( 0.88, 0.88, 0.88, 1 ) +TextEdit/colors/font_color_readonly = Color( 0.88, 0.88, 0.88, 0.5 ) +TextEdit/colors/font_color_selected = Color( 0, 0, 0, 1 ) +TextEdit/colors/function_color = Color( 0.4, 0.64, 0.81, 1 ) +TextEdit/colors/line_number_color = Color( 0.67, 0.67, 0.67, 0.4 ) +TextEdit/colors/mark_color = Color( 1, 0.4, 0.4, 0.4 ) +TextEdit/colors/member_variable_color = Color( 0.9, 0.31, 0.35, 1 ) +TextEdit/colors/number_color = Color( 0.92, 0.58, 0.2, 1 ) +TextEdit/colors/safe_line_number_color = Color( 0.67, 0.78, 0.67, 0.6 ) +TextEdit/colors/selection_color = Color( 0.49, 0.49, 0.49, 1 ) +TextEdit/colors/symbol_color = Color( 0.94, 0.94, 0.94, 1 ) +TextEdit/colors/word_highlighted_color = Color( 0.8, 0.9, 0.9, 0.15 ) +TextEdit/constants/completion_lines = 7 +TextEdit/constants/completion_max_width = 50 +TextEdit/constants/completion_scroll_width = 3 +TextEdit/constants/line_spacing = 4 +TextEdit/fonts/font = null +TextEdit/icons/fold = null +TextEdit/icons/folded = null +TextEdit/icons/space = null +TextEdit/icons/tab = null +TextEdit/styles/completion = SubResource( 7 ) +TextEdit/styles/focus = SubResource( 7 ) +TextEdit/styles/normal = SubResource( 7 ) +TextEdit/styles/read_only = SubResource( 7 ) +ToolButton/colors/font_color = Color( 1, 1, 1, 1 ) +ToolButton/colors/font_color_disabled = Color( 1, 1, 1, 1 ) +ToolButton/colors/font_color_hover = Color( 1, 1, 1, 1 ) +ToolButton/colors/font_color_pressed = Color( 1, 1, 1, 1 ) +ToolButton/constants/hseparation = 0 +ToolButton/fonts/font = null +ToolButton/styles/disabled = SubResource( 16 ) +ToolButton/styles/focus = SubResource( 16 ) +ToolButton/styles/hover = SubResource( 16 ) +ToolButton/styles/normal = SubResource( 16 ) +ToolButton/styles/pressed = SubResource( 16 ) +TooltipPanel/styles/panel = SubResource( 17 ) +VScrollBar/icons/decrement = null +VScrollBar/icons/decrement_highlight = null +VScrollBar/icons/increment = null +VScrollBar/icons/increment_highlight = null +VScrollBar/styles/grabber = SubResource( 4 ) +VScrollBar/styles/grabber_highlight = SubResource( 5 ) +VScrollBar/styles/grabber_pressed = SubResource( 5 ) +VScrollBar/styles/scroll = SubResource( 18 ) +VScrollBar/styles/scroll_focus = SubResource( 18 ) +WindowDialog/colors/title_color = Color( 0.145098, 0.196078, 0.215686, 1 ) +WindowDialog/constants/close_h_ofs = 18 +WindowDialog/constants/close_v_ofs = 18 +WindowDialog/constants/scaleborder_size = 4 +WindowDialog/constants/title_height = 20 +WindowDialog/fonts/title_font = null +WindowDialog/icons/close = null +WindowDialog/icons/close_highlight = null +WindowDialog/styles/panel = SubResource( 19 ) [node name="MainWindow" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = -0.840881 +margin_top = -0.840881 +margin_right = -0.840881 +margin_bottom = -0.840881 +theme = SubResource( 22 ) script = ExtResource( 1 ) __meta__ = { "_edit_use_anchors_": false } + +[node name="LoadStylePopup" type="WindowDialog" parent="."] +visible = true +margin_left = 1.0 +margin_top = 1.0 +margin_right = 701.0 +margin_bottom = 131.0 +popup_exclusive = true +window_title = "Load Style" +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="LoadStyle" parent="LoadStylePopup" instance=ExtResource( 2 )] +anchor_right = 0.0 +margin_left = 10.0 +margin_top = 10.0 +margin_right = 690.0 +margin_bottom = 134.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +[connection signal="resized" from="." to="." method="_resized"] +[connection signal="resized" from="LoadStylePopup/LoadStyle" to="." method="_loadstyle_resized"] +[connection signal="style_selected" from="LoadStylePopup/LoadStyle" to="." method="_style_selected"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..e3b3eff --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +Teggy's Map Maker +========================= + + A tilemap editor built using the Godot Game Engine. + + + +Features +--------------------------- + +- Create a custom style using a JSON file. +- Load a style to be able to draw a map using the tiles it provides. +- Save the result as a PNG image. + +How To Install And Use +------------------------- + +Download the zip file from the latest release. This zip file would include an executable, a PCK file, and a folder called 'styles'. The PCK file must be in the same folder that contains the executable for it to work. The 'styles' folder contains some styles that aim to serve as a tutorial on how to create your own. + +When you execute the app, it would ask you to select a configuration file. Select one of those provide alongside the executable inside the 'styles' folder or anyone that you have created. + +How To Compile +------------------------- + +You would need the source code of: +- [Godot v.3.2.2](https://github.com/godotengine/godot/releases/tag/3.2.2-stable) +- [Goost](https://github.com/goostengine/goost) + +Then you would need to compile Godot with Goost as a custom module: +- [Compiling Godot](https://docs.godotengine.org/en/stable/development/compiling/index.html) +- [Including a custom module](https://docs.godotengine.org/en/stable/development/cpp/custom_modules_in_cpp.html#compiling-a-module-externally) + +Once you have compiled the editor, you can import this project. diff --git a/brush.png b/brush.png deleted file mode 100644 index c8f3ce7..0000000 Binary files a/brush.png and /dev/null differ diff --git a/classes/parser/BaseParser.gd b/classes/parser/BaseParser.gd new file mode 100644 index 0000000..0d4e7a8 --- /dev/null +++ b/classes/parser/BaseParser.gd @@ -0,0 +1,381 @@ +class_name BaseParser + +var _directory : Directory = Directory.new() +var _configuration : Dictionary = {} +var _errors : Array = [] +var _warnings : Array = [] +const _error_diff : float = 0.0000001 + +# Public + +func open_dir_from_file_path(path : String) -> void: + if _directory.open(path.get_base_dir()) != OK: + print("Error while opening the style directoru") + +# Private + +func _add_error(error : String) -> void: + _errors.append(error) + +func _add_warning(warning : String) -> void: + _warnings.append(warning) + +# Checkers + +func _check_obligatory_object(configuration : Dictionary, + parameter : String, + context : String = "") -> Dictionary: + var object = {} + + if configuration.has(parameter): + object = _check_object(configuration, parameter, context) + else: + _missing(parameter, "Object", context) + + return object + +func _check_object(configuration : Dictionary, + parameter : String, + context : String = "") -> Dictionary: + var object = {} + var conf_parameter = configuration.get(parameter) + + if typeof(conf_parameter) == TYPE_DICTIONARY: + object = conf_parameter + else: + _incorrect_type(parameter, "Object", context) + + return object + +func _check_obligatory_string(configuration : Dictionary, + parameter : String, + max_length : int = -1, + context : String = "") -> String: + var string = "" + + if configuration.has(parameter): + string = _check_string(configuration, parameter, max_length, context) + else: + _missing(parameter, "String", context) + + return string + +func _check_string(configuration : Dictionary, + parameter : String, + max_length : int = -1, + context : String = "") -> String: + var string = "" + var conf_parameter = configuration.get(parameter) + + if typeof(conf_parameter) == TYPE_STRING: + if conf_parameter.length() > max_length and max_length != -1: + _longer_string(parameter, max_length, context) + else: + if conf_parameter == "": + _empty_string(parameter, context) + else: + string = conf_parameter + else: + _incorrect_type(parameter, "String", context) + + return string + +func _check_obligatory_int(configuration : Dictionary, + parameter : String, + max_value : int = -1, + context : String = "") -> int: + var integer = 1 + + if configuration.has(parameter): + integer = _check_int(configuration, parameter, max_value, context) + else: + _missing(parameter, "Integer", context) + + return integer + +func _check_int(configuration : Dictionary, + parameter : String, + max_value : int = -1, + context : String = "") -> int: + var integer = 1 + var conf_parameter = configuration.get(parameter) + + if typeof(conf_parameter) == TYPE_REAL: + if _is_an_integer(conf_parameter): + conf_parameter = int(conf_parameter) + + if conf_parameter < 1: + _smaller_int(parameter, context) + elif conf_parameter > max_value and max_value != -1: + _bigger_int(parameter, max_value, context) + else: + integer = conf_parameter + else: + _incorrect_type(parameter, "Integer", context) + else: + _incorrect_type(parameter, "Integer", context) + + return integer + +func _check_obligatory_color(configuration : Dictionary, + parameter : String, + context : String = "") -> Color: + var color = Color(0, 0, 0, 1) + + if configuration.has(parameter): + color = _check_color(configuration, parameter, context) + else: + _missing(parameter, "Color", context) + + return color + +func _check_color(configuration : Dictionary, + parameter : String, + context : String = "") -> Color: + var color = Color(0, 0, 0, 1) + var conf_parameter = configuration.get(parameter) + + if typeof(conf_parameter) == TYPE_ARRAY: + if conf_parameter.size() == 3 or conf_parameter.size() == 4: + var success = true + + for element in conf_parameter: + if typeof(element) == TYPE_REAL and _is_an_integer(element): + if element < 0 or element >= 256: + _incorrect_color_element(parameter, context) + success = false + break + else: + _incorrect_color_element(parameter, context) + success = false + break + + if success: + for i in range(conf_parameter.size()): + color[i] = conf_parameter[i] / 255.0 + else: + _incorrect_type(parameter, "Color", context) + else: + _incorrect_type(parameter, "Color", context) + + return color + +func _check_obligatory_image(configuration : Dictionary, + parameter : String, + recomended_size : Vector2 = Vector2.ZERO, + context : String = "") -> Image: + var image = Image.new() + if recomended_size != Vector2.ZERO: + image.create(recomended_size.x, recomended_size.y, false, Image.FORMAT_RGBA8) + else: + image.create(16, 16, false, Image.FORMAT_RGBA8) + + if configuration.has(parameter): + image = _check_image(configuration, parameter, recomended_size, context) + else: + _missing(parameter, "Image", context) + + return image + +func _check_image(configuration : Dictionary, + parameter : String, + recomended_size : Vector2 = Vector2.ZERO, + context : String = "") -> Image: + var image = Image.new() + if recomended_size != Vector2.ZERO: + image.create(recomended_size.x, recomended_size.y, false, Image.FORMAT_RGBA8) + else: + image.create(16, 16, false, Image.FORMAT_RGBA8) + + var conf_parameter = configuration.get(parameter) + + if typeof(conf_parameter) == TYPE_STRING: + if _directory.file_exists(conf_parameter): + var image_path = _directory.get_current_dir().plus_file(conf_parameter) + + if image.load(image_path) == OK: + image.convert(Image.FORMAT_RGBA8) + + if image.get_size() != recomended_size and recomended_size != Vector2.ZERO: + image.resize(recomended_size.x, recomended_size.y, Image.INTERPOLATE_NEAREST) + _image_is_not_the_recommended_size(parameter, recomended_size, context) + else: + _error_opening_image(parameter, context) + else: + _file_not_found(parameter, context) + else: + _incorrect_type(parameter, "Image", context) + + return image + +func _check_obligatory_array(configuration : Dictionary, + singular_parameter : String, + plural_parameter : String, + max_size : int = -1, + context : String = "") -> Array: + var array = [] + + if not (configuration.has(singular_parameter) or configuration.has(plural_parameter)): + _missing(plural_parameter, "Array", context) + else: + array = _check_array(configuration, singular_parameter, plural_parameter, max_size, context) + + return array + +func _check_array(configuration : Dictionary, + singular_parameter : String, + plural_parameter : String, + max_size : int = -1, + context : String = "") -> Array: + var array = [] + + if _has_only_one_parameter(configuration, singular_parameter, plural_parameter): + if configuration.has(singular_parameter): + var conf_parameter = configuration.get(singular_parameter) + + array.append(conf_parameter) + else: + var conf_parameter = configuration.get(plural_parameter) + + if typeof(conf_parameter) == TYPE_ARRAY: + if conf_parameter.size() == 0: + _no_empty_array(plural_parameter, context) + elif conf_parameter.size() == 1: + _no_single_element_array(singular_parameter, plural_parameter, context) + elif conf_parameter.size() > max_size and max_size != -1: + _bigger_array(plural_parameter, max_size, context) + else: + array = conf_parameter + else: + _incorrect_type(plural_parameter, "Array", context) + elif _have_both_parameters(configuration, singular_parameter, plural_parameter): + _cant_have_both(singular_parameter, plural_parameter, context) + + return array + +# Error messages + +func _empty_file() -> void: + _add_error("Empty file") + +func _json_parse_error(error : String, line : int) -> void: + _add_error("Error parsing JSON at line " + String(line) + ": " + error) + +func _expected_an_object() -> void: + _add_error("Expected the JSON file to contain an Object") + +func _missing(parameter : String, type : String, context : String = "") -> void: + var error = "Expected '" + parameter + "' " + type + + _add_error(_with_context(error, context)) + +func _incorrect_type(parameter : String, correct_type : String, context : String = "") -> void: + var to_be_a = "' to be an " if _is_a_vowel(correct_type[0]) else "' to be a " + + var error = "Expected '" + parameter + to_be_a + correct_type + + _add_error(_with_context(error, context)) + +func _longer_string(parameter : String, max_length : int, context : String = "") -> void: + var error = "'" + parameter + "' String is longer than " + String(max_length) + " characters" + + _add_error(_with_context(error, context)) + +func _smaller_int(parameter : String, context : String = "") -> void: + var error = "'" + parameter + "' Number is smaller than 1" + + _add_error(_with_context(error, context)) + +func _bigger_int(parameter : String, max_value : int, context : String = "") -> void: + var error = "'" + parameter + "' Number is bigger than " + String(max_value) + + _add_error(_with_context(error, context)) + +func _bigger_array(parameter : String, max_size : int, context : String = "") -> void: + var error = "'" + parameter + "' Array is bigger than " + String(max_size) + + _add_error(_with_context(error, context)) + +func _incorrect_color_element(parameter : String, context : String = "") -> void: + var error = "Expected '" + parameter + "' Color Elements to be Integers in the range [0, 255]" + + _add_error(_with_context(error, context)) + +func _file_not_found(parameter : String, context : String = "") -> void: + var error = "'" + parameter + "' contain a path to a file that doesn't exist" + + _add_error(_with_context(error, context)) + +func _error_opening_image(parameter : String, context : String = "") -> void: + var error = "An error ocurred opening '" + parameter + "' Image" + + _add_error(_with_context(error, context)) + +func _cant_have_both(p1 : String, p2 : String, context : String = "") -> void: + var error = "'" + p1 + "' and '" + p2 + "' can't be declared simultaneously" + + _add_error(_with_context(error, context)) + +func _no_empty_array(parameter : String, context : String = "") -> void: + var error = "'" + parameter + "' Array can't be empty" + + _add_error(_with_context(error, context)) + +func _no_single_element_array(p1 : String, p2 : String, context : String = "") -> void: + var error = "'" + p2 + "' Array can't have just one element" + error = error + ", replace the keyword with its singular form '" + p1 + "'" + + _add_error(_with_context(error, context)) + +func _no_registered_extra_tool(context : String = "") -> void: + var error = "Incorrect value for an 'ExtraTool'" + + _add_error(_with_context(error, context)) + +func _two_elements_are_equal(parameter : String, context : String = "") -> void: + var error = "There are two '" + parameter + "'" + + _add_error(_with_context(error, context)) + +func _no_registered_connection(context : String = "") -> void: + var error = "Incorrect value for an 'Connection'" + + _add_error(_with_context(error, context)) + +func _empty_string(parameter : String, context : String = "") -> void: + var warning = "'" + parameter + "' is an empty String" + + _add_warning(_with_context(warning, context)) + +func _image_is_not_the_recommended_size(parameter : String, recomended_size : Vector2, context : String = "") -> void: + var warning = "'" + parameter + "' Image is not the recomended size (" + warning = warning + String(recomended_size.x) + "x" + String(recomended_size.y) + ")" + + _add_warning(_with_context(warning, context)) + +func _no_tiles_detected(context : String = "") -> void: + var warning = "No tile has been declared" + + _add_warning(_with_context(warning, context)) + +static func _with_context(text : String, context : String = "") -> String: + if context == "": + return text + else: + return text + " in '" + context + "'" + +# Auxiliary functions + +static func _has_only_one_parameter(conf : Dictionary, p1 : String, p2 : String) -> bool: + return (conf.has(p1) or conf.has(p2)) and not _have_both_parameters(conf, p1, p2) + +static func _have_both_parameters(conf : Dictionary, p1 : String, p2 : String) -> bool: + return conf.has(p1) and conf.has(p2) + +static func _is_an_integer(i : float) -> bool: + return abs(int(i) - i) < _error_diff + +static func _is_a_vowel(c : String) -> bool: + c = c.to_upper() + + return c == "A" or c == "E" or c == "I" or c == "O" or c == "U" diff --git a/classes/parser/MainParser.gd b/classes/parser/MainParser.gd new file mode 100644 index 0000000..ec4e85d --- /dev/null +++ b/classes/parser/MainParser.gd @@ -0,0 +1,62 @@ +class_name MainParser + +var _base_parser : BaseParser = BaseParser.new() + +# Public + +func parse(path : String) -> void: + _base_parser.open_dir_from_file_path(path) + + var file = File.new() + file.open(path, File.READ) + + var json_parsed_configuration = _parse_json(file.get_as_text()) + + if not has_errors(): + _parse_style(json_parsed_configuration) + +func get_configuration(): + return _base_parser._configuration + +func has_errors() -> bool: + return _base_parser._errors.size() != 0 + +func get_errors() -> Array: + return _base_parser._errors + +func has_warnings() -> bool: + return _base_parser._warnings.size() != 0 + +func get_warnings() -> Array: + return _base_parser._warnings + +# Private + +func _parse_json(configuration : String) -> Dictionary: + var parsed_configuration = {} + + var result = JSON.parse(configuration) + + if result.error != OK: + if configuration == "": + _base_parser._empty_file() + else: + _base_parser._json_parse_error(result.error_string, result.error_line) + elif typeof(result.result) != TYPE_DICTIONARY: + _base_parser._expected_an_object() + else: + parsed_configuration = result.result + + return parsed_configuration + +func _parse_style(configuration : Dictionary) -> void: + var style_data_parser = StyleDataParser.new() + _base_parser._configuration.StyleData = style_data_parser.parse(_base_parser, configuration) + + var layer = {} + layer.Type = "TileMap" + var tyle_map_parser = TilemapParser.new() + layer.Configuration = tyle_map_parser.parse(_base_parser, configuration) + + _base_parser._configuration.Layers = [] + _base_parser._configuration.Layers.append(layer) diff --git a/classes/parser/StyleDataParser.gd b/classes/parser/StyleDataParser.gd new file mode 100644 index 0000000..040a1d1 --- /dev/null +++ b/classes/parser/StyleDataParser.gd @@ -0,0 +1,15 @@ +class_name StyleDataParser + +var _base_parser : BaseParser +const _max_StyleData_Author_length : int = 20 +const _max_StyleData_Name_length : int = 20 + +func parse(base_parser : BaseParser, configuration : Dictionary) -> Dictionary: + _base_parser = base_parser + var style_data = _base_parser._check_obligatory_object(configuration, "StyleData") + + var parsed_conf = {} + parsed_conf.Author = _base_parser._check_obligatory_string(style_data, "Author", _max_StyleData_Author_length, "StyleData") + parsed_conf.Name = _base_parser._check_obligatory_string(style_data, "Name", _max_StyleData_Name_length, "StyleData") + + return parsed_conf diff --git a/classes/parser/TilemapParser.gd b/classes/parser/TilemapParser.gd new file mode 100644 index 0000000..fdf07fa --- /dev/null +++ b/classes/parser/TilemapParser.gd @@ -0,0 +1,324 @@ +class_name TilemapParser + +var _base_parser : BaseParser +var _tile_size : int = 0 +var _n_tiles : int = 0 +var _layers : Dictionary = {} +var _connected_groups : Dictionary = {"": 0} +var _correct_variations : bool = true +var _connection_type : int = Tile.Connection_type.ISOLATED +const _max_TileSize : int = 64 +const _max_TileSetSize : int = 100 +const _max_Tile_Name_length : int = 100 +const _max_Tile_Layer_length : int = 100 +const _max_Tile_ConnectedGroup_length : int = 100 +const _max_Tile_ExtraToolsSize : int = 2 +const _max_Tile_VariationsSize : int = 256 +const _max_Tile_VariationsConditionsSize : int = 8 + +func parse(base_parser : BaseParser, configuration : Dictionary) -> Dictionary: + _base_parser = base_parser + var tilemap_conf = _base_parser._check_obligatory_object(configuration, "Configuration") + + var parsed_conf = {} + parsed_conf.TileSize = _base_parser._check_obligatory_int(tilemap_conf, "TileSize", _max_TileSize, "Configuration") + _tile_size = parsed_conf.TileSize + parsed_conf.Background = _check_background(tilemap_conf) + parsed_conf.TileSet = _check_tileset(tilemap_conf) + + return parsed_conf + +func _check_background(tilemap_conf : Dictionary) -> Image: + var background = Image.new() + background.create(_tile_size, _tile_size, false, Image.FORMAT_RGBA8) + + if tilemap_conf.has("Background"): + if typeof(tilemap_conf.Background) == TYPE_ARRAY: + background.fill(_base_parser._check_color(tilemap_conf, "Background", "Configuration")) + elif typeof(tilemap_conf.Background) == TYPE_STRING: + var recomended_size = Vector2(_tile_size, _tile_size) + var image = _base_parser._check_image(tilemap_conf, "Background", recomended_size, "Configuration") + + background.copy_from(image) + else: + _base_parser._incorrect_type("Background", "Color or an Image", "Configuration") + else: + background.fill(Color.transparent) + + return background + +func _check_tileset(tilemap_conf : Dictionary) -> Array: + var tileset = [] + + tileset = _base_parser._check_array(tilemap_conf, "Tile", "TileSet", _max_TileSetSize, "Configuration") + + if tileset.size() != 0: + for i in range(tileset.size()): + var context + if tileset.size() == 1: + context = "Configuration/Tile" + else: + context = "Configuration/TileSet[" + String(i) + "]" + + if typeof(tileset[i]) == TYPE_DICTIONARY: + tileset[i] = _check_tile(tileset[i], context) + else: + tileset[i] = {} + + if tileset.size() == 1: + _base_parser._incorrect_type("Tile", "Dictionary", "Configuration") + else: + _base_parser._incorrect_type("Tile", "Dictionary", context) + + return tileset + +func _check_tile(tile_conf : Dictionary, context : String) -> Dictionary: + var tile = {} + + tile.ID = _n_tiles + _n_tiles = _n_tiles + 1 + + if tile_conf.has("Name"): + tile.Name = _base_parser._check_string(tile_conf, "Name", _max_Tile_Name_length, context) + else: + tile.Name = "" + + var recomended_size = Vector2(_tile_size, _tile_size) + tile.Image = _base_parser._check_obligatory_image(tile_conf, "Image", recomended_size, context) + + var layer + if tile_conf.has("Layer"): + layer = _base_parser._check_string(tile_conf, "Layer", _max_Tile_Layer_length, context) + else: + layer = "" + + if _layers.has(layer): + tile.Layer = _layers.get(layer) + else: + var layer_id = _layers.size() + tile.Layer = layer_id + _layers[layer] = layer_id + + var connected_group + if tile_conf.has("ConnectedGroup"): + connected_group = _base_parser._check_string(tile_conf, "ConnectedGroup", _max_Tile_ConnectedGroup_length, context) + else: + connected_group = "" + + if connected_group == "": + tile.ConnectedGroup = 0 + elif _connected_groups.has(layer): + tile.ConnectedGroup = _connected_groups.get(layer) + else: + var connected_group_id = _connected_groups.size() + tile.ConnectedGroup = connected_group_id + _connected_groups[connected_group] = connected_group_id + + var extra_tools = [] + + extra_tools = _base_parser._check_array(tile_conf, "ExtraTool", "ExtraTools", _max_Tile_ExtraToolsSize, context) + + if extra_tools.size() != 0: + var extra_tools_flags = [false, false] + + for i in range(extra_tools.size()): + var extra_tools_context + if extra_tools.size() == 1: + extra_tools_context = context + "/ExtraTool" + else: + extra_tools_context = context + "/ExtraTools[" + String(i) + "]" + + if typeof(extra_tools[i]) == TYPE_STRING: + match extra_tools[i]: + "Wrench": + if extra_tools_flags[0] == false: + extra_tools_flags[0] = true + else: + _base_parser._two_elements_are_equal("Wrench", context) + + extra_tools[i] = Tilemap.Tool.WRENCH + "BukectFill": + if extra_tools_flags[1] == false: + extra_tools_flags[1] = true + else: + _base_parser._two_elements_are_equal("BukectFill", context) + + extra_tools[i] = Tilemap.Tool.BUCKET_FILL + _: + extra_tools[i] = Tilemap.Tool.PENCIL + + _base_parser._no_registered_extra_tool(extra_tools_context) + else: + extra_tools[i] = Tilemap.Tool.PENCIL + + if extra_tools.size() == 1: + _base_parser._incorrect_type("ExtraTool", "String", context) + else: + _base_parser._incorrect_type("ExtraTool", "String", extra_tools_context) + + tile.ExtraTools = extra_tools + + var variations = [] + + variations = _base_parser._check_array(tile_conf, "Variation", "Variations", _max_Tile_VariationsSize, context) + + if variations.size() != 0: + _connection_type = Tile.Connection_type.CROSS + _correct_variations = true + + for i in range(variations.size()): + var variation_context + if variations.size() == 1: + variation_context = context + "/Variation" + else: + variation_context = context + "/Variations[" + String(i) + "]" + + if typeof(variations[i]) == TYPE_DICTIONARY: + variations[i] = _check_variation(variations[i], variation_context) + else: + variations[i] = {} + + if variations.size() == 1: + _base_parser._incorrect_type("Variation", "Dictionary", context) + else: + _base_parser._incorrect_type("Variation", "Dictionary", variation_context) + else: + _connection_type = Tile.Connection_type.ISOLATED + _correct_variations = false + + if _connection_type != Tile.Connection_type.ISOLATED: + _transform_variations(variations) + + tile.ConnectionType = _connection_type + tile.Variations = variations + + return tile + +func _check_variation(variation_conf : Dictionary, context : String) -> Dictionary: + var variation = {} + + var recomended_size = Vector2(_tile_size, _tile_size) + variation.Image = _base_parser._check_obligatory_image(variation_conf, "Image", recomended_size, context) + + var connections = _base_parser._check_obligatory_array(variation_conf, "Connection", "Connections", _max_Tile_VariationsConditionsSize, context) + if connections.size() != 0: + for i in range(connections.size()): + var connection_context + if connections.size() == 1: + connection_context = context + "/Connection" + else: + connection_context = context + "/Connections[" + String(i) + "]" + + if typeof(connections[i]) == TYPE_ARRAY: + connections[i] = _check_connection(connections[i], connection_context) + else: + _correct_variations = false + connections[i] = [] + + if connections.size() == 1: + _base_parser._incorrect_type("Connection", "Array", context) + else: + _base_parser._incorrect_type("Connection", "Array", connection_context) + else: + _correct_variations = false + + variation.Connections = connections + + return variation + +func _check_connection(connection_array : Array, context : String) -> Array: + var bitmask = [false, false, false, false, false, false, false, false] + + for element in connection_array: + if typeof(element) == TYPE_STRING: + match element: + "North": + if bitmask[0] == false: + bitmask[0] = true + else: + _correct_variations = false + _base_parser._two_elements_are_equal("North", context) + "NorthEast": + if bitmask[1] == false: + bitmask[1] = true + _connection_type = Tile.Connection_type.CIRCLE + else: + _correct_variations = false + _base_parser._two_elements_are_equal("NorthEast", context) + "East": + if bitmask[2] == false: + bitmask[2] = true + else: + _correct_variations = false + _base_parser._two_elements_are_equal("East", context) + "SouthEast": + if bitmask[3] == false: + bitmask[3] = true + _connection_type = Tile.Connection_type.CIRCLE + else: + _correct_variations = false + _base_parser._two_elements_are_equal("SouthEast", context) + "South": + if bitmask[4] == false: + bitmask[4] = true + else: + _correct_variations = false + _base_parser._two_elements_are_equal("South", context) + "SouthWest": + if bitmask[5] == false: + bitmask[5] = true + _connection_type = Tile.Connection_type.CIRCLE + else: + _correct_variations = false + _base_parser._two_elements_are_equal("SouthWest", context) + "West": + if bitmask[6] == false: + bitmask[6] = true + else: + _correct_variations = false + _base_parser._two_elements_are_equal("West", context) + "NorthWest": + if bitmask[7] == false: + bitmask[7] = true + _connection_type = Tile.Connection_type.CIRCLE + else: + _correct_variations = false + _base_parser._two_elements_are_equal("NorthWest", context) + _: + _correct_variations = false + _base_parser._no_registered_connection(context) + else: + _correct_variations = false + _base_parser._incorrect_type("Element", "String", context) + + return bitmask + +func _transform_variations(variations : Array) -> void: + for variation in variations: + var connections = [] + + for connection in variation.Connections: + if _correct_variations: + var acc = 0 + + if _connection_type == Tile.Connection_type.CROSS: + if connection[0]: + acc += 1 + if connection[2]: + acc += 2 + if connection[4]: + acc += 4 + if connection[6]: + acc += 8 + else: + for i in range(connection.size()): + if connection[i]: + acc += pow(2, i) + + acc = int(acc) + + connections.append(acc) + else: + connections.append(0) + + variation.Connections = connections diff --git a/classes/tilemap/Tile.gd b/classes/tilemap/Tile.gd new file mode 100644 index 0000000..4cf21de --- /dev/null +++ b/classes/tilemap/Tile.gd @@ -0,0 +1,84 @@ +class_name Tile + +# Custom enums + +# Special kinds of tiles +enum Special_tile { + AIR = -1, + OUT_OF_BOUNDS = -2, + UNSELECTED = -3 +} + +# Connection types +enum Connection_type { + ISOLATED, + CROSS, + CIRCLE +} + +# Private variables + +var _id : int = 0 +var _layer : int = 0 +var _images : Array = [] +var _connections_for_each_state : Dictionary = {} +var _connection_type : int +var _connected_group : int = 0 +var _can_connect_to_borders : bool = true + +# Class public functions + +func init(tile_conf : Dictionary): + _id = tile_conf.ID + _layer = tile_conf.Layer + + _add_state(tile_conf.Image) + + _connection_type = tile_conf.ConnectionType + + for variation in tile_conf.Variations: + _add_state(variation.Image, variation.Connections) + + _connected_group = tile_conf.ConnectedGroup + +func get_id() -> int: + return _id + +func get_layer() -> int: + return _layer + +func get_state(connection : int) -> int: + if _connections_for_each_state.has(connection): + return _connections_for_each_state[connection] + else: + return 0 + +func get_n_states() -> int: + return _images.size() + +func get_image(state : int = 0) -> Image: + return _images[state] + +func get_connection_type() -> int: + return _connection_type + +func can_connect_to(another_tile : Tile) -> bool: + if another_tile._id == Special_tile.AIR: + return false + elif another_tile._id == Special_tile.OUT_OF_BOUNDS: + return _can_connect_to_borders + else: + if _id == another_tile._id: + return true + else: + var same_group = _connected_group == another_tile._connected_group + return same_group and _connected_group != 0 + +# Class private functions + +func _add_state(image : Image, connections : Array = []): + var state = _images.size() + _images.append(image) + + for connection in connections: + _connections_for_each_state[connection] = state diff --git a/classes/tilemap/Tilemap.gd b/classes/tilemap/Tilemap.gd new file mode 100644 index 0000000..eccb16a --- /dev/null +++ b/classes/tilemap/Tilemap.gd @@ -0,0 +1,121 @@ +class_name Tilemap + +enum Tool{ + PENCIL, + WRENCH, + ERASER, + BUCKET_FILL +} + +# Private variables + +var _width : int = 0 +var _height : int = 0 +var _tile_size : int = 0 +var _background : Image = Image.new() +var _tilemaplayers : Array = [] +var _tileset : Array = [] +var _special_tileset : Dictionary = {} +var _selected_tile : Tile = Tile.new() + +# Class public functions + +func init(canvas_conf : Dictionary, layer_conf : Dictionary): + _width = canvas_conf.Width + _height = canvas_conf.Height + + _tile_size = layer_conf.TileSize + + _create_background(layer_conf.Background) + + _create_special_tileset() + for tile_conf in layer_conf.TileSet: + _add_tile(tile_conf) + +func get_image() -> Image: + var image = Image.new() + var rect = Rect2(Vector2.ZERO, Vector2(_tile_size * _width, _tile_size * _height)) + var pos = Vector2.ZERO + + image.copy_from(_background) + for tilemaplayer in _tilemaplayers: + image.blend_rect(tilemaplayer.get_image(), rect, pos) + + return image + +func select_tile(tile_id : int): + _selected_tile = _tileset[tile_id] + +func place_tile(i : int, j : int): + var selected_layer = _selected_tile.get_layer() + _tilemaplayers[selected_layer].set_tile(i, j, _selected_tile) + +func erase_tile(i : int, j : int): + var selected_layer = _selected_tile.get_layer() + _tilemaplayers[selected_layer].set_tile(i, j, _special_tileset[Tile.Special_tile.AIR]) + +func change_tile_state(i : int, j : int): + var selected_layer = _selected_tile.get_layer() + _tilemaplayers[selected_layer].change_tile_state(i, j) + +func fill(i : int, j : int): + var selected_layer = _selected_tile.get_layer() + _tilemaplayers[selected_layer].fill(i, j, _selected_tile) + +func erase_tile_in_every_layer(i : int, j : int): + for tilemaplayer in _tilemaplayers: + tilemaplayer.set_tile(i, j, _special_tileset[Tile.Special_tile.AIR]) + +func retrieve_previous_tilemap(): + var tilemaplayers = [] + for i in range(_tilemaplayers.size()): + if _tilemaplayers[i].has_been_modified(): + tilemaplayers.append({ + "ID": i, + "TileMap": _tilemaplayers[i].retrieve_previous_tilemaplayer() + }) + + return tilemaplayers + +func load_tilemap(tilemaplayers : Array): + for tilemaplayer in tilemaplayers: + _tilemaplayers[tilemaplayer.ID].load_tilemaplayer(tilemaplayer.TileMap) + +# Class private functions + +func _create_background(background_tile : Image): + var background_size = Vector2(_tile_size * _width, _tile_size * _height) + _background = GoostImage.tile(background_tile, background_size) + +func _create_special_tileset(): + var empty_tile_image = Image.new() + empty_tile_image.create(_tile_size, _tile_size, false, Image.FORMAT_RGBA8) + empty_tile_image.fill(Color.transparent) + + var special_tile_conf = { + "Layer": 0, + "ConnectionType": Tile.Connection_type.ISOLATED, + "Image": empty_tile_image, + "Variations": [], + "ConnectedGroup": 0 + } + for special_tile_id in Tile.Special_tile.values(): + special_tile_conf.ID = special_tile_id + + var special_tile = Tile.new() + special_tile.init(special_tile_conf) + _special_tileset[special_tile_id] = special_tile + +func _add_tile(tile_conf : Dictionary): + if tile_conf.Layer == _tilemaplayers.size(): + _add_layer() + + var tile = Tile.new() + tile.init(tile_conf) + _tileset.append(tile) + +func _add_layer(): + var tilemaplayer = TilemapLayer.new() + tilemaplayer.init(_width, _height, _tile_size, _tileset, _special_tileset) + + _tilemaplayers.append(tilemaplayer) diff --git a/classes/tilemap/TilemapLayer.gd b/classes/tilemap/TilemapLayer.gd new file mode 100644 index 0000000..88cc45c --- /dev/null +++ b/classes/tilemap/TilemapLayer.gd @@ -0,0 +1,217 @@ +class_name TilemapLayer + +# Private variables + +var _width : int = 0 +var _height : int = 0 +var _tile_size : int = 0 +var _map : Array = [] +var _image : Image = Image.new() +var _tileset : Array = [] +var _special_tileset : Dictionary = {} +var _previous_tilemaplayer : Array = [] +var _has_been_modified : bool = false +var _count = 0 + +# Class public functions + +func init(width : int, height : int, tile_size : int, tileset : Array, special_tileset : Dictionary): + _width = width + _height = height + + _tile_size = tile_size + + _create_map() + _create_image() + + _tileset = tileset + _special_tileset = special_tileset + +func get_image() -> Image: + return _image + +func set_tile(i : int, j : int, tile : Tile): + var id = tile.get_id() + if(i >= 0 and i < _height and j >= 0 and j < _width): + if _get_tile_id(i, j) != id: + _map[i][j] = {"ID": id, "State": 0} + + _update_tile(i, j) + _update_tiles_around(i, j) + + _has_been_modified = true + +func fill(i : int, j : int, tile : Tile): + if(i >= 0 and i < _height and j >= 0 and j < _width): + var tile_to_replace_id = _get_tile_id(i, j) + + if tile_to_replace_id == tile.get_id(): + return + + var process_now = [] + process_now.append(Vector2(i, j)) + + var process_next = [] + + var marked = [] + for i in range(_height): + marked.append([]) + for j in range(_width): + marked[i].append([]) + marked[i][j] = false + + while process_now.size() != 0: + process_next = [] + + for pos in process_now: + set_tile(pos.x, pos.y, tile) + + if _get_tile_id(pos.x + 1, pos.y) == tile_to_replace_id: + if marked[pos.x + 1][pos.y] == false: + process_next.append(Vector2(pos.x + 1, pos.y)) + marked[pos.x + 1][pos.y] = true + + if _get_tile_id(pos.x, pos.y + 1) == tile_to_replace_id: + if marked[pos.x][pos.y + 1] == false: + process_next.append(Vector2(pos.x, pos.y + 1)) + marked[pos.x][pos.y + 1] = true + + if _get_tile_id(pos.x - 1, pos.y) == tile_to_replace_id: + if marked[pos.x - 1][pos.y] == false: + process_next.append(Vector2(pos.x - 1, pos.y)) + marked[pos.x - 1][pos.y] = true + + if _get_tile_id(pos.x, pos.y - 1) == tile_to_replace_id: + if marked[pos.x][pos.y - 1] == false: + process_next.append(Vector2(pos.x, pos.y - 1)) + marked[pos.x][pos.y - 1] = true + + process_now = process_next + +func change_tile_state(i : int, j : int): + if(i >= 0 and i < _height and j >= 0 and j < _width): + if _get_tile(i, j).get_n_states() > 1: + var state = (_get_tile_state(i, j) + 1) % _get_tile(i, j).get_n_states() + _map[i][j].State = state + _place_tile_image(i, j, _get_tile(i, j).get_image(state)) + + _has_been_modified = true + +func has_been_modified(): + return _has_been_modified + +func retrieve_previous_tilemaplayer(): + var previous_tilemaplayer = _previous_tilemaplayer + _previous_tilemaplayer = _map.duplicate(true) + + _has_been_modified = false + + return previous_tilemaplayer + +func load_tilemaplayer(map : Array): + _map = map + _has_been_modified = true + + for i in range(_height): + for j in range(_width): + _place_tile_image(i, j, _get_tile(i, j).get_image(_get_tile_state(i, j))) + +# Class private functions + +func _create_map(): + _map = [] + for i in range(_height): + _map.append([]) + for j in range(_width): + _map[i].append([]) + _map[i][j] = {"ID": Tile.Special_tile.AIR, "State": 0} + + _previous_tilemaplayer = _map.duplicate(true) + +func _create_image(): + _image = Image.new() + + var w = _tile_size * _width + var h = _tile_size * _height + + _image.create(w, h, false, Image.FORMAT_RGBA8) + +func _update_tiles_around(i : int, j : int): + _update_tile(i - 1, j ) + _update_tile(i - 1, j + 1) + _update_tile(i , j + 1) + _update_tile(i + 1, j + 1) + _update_tile(i + 1, j ) + _update_tile(i + 1, j - 1) + _update_tile(i , j - 1) + _update_tile(i - 1, j - 1) + +func _update_tile(i : int, j : int): + if _get_tile_id(i, j) == Tile.Special_tile.OUT_OF_BOUNDS: + pass + elif _get_tile(i, j).get_connection_type() == Tile.Connection_type.ISOLATED: + _place_tile_image(i, j, _get_tile(i, j).get_image()) + else: + var condition = 0 + var tile = _get_tile(i, j) + + if tile.get_connection_type() == Tile.Connection_type.CROSS: + condition = _get_cross_condition_id_of_tile(i, j) + else: + condition = _get_circle_condition_id_of_tile(i, j) + + var state = tile.get_state(condition) + _map[i][j].State = state + _place_tile_image(i, j, tile.get_image(state)) + +func _get_cross_condition_id_of_tile(i : int, j : int) -> int: + var condition = 0 + var tile = _get_tile(i, j) + + condition += 1 if tile.can_connect_to(_get_tile(i - 1, j)) else 0 + condition += 2 if tile.can_connect_to(_get_tile(i, j + 1)) else 0 + condition += 4 if tile.can_connect_to(_get_tile(i + 1, j)) else 0 + condition += 8 if tile.can_connect_to(_get_tile(i, j - 1)) else 0 + + return condition + +func _get_circle_condition_id_of_tile(i : int, j : int) -> int: + var condition = 0 + var tile = _get_tile(i, j) + + condition += 1 if tile.can_connect_to(_get_tile(i - 1, j )) else 0 + condition += 2 if tile.can_connect_to(_get_tile(i - 1, j + 1)) else 0 + condition += 4 if tile.can_connect_to(_get_tile(i , j + 1)) else 0 + condition += 8 if tile.can_connect_to(_get_tile(i + 1, j + 1)) else 0 + condition += 16 if tile.can_connect_to(_get_tile(i + 1, j )) else 0 + condition += 32 if tile.can_connect_to(_get_tile(i + 1, j - 1)) else 0 + condition += 64 if tile.can_connect_to(_get_tile(i , j - 1)) else 0 + condition += 128 if tile.can_connect_to(_get_tile(i - 1, j - 1)) else 0 + + return condition + +func _place_tile_image(i : int, j : int, tile_image : Image): + var rect = Rect2(Vector2.ZERO, Vector2(_tile_size, _tile_size)) + var pos = Vector2(j * _tile_size, i * _tile_size) + + _image.blit_rect(tile_image, rect, pos) + +func _get_tile_id(i : int, j : int) -> int: + if(i >= 0 and i < _height and j >= 0 and j < _width): + return _map[i][j].ID + + return Tile.Special_tile.OUT_OF_BOUNDS + +func _get_tile_state(i : int, j : int) -> int: + if(i >= 0 and i < _height and j >= 0 and j < _width): + return _map[i][j].State + + return 0 + +func _get_tile(i : int, j : int) -> Tile: + var tile_id = _get_tile_id(i, j) + + if tile_id >= 0: + return _tileset[tile_id] + else: + return _special_tileset[tile_id] diff --git a/doc/images/screenshot.png b/doc/images/screenshot.png new file mode 100644 index 0000000..2a43c30 Binary files /dev/null and b/doc/images/screenshot.png differ diff --git a/panels/Canvas.gd b/panels/Canvas.gd new file mode 100644 index 0000000..dd626a9 --- /dev/null +++ b/panels/Canvas.gd @@ -0,0 +1,149 @@ +extends ScrollContainer + +# Private variables + +var _has_initiate : bool = false +var _base_scale : Vector2 = Vector2.ONE +var _scale_factor : float = 1.0 +var _default_scrollbar : Vector2 = Vector2.ZERO +var _current_scrollbar : Vector2 = Vector2.ZERO +var _number_of_layers : int = 0 +var _selected_layer : int = 0 + +func _process(_delta): + if _has_initiate == false: + _update_rect() + +# Panel public functions +func init(canvas_conf : Dictionary, style_conf : Dictionary): + for layer_conf in style_conf.Layers: + _add_layer(canvas_conf, layer_conf) + + _set_overlay() + + get_h_scrollbar().connect("scrolling", self, "_h_scrollbar_scrolling") + get_v_scrollbar().connect("scrolling", self, "_v_scrollbar_scrolling") + + get_node("CanvasViewport").connect("gui_input", self, "_gui_input") + self.connect("resized", self, "_update_rect") + +func transform(offset : Vector2, scale : Vector2): + get_node("CanvasViewport").set_custom_minimum_size(scale * get_size() + (offset * 2)) + get_node("CanvasViewport/Layers").set_canvas_transform(Transform2D().scaled(scale).translated(offset / scale)) + get_node("CanvasViewport").get_child(1).set_transform(offset, scale) + +func get_size(): + return _get_layer(_selected_layer).get_image().get_size() + +func get_image(): + var image = Image.new() + image.copy_from(get_node("CanvasViewport/Layers").get_child(0).get_image()) + + for layer in get_node("CanvasViewport/Layers").get_children(): + image.blend_rect(layer.get_image(), Rect2(Vector2.ZERO, layer.get_image().get_size()), Vector2.ZERO) + + return image + +func get_current_tool_box(): + return _get_layer(_selected_layer).get_tool_box() + +func connect_with_undo_redo(undo_redo : Control): + _get_layer(0).connect("register_action", undo_redo, "_register_action", [0]) + + undo_redo.connect("apply_action", self, "_apply_action") + +# Panel private functions +func _gui_input(event): + emit_signal("gui_input", event) + _get_layer(_selected_layer)._gui_input(event) + +func _add_layer(canvas_conf : Dictionary, layer_conf : Dictionary): + var new_layer + match layer_conf.Type: + "TileMap": + new_layer = preload("res://panels/layers/TileMapCanvasLayer.tscn").instance() + + get_node("CanvasViewport/Layers").add_child(new_layer) + new_layer.init(canvas_conf, layer_conf.Configuration) + + _number_of_layers = _number_of_layers + 1 + +func _get_layer(layer_id : int): + return get_node("CanvasViewport/Layers").get_child(layer_id) + +func _set_overlay(): + get_node("CanvasViewport").add_child(_get_layer(_selected_layer).get_overlay()) + +func _apply_action(data, layer : int): + _get_layer(layer).apply_action(data) + +func _h_scrollbar_scrolling(): + _current_scrollbar.x = scroll_horizontal + +func _v_scrollbar_scrolling(): + _current_scrollbar.y = scroll_vertical + +func _get_size(): + return get_size() + +func _get_size_scaled(scale): + return _get_size() * scale + +func _update_rect(): + if _has_initiate == false: + _calculte_base_scale() + _update_canvas(_base_scale) + _has_initiate = true + else: + var scale = _base_scale * _scale_factor + _update_canvas(scale) + +func _calculte_base_scale(): + var scale = get_rect().size / _get_size() + + if scale.x < scale.y: + _base_scale = Vector2(scale.x, scale.x) + else: + _base_scale = Vector2(scale.y, scale.y) + +func _update_canvas(scale : Vector2): + var canvas_size = get_rect().size + var size_scaled = _get_size_scaled(scale) + + var pos = (canvas_size - size_scaled) / 2.0 + + var offset = Vector2(0,0) + offset.x = pos.x if pos.x > 0 else 0 + offset.y = pos.y if pos.y > 0 else 0 + + var scrollbar = Vector2(0,0) + scrollbar.x = -pos.x if pos.x < 0 else 0 + scrollbar.y = -pos.y if pos.y < 0 else 0 + + var scrolled = Vector2(0,0) + scrolled.x = _current_scrollbar.x / _default_scrollbar.x if _default_scrollbar.x > 0 else 1.0 + scrolled.y = _current_scrollbar.y / _default_scrollbar.y if _default_scrollbar.y > 0 else 1.0 + + _default_scrollbar = scrollbar + scrollbar = scrollbar * scrolled + _current_scrollbar = scrollbar + + transform(offset, scale) + + if scrollbar.x != 0: + yield(get_h_scrollbar(), "changed") + scroll_horizontal = scrollbar.x + + if scrollbar.y != 0: + yield(get_v_scrollbar(), "changed") + scroll_vertical = scrollbar.y + +func _update_scale_factor(percentage : float): + _scale_factor = 3.75 * percentage + 0.25 + _update_rect() + +func _on_CanvasViewport_mouse_entered(): + _get_layer(_selected_layer)._mouse_entered() + +func _on_CanvasViewport_mouse_exited(): + _get_layer(_selected_layer)._mouse_exited() diff --git a/panels/Canvas.tscn b/panels/Canvas.tscn new file mode 100644 index 0000000..3d7687b --- /dev/null +++ b/panels/Canvas.tscn @@ -0,0 +1,25 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://panels/Canvas.gd" type="Script" id=1] + +[node name="Canvas" type="ScrollContainer"] +mouse_filter = 2 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="CanvasViewport" type="ViewportContainer" parent="."] +margin_right = 12.0 +margin_bottom = 12.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +stretch = true + +[node name="Layers" type="Viewport" parent="CanvasViewport"] +size = Vector2( 12, 12 ) +handle_input_locally = false +render_target_update_mode = 3 +gui_disable_input = true +[connection signal="mouse_entered" from="CanvasViewport" to="." method="_on_CanvasViewport_mouse_entered"] +[connection signal="mouse_exited" from="CanvasViewport" to="." method="_on_CanvasViewport_mouse_exited"] diff --git a/panels/MagnifyingGlass.gd b/panels/MagnifyingGlass.gd new file mode 100644 index 0000000..2826446 --- /dev/null +++ b/panels/MagnifyingGlass.gd @@ -0,0 +1,41 @@ +extends Control + +# Custom signals + +signal magnifying_factor_updated(value) + +# Private variables + +var _magnifying_factor : int = 20 + +# Panel public functions + +func process_mouse_wheel(event): + if event is InputEventMouseButton: + if event.is_pressed(): + if event.button_index == BUTTON_WHEEL_UP: + _add_to_magnifying_factor(2) + elif event.button_index == BUTTON_WHEEL_DOWN: + _add_to_magnifying_factor(-2) + +# Panel private functions + +func _input(event): + if event.is_action_pressed("ui_zoom_plus"): + _add_to_magnifying_factor(10) + elif event.is_action_pressed("ui_zoom_minus"): + _add_to_magnifying_factor(-10) + +func _add_to_magnifying_factor(value : int): + var magnifying_factor = _magnifying_factor + value + + if magnifying_factor >= 0 and magnifying_factor <= 100: + get_node("Slider").set_value(magnifying_factor) + elif magnifying_factor > 100 and _magnifying_factor < 100: + get_node("Slider").set_value(100) + elif magnifying_factor < 0 and _magnifying_factor > 0: + get_node("Slider").set_value(0) + +func _set_magnifying_factor(value : int): + _magnifying_factor = value + emit_signal("magnifying_factor_updated", _magnifying_factor / 100.0) diff --git a/panels/MagnifyingGlass.tscn b/panels/MagnifyingGlass.tscn new file mode 100644 index 0000000..43fc6d0 --- /dev/null +++ b/panels/MagnifyingGlass.tscn @@ -0,0 +1,69 @@ +[gd_scene load_steps=6 format=2] + +[ext_resource path="res://resources/icons/zoom_minus.png" type="Texture" id=1] +[ext_resource path="res://resources/icons/zoom_plus.png" type="Texture" id=2] +[ext_resource path="res://panels/MagnifyingGlass.gd" type="Script" id=3] + +[sub_resource type="Shader" id=1] +code = "shader_type canvas_item; + +uniform vec4 color : hint_color; + +void fragment() { + if(texture(TEXTURE, UV) == vec4(1.0, 1.0, 1.0, 1.0)){ + COLOR = vec4(1.0, 1.0, 1.0, 0.0); + } else { + COLOR = vec4(color.rgb, texture(TEXTURE, UV).a); + } +}" +custom_defines = "" + +[sub_resource type="ShaderMaterial" id=2] +shader = SubResource( 1 ) +shader_param/color = Color( 1, 1, 1, 1 ) + +[node name="MagnifyingGlass" type="HBoxContainer"] +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource( 3 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="MinusContainer" type="CenterContainer" parent="."] +margin_right = 44.0 +margin_bottom = 600.0 + +[node name="Minus" type="ToolButton" parent="MinusContainer"] +material = SubResource( 2 ) +margin_top = 280.0 +margin_right = 44.0 +margin_bottom = 320.0 +hint_tooltip = "Zoom -" +size_flags_vertical = 0 +icon = ExtResource( 1 ) + +[node name="Slider" type="HSlider" parent="."] +margin_left = 48.0 +margin_right = 976.0 +margin_bottom = 600.0 +size_flags_horizontal = 3 +size_flags_vertical = 1 +value = 20.0 + +[node name="PlusContainer" type="CenterContainer" parent="."] +margin_left = 980.0 +margin_right = 1024.0 +margin_bottom = 600.0 + +[node name="Plus" type="ToolButton" parent="PlusContainer"] +material = SubResource( 2 ) +margin_top = 280.0 +margin_right = 44.0 +margin_bottom = 320.0 +hint_tooltip = "Zoom +" +size_flags_vertical = 0 +icon = ExtResource( 2 ) +[connection signal="pressed" from="MinusContainer/Minus" to="." method="_add_to_magnifying_factor" binds= [ -10 ]] +[connection signal="value_changed" from="Slider" to="." method="_set_magnifying_factor"] +[connection signal="pressed" from="PlusContainer/Plus" to="." method="_add_to_magnifying_factor" binds= [ 10 ]] diff --git a/panels/UndoRedo.gd b/panels/UndoRedo.gd new file mode 100644 index 0000000..cead4d4 --- /dev/null +++ b/panels/UndoRedo.gd @@ -0,0 +1,50 @@ +extends Control + +# Custom signals + +signal apply_action(data, layer) + +# Public variables + +export var number_of_actions : int = 20 + +# Private variables + +var _previous_actions : Array = [] +var _next_actions : Array = [] +var _undo_was_pressed : bool = false +var _redo_was_pressed : bool = false + +# Panel private functions + +func _input(event): + if event.is_action_pressed("ui_undo"): + _undo() + elif event.is_action_pressed("ui_redo"): + _redo() + +func _register_action(data, layer : int): + if _undo_was_pressed: + _next_actions.append({"data": data, "layer": layer}) + _undo_was_pressed = false + elif _redo_was_pressed: + _previous_actions.append({"data": data, "layer": layer}) + _redo_was_pressed = false + else: + _previous_actions.append({"data": data, "layer": layer}) + if _previous_actions.size() > number_of_actions: + _previous_actions.pop_front() + + _next_actions.clear() + +func _undo(): + if _previous_actions.size() > 0: + var action = _previous_actions.pop_back() + _undo_was_pressed = true + emit_signal("apply_action", action.data, action.layer) + +func _redo(): + if _next_actions.size() > 0: + var action = _next_actions.pop_back() + _redo_was_pressed = true + emit_signal("apply_action", action.data, action.layer) diff --git a/panels/UndoRedo.tscn b/panels/UndoRedo.tscn new file mode 100644 index 0000000..32dbc78 --- /dev/null +++ b/panels/UndoRedo.tscn @@ -0,0 +1,64 @@ +[gd_scene load_steps=6 format=2] + +[ext_resource path="res://panels/UndoRedo.gd" type="Script" id=1] +[ext_resource path="res://resources/icons/undo.png" type="Texture" id=2] +[ext_resource path="res://resources/icons/redo.png" type="Texture" id=3] + +[sub_resource type="Shader" id=1] +code = "shader_type canvas_item; + +uniform vec4 color : hint_color; + +void fragment() { + if(texture(TEXTURE, UV) == vec4(1.0, 1.0, 1.0, 1.0)){ + COLOR = vec4(1.0, 1.0, 1.0, 0.0); + } else { + COLOR = vec4(color.rgb, texture(TEXTURE, UV).a); + } +}" +custom_defines = "" + +[sub_resource type="ShaderMaterial" id=2] +shader = SubResource( 1 ) +shader_param/color = Color( 1, 1, 1, 1 ) + +[node name="UndoRedo" type="HBoxContainer"] +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="UndoContainer" type="CenterContainer" parent="."] +margin_right = 44.0 +margin_bottom = 600.0 + +[node name="Undo" type="ToolButton" parent="UndoContainer"] +material = SubResource( 2 ) +margin_top = 280.0 +margin_right = 44.0 +margin_bottom = 320.0 +hint_tooltip = "Undo" +icon = ExtResource( 2 ) + +[node name="Spacing" type="CenterContainer" parent="."] +margin_left = 48.0 +margin_right = 976.0 +margin_bottom = 600.0 +size_flags_horizontal = 3 + +[node name="RedoContainer" type="CenterContainer" parent="."] +margin_left = 980.0 +margin_right = 1024.0 +margin_bottom = 600.0 + +[node name="Redo" type="ToolButton" parent="RedoContainer"] +material = SubResource( 2 ) +margin_top = 280.0 +margin_right = 44.0 +margin_bottom = 320.0 +hint_tooltip = "Redo" +icon = ExtResource( 3 ) +[connection signal="pressed" from="UndoContainer/Undo" to="." method="_undo"] +[connection signal="pressed" from="RedoContainer/Redo" to="." method="_redo"] diff --git a/panels/layers/TileMapCanvasLayer.gd b/panels/layers/TileMapCanvasLayer.gd new file mode 100644 index 0000000..334ef37 --- /dev/null +++ b/panels/layers/TileMapCanvasLayer.gd @@ -0,0 +1,218 @@ +extends Control + +# Custom signals + +signal register_action(data) + +# Private variables + +var _tile_size : int = 0 +var _tilemap : Tilemap = Tilemap.new() +var _tilemap_tex : ImageTexture = ImageTexture.new() +var _overlay : Control +var _tool_box : Control +var _tool = Tilemap.Tool.PENCIL +var _drawing = false +var _placing_tiles : bool +var _previous_pos +var _has_tiles : bool = false + +# Layer public functions + +func init(canvas_conf : Dictionary, layer_conf : Dictionary): + _tile_size = layer_conf.TileSize + _create_tilemap(canvas_conf, layer_conf) + _create_overlay(canvas_conf, layer_conf) + _create_tool_box(layer_conf) + + if layer_conf.TileSet.size() > 0: _has_tiles = true + +func get_image(): + return _tilemap.get_image() + +func get_overlay(): + return _overlay + +func get_tool_box(): + return _tool_box + +func apply_action(data): + _tilemap.load_tilemap(data) + _register_action() + _update_layer() + +# Layer private functions + +func _create_tilemap(canvas_conf : Dictionary, layer_conf : Dictionary): + _tilemap.init(canvas_conf, layer_conf) + _tilemap_tex.create_from_image(_tilemap.get_image(), 3) + +func _create_overlay(canvas_conf : Dictionary, layer_conf : Dictionary): + _overlay = preload("res://panels/layers/TileMapOverlay.tscn").instance() + + _overlay.init(canvas_conf, layer_conf) + +func _create_tool_box(layer_conf : Dictionary): + _tool_box = preload("res://panels/layers/TileMapToolBox.tscn").instance() + if _tool_box.connect("tile_selected", self, "_select_tile") != OK: + print("Error connecting ToolBox's 'tile_selected' signal") + if _tool_box.connect("tool_selected", self, "_select_tool") != OK: + print("Error connecting ToolBox's 'tool_selected' signal") + if _tool_box.connect("grid_visibility_changed", _overlay, "set_grid_visibility") != OK: + print("Error connecting ToolBox's 'grid_visibility_changed' signal") + + _tool_box.init(layer_conf) + +func _select_tile(tile_id : int): + _tilemap.select_tile(tile_id) + +func _select_tool(tool_id : int): + _tool = tool_id + +func _draw(): + draw_texture(_tilemap_tex, Vector2.ZERO) + + _overlay.update() + +func _gui_input(event): + var position = (get_local_mouse_position() / _tile_size).floor() + + if _has_tiles: + if event is InputEventMouseButton: + _mouse_button(event.get_button_index(), event.is_pressed(), position) + elif event is InputEventMouseMotion: + _mouse_motion(position) + +func _mouse_button(button_index : int, is_pressed : bool, position : Vector2): + match _tool: + Tilemap.Tool.PENCIL: + if button_index == BUTTON_LEFT: + _placing_tiles = true + if is_pressed: + _start_drawing(position) + _draw_line(position) + else: + _end_drawing() + elif button_index == BUTTON_RIGHT: + _placing_tiles = false + if is_pressed: + _start_drawing(position) + _draw_line(position) + else: + _end_drawing() + + Tilemap.Tool.WRENCH: + if button_index == BUTTON_LEFT: + if is_pressed: + _change_tile_state(int(position.y), int(position.x)) + + Tilemap.Tool.ERASER: + if button_index == BUTTON_LEFT: + if is_pressed: + _start_drawing(position) + _draw_line(position) + else: + _end_drawing() + + Tilemap.Tool.BUCKET_FILL: + if button_index == BUTTON_LEFT: + if is_pressed: + _fill(int(position.y), int(position.x)) + +func _mouse_motion(position : Vector2): + if _drawing: + _draw_line(position) + + _overlay.highlight(position.x, position.y) + +func _start_drawing(position : Vector2): + _drawing = true + _previous_pos = position + +func _draw_line(position : Vector2): + var p0 = _previous_pos + var p1 = position + + var dx = abs(p1.x - p0.x) + var sx = 1 if p0.x < p1.x else -1 + var dy = -abs(p1.y - p0.y) + var sy = 1 if p0.y < p1.y else -1 + var err = dx + dy + + while true: + _set_tile(p0.y, p0.x) + + if p0.x == p1.x and p0.y == p1.y: + break + + var e2 = 2*err; + if e2 >= dy: + err += dy + p0.x += sx + if e2 <= dx: + err += dx + p0.y += sy + + _previous_pos = position + + _update_layer() + +func _end_drawing(): + _register_action() + _drawing = false + +func _set_tile(i : int, j : int): + match _tool: + Tilemap.Tool.PENCIL: + if _placing_tiles: + _tilemap.place_tile(i, j) + else: + _tilemap.erase_tile(i, j) + Tilemap.Tool.ERASER: + _tilemap.erase_tile_in_every_layer(i, j) + +func _change_tile_state(i : int, j : int): + _tilemap.change_tile_state(i, j) + _register_action() + _update_layer() + +func _fill(i : int, j : int): + _tilemap.fill(i, j) + _register_action() + _update_layer() + +func _register_action(): + var tilemap_hist = _tilemap.retrieve_previous_tilemap() + + if tilemap_hist.size() > 0: + emit_signal("register_action", tilemap_hist) + +func _update_layer(): + _tilemap_tex.set_data(_tilemap.get_image()) + update() + +func _mouse_entered(): + match _tool: + Tilemap.Tool.PENCIL: + var image = load("res://resources/icons/pencil.png") + var hotspot = Vector2(0, image.get_size().y) + Input.set_custom_mouse_cursor(image, 0, hotspot) + + Tilemap.Tool.WRENCH: + var image = load("res://resources/icons/wrench.png") + var hotspot = Vector2(image.get_size().x, 0) + Input.set_custom_mouse_cursor(image, 0, hotspot) + + Tilemap.Tool.ERASER: + var image = load("res://resources/icons/eraser.png") + var hotspot = Vector2(0, image.get_size().y) + Input.set_custom_mouse_cursor(image, 0, hotspot) + + Tilemap.Tool.BUCKET_FILL: + var image = load("res://resources/icons/bucket_fill.png") + var hotspot = Vector2(0, image.get_size().y) + Input.set_custom_mouse_cursor(image, 0, hotspot) + +func _mouse_exited(): + _overlay.highlight(-1, -1) + Input.set_custom_mouse_cursor(null) diff --git a/panels/layers/TileMapCanvasLayer.tscn b/panels/layers/TileMapCanvasLayer.tscn new file mode 100644 index 0000000..72bb401 --- /dev/null +++ b/panels/layers/TileMapCanvasLayer.tscn @@ -0,0 +1,12 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://panels/layers/TileMapCanvasLayer.gd" type="Script" id=1] + +[node name="Control" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +mouse_filter = 1 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} diff --git a/panels/layers/TileMapOverlay.gd b/panels/layers/TileMapOverlay.gd new file mode 100644 index 0000000..09ec0b5 --- /dev/null +++ b/panels/layers/TileMapOverlay.gd @@ -0,0 +1,62 @@ +extends Control + +##################### +# Private variables # +##################### + +# Width in number of tiles +var _width : int = 0 +# Height in number of tiles +var _height : int = 0 +# Size of the tile in pixels +var _tile_size : int = 0 + +#################### +# Public functions # +#################### + +# Configuration dictionary description +# + grid_visibility: visibility of the grid (bool) +# + width: Width in number of tiles (int) +# + height: Height in number of tiles (int) +# + tile_size: Size of the tile in pixels (int) +func init(canvas_conf : Dictionary, layer_conf : Dictionary) -> void: + _width = canvas_conf.Width + _height = canvas_conf.Height + _tile_size = layer_conf.TileSize + + get_node("Grid").init(_width, _height, _tile_size) + get_node("Square").init(_tile_size) + +# Sets the grid visibility +func set_grid_visibility(visibility : bool) -> void: + if visibility: + get_node("Grid").show() + else: + get_node("Grid").hide() + +# Sets a position on the grid to highlight +func highlight(x : int, y : int) -> void: + if x >= 0 and x < _width and y >= 0 and y < _height: + get_node("Square").set_pos(Vector2(x * _tile_size, y * _tile_size)) + get_node("Square").show() + else: + get_node("Square").hide() + +# Sets the transformation +func set_transform(offset : Vector2, scale : Vector2) -> void: + for child in get_children(): + child.set_transform(offset, scale) + child.set_transform(offset, scale) + + update() + +##################### +# Private functions # +##################### + +# Draws the overlay +func _draw() -> void: + for child in get_children(): + child.update() + child.update() diff --git a/panels/layers/TileMapOverlay.tscn b/panels/layers/TileMapOverlay.tscn new file mode 100644 index 0000000..20edc68 --- /dev/null +++ b/panels/layers/TileMapOverlay.tscn @@ -0,0 +1,25 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://panels/layers/TileMapOverlay.gd" type="Script" id=1] +[ext_resource path="res://panels/layers/overlays/Grid.tscn" type="PackedScene" id=2] +[ext_resource path="res://panels/layers/overlays/Square.tscn" type="PackedScene" id=4] + +[node name="TileMapOverlay" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +mouse_filter = 2 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Grid" parent="." instance=ExtResource( 2 )] +visible = false +margin_right = 0.0 +margin_bottom = 0.0 + +[node name="Square" parent="." instance=ExtResource( 4 )] +visible = false +material = null +margin_right = -40.0 +margin_bottom = -40.0 diff --git a/panels/layers/TileMapToolBox.gd b/panels/layers/TileMapToolBox.gd new file mode 100644 index 0000000..70ff23b --- /dev/null +++ b/panels/layers/TileMapToolBox.gd @@ -0,0 +1,174 @@ +extends VSplitContainer + +################## +# Custom signals # +################## + +# Notifies when a tile has been selected +signal tile_selected(tile_id) +# Notifies when a tool has been selected +signal tool_selected(tool_id) +# Notifies when the grid visibility has changed +signal grid_visibility_changed(visibility) + +##################### +# Private variables # +##################### + +# If the wrench is present +var _wrench_flag : bool = false +# Wrench item +var _wrench_item : Button = preload("res://panels/layers/elements/ToolItem.tscn").instance() +# If the bucket fill is present +var _bucket_fill_flag : bool = false +# Bucket fill item +var _bucket_fill_item : Button = preload("res://panels/layers/elements/ToolItem.tscn").instance() + +#################### +# Public functions # +#################### + +# Configuration dictionary description +# + tileset: Tile set information (Array) +# - Each element contain the configuration of a TileItem +# + id: Tile id (int) +# + name: Tile name (String) +# + icon: Tile icon (Image) +# + extra_tools: Tile extra tools available (Array) +# - Each element is a member of the enum _TileMap.Tool +func init(configuration : Dictionary) -> void: + var tile_item_group = ButtonGroup.new() + + for tile in configuration.TileSet: + _add_tile_item(tile_item_group, tile) + + _init_tools() + + if get_node("TilesScroller/TilesGridPanel/Margin/TilesGrid").get_child_count() > 0: + _get_tile_item(0).select() + +##################### +# Private functions # +##################### + +# Adds a tile item +# Configuration dictionary description +# + id: Tile id (int) +# + name: Tile name (String) +# + icon: Tile icon (Image) +# + extra_tools: Tile extra tools available (Array) +# - Each element is a member of the enum _TileMap.Tool +func _add_tile_item(tile_item_group : ButtonGroup, configuration : Dictionary) -> void: + var tile_item = preload("res://panels/layers/elements/TileItem.tscn").instance() + tile_item.init(configuration) + tile_item.add_to_button_group(tile_item_group) + + get_node("TilesScroller/TilesGridPanel/Margin/TilesGrid").add_child(tile_item) + tile_item.connect("tile_item_selected", self, "_select_tile") + +# Returns a tile item +func _get_tile_item(idx : int) -> Node: + return get_node("TilesScroller/TilesGridPanel/Margin/TilesGrid").get_child(idx) + +# It is called when the tile item emits the tile_item_selected signal +func _select_tile(tile_id : int, extra_tools : Array) -> void: + _update_extra_tools(extra_tools) + emit_signal("tile_selected", tile_id) + +# Updates the extra tools +func _update_extra_tools(extra_tools): + var wrench_flag = false + var bucket_fill_flag = false + + for extra_tool in extra_tools: + match extra_tool: + Tilemap.Tool.WRENCH: + wrench_flag = true + if _wrench_flag == false: + _wrench_flag = true + get_node("ToolsPanel/Tools/LeftTools").add_child(_wrench_item) + Tilemap.Tool.BUCKET_FILL: + bucket_fill_flag = true + if _bucket_fill_flag == false: + _bucket_fill_flag = true + get_node("ToolsPanel/Tools/LeftTools").add_child(_bucket_fill_item) + + if wrench_flag == false and _wrench_flag: + _wrench_flag = false + get_node("ToolsPanel/Tools/LeftTools").remove_child(_wrench_item) + + if bucket_fill_flag == false and _bucket_fill_flag: + _bucket_fill_flag = false + get_node("ToolsPanel/Tools/LeftTools").remove_child(_bucket_fill_item) + + get_node("ToolsPanel/Tools/LeftTools/Pencil").select() + +# Init tools +func _init_tools(): + var tool_item_group = ButtonGroup.new() + _init_default_tools_items(tool_item_group) + _init_extra_tools_items(tool_item_group) + +# Init default tools items +func _init_default_tools_items(tool_item_group : ButtonGroup): + _init_pencil_item(tool_item_group) + _init_eraser_item(tool_item_group) + _init_grid_item() + +# Init pencil item +func _init_pencil_item(tool_item_group : ButtonGroup): + var conf = {"id": Tilemap.Tool.PENCIL, "name": "Pencil", "icon": _get_image("pencil")} + get_node("ToolsPanel/Tools/LeftTools/Pencil").init(conf) + get_node("ToolsPanel/Tools/LeftTools/Pencil").add_to_button_group(tool_item_group) + get_node("ToolsPanel/Tools/LeftTools/Pencil").connect("tool_item_selected", self, "_select_tool") + +# Init eraser item +func _init_eraser_item(tool_item_group : ButtonGroup): + var conf = {"id": Tilemap.Tool.ERASER, "name": "Eraser", "icon": _get_image("eraser")} + get_node("ToolsPanel/Tools/RightTools/Eraser").init(conf) + get_node("ToolsPanel/Tools/RightTools/Eraser").add_to_button_group(tool_item_group) + get_node("ToolsPanel/Tools/RightTools/Eraser").connect("tool_item_selected", self, "_select_tool") + +# Init grid item +func _init_grid_item(): + var conf = {"name": "Grid", "toggled": false, "icon": _get_image("grid")} + get_node("ToolsPanel/Tools/RightTools/Grid").init(conf) + get_node("ToolsPanel/Tools/RightTools/Grid").connect("toggle_item_updated", self, "_grid_visibility_changed") + +# Init extra tools items +func _init_extra_tools_items(tool_item_group : ButtonGroup): + _init_wrench_item(tool_item_group) + _init_bucket_fill_item(tool_item_group) + +# Init wrench item +func _init_wrench_item(tool_item_group : ButtonGroup): + var conf = {"id": Tilemap.Tool.WRENCH, "name": "Wrench", "icon": _get_image("wrench")} + _wrench_item.init(conf) + _wrench_item.add_to_button_group(tool_item_group) + _wrench_item.connect("tool_item_selected", self, "_select_tool") + +# Init bucket fill item +func _init_bucket_fill_item(tool_item_group : ButtonGroup): + var conf = {"id": Tilemap.Tool.BUCKET_FILL, "name": "Bucket fill", "icon": _get_image("bucket_fill")} + _bucket_fill_item.init(conf) + _bucket_fill_item.add_to_button_group(tool_item_group) + _bucket_fill_item.connect("tool_item_selected", self, "_select_tool") + +# Returns the image from the resources folder +func _get_image(name : String) -> Image: + return load("res://resources/icons/" + name + ".png").get_data() + +# It is called when the tool item emits the tool_item_selected signal +func _select_tool(tool_id : int) -> void: + emit_signal("tool_selected", tool_id) + +# It is called when the toggle item emits the toggle_item_updated signal +func _grid_visibility_changed(visibility : bool) -> void: + emit_signal("grid_visibility_changed", visibility) + + +func _grid_resized(): + pass +# var scroller_size = get_node("TilesScroller").get_size() +# var grid_size = get_node("TilesScroller/TilesGridPanel/Margin").get_size() +# get_node("TilesScroller").set_size(Vector2(scroller_size.x, grid_size.y)) diff --git a/panels/layers/TileMapToolBox.tscn b/panels/layers/TileMapToolBox.tscn new file mode 100644 index 0000000..cc7340c --- /dev/null +++ b/panels/layers/TileMapToolBox.tscn @@ -0,0 +1,134 @@ +[gd_scene load_steps=12 format=2] + +[ext_resource path="res://panels/layers/elements/ToolItem.tscn" type="PackedScene" id=3] +[ext_resource path="res://panels/layers/TileMapToolBox.gd" type="Script" id=5] +[ext_resource path="res://panels/layers/elements/ToggleItem.tscn" type="PackedScene" id=6] + +[sub_resource type="StyleBoxFlat" id=1] +bg_color = Color( 1, 1, 1, 1 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="Theme" id=2] +PanelContainer/styles/panel = SubResource( 1 ) + +[sub_resource type="StyleBoxFlat" id=3] +bg_color = Color( 1, 1, 1, 1 ) + +[sub_resource type="StyleBoxFlat" id=4] +bg_color = Color( 0.866667, 0.882353, 0.376471, 0 ) +border_color = Color( 0.8, 0.8, 0.8, 0 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="StyleBoxFlat" id=5] +bg_color = Color( 0.976471, 0.984314, 0.698039, 1 ) +border_color = Color( 0.266667, 0.427451, 0.964706, 1 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="StyleBoxFlat" id=6] +bg_color = Color( 0.866667, 0.882353, 0.376471, 0 ) +border_color = Color( 0.8, 0.8, 0.8, 0 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="StyleBoxFlat" id=7] +bg_color = Color( 0.972549, 0.690196, 0.501961, 1 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="Theme" id=8] +Button/colors/font_color = Color( 0.88, 0.88, 0.88, 1 ) +Button/colors/font_color_disabled = Color( 0.9, 0.9, 0.9, 0.2 ) +Button/colors/font_color_hover = Color( 0.94, 0.94, 0.94, 1 ) +Button/colors/font_color_pressed = Color( 1, 1, 1, 1 ) +Button/constants/hseparation = 2 +Button/fonts/font = null +Button/styles/disabled = SubResource( 3 ) +Button/styles/focus = SubResource( 4 ) +Button/styles/hover = SubResource( 5 ) +Button/styles/normal = SubResource( 6 ) +Button/styles/pressed = SubResource( 7 ) + +[node name="ToolBox" type="VSplitContainer"] +anchor_bottom = 1.0 +margin_right = 320.0 +dragger_visibility = 1 +script = ExtResource( 5 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="ToolsPanel" type="PanelContainer" parent="."] +margin_right = 320.0 +margin_bottom = 40.0 +rect_min_size = Vector2( 318, 0 ) +theme = SubResource( 2 ) + +[node name="Tools" type="HBoxContainer" parent="ToolsPanel"] +margin_right = 320.0 +margin_bottom = 40.0 +rect_min_size = Vector2( 318, 0 ) +theme = SubResource( 8 ) + +[node name="LeftTools" type="HBoxContainer" parent="ToolsPanel/Tools"] +margin_right = 44.0 +margin_bottom = 40.0 + +[node name="Pencil" parent="ToolsPanel/Tools/LeftTools" instance=ExtResource( 3 )] +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_right = 44.0 +margin_bottom = 40.0 + +[node name="RightTools" type="HBoxContainer" parent="ToolsPanel/Tools"] +margin_left = 48.0 +margin_right = 320.0 +margin_bottom = 40.0 +size_flags_horizontal = 3 +alignment = 2 + +[node name="Eraser" parent="ToolsPanel/Tools/RightTools" instance=ExtResource( 3 )] +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 180.0 +margin_right = 224.0 +margin_bottom = 40.0 + +[node name="Grid" parent="ToolsPanel/Tools/RightTools" instance=ExtResource( 6 )] +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 228.0 +margin_right = 272.0 +margin_bottom = 40.0 + +[node name="TilesScroller" type="ScrollContainer" parent="."] +margin_top = 52.0 +margin_right = 320.0 +margin_bottom = 600.0 +rect_min_size = Vector2( 320, 0 ) +scroll_horizontal_enabled = false + +[node name="TilesGridPanel" type="PanelContainer" parent="TilesScroller"] +margin_right = 320.0 +size_flags_horizontal = 3 +theme = SubResource( 2 ) + +[node name="Margin" type="MarginContainer" parent="TilesScroller/TilesGridPanel"] +margin_right = 320.0 + +[node name="TilesGrid" type="GridContainer" parent="TilesScroller/TilesGridPanel/Margin"] +margin_right = 320.0 +columns = 4 +[connection signal="resized" from="TilesScroller/TilesGridPanel/Margin/TilesGrid" to="." method="_grid_resized"] diff --git a/panels/layers/elements/TileItem.gd b/panels/layers/elements/TileItem.gd new file mode 100644 index 0000000..d31abc2 --- /dev/null +++ b/panels/layers/elements/TileItem.gd @@ -0,0 +1,73 @@ +extends Button + +################## +# Custom signals # +################## + +# Notifies when this tile item has been selected +signal tile_item_selected(tile_id, extra_tools) + +##################### +# Private variables # +##################### + +# Tile id +var _id : int = 0 +# Tile name +var _name : String = "" +# Tile extra tools available +var _extra_tools : Array = [] + +#################### +# Public functions # +#################### + +# Configuration dictionary description +# + ID: Tile id (int) +# + Name: Tile name (String) +# + Image: Tile icon (Image) +# + ExtraTools: Tile extra tools available (Array) +# - Each element is a member of the enum _TileMap.Tool +func init(configuration : Dictionary) -> void: + _set_id(configuration.ID) + _set_name(configuration.Name) + _set_icon(configuration.Image) + + for extra_tool in configuration.ExtraTools: + _add_extra_tool(extra_tool) + +# Selects this tile +func select() -> void: + set_pressed(true) + _tile_item_pressed() + +# Adds this tile item to a button group +func add_to_button_group(group : ButtonGroup) -> void: + set_button_group(group) + +##################### +# Private functions # +##################### + +# Sets tile id +func _set_id(id : int) -> void: + _id = id + +# Sets tile name and updates the tooltip +func _set_name(name : String) -> void: + _name = name + set_tooltip(_name) + +# Sets tile icon and updates the texture +func _set_icon(icon : Image) -> void: + var icon_tex = ImageTexture.new() + icon_tex.create_from_image(icon, 3) + get_node("Icon").set_texture(icon_tex) + +# Adds a tile extra tool +func _add_extra_tool(extra_tool : int) -> void: + _extra_tools.append(extra_tool) + +# It is called when the tile item is pressed +func _tile_item_pressed() -> void: + emit_signal("tile_item_selected", _id, _extra_tools) diff --git a/panels/layers/elements/TileItem.tscn b/panels/layers/elements/TileItem.tscn new file mode 100644 index 0000000..9dbeaf4 --- /dev/null +++ b/panels/layers/elements/TileItem.tscn @@ -0,0 +1,118 @@ +[gd_scene load_steps=9 format=2] + +[ext_resource path="res://panels/layers/elements/TileItem.gd" type="Script" id=1] + +[sub_resource type="StyleBoxFlat" id=1] +bg_color = Color( 0.972549, 0.690196, 0.501961, 1 ) +border_color = Color( 0.266667, 0.427451, 0.964706, 1 ) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="StyleBoxFlat" id=2] +bg_color = Color( 0.972549, 0.690196, 0.501961, 1 ) +border_color = Color( 0.266667, 0.427451, 0.964706, 1 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="StyleBoxFlat" id=3] +bg_color = Color( 0.976471, 0.984314, 0.698039, 1 ) +border_color = Color( 0.266667, 0.427451, 0.964706, 1 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="StyleBoxFlat" id=4] +bg_color = Color( 0.266667, 0.427451, 0.964706, 1 ) +border_color = Color( 0.266667, 0.427451, 0.964706, 1 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="Theme" id=5] +Button/colors/font_color = Color( 0.88, 0.88, 0.88, 1 ) +Button/colors/font_color_disabled = Color( 0.9, 0.9, 0.9, 0.2 ) +Button/colors/font_color_hover = Color( 0.94, 0.94, 0.94, 1 ) +Button/colors/font_color_pressed = Color( 1, 1, 1, 1 ) +Button/constants/hseparation = 2 +Button/fonts/font = null +Button/styles/disabled = SubResource( 1 ) +Button/styles/focus = SubResource( 2 ) +Button/styles/hover = SubResource( 3 ) +Button/styles/normal = SubResource( 4 ) +Button/styles/pressed = SubResource( 2 ) + +[sub_resource type="Shader" id=6] +code = "shader_type canvas_item; + +uniform float width; +uniform vec2 tex_size; +uniform vec4 outline_color : hint_color; + +vec4 tex(sampler2D tex, vec2 uv) { + if (0.0 <= uv.x && 1.0 >= uv.x && 0.0 <= uv.y && 1.0 >= uv.y) { + return texture(tex, uv); + } else { + return vec4(1.0, 1.0, 1.0, 0.0); + } +} + +void fragment() { + vec2 offset = vec2(width, width) / tex_size; + vec2 scale = tex_size / (tex_size - 2.0 * vec2(width, width)); + vec2 uv = (UV - offset) * scale; + + float size = width / (tex_size.x * scale.x); + + vec4 sprite_color = tex(TEXTURE, uv); + float alpha = -8.0 * sprite_color.a; + alpha += tex(TEXTURE, uv + vec2(size, 0.0)).a; + alpha += tex(TEXTURE, uv + vec2(-size, 0.0)).a; + alpha += tex(TEXTURE, uv + vec2(0.0, size)).a; + alpha += tex(TEXTURE, uv + vec2(0.0, -size)).a; + alpha += tex(TEXTURE, uv + vec2(size, size)).a; + alpha += tex(TEXTURE, uv + vec2(-size, size)).a; + alpha += tex(TEXTURE, uv + vec2(size, -size)).a; + alpha += tex(TEXTURE, uv + vec2(-size, -size)).a; + + vec4 final_color = mix(sprite_color, outline_color, clamp(alpha, 0.0, 1.0)); + COLOR = vec4(final_color.rgb, clamp(abs(alpha) + sprite_color.a, 0.0, 1.0)); +}" +custom_defines = "" + +[sub_resource type="ShaderMaterial" id=7] +shader = SubResource( 6 ) +shader_param/width = 4.0 +shader_param/tex_size = Vector2( 58, 58 ) +shader_param/outline_color = Color( 1, 1, 1, 1 ) + +[node name="TileItem" type="Button"] +anchor_right = 0.072 +anchor_bottom = 1.0 +margin_right = 0.271996 +margin_bottom = -526.0 +rect_min_size = Vector2( 74, 74 ) +theme = SubResource( 5 ) +toggle_mode = true +action_mode = 0 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Icon" type="TextureRect" parent="."] +material = SubResource( 7 ) +margin_left = 8.0 +margin_top = 8.0 +margin_right = 66.0 +margin_bottom = 66.0 +expand = true +__meta__ = { +"_edit_use_anchors_": false +} +[connection signal="pressed" from="." to="." method="_tile_item_pressed"] diff --git a/panels/layers/elements/ToggleItem.gd b/panels/layers/elements/ToggleItem.gd new file mode 100644 index 0000000..4c7bfb4 --- /dev/null +++ b/panels/layers/elements/ToggleItem.gd @@ -0,0 +1,52 @@ +extends Button + +################## +# Custom signals # +################## + +# Notifies when this tool item has been selected +signal toggle_item_updated(is_toggled) + +##################### +# Private variables # +##################### + +# Toggle name +var _name : String = "" + +#################### +# Public functions # +#################### + +# Configuration dictionary description +# + name: Toggle name (String) +# + toggled: Toggle is toggled (bool) +# + icon: Toggle icon (Image) +func init(configuration : Dictionary) -> void: + _set_name(configuration.name) + set_pressed(configuration.toggled) + _set_icon(configuration.icon) + +# Selects this toggle +func select() -> void: + set_pressed(true) + _toggle_item_pressed() + +##################### +# Private functions # +##################### + +# Sets toggle name and updates the tooltip +func _set_name(name : String) -> void: + _name = name + set_tooltip(_name) + +# Sets toggle icon and updates the texture +func _set_icon(icon : Image) -> void: + var icon_tex = ImageTexture.new() + icon_tex.create_from_image(icon) + get_node("Icon").set_texture(icon_tex) + +# It is called when the toggle item is pressed +func _toggle_item_pressed() -> void: + emit_signal("toggle_item_updated", is_pressed()) diff --git a/panels/layers/elements/ToggleItem.tscn b/panels/layers/elements/ToggleItem.tscn new file mode 100644 index 0000000..4adc73b --- /dev/null +++ b/panels/layers/elements/ToggleItem.tscn @@ -0,0 +1,40 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://panels/layers/elements/ToggleItem.gd" type="Script" id=1] + +[sub_resource type="Shader" id=1] +code = "shader_type canvas_item; + +uniform vec4 color : hint_color; + +void fragment() { + COLOR = vec4(color.rgb, texture(TEXTURE, UV).a); +}" +custom_defines = "" + +[sub_resource type="ShaderMaterial" id=2] +shader = SubResource( 1 ) +shader_param/color = Color( 0.145098, 0.196078, 0.215686, 1 ) + +[node name="ToggleItem" type="Button"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_right = -980.0 +margin_bottom = -560.0 +rect_min_size = Vector2( 44, 40 ) +toggle_mode = true +action_mode = 0 +script = ExtResource( 1 ) + +[node name="Icon" type="TextureRect" parent="."] +material = SubResource( 2 ) +margin_left = 4.0 +margin_top = 2.0 +margin_right = 40.0 +margin_bottom = 38.0 +rect_min_size = Vector2( 36, 36 ) +expand = true +__meta__ = { +"_edit_use_anchors_": false +} +[connection signal="pressed" from="." to="." method="_toggle_item_pressed"] diff --git a/panels/layers/elements/ToolItem.gd b/panels/layers/elements/ToolItem.gd new file mode 100644 index 0000000..3acb876 --- /dev/null +++ b/panels/layers/elements/ToolItem.gd @@ -0,0 +1,64 @@ +extends Button + +################## +# Custom signals # +################## + +# Notifies when this tool item has been selected +signal tool_item_selected(tool_id) + +##################### +# Private variables # +##################### + +# Tool id +var _id : int = 0 +# Tool name +var _name : String = "" + +#################### +# Public functions # +#################### + +# Configuration dictionary description +# + id: Tool id (int) +# + name: Tool name (String) +# + icon: Tool icon (Image) +func init(configuration : Dictionary) -> void: + _set_id(configuration.id) + _set_name(configuration.name) + _set_icon(configuration.icon) + + update() + +# Selects this tool +func select() -> void: + set_pressed(true) + _tool_item_pressed() + +# Adds this tool item to a button group +func add_to_button_group(group : ButtonGroup) -> void: + set_button_group(group) + +##################### +# Private functions # +##################### + +# Sets tool id +func _set_id(id : int) -> void: + _id = id + +# Sets tool name and updates the tooltip +func _set_name(name : String) -> void: + _name = name + set_tooltip(_name) + +# Sets tool icon and updates the texture +func _set_icon(icon : Image) -> void: + var icon_tex = ImageTexture.new() + icon_tex.create_from_image(icon) + get_node("Icon").set_texture(icon_tex) + +# It is called when the tool item is pressed +func _tool_item_pressed() -> void: + emit_signal("tool_item_selected", _id) diff --git a/panels/layers/elements/ToolItem.tscn b/panels/layers/elements/ToolItem.tscn new file mode 100644 index 0000000..0fb0573 --- /dev/null +++ b/panels/layers/elements/ToolItem.tscn @@ -0,0 +1,43 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://panels/layers/elements/ToolItem.gd" type="Script" id=1] + +[sub_resource type="Shader" id=1] +code = "shader_type canvas_item; + +uniform vec4 color : hint_color; + +void fragment() { + COLOR = vec4(color.rgb, texture(TEXTURE, UV).a); +}" +custom_defines = "" + +[sub_resource type="ShaderMaterial" id=2] +shader = SubResource( 1 ) +shader_param/color = Color( 0.145098, 0.196078, 0.215686, 1 ) + +[node name="ToolItem" type="Button"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_right = -980.0 +margin_bottom = -560.0 +rect_min_size = Vector2( 44, 40 ) +toggle_mode = true +action_mode = 0 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Icon" type="TextureRect" parent="."] +material = SubResource( 2 ) +margin_left = 4.0 +margin_top = 2.0 +margin_right = 40.0 +margin_bottom = 38.0 +rect_min_size = Vector2( 36, 36 ) +expand = true +__meta__ = { +"_edit_use_anchors_": false +} +[connection signal="pressed" from="." to="." method="_tool_item_pressed"] diff --git a/panels/layers/overlays/Grid.gd b/panels/layers/overlays/Grid.gd new file mode 100644 index 0000000..6c575d3 --- /dev/null +++ b/panels/layers/overlays/Grid.gd @@ -0,0 +1,56 @@ +extends Control + +##################### +# Private variables # +##################### + +# Horizontal lines of the grid +var _grid_h_lines : Array = [] +# Vertical lines of the grid +var _grid_v_lines : Array = [] +# Offset of the grid +var _offset : Vector2 = Vector2.ZERO +# Scale of the grid +var _scale : Vector2 = Vector2.ONE + +#################### +# Public functions # +#################### + +# + width: Width in number of tiles (int) +# + height: Height in number of tiles (int) +# + tile_size: Size of the tile in pixels (int) +func init(width : int, height : int, size : int) -> void: + _create_grid_lines(width, height, size) + +# Sets the transformation +func set_transform(offset : Vector2, scale : Vector2) -> void: + _offset = offset + _scale = scale + +##################### +# Private functions # +##################### + +# Creates the grid lines +func _create_grid_lines(width : int, height : int, size : int) -> void: + for i in range(height - 1): + _grid_h_lines.append([]) + _grid_h_lines[i].append(Vector2(0 , (i + 1) * size)) + _grid_h_lines[i].append(Vector2(width * size, (i + 1) * size)) + + for i in range(width - 1): + _grid_v_lines.append([]) + _grid_v_lines[i].append(Vector2((i + 1) * size, 0 )) + _grid_v_lines[i].append(Vector2((i + 1) * size, height * size)) + +# Draws the grid +func _draw() -> void: + for line in _grid_h_lines: + draw_line(_transform(line[0]), _transform(line[1]), Color.red, 2) + for line in _grid_v_lines: + draw_line(_transform(line[0]), _transform(line[1]), Color.green, 2) + +# Transform a point +func _transform(p : Vector2) -> Vector2: + return p * _scale + _offset diff --git a/panels/layers/overlays/Grid.tscn b/panels/layers/overlays/Grid.tscn new file mode 100644 index 0000000..ac304ba --- /dev/null +++ b/panels/layers/overlays/Grid.tscn @@ -0,0 +1,49 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://panels/layers/overlays/Grid.gd" type="Script" id=1] + +[sub_resource type="Shader" id=1] +code = "shader_type canvas_item; + +uniform vec4 dark_color : hint_color; +const vec4 light_color = vec4(1.0, 1.0, 1.0, 1.0); +const vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0); + +void fragment(){ + bool parity; + + if (COLOR.r > 0.5) { + parity = (int(FRAGCOORD.x) / 10) % 2 == 0; + } else { + parity = (int(FRAGCOORD.y) / 10) % 2 == 1; + } + + if (parity) { + vec4 screen_color = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0); + float v = max(max(screen_color.r, screen_color.g), screen_color.b); + if (v > 0.5) { + COLOR = dark_color; + } else { + COLOR = light_color; + } + } else { + COLOR = transparent; + } +}" +custom_defines = "" + +[sub_resource type="ShaderMaterial" id=2] +shader = SubResource( 1 ) +shader_param/dark_color = Color( 0.145098, 0.196078, 0.215686, 1 ) + +[node name="Grid" type="Control"] +material = SubResource( 2 ) +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_right = -1024.0 +margin_bottom = -600.0 +mouse_filter = 2 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} diff --git a/panels/layers/overlays/Image.gd b/panels/layers/overlays/Image.gd new file mode 100644 index 0000000..78ea8c2 --- /dev/null +++ b/panels/layers/overlays/Image.gd @@ -0,0 +1,43 @@ +extends Control + +##################### +# Private variables # +##################### + +# Texture of the image to show +var _image : ImageTexture = ImageTexture.new() +# Position to show the image +var _pos : Vector2 = Vector2.ZERO + +#################### +# Public functions # +#################### + +# + image: Image (Image) +# + pos: Position to show the image (Vector2) +func init(image : Image, pos : Vector2) -> void: + set_image(image) + set_pos(pos) + +# Sets the image +func set_image(image : Image) -> void: + _image.create_from_image(image, 3) + update() + +# Sets the position +func set_pos(pos : Vector2) -> void: + _pos = pos + update() + +# Sets the transformation +func set_transform(offset : Vector2, scale : Vector2) -> void: + get_material().set_shader_param("offset", offset) + get_material().set_shader_param("scale", scale) + +##################### +# Private functions # +##################### + +# Draws the image +func _draw() -> void: + draw_texture(_image, _pos) diff --git a/panels/layers/overlays/Image.tscn b/panels/layers/overlays/Image.tscn new file mode 100644 index 0000000..299f01f --- /dev/null +++ b/panels/layers/overlays/Image.tscn @@ -0,0 +1,37 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://panels/layers/overlays/Image.gd" type="Script" id=1] + +[sub_resource type="Shader" id=1] +code = "shader_type canvas_item; + +uniform vec2 offset; +uniform vec2 scale; + +void vertex() { + VERTEX *= scale; + VERTEX += offset; +} + +void fragment() { + COLOR = vec4(texture(TEXTURE, UV).rgb, min(texture(TEXTURE, UV).a, 0.75)); +} +" +custom_defines = "" + +[sub_resource type="ShaderMaterial" id=2] +shader = SubResource( 1 ) +shader_param/offset = null +shader_param/scale = null + +[node name="Image" type="Control"] +material = SubResource( 2 ) +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_right = -1024.0 +margin_bottom = -600.0 +mouse_filter = 2 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} diff --git a/panels/layers/overlays/Square.gd b/panels/layers/overlays/Square.gd new file mode 100644 index 0000000..ce0b907 --- /dev/null +++ b/panels/layers/overlays/Square.gd @@ -0,0 +1,49 @@ +extends Control + +##################### +# Private variables # +##################### + +# Size of the square +var _size : int = 0 +# Position of the square +var _pos : Vector2 = Vector2.ZERO +# Offset of the square +var _offset : Vector2 = Vector2.ZERO +# Scale of the square +var _scale : Vector2 = Vector2.ONE + +#################### +# Public functions # +#################### + +# + size: size of the square (int) +func init(size : int) -> void: + _size = size + +# Sets the position +func set_pos(pos : Vector2) -> void: + _pos = pos + update() + +# Sets the transformation +func set_transform(offset : Vector2, scale : Vector2) -> void: + _offset = offset + _scale = scale + +##################### +# Private functions # +##################### + +# Draws the square +func _draw() -> void: + var color_1 = Color(242 / 255.0, 149 / 255.0, 89 / 255.0, 0.75) + var color_2 = Color(242 / 255.0, 149 / 255.0, 89 / 255.0, 0.25) + var width = 4 + + draw_rect(Rect2(_transform(_pos), Vector2(_size, _size) * _scale), color_2, true) + draw_rect(Rect2(_transform(_pos), Vector2(_size, _size) * _scale), color_1, false, width, true) + +# Transform a point +func _transform(p : Vector2) -> Vector2: + return p * _scale + _offset diff --git a/panels/layers/overlays/Square.tscn b/panels/layers/overlays/Square.tscn new file mode 100644 index 0000000..c1fb7bb --- /dev/null +++ b/panels/layers/overlays/Square.tscn @@ -0,0 +1,33 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://panels/layers/overlays/Square.gd" type="Script" id=1] + +[sub_resource type="Shader" id=1] +code = "shader_type canvas_item; + +uniform vec2 offset; +uniform vec2 scale; + +void vertex() { + VERTEX *= scale; + VERTEX += offset; +} +" +custom_defines = "" + +[sub_resource type="ShaderMaterial" id=2] +shader = SubResource( 1 ) +shader_param/offset = null +shader_param/scale = null + +[node name="Square" type="Control"] +material = SubResource( 2 ) +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_right = -1024.0 +margin_bottom = -600.0 +mouse_filter = 2 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} diff --git a/project.godot b/project.godot index 6c4478e..62e01fa 100644 --- a/project.godot +++ b/project.godot @@ -8,9 +8,50 @@ config_version=4 -_global_script_classes=[ ] +_global_script_classes=[ { +"base": "Reference", +"class": "BaseParser", +"language": "GDScript", +"path": "res://classes/parser/BaseParser.gd" +}, { +"base": "Reference", +"class": "MainParser", +"language": "GDScript", +"path": "res://classes/parser/MainParser.gd" +}, { +"base": "Reference", +"class": "StyleDataParser", +"language": "GDScript", +"path": "res://classes/parser/StyleDataParser.gd" +}, { +"base": "Reference", +"class": "Tile", +"language": "GDScript", +"path": "res://classes/tilemap/Tile.gd" +}, { +"base": "Reference", +"class": "Tilemap", +"language": "GDScript", +"path": "res://classes/tilemap/Tilemap.gd" +}, { +"base": "Reference", +"class": "TilemapLayer", +"language": "GDScript", +"path": "res://classes/tilemap/TilemapLayer.gd" +}, { +"base": "Reference", +"class": "TilemapParser", +"language": "GDScript", +"path": "res://classes/parser/TilemapParser.gd" +} ] _global_script_class_icons={ - +"BaseParser": "", +"MainParser": "", +"StyleDataParser": "", +"Tile": "", +"Tilemap": "", +"TilemapLayer": "", +"TilemapParser": "" } [application] @@ -19,6 +60,30 @@ config/name="Teggy's Map Maker" run/main_scene="res://MainWindow.tscn" config/icon="res://icon.png" +[input] + +ui_zoom_plus={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":true,"meta":false,"command":true,"pressed":false,"scancode":43,"unicode":0,"echo":false,"script":null) + ] +} +ui_zoom_minus={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":true,"meta":false,"command":true,"pressed":false,"scancode":45,"unicode":0,"echo":false,"script":null) + ] +} +ui_undo={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":true,"meta":false,"command":true,"pressed":false,"scancode":90,"unicode":0,"echo":false,"script":null) + ] +} +ui_redo={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":true,"meta":false,"command":true,"pressed":false,"scancode":89,"unicode":0,"echo":false,"script":null) + ] +} + [rendering] +environment/default_clear_color=Color( 0.145098, 0.196078, 0.215686, 1 ) environment/default_environment="res://default_env.tres" diff --git a/resources/fonts/Poppins/OFL.txt b/resources/fonts/Poppins/OFL.txt new file mode 100644 index 0000000..246c977 --- /dev/null +++ b/resources/fonts/Poppins/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2020 The Poppins Project Authors (https://github.com/itfoundry/Poppins) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/resources/fonts/Poppins/Poppins-Black.ttf b/resources/fonts/Poppins/Poppins-Black.ttf new file mode 100644 index 0000000..a9520b7 Binary files /dev/null and b/resources/fonts/Poppins/Poppins-Black.ttf differ diff --git a/resources/fonts/Poppins/Poppins-BlackItalic.ttf b/resources/fonts/Poppins/Poppins-BlackItalic.ttf new file mode 100644 index 0000000..ebfdd70 Binary files /dev/null and b/resources/fonts/Poppins/Poppins-BlackItalic.ttf differ diff --git a/resources/fonts/Poppins/Poppins-Bold.ttf b/resources/fonts/Poppins/Poppins-Bold.ttf new file mode 100644 index 0000000..b94d47f Binary files /dev/null and b/resources/fonts/Poppins/Poppins-Bold.ttf differ diff --git a/resources/fonts/Poppins/Poppins-BoldItalic.ttf b/resources/fonts/Poppins/Poppins-BoldItalic.ttf new file mode 100644 index 0000000..e2e6445 Binary files /dev/null and b/resources/fonts/Poppins/Poppins-BoldItalic.ttf differ diff --git a/resources/fonts/Poppins/Poppins-ExtraBold.ttf b/resources/fonts/Poppins/Poppins-ExtraBold.ttf new file mode 100644 index 0000000..8f008c3 Binary files /dev/null and b/resources/fonts/Poppins/Poppins-ExtraBold.ttf differ diff --git a/resources/fonts/Poppins/Poppins-ExtraBoldItalic.ttf b/resources/fonts/Poppins/Poppins-ExtraBoldItalic.ttf new file mode 100644 index 0000000..b2a9bf5 Binary files /dev/null and b/resources/fonts/Poppins/Poppins-ExtraBoldItalic.ttf differ diff --git a/resources/fonts/Poppins/Poppins-ExtraLight.ttf b/resources/fonts/Poppins/Poppins-ExtraLight.ttf new file mode 100644 index 0000000..ee62382 Binary files /dev/null and b/resources/fonts/Poppins/Poppins-ExtraLight.ttf differ diff --git a/resources/fonts/Poppins/Poppins-ExtraLightItalic.ttf b/resources/fonts/Poppins/Poppins-ExtraLightItalic.ttf new file mode 100644 index 0000000..e392492 Binary files /dev/null and b/resources/fonts/Poppins/Poppins-ExtraLightItalic.ttf differ diff --git a/resources/fonts/Poppins/Poppins-Italic.ttf b/resources/fonts/Poppins/Poppins-Italic.ttf new file mode 100644 index 0000000..4620399 Binary files /dev/null and b/resources/fonts/Poppins/Poppins-Italic.ttf differ diff --git a/resources/fonts/Poppins/Poppins-Light.ttf b/resources/fonts/Poppins/Poppins-Light.ttf new file mode 100644 index 0000000..2ab0221 Binary files /dev/null and b/resources/fonts/Poppins/Poppins-Light.ttf differ diff --git a/resources/fonts/Poppins/Poppins-LightItalic.ttf b/resources/fonts/Poppins/Poppins-LightItalic.ttf new file mode 100644 index 0000000..6f9279d Binary files /dev/null and b/resources/fonts/Poppins/Poppins-LightItalic.ttf differ diff --git a/resources/fonts/Poppins/Poppins-Medium.ttf b/resources/fonts/Poppins/Poppins-Medium.ttf new file mode 100644 index 0000000..e90e87e Binary files /dev/null and b/resources/fonts/Poppins/Poppins-Medium.ttf differ diff --git a/resources/fonts/Poppins/Poppins-MediumItalic.ttf b/resources/fonts/Poppins/Poppins-MediumItalic.ttf new file mode 100644 index 0000000..d8a251c Binary files /dev/null and b/resources/fonts/Poppins/Poppins-MediumItalic.ttf differ diff --git a/resources/fonts/Poppins/Poppins-Regular.ttf b/resources/fonts/Poppins/Poppins-Regular.ttf new file mode 100644 index 0000000..be06e7f Binary files /dev/null and b/resources/fonts/Poppins/Poppins-Regular.ttf differ diff --git a/resources/fonts/Poppins/Poppins-SemiBold.ttf b/resources/fonts/Poppins/Poppins-SemiBold.ttf new file mode 100644 index 0000000..dabf7c2 Binary files /dev/null and b/resources/fonts/Poppins/Poppins-SemiBold.ttf differ diff --git a/resources/fonts/Poppins/Poppins-SemiBoldItalic.ttf b/resources/fonts/Poppins/Poppins-SemiBoldItalic.ttf new file mode 100644 index 0000000..29d5f74 Binary files /dev/null and b/resources/fonts/Poppins/Poppins-SemiBoldItalic.ttf differ diff --git a/resources/fonts/Poppins/Poppins-Thin.ttf b/resources/fonts/Poppins/Poppins-Thin.ttf new file mode 100644 index 0000000..f5c0fdd Binary files /dev/null and b/resources/fonts/Poppins/Poppins-Thin.ttf differ diff --git a/resources/fonts/Poppins/Poppins-ThinItalic.ttf b/resources/fonts/Poppins/Poppins-ThinItalic.ttf new file mode 100644 index 0000000..b910089 Binary files /dev/null and b/resources/fonts/Poppins/Poppins-ThinItalic.ttf differ diff --git a/resources/fonts/Roboto_Mono/LICENSE.txt b/resources/fonts/Roboto_Mono/LICENSE.txt new file mode 100644 index 0000000..75b5248 --- /dev/null +++ b/resources/fonts/Roboto_Mono/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/resources/fonts/Roboto_Mono/README.txt b/resources/fonts/Roboto_Mono/README.txt new file mode 100644 index 0000000..b34e21b --- /dev/null +++ b/resources/fonts/Roboto_Mono/README.txt @@ -0,0 +1,77 @@ +Roboto Mono Variable Font +========================= + +This download contains Roboto Mono as both variable fonts and static fonts. + +Roboto Mono is a variable font with this axis: + wght + +This means all the styles are contained in these files: + RobotoMono-VariableFont_wght.ttf + RobotoMono-Italic-VariableFont_wght.ttf + +If your app fully supports variable fonts, you can now pick intermediate styles +that aren’t available as static fonts. Not all apps support variable fonts, and +in those cases you can use the static font files for Roboto Mono: + static/RobotoMono-Thin.ttf + static/RobotoMono-ExtraLight.ttf + static/RobotoMono-Light.ttf + static/RobotoMono-Regular.ttf + static/RobotoMono-Medium.ttf + static/RobotoMono-SemiBold.ttf + static/RobotoMono-Bold.ttf + static/RobotoMono-ThinItalic.ttf + static/RobotoMono-ExtraLightItalic.ttf + static/RobotoMono-LightItalic.ttf + static/RobotoMono-Italic.ttf + static/RobotoMono-MediumItalic.ttf + static/RobotoMono-SemiBoldItalic.ttf + static/RobotoMono-BoldItalic.ttf + +Get started +----------- + +1. Install the font files you want to use + +2. Use your app's font picker to view the font family and all the +available styles + +Learn more about variable fonts +------------------------------- + + https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts + https://variablefonts.typenetwork.com + https://medium.com/variable-fonts + +In desktop apps + + https://theblog.adobe.com/can-variable-fonts-illustrator-cc + https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts + +Online + + https://developers.google.com/fonts/docs/getting_started + https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide + https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts + +Installing fonts + + MacOS: https://support.apple.com/en-us/HT201749 + Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux + Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows + +Android Apps + + https://developers.google.com/fonts/docs/android + https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts + +License +------- +Please read the full license text (LICENSE.txt) to understand the permissions, +restrictions and requirements for usage, redistribution, and modification. + +You can use them freely in your products & projects - print or digital, +commercial or otherwise. However, you can't sell the fonts on their own. + +This isn't legal advice, please consider consulting a lawyer and see the full +license for all details. diff --git a/resources/fonts/Roboto_Mono/RobotoMono-Italic-VariableFont_wght.ttf b/resources/fonts/Roboto_Mono/RobotoMono-Italic-VariableFont_wght.ttf new file mode 100644 index 0000000..d30055a Binary files /dev/null and b/resources/fonts/Roboto_Mono/RobotoMono-Italic-VariableFont_wght.ttf differ diff --git a/resources/fonts/Roboto_Mono/RobotoMono-VariableFont_wght.ttf b/resources/fonts/Roboto_Mono/RobotoMono-VariableFont_wght.ttf new file mode 100644 index 0000000..d2b4746 Binary files /dev/null and b/resources/fonts/Roboto_Mono/RobotoMono-VariableFont_wght.ttf differ diff --git a/resources/fonts/Roboto_Mono/static/RobotoMono-Bold.ttf b/resources/fonts/Roboto_Mono/static/RobotoMono-Bold.ttf new file mode 100644 index 0000000..900fce6 Binary files /dev/null and b/resources/fonts/Roboto_Mono/static/RobotoMono-Bold.ttf differ diff --git a/resources/fonts/Roboto_Mono/static/RobotoMono-BoldItalic.ttf b/resources/fonts/Roboto_Mono/static/RobotoMono-BoldItalic.ttf new file mode 100644 index 0000000..4bfe29a Binary files /dev/null and b/resources/fonts/Roboto_Mono/static/RobotoMono-BoldItalic.ttf differ diff --git a/resources/fonts/Roboto_Mono/static/RobotoMono-ExtraLight.ttf b/resources/fonts/Roboto_Mono/static/RobotoMono-ExtraLight.ttf new file mode 100644 index 0000000..d535884 Binary files /dev/null and b/resources/fonts/Roboto_Mono/static/RobotoMono-ExtraLight.ttf differ diff --git a/resources/fonts/Roboto_Mono/static/RobotoMono-ExtraLightItalic.ttf b/resources/fonts/Roboto_Mono/static/RobotoMono-ExtraLightItalic.ttf new file mode 100644 index 0000000..b28960a Binary files /dev/null and b/resources/fonts/Roboto_Mono/static/RobotoMono-ExtraLightItalic.ttf differ diff --git a/resources/fonts/Roboto_Mono/static/RobotoMono-Italic.ttf b/resources/fonts/Roboto_Mono/static/RobotoMono-Italic.ttf new file mode 100644 index 0000000..4ee4dc4 Binary files /dev/null and b/resources/fonts/Roboto_Mono/static/RobotoMono-Italic.ttf differ diff --git a/resources/fonts/Roboto_Mono/static/RobotoMono-Light.ttf b/resources/fonts/Roboto_Mono/static/RobotoMono-Light.ttf new file mode 100644 index 0000000..276af4c Binary files /dev/null and b/resources/fonts/Roboto_Mono/static/RobotoMono-Light.ttf differ diff --git a/resources/fonts/Roboto_Mono/static/RobotoMono-LightItalic.ttf b/resources/fonts/Roboto_Mono/static/RobotoMono-LightItalic.ttf new file mode 100644 index 0000000..a2801c2 Binary files /dev/null and b/resources/fonts/Roboto_Mono/static/RobotoMono-LightItalic.ttf differ diff --git a/resources/fonts/Roboto_Mono/static/RobotoMono-Medium.ttf b/resources/fonts/Roboto_Mono/static/RobotoMono-Medium.ttf new file mode 100644 index 0000000..8461be7 Binary files /dev/null and b/resources/fonts/Roboto_Mono/static/RobotoMono-Medium.ttf differ diff --git a/resources/fonts/Roboto_Mono/static/RobotoMono-MediumItalic.ttf b/resources/fonts/Roboto_Mono/static/RobotoMono-MediumItalic.ttf new file mode 100644 index 0000000..a3bfaa1 Binary files /dev/null and b/resources/fonts/Roboto_Mono/static/RobotoMono-MediumItalic.ttf differ diff --git a/resources/fonts/Roboto_Mono/static/RobotoMono-Regular.ttf b/resources/fonts/Roboto_Mono/static/RobotoMono-Regular.ttf new file mode 100644 index 0000000..7c4ce36 Binary files /dev/null and b/resources/fonts/Roboto_Mono/static/RobotoMono-Regular.ttf differ diff --git a/resources/fonts/Roboto_Mono/static/RobotoMono-SemiBold.ttf b/resources/fonts/Roboto_Mono/static/RobotoMono-SemiBold.ttf new file mode 100644 index 0000000..15ee6c6 Binary files /dev/null and b/resources/fonts/Roboto_Mono/static/RobotoMono-SemiBold.ttf differ diff --git a/resources/fonts/Roboto_Mono/static/RobotoMono-SemiBoldItalic.ttf b/resources/fonts/Roboto_Mono/static/RobotoMono-SemiBoldItalic.ttf new file mode 100644 index 0000000..8e21497 Binary files /dev/null and b/resources/fonts/Roboto_Mono/static/RobotoMono-SemiBoldItalic.ttf differ diff --git a/resources/fonts/Roboto_Mono/static/RobotoMono-Thin.ttf b/resources/fonts/Roboto_Mono/static/RobotoMono-Thin.ttf new file mode 100644 index 0000000..ee8a3fd Binary files /dev/null and b/resources/fonts/Roboto_Mono/static/RobotoMono-Thin.ttf differ diff --git a/resources/fonts/Roboto_Mono/static/RobotoMono-ThinItalic.ttf b/resources/fonts/Roboto_Mono/static/RobotoMono-ThinItalic.ttf new file mode 100644 index 0000000..40b01e4 Binary files /dev/null and b/resources/fonts/Roboto_Mono/static/RobotoMono-ThinItalic.ttf differ diff --git a/resources/icons/Slider.png b/resources/icons/Slider.png new file mode 100644 index 0000000..632c130 Binary files /dev/null and b/resources/icons/Slider.png differ diff --git a/resources/icons/Slider.png.import b/resources/icons/Slider.png.import new file mode 100644 index 0000000..e8f6c55 --- /dev/null +++ b/resources/icons/Slider.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/Slider.png-109ea8c44a3ca59e69d802d1496eefb0.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resources/icons/Slider.png" +dest_files=[ "res://.import/Slider.png-109ea8c44a3ca59e69d802d1496eefb0.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/resources/icons/bucket_fill.png b/resources/icons/bucket_fill.png new file mode 100644 index 0000000..bc437b8 Binary files /dev/null and b/resources/icons/bucket_fill.png differ diff --git a/resources/icons/bucket_fill.png.import b/resources/icons/bucket_fill.png.import new file mode 100644 index 0000000..5758cc0 --- /dev/null +++ b/resources/icons/bucket_fill.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/bucket_fill.png-0f5d9bb6b30916c981158e885ca08350.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resources/icons/bucket_fill.png" +dest_files=[ "res://.import/bucket_fill.png-0f5d9bb6b30916c981158e885ca08350.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/resources/icons/color.png.import b/resources/icons/color.png.import new file mode 100644 index 0000000..da3398b --- /dev/null +++ b/resources/icons/color.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/color.png-566b2c6091e37e225875f3d7d7022594.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://toolboxes/icons/color.png" +dest_files=[ "res://.import/color.png-566b2c6091e37e225875f3d7d7022594.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/resources/icons/eraser.png b/resources/icons/eraser.png new file mode 100644 index 0000000..bd44e2f Binary files /dev/null and b/resources/icons/eraser.png differ diff --git a/resources/icons/eraser.png.import b/resources/icons/eraser.png.import new file mode 100644 index 0000000..90386f8 --- /dev/null +++ b/resources/icons/eraser.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/eraser.png-5de4c94f24172b105fb174f48a479780.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resources/icons/eraser.png" +dest_files=[ "res://.import/eraser.png-5de4c94f24172b105fb174f48a479780.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/resources/icons/error.png b/resources/icons/error.png new file mode 100644 index 0000000..88a3a45 Binary files /dev/null and b/resources/icons/error.png differ diff --git a/resources/icons/error.png.import b/resources/icons/error.png.import new file mode 100644 index 0000000..8b8eb6e --- /dev/null +++ b/resources/icons/error.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/error.png-07e387354ffd8c62fc7ddee7d66ab516.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resources/icons/error.png" +dest_files=[ "res://.import/error.png-07e387354ffd8c62fc7ddee7d66ab516.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/resources/icons/grid.png b/resources/icons/grid.png new file mode 100644 index 0000000..0633aa5 Binary files /dev/null and b/resources/icons/grid.png differ diff --git a/resources/icons/grid.png.import b/resources/icons/grid.png.import new file mode 100644 index 0000000..32545ef --- /dev/null +++ b/resources/icons/grid.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/grid.png-8a100c4c829c7997a9b346dfa394adcb.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resources/icons/grid.png" +dest_files=[ "res://.import/grid.png-8a100c4c829c7997a9b346dfa394adcb.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/resources/icons/ok.png b/resources/icons/ok.png new file mode 100644 index 0000000..0bd68bd Binary files /dev/null and b/resources/icons/ok.png differ diff --git a/brush.png.import b/resources/icons/ok.png.import similarity index 71% rename from brush.png.import rename to resources/icons/ok.png.import index 3d0594a..1c84a41 100644 --- a/brush.png.import +++ b/resources/icons/ok.png.import @@ -2,15 +2,15 @@ importer="texture" type="StreamTexture" -path="res://.import/brush.png-a97626a40f24e0d8d908084fdef855df.stex" +path="res://.import/ok.png-3f7b80b38c7f2860dbcf10e7a8a8f25a.stex" metadata={ "vram_texture": false } [deps] -source_file="res://brush.png" -dest_files=[ "res://.import/brush.png-a97626a40f24e0d8d908084fdef855df.stex" ] +source_file="res://resources/icons/ok.png" +dest_files=[ "res://.import/ok.png-3f7b80b38c7f2860dbcf10e7a8a8f25a.stex" ] [params] diff --git a/resources/icons/pencil.png b/resources/icons/pencil.png new file mode 100644 index 0000000..50d34eb Binary files /dev/null and b/resources/icons/pencil.png differ diff --git a/resources/icons/pencil.png.import b/resources/icons/pencil.png.import new file mode 100644 index 0000000..0d3f331 --- /dev/null +++ b/resources/icons/pencil.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/pencil.png-a0118b6f3fd22cde1aeeb3369906995e.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resources/icons/pencil.png" +dest_files=[ "res://.import/pencil.png-a0118b6f3fd22cde1aeeb3369906995e.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/resources/icons/redo.png b/resources/icons/redo.png new file mode 100644 index 0000000..63e2c04 Binary files /dev/null and b/resources/icons/redo.png differ diff --git a/resources/icons/redo.png.import b/resources/icons/redo.png.import new file mode 100644 index 0000000..604c19a --- /dev/null +++ b/resources/icons/redo.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/redo.png-f66fffe2e98e248034df7f4541aa0a8c.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resources/icons/redo.png" +dest_files=[ "res://.import/redo.png-f66fffe2e98e248034df7f4541aa0a8c.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/resources/icons/undo.png b/resources/icons/undo.png new file mode 100644 index 0000000..0a5ade7 Binary files /dev/null and b/resources/icons/undo.png differ diff --git a/resources/icons/undo.png.import b/resources/icons/undo.png.import new file mode 100644 index 0000000..cc1c1c4 --- /dev/null +++ b/resources/icons/undo.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/undo.png-e2e6f28da41fee8b5f078ed505310768.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resources/icons/undo.png" +dest_files=[ "res://.import/undo.png-e2e6f28da41fee8b5f078ed505310768.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/resources/icons/warning.png b/resources/icons/warning.png new file mode 100644 index 0000000..fcf1195 Binary files /dev/null and b/resources/icons/warning.png differ diff --git a/resources/icons/warning.png.import b/resources/icons/warning.png.import new file mode 100644 index 0000000..86af845 --- /dev/null +++ b/resources/icons/warning.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/warning.png-bffe7a8685dd111f00d45c218a1c21b8.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resources/icons/warning.png" +dest_files=[ "res://.import/warning.png-bffe7a8685dd111f00d45c218a1c21b8.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/resources/icons/wrench.png b/resources/icons/wrench.png new file mode 100644 index 0000000..353b373 Binary files /dev/null and b/resources/icons/wrench.png differ diff --git a/resources/icons/wrench.png.import b/resources/icons/wrench.png.import new file mode 100644 index 0000000..0f688a7 --- /dev/null +++ b/resources/icons/wrench.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/wrench.png-c6757b39db9dd0c8a3d9f31096b688f8.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resources/icons/wrench.png" +dest_files=[ "res://.import/wrench.png-c6757b39db9dd0c8a3d9f31096b688f8.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/resources/icons/zoom_minus.png b/resources/icons/zoom_minus.png new file mode 100755 index 0000000..8637403 Binary files /dev/null and b/resources/icons/zoom_minus.png differ diff --git a/resources/icons/zoom_minus.png.import b/resources/icons/zoom_minus.png.import new file mode 100644 index 0000000..0b89ffc --- /dev/null +++ b/resources/icons/zoom_minus.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/zoom_minus.png-0c81943e92110759deed7ace3237885a.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resources/icons/zoom_minus.png" +dest_files=[ "res://.import/zoom_minus.png-0c81943e92110759deed7ace3237885a.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/resources/icons/zoom_plus.png b/resources/icons/zoom_plus.png new file mode 100755 index 0000000..edf83f5 Binary files /dev/null and b/resources/icons/zoom_plus.png differ diff --git a/resources/icons/zoom_plus.png.import b/resources/icons/zoom_plus.png.import new file mode 100644 index 0000000..3ec91f6 --- /dev/null +++ b/resources/icons/zoom_plus.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/zoom_plus.png-0eb6311cc4838792c80f213520cd7b86.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resources/icons/zoom_plus.png" +dest_files=[ "res://.import/zoom_plus.png-0eb6311cc4838792c80f213520cd7b86.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/styles/00-TheNothingness.json b/styles/00-TheNothingness.json new file mode 100755 index 0000000..92181d9 --- /dev/null +++ b/styles/00-TheNothingness.json @@ -0,0 +1,9 @@ +{ + "StyleData": { + "Author": "Tomás Espejo Gómez", + "Name": "The Nothingness" + }, + "Configuration": { + "TileSize": 16 + } +} \ No newline at end of file diff --git a/styles/01-AColor.json b/styles/01-AColor.json new file mode 100755 index 0000000..44dbbbb --- /dev/null +++ b/styles/01-AColor.json @@ -0,0 +1,10 @@ +{ + "StyleData": { + "Author": "Tomás Espejo Gómez", + "Name": "A Color" + }, + "Configuration": { + "TileSize": 16, + "Background": [0, 120, 248, 255] + } +} \ No newline at end of file diff --git a/styles/02-BasicExample.json b/styles/02-BasicExample.json new file mode 100755 index 0000000..6a01fca --- /dev/null +++ b/styles/02-BasicExample.json @@ -0,0 +1,14 @@ +{ + "StyleData": { + "Author": "Tomás Espejo Gómez", + "Name": "Basic Example" + }, + "Configuration": { + "TileSize": 16, + "Background": "Images/Water.png", + "Tile": { + "Name": "Land", + "Image": "Images/Land.png" + } + } +} \ No newline at end of file diff --git a/styles/03-TileSet.json b/styles/03-TileSet.json new file mode 100755 index 0000000..1d5bd4f --- /dev/null +++ b/styles/03-TileSet.json @@ -0,0 +1,28 @@ +{ + "StyleData": { + "Author": "Tomás Espejo Gómez", + "Name": "TileSet" + }, + "Configuration": { + "TileSize": 16, + "Background": "Images/Water.png", + "TileSet": [ + { + "Name": "Land", + "Image": "Images/Land.png" + }, + { + "Name": "Sand", + "Image": "Images/Sand.png" + }, + { + "Name": "Tree", + "Image": "Images/Tree.png" + }, + { + "Name": "Cactus", + "Image": "Images/Cactus.png" + } + ] + } +} \ No newline at end of file diff --git a/styles/04-Layers.json b/styles/04-Layers.json new file mode 100755 index 0000000..0cdd770 --- /dev/null +++ b/styles/04-Layers.json @@ -0,0 +1,32 @@ +{ + "StyleData": { + "Author": "Tomás Espejo Gómez", + "Name": "Layers" + }, + "Configuration": { + "TileSize": 16, + "Background": "Images/Water.png", + "TileSet": [ + { + "Name": "Land", + "Image": "Images/Land.png", + "Layer": "Land" + }, + { + "Name": "Sand", + "Image": "Images/Sand.png", + "Layer": "Land" + }, + { + "Name": "Tree", + "Image": "Images/Tree.png", + "Layer": "Decoration" + }, + { + "Name": "Cactus", + "Image": "Images/Cactus.png", + "Layer": "Decoration" + } + ] + } +} \ No newline at end of file diff --git a/styles/05-Variations.json b/styles/05-Variations.json new file mode 100755 index 0000000..55af313 --- /dev/null +++ b/styles/05-Variations.json @@ -0,0 +1,114 @@ +{ + "StyleData": { + "Author": "Tomás Espejo Gómez", + "Name": "Variations" + }, + "Configuration": { + "TileSize": 16, + "Background": "Images/Water.png", + "TileSet": [ + { + "Name": "Land", + "Image": "Images/Land.png", + "Layer": "Land", + "Variations": [ + { + "Image": "Images/Land-NE.png", + "Connection": ["North", "East"] + }, + { + "Image": "Images/Land-NW.png", + "Connection": ["North", "West"] + }, + { + "Image": "Images/Land-SE.png", + "Connection": ["South", "East"] + }, + { + "Image": "Images/Land-SW.png", + "Connection": ["South", "West"] + } + ] + }, + { + "Name": "Sand", + "Image": "Images/Sand.png", + "Layer": "Land", + "Variations": [ + { + "Image": "Images/Sand-NE.png", + "Connection": ["North", "East"] + }, + { + "Image": "Images/Sand-NW.png", + "Connection": ["North", "West"] + }, + { + "Image": "Images/Sand-SE.png", + "Connection": ["South", "East"] + }, + { + "Image": "Images/Sand-SW.png", + "Connection": ["South", "West"] + } + ] + }, + { + "Name": "BlackPath", + "Image": "Images/BlackPath.png", + "Layer": "Path", + "Variations": [ + { + "Image": "Images/BlackPath-H.png", + "Connections": [ + ["East"], + ["West"], + ["East", "West"] + ] + }, + { + "Image": "Images/BlackPath-V.png", + "Connections": [ + ["North"], + ["South"], + ["North", "South"] + ] + } + ] + }, + { + "Name": "WhitePath", + "Image": "Images/WhitePath.png", + "Layer": "Path", + "Variations": [ + { + "Image": "Images/WhitePath-H.png", + "Connections": [ + ["East"], + ["West"], + ["East", "West"] + ] + }, + { + "Image": "Images/WhitePath-V.png", + "Connections": [ + ["North"], + ["South"], + ["North", "South"] + ] + } + ] + }, + { + "Name": "Tree", + "Image": "Images/Tree.png", + "Layer": "Decoration" + }, + { + "Name": "Cactus", + "Image": "Images/Cactus.png", + "Layer": "Decoration" + } + ] + } +} \ No newline at end of file diff --git a/styles/06-ConnectedGroups.json b/styles/06-ConnectedGroups.json new file mode 100755 index 0000000..cd59f11 --- /dev/null +++ b/styles/06-ConnectedGroups.json @@ -0,0 +1,118 @@ +{ + "StyleData": { + "Author": "Tomás Espejo Gómez", + "Name": "Connected Groups" + }, + "Configuration": { + "TileSize": 16, + "Background": "Images/Water.png", + "TileSet": [ + { + "Name": "Land", + "Image": "Images/Land.png", + "Layer": "Land", + "ConnectedGroup": "Land", + "Variations": [ + { + "Image": "Images/Land-NE.png", + "Connection": ["North", "East"] + }, + { + "Image": "Images/Land-NW.png", + "Connection": ["North", "West"] + }, + { + "Image": "Images/Land-SE.png", + "Connection": ["South", "East"] + }, + { + "Image": "Images/Land-SW.png", + "Connection": ["South", "West"] + } + ] + }, + { + "Name": "Sand", + "Image": "Images/Sand.png", + "Layer": "Land", + "ConnectedGroup": "Land", + "Variations": [ + { + "Image": "Images/Sand-NE.png", + "Connection": ["North", "East"] + }, + { + "Image": "Images/Sand-NW.png", + "Connection": ["North", "West"] + }, + { + "Image": "Images/Sand-SE.png", + "Connection": ["South", "East"] + }, + { + "Image": "Images/Sand-SW.png", + "Connection": ["South", "West"] + } + ] + }, + { + "Name": "BlackPath", + "Image": "Images/BlackPath.png", + "Layer": "Path", + "ConnectedGroup": "Path", + "Variations": [ + { + "Image": "Images/BlackPath-H.png", + "Connections": [ + ["East"], + ["West"], + ["East", "West"] + ] + }, + { + "Image": "Images/BlackPath-V.png", + "Connections": [ + ["North"], + ["South"], + ["North", "South"] + ] + } + ] + }, + { + "Name": "WhitePath", + "Image": "Images/WhitePath.png", + "Layer": "Path", + "ConnectedGroup": "Path", + "Variations": [ + { + "Image": "Images/WhitePath-H.png", + "Connections": [ + ["East"], + ["West"], + ["East", "West"] + ] + }, + { + "Image": "Images/WhitePath-V.png", + "Connections": [ + ["North"], + ["South"], + ["North", "South"] + ] + } + ] + }, + { + "Name": "Tree", + "Image": "Images/Tree.png", + "Layer": "Decoration" + }, + { + "Name": "Cactus", + "Image": "Images/Cactus.png", + "Layer": "Decoration" + } + ] + } +} \ No newline at end of file diff --git a/styles/07-AvancedVariations.json b/styles/07-AvancedVariations.json new file mode 100755 index 0000000..0c46c2a --- /dev/null +++ b/styles/07-AvancedVariations.json @@ -0,0 +1,206 @@ +{ + "StyleData": { + "Author": "Tomás Espejo Gómez", + "Name": "Avanced Variations" + }, + "Configuration": { + "TileSize": 16, + "Background": "Images/Water.png", + "TileSet": [ + { + "Name": "Land", + "Image": "Images/Land.png", + "Layer": "Land", + "ConnectedGroup": "Land", + "Variations": [ + { + "Image": "Images/Land-NE.png", + "Connection": ["North", "NorthEast", "East"] + }, + { + "Image": "Images/Land-NW.png", + "Connection": ["North", "NorthWest", "West"] + }, + { + "Image": "Images/Land-SE.png", + "Connection": ["South", "SouthEast", "East"] + }, + { + "Image": "Images/Land-SW.png", + "Connection": ["South", "SouthWest", "West"] + } + ] + }, + { + "Name": "Sand", + "Image": "Images/Sand.png", + "Layer": "Land", + "ConnectedGroup": "Land", + "Variations": [ + { + "Image": "Images/Sand-NE.png", + "Connection": ["North", "NorthEast", "East"] + }, + { + "Image": "Images/Sand-NW.png", + "Connection": ["North", "NorthWest", "West"] + }, + { + "Image": "Images/Sand-SE.png", + "Connection": ["South", "SouthEast", "East"] + }, + { + "Image": "Images/Sand-SW.png", + "Connection": ["South", "SouthWest", "West"] + } + ] + }, + { + "Name": "BlackPath", + "Image": "Images/BlackPath-0.png", + "Layer": "Path", + "ConnectedGroup": "Path", + "Variations": [ + { + "Image": "Images/BlackPath-N.png", + "Connection": ["North"] + }, + { + "Image": "Images/BlackPath-E.png", + "Connection": ["East"] + }, + { + "Image": "Images/BlackPath-S.png", + "Connection": ["South"] + }, + { + "Image": "Images/BlackPath-W.png", + "Connection": ["West"] + }, + { + "Image": "Images/BlackPath-NE.png", + "Connection": ["North", "East"] + }, + { + "Image": "Images/BlackPath-NW.png", + "Connection": ["North", "West"] + }, + { + "Image": "Images/BlackPath-SE.png", + "Connection": ["South", "East"] + }, + { + "Image": "Images/BlackPath-SW.png", + "Connection": ["South", "West"] + }, + { + "Image": "Images/BlackPath-NES.png", + "Connection": ["North", "East", "South"] + }, + { + "Image": "Images/BlackPath-ESW.png", + "Connection": ["East", "South", "West"] + }, + { + "Image": "Images/BlackPath-SWN.png", + "Connection": ["South", "West", "North"] + }, + { + "Image": "Images/BlackPath-WNE.png", + "Connection": ["West", "North", "East"] + }, + { + "Image": "Images/BlackPath-NESW.png", + "Connection": ["North", "East", "South", "West"] + }, + { + "Image": "Images/BlackPath-V.png", + "Connection": ["North", "South"] + }, + { + "Image": "Images/BlackPath-H.png", + "Connection": ["East", "West"] + } + ] + }, + { + "Name": "WhitePath", + "Image": "Images/WhitePath-0.png", + "Layer": "Path", + "ConnectedGroup": "Path", + "Variations": [ + { + "Image": "Images/WhitePath-N.png", + "Connection": ["North"] + }, + { + "Image": "Images/WhitePath-E.png", + "Connection": ["East"] + }, + { + "Image": "Images/WhitePath-S.png", + "Connection": ["South"] + }, + { + "Image": "Images/WhitePath-W.png", + "Connection": ["West"] + }, + { + "Image": "Images/WhitePath-NE.png", + "Connection": ["North", "East"] + }, + { + "Image": "Images/WhitePath-NW.png", + "Connection": ["North", "West"] + }, + { + "Image": "Images/WhitePath-SE.png", + "Connection": ["South", "East"] + }, + { + "Image": "Images/WhitePath-SW.png", + "Connection": ["South", "West"] + }, + { + "Image": "Images/WhitePath-NES.png", + "Connection": ["North", "East", "South"] + }, + { + "Image": "Images/WhitePath-ESW.png", + "Connection": ["East", "South", "West"] + }, + { + "Image": "Images/WhitePath-SWN.png", + "Connection": ["South", "West", "North"] + }, + { + "Image": "Images/WhitePath-WNE.png", + "Connection": ["West", "North", "East"] + }, + { + "Image": "Images/WhitePath-NESW.png", + "Connection": ["North", "East", "South", "West"] + }, + { + "Image": "Images/WhitePath-V.png", + "Connection": ["North", "South"] + }, + { + "Image": "Images/WhitePath-H.png", + "Connection": ["East", "West"] + } + ] + }, + { + "Name": "Tree", + "Image": "Images/Tree.png", + "Layer": "Decoration" + }, + { + "Name": "Cactus", + "Image": "Images/Cactus.png", + "Layer": "Decoration" + } + ] + } +} \ No newline at end of file diff --git a/styles/08-ExtraTools.json b/styles/08-ExtraTools.json new file mode 100755 index 0000000..89b340d --- /dev/null +++ b/styles/08-ExtraTools.json @@ -0,0 +1,208 @@ +{ + "StyleData": { + "Author": "Tomás Espejo Gómez", + "Name": "Extra Tools" + }, + "Configuration": { + "TileSize": 16, + "Background": "Images/Water.png", + "TileSet": [ + { + "Name": "Land", + "Image": "Images/Land.png", + "Layer": "Land", + "ExtraTools": ["Wrench", "BukectFill"], + "ConnectedGroup": "Land", + "Variations": [ + { + "Image": "Images/Land-NE.png", + "Connection": ["North", "East"] + }, + { + "Image": "Images/Land-NW.png", + "Connection": ["North", "West"] + }, + { + "Image": "Images/Land-SE.png", + "Connection": ["South", "East"] + }, + { + "Image": "Images/Land-SW.png", + "Connection": ["South", "West"] + } + ] + }, + { + "Name": "Sand", + "Image": "Images/Sand.png", + "Layer": "Land", + "ExtraTools": ["Wrench", "BukectFill"], + "ConnectedGroup": "Land", + "Variations": [ + { + "Image": "Images/Sand-NE.png", + "Connection": ["North", "East"] + }, + { + "Image": "Images/Sand-NW.png", + "Connection": ["North", "West"] + }, + { + "Image": "Images/Sand-SE.png", + "Connection": ["South", "East"] + }, + { + "Image": "Images/Sand-SW.png", + "Connection": ["South", "West"] + } + ] + }, + { + "Name": "BlackPath", + "Image": "Images/BlackPath-0.png", + "Layer": "Path", + "ConnectedGroup": "Path", + "Variations": [ + { + "Image": "Images/BlackPath-N.png", + "Connection": ["North"] + }, + { + "Image": "Images/BlackPath-E.png", + "Connection": ["East"] + }, + { + "Image": "Images/BlackPath-S.png", + "Connection": ["South"] + }, + { + "Image": "Images/BlackPath-W.png", + "Connection": ["West"] + }, + { + "Image": "Images/BlackPath-NE.png", + "Connection": ["North", "East"] + }, + { + "Image": "Images/BlackPath-NW.png", + "Connection": ["North", "West"] + }, + { + "Image": "Images/BlackPath-SE.png", + "Connection": ["South", "East"] + }, + { + "Image": "Images/BlackPath-SW.png", + "Connection": ["South", "West"] + }, + { + "Image": "Images/BlackPath-NES.png", + "Connection": ["North", "East", "South"] + }, + { + "Image": "Images/BlackPath-ESW.png", + "Connection": ["East", "South", "West"] + }, + { + "Image": "Images/BlackPath-SWN.png", + "Connection": ["South", "West", "North"] + }, + { + "Image": "Images/BlackPath-WNE.png", + "Connection": ["West", "North", "East"] + }, + { + "Image": "Images/BlackPath-NESW.png", + "Connection": ["North", "East", "South", "West"] + }, + { + "Image": "Images/BlackPath-V.png", + "Connection": ["North", "South"] + }, + { + "Image": "Images/BlackPath-H.png", + "Connection": ["East", "West"] + } + ] + }, + { + "Name": "WhitePath", + "Image": "Images/WhitePath-0.png", + "Layer": "Path", + "ConnectedGroup": "Path", + "Variations": [ + { + "Image": "Images/WhitePath-N.png", + "Connection": ["North"] + }, + { + "Image": "Images/WhitePath-E.png", + "Connection": ["East"] + }, + { + "Image": "Images/WhitePath-S.png", + "Connection": ["South"] + }, + { + "Image": "Images/WhitePath-W.png", + "Connection": ["West"] + }, + { + "Image": "Images/WhitePath-NE.png", + "Connection": ["North", "East"] + }, + { + "Image": "Images/WhitePath-NW.png", + "Connection": ["North", "West"] + }, + { + "Image": "Images/WhitePath-SE.png", + "Connection": ["South", "East"] + }, + { + "Image": "Images/WhitePath-SW.png", + "Connection": ["South", "West"] + }, + { + "Image": "Images/WhitePath-NES.png", + "Connection": ["North", "East", "South"] + }, + { + "Image": "Images/WhitePath-ESW.png", + "Connection": ["East", "South", "West"] + }, + { + "Image": "Images/WhitePath-SWN.png", + "Connection": ["South", "West", "North"] + }, + { + "Image": "Images/WhitePath-WNE.png", + "Connection": ["West", "North", "East"] + }, + { + "Image": "Images/WhitePath-NESW.png", + "Connection": ["North", "East", "South", "West"] + }, + { + "Image": "Images/WhitePath-V.png", + "Connection": ["North", "South"] + }, + { + "Image": "Images/WhitePath-H.png", + "Connection": ["East", "West"] + } + ] + }, + { + "Name": "Tree", + "Image": "Images/Tree.png", + "Layer": "Decoration" + }, + { + "Name": "Cactus", + "Image": "Images/Cactus.png", + "Layer": "Decoration" + } + ] + } +} \ No newline at end of file diff --git a/styles/Images/BlackPath-0.png b/styles/Images/BlackPath-0.png new file mode 100755 index 0000000..f1d4c1d Binary files /dev/null and b/styles/Images/BlackPath-0.png differ diff --git a/styles/Images/BlackPath-E.png b/styles/Images/BlackPath-E.png new file mode 100755 index 0000000..3501fe3 Binary files /dev/null and b/styles/Images/BlackPath-E.png differ diff --git a/styles/Images/BlackPath-ESW.png b/styles/Images/BlackPath-ESW.png new file mode 100755 index 0000000..e659bc1 Binary files /dev/null and b/styles/Images/BlackPath-ESW.png differ diff --git a/styles/Images/BlackPath-H.png b/styles/Images/BlackPath-H.png new file mode 100755 index 0000000..3e88253 Binary files /dev/null and b/styles/Images/BlackPath-H.png differ diff --git a/styles/Images/BlackPath-N.png b/styles/Images/BlackPath-N.png new file mode 100755 index 0000000..4c8954f Binary files /dev/null and b/styles/Images/BlackPath-N.png differ diff --git a/styles/Images/BlackPath-NE.png b/styles/Images/BlackPath-NE.png new file mode 100755 index 0000000..5083496 Binary files /dev/null and b/styles/Images/BlackPath-NE.png differ diff --git a/styles/Images/BlackPath-NES.png b/styles/Images/BlackPath-NES.png new file mode 100755 index 0000000..3229a77 Binary files /dev/null and b/styles/Images/BlackPath-NES.png differ diff --git a/styles/Images/BlackPath-NESW.png b/styles/Images/BlackPath-NESW.png new file mode 100755 index 0000000..ec1040c Binary files /dev/null and b/styles/Images/BlackPath-NESW.png differ diff --git a/styles/Images/BlackPath-NW.png b/styles/Images/BlackPath-NW.png new file mode 100755 index 0000000..4cccd7b Binary files /dev/null and b/styles/Images/BlackPath-NW.png differ diff --git a/styles/Images/BlackPath-S.png b/styles/Images/BlackPath-S.png new file mode 100755 index 0000000..5a79749 Binary files /dev/null and b/styles/Images/BlackPath-S.png differ diff --git a/styles/Images/BlackPath-SE.png b/styles/Images/BlackPath-SE.png new file mode 100755 index 0000000..707f763 Binary files /dev/null and b/styles/Images/BlackPath-SE.png differ diff --git a/styles/Images/BlackPath-SW.png b/styles/Images/BlackPath-SW.png new file mode 100755 index 0000000..b48a022 Binary files /dev/null and b/styles/Images/BlackPath-SW.png differ diff --git a/styles/Images/BlackPath-SWN.png b/styles/Images/BlackPath-SWN.png new file mode 100755 index 0000000..85640f7 Binary files /dev/null and b/styles/Images/BlackPath-SWN.png differ diff --git a/styles/Images/BlackPath-V.png b/styles/Images/BlackPath-V.png new file mode 100755 index 0000000..900bf9b Binary files /dev/null and b/styles/Images/BlackPath-V.png differ diff --git a/styles/Images/BlackPath-W.png b/styles/Images/BlackPath-W.png new file mode 100755 index 0000000..827e25d Binary files /dev/null and b/styles/Images/BlackPath-W.png differ diff --git a/styles/Images/BlackPath-WNE.png b/styles/Images/BlackPath-WNE.png new file mode 100755 index 0000000..066f464 Binary files /dev/null and b/styles/Images/BlackPath-WNE.png differ diff --git a/styles/Images/BlackPath.png b/styles/Images/BlackPath.png new file mode 100755 index 0000000..ec1040c Binary files /dev/null and b/styles/Images/BlackPath.png differ diff --git a/styles/Images/Cactus.png b/styles/Images/Cactus.png new file mode 100755 index 0000000..96dfa50 Binary files /dev/null and b/styles/Images/Cactus.png differ diff --git a/styles/Images/Land-NE.png b/styles/Images/Land-NE.png new file mode 100755 index 0000000..49c27c5 Binary files /dev/null and b/styles/Images/Land-NE.png differ diff --git a/styles/Images/Land-NW.png b/styles/Images/Land-NW.png new file mode 100755 index 0000000..d06c3d9 Binary files /dev/null and b/styles/Images/Land-NW.png differ diff --git a/styles/Images/Land-SE.png b/styles/Images/Land-SE.png new file mode 100755 index 0000000..0c49375 Binary files /dev/null and b/styles/Images/Land-SE.png differ diff --git a/styles/Images/Land-SW.png b/styles/Images/Land-SW.png new file mode 100755 index 0000000..1c7c44f Binary files /dev/null and b/styles/Images/Land-SW.png differ diff --git a/styles/Images/Land.png b/styles/Images/Land.png new file mode 100755 index 0000000..cf3d48a Binary files /dev/null and b/styles/Images/Land.png differ diff --git a/styles/Images/Sand-NE.png b/styles/Images/Sand-NE.png new file mode 100755 index 0000000..32ce228 Binary files /dev/null and b/styles/Images/Sand-NE.png differ diff --git a/styles/Images/Sand-NW.png b/styles/Images/Sand-NW.png new file mode 100755 index 0000000..c022480 Binary files /dev/null and b/styles/Images/Sand-NW.png differ diff --git a/styles/Images/Sand-SE.png b/styles/Images/Sand-SE.png new file mode 100755 index 0000000..92da738 Binary files /dev/null and b/styles/Images/Sand-SE.png differ diff --git a/styles/Images/Sand-SW.png b/styles/Images/Sand-SW.png new file mode 100755 index 0000000..ce5030d Binary files /dev/null and b/styles/Images/Sand-SW.png differ diff --git a/styles/Images/Sand.png b/styles/Images/Sand.png new file mode 100755 index 0000000..902aeeb Binary files /dev/null and b/styles/Images/Sand.png differ diff --git a/styles/Images/Tree.png b/styles/Images/Tree.png new file mode 100755 index 0000000..58c60a0 Binary files /dev/null and b/styles/Images/Tree.png differ diff --git a/styles/Images/Water.png b/styles/Images/Water.png new file mode 100755 index 0000000..eb9319a Binary files /dev/null and b/styles/Images/Water.png differ diff --git a/styles/Images/WhitePath-0.png b/styles/Images/WhitePath-0.png new file mode 100755 index 0000000..a633d96 Binary files /dev/null and b/styles/Images/WhitePath-0.png differ diff --git a/styles/Images/WhitePath-E.png b/styles/Images/WhitePath-E.png new file mode 100755 index 0000000..785127e Binary files /dev/null and b/styles/Images/WhitePath-E.png differ diff --git a/styles/Images/WhitePath-ESW.png b/styles/Images/WhitePath-ESW.png new file mode 100755 index 0000000..1008029 Binary files /dev/null and b/styles/Images/WhitePath-ESW.png differ diff --git a/styles/Images/WhitePath-H.png b/styles/Images/WhitePath-H.png new file mode 100755 index 0000000..8793059 Binary files /dev/null and b/styles/Images/WhitePath-H.png differ diff --git a/styles/Images/WhitePath-N.png b/styles/Images/WhitePath-N.png new file mode 100755 index 0000000..f3462dc Binary files /dev/null and b/styles/Images/WhitePath-N.png differ diff --git a/styles/Images/WhitePath-NE.png b/styles/Images/WhitePath-NE.png new file mode 100755 index 0000000..90d1224 Binary files /dev/null and b/styles/Images/WhitePath-NE.png differ diff --git a/styles/Images/WhitePath-NES.png b/styles/Images/WhitePath-NES.png new file mode 100755 index 0000000..d5f3f6f Binary files /dev/null and b/styles/Images/WhitePath-NES.png differ diff --git a/styles/Images/WhitePath-NESW.png b/styles/Images/WhitePath-NESW.png new file mode 100755 index 0000000..f18ae8c Binary files /dev/null and b/styles/Images/WhitePath-NESW.png differ diff --git a/styles/Images/WhitePath-NW.png b/styles/Images/WhitePath-NW.png new file mode 100755 index 0000000..1cffa67 Binary files /dev/null and b/styles/Images/WhitePath-NW.png differ diff --git a/styles/Images/WhitePath-S.png b/styles/Images/WhitePath-S.png new file mode 100755 index 0000000..3314d3b Binary files /dev/null and b/styles/Images/WhitePath-S.png differ diff --git a/styles/Images/WhitePath-SE.png b/styles/Images/WhitePath-SE.png new file mode 100755 index 0000000..76e1523 Binary files /dev/null and b/styles/Images/WhitePath-SE.png differ diff --git a/styles/Images/WhitePath-SW.png b/styles/Images/WhitePath-SW.png new file mode 100755 index 0000000..0ef46a9 Binary files /dev/null and b/styles/Images/WhitePath-SW.png differ diff --git a/styles/Images/WhitePath-SWN.png b/styles/Images/WhitePath-SWN.png new file mode 100755 index 0000000..a9e7334 Binary files /dev/null and b/styles/Images/WhitePath-SWN.png differ diff --git a/styles/Images/WhitePath-V.png b/styles/Images/WhitePath-V.png new file mode 100755 index 0000000..65a5128 Binary files /dev/null and b/styles/Images/WhitePath-V.png differ diff --git a/styles/Images/WhitePath-W.png b/styles/Images/WhitePath-W.png new file mode 100755 index 0000000..6c639a6 Binary files /dev/null and b/styles/Images/WhitePath-W.png differ diff --git a/styles/Images/WhitePath-WNE.png b/styles/Images/WhitePath-WNE.png new file mode 100755 index 0000000..c8cdfe5 Binary files /dev/null and b/styles/Images/WhitePath-WNE.png differ diff --git a/styles/Images/WhitePath.png b/styles/Images/WhitePath.png new file mode 100755 index 0000000..f18ae8c Binary files /dev/null and b/styles/Images/WhitePath.png differ diff --git a/views/LoadStyle.gd b/views/LoadStyle.gd new file mode 100644 index 0000000..606d409 --- /dev/null +++ b/views/LoadStyle.gd @@ -0,0 +1,119 @@ +extends Control + +signal style_selected(canvas_conf, style_conf) + +enum Result { + OK = 0, + WARNING = 1, + ERROR = 2 +} + +var _ok_tex : ImageTexture = ImageTexture.new() +var _warning_tex : ImageTexture = ImageTexture.new() +var _error_tex : ImageTexture = ImageTexture.new() +var _style_conf : Dictionary = {} + +func _ready(): + var stream_texture + + stream_texture = load("res://resources/icons/ok.png") + _ok_tex.create_from_image(stream_texture.get_data()) + + stream_texture = load("res://resources/icons/warning.png") + _warning_tex.create_from_image(stream_texture.get_data()) + + stream_texture = load("res://resources/icons/error.png") + _error_tex.create_from_image(stream_texture.get_data()) + +func _set_style_parse_result(result : int): + get_node("ParseResult").show() + match result: + Result.OK: + get_node("ParseResult/Icon").set_texture(_ok_tex) + get_node("ParseResult/Icon").get_material().set_shader_param("mode", result) + get_node("ParseResult/Message").set_text("Successfully Loaded") + Result.WARNING: + get_node("ParseResult/Icon").set_texture(_warning_tex) + get_node("ParseResult/Icon").get_material().set_shader_param("mode", result) + get_node("ParseResult/Message").set_text("Loaded with Warnings") + Result.ERROR: + get_node("ParseResult/Icon").set_texture(_error_tex) + get_node("ParseResult/Icon").get_material().set_shader_param("mode", result) + get_node("ParseResult/Message").set_text("Errors Occurred") + +func _show_errors(errors : Array): + if errors.size() != 0: + get_node("Messages").show() + get_node("Messages").set_current_tab(0) + get_node("Messages").set_tab_disabled(0, false) + for error in errors: + get_node("Messages/Error(s)/Errors").add_text(error + "\n") + else: + get_node("Messages").set_tab_disabled(0, true) + +func _show_warnings(warnings : Array): + if warnings.size() != 0: + get_node("Messages").show() + get_node("Messages").set_current_tab(1) + get_node("Messages").set_tab_disabled(1, false) + for warning in warnings: + get_node("Messages/Warning(s)/Warnings").add_text(warning + "\n") + else: + get_node("Messages").set_tab_disabled(1, true) + +func _path_text_clicked(event : InputEvent): + if event is InputEventMouseButton: + if event.get_button_index() == BUTTON_LEFT: + if event.is_pressed(): + _select_style() + +func _select_style(): + get_node("SelectStyle").popup_centered() + +func _style_selected(path : String): + get_node("Messages").hide() + set_size(Vector2(get_size().x, get_minimum_size().y)) + + get_node("Messages/Error(s)/Errors").clear() + get_node("Messages/Warning(s)/Warnings").clear() + + get_node("PathSelection/Path").set_text(path.get_file()) + + var configuration_parser = MainParser.new() + configuration_parser.parse(path) + + _style_conf = configuration_parser.get_configuration() + + if configuration_parser.get_errors().size() != 0: + _set_style_parse_result(Result.ERROR) + + _show_warnings(configuration_parser.get_warnings()) + _show_errors(configuration_parser.get_errors()) + + get_node("StartContainer/StartButton").disabled = true + get_node("Style").hide() + elif configuration_parser.get_warnings().size() != 0: + _set_style_parse_result(Result.WARNING) + + _show_warnings(configuration_parser.get_warnings()) + _show_errors(configuration_parser.get_errors()) + + get_node("StartContainer/StartButton").disabled = false + get_node("Style").show() + get_node("Style").set_text(_style_conf.StyleData.Name + " by " + _style_conf.StyleData.Author + ":") + else: + _set_style_parse_result(Result.OK) + get_node("StartContainer/StartButton").disabled = false + get_node("Style").show() + get_node("Style").set_text(_style_conf.StyleData.Name + " by " + _style_conf.StyleData.Author + ":") + +func _create_proyect(): + var width = get_node("SizeContainer/Width").get_value() + var height = get_node("SizeContainer/Height").get_value() + + var canvas_conf = { + "Width": width, + "Height": height + } + + emit_signal("style_selected", canvas_conf, _style_conf) diff --git a/views/LoadStyle.tscn b/views/LoadStyle.tscn new file mode 100644 index 0000000..321a148 --- /dev/null +++ b/views/LoadStyle.tscn @@ -0,0 +1,199 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://views/LoadStyle.gd" type="Script" id=1] +[ext_resource path="res://resources/icons/ok.png" type="Texture" id=2] + +[sub_resource type="Shader" id=1] +code = "shader_type canvas_item; + +uniform int mode = 0; +const vec3 ok_color = vec3(0.0, 1.0, 0.0); +const vec3 warning_color = vec3(1.0, 1.0, 0.1); +const vec3 error_color = vec3(1.0, 0.0, 0.0); + +void fragment(){ + vec4 tex_color = texture(TEXTURE, UV); + switch (mode) { + case 0: + COLOR = vec4(ok_color, tex_color.a); + break; + case 1: + COLOR = vec4(warning_color, tex_color.a); + break; + case 2: + COLOR = vec4(error_color, tex_color.a); + break; + } +}" +custom_defines = "" + +[sub_resource type="ShaderMaterial" id=2] +shader = SubResource( 1 ) +shader_param/mode = 0 + +[node name="LoadStyle" type="VBoxContainer"] +anchor_right = 1.0 +margin_bottom = 100.0 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="PathSelection" type="HBoxContainer" parent="."] +margin_right = 1024.0 +margin_bottom = 20.0 + +[node name="PathLabel" type="Label" parent="PathSelection"] +margin_top = 3.0 +margin_right = 115.0 +margin_bottom = 17.0 +text = "Configuration File:" + +[node name="Path" type="TextEdit" parent="PathSelection"] +margin_left = 119.0 +margin_right = 978.0 +margin_bottom = 20.0 +rect_min_size = Vector2( 0, 20 ) +size_flags_horizontal = 3 +readonly = true + +[node name="LoadStyle" type="Button" parent="PathSelection"] +margin_left = 982.0 +margin_right = 1024.0 +margin_bottom = 20.0 +text = "Load" + +[node name="Style" type="Label" parent="."] +visible = false +margin_top = 42.0 +margin_right = 1024.0 +margin_bottom = 56.0 + +[node name="ParseResult" type="HBoxContainer" parent="."] +visible = false +margin_top = 24.0 +margin_right = 1024.0 +margin_bottom = 38.0 + +[node name="Icon" type="TextureRect" parent="ParseResult"] +material = SubResource( 2 ) +margin_right = 14.0 +margin_bottom = 14.0 +rect_min_size = Vector2( 14, 14 ) +texture = ExtResource( 2 ) +expand = true +stretch_mode = 6 + +[node name="Message" type="Label" parent="ParseResult"] +margin_left = 18.0 +margin_right = 139.0 +margin_bottom = 14.0 +text = "Succesfully Loaded" + +[node name="Messages" type="TabContainer" parent="."] +visible = false +margin_top = 24.0 +margin_right = 1024.0 +margin_bottom = 224.0 +rect_min_size = Vector2( 0, 200 ) +tab_align = 0 + +[node name="Error(s)" type="PanelContainer" parent="Messages"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 4.0 +margin_top = 32.0 +margin_right = -4.0 +margin_bottom = -4.0 + +[node name="Errors" type="RichTextLabel" parent="Messages/Error(s)"] +margin_left = 7.0 +margin_top = 7.0 +margin_right = 1009.0 +margin_bottom = 157.0 + +[node name="Warning(s)" type="PanelContainer" parent="Messages"] +visible = false +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 4.0 +margin_top = 32.0 +margin_right = -4.0 +margin_bottom = -4.0 + +[node name="Warnings" type="RichTextLabel" parent="Messages/Warning(s)"] +margin_left = -4.0 +margin_top = 22.0 +margin_right = 1020.0 +margin_bottom = 22.0 + +[node name="Size" type="Label" parent="."] +margin_top = 24.0 +margin_right = 1024.0 +margin_bottom = 38.0 +text = "Canvas Size:" + +[node name="SizeContainer" type="HBoxContainer" parent="."] +margin_top = 42.0 +margin_right = 1024.0 +margin_bottom = 66.0 + +[node name="WidthLabel" type="Label" parent="SizeContainer"] +margin_top = 5.0 +margin_right = 38.0 +margin_bottom = 19.0 +text = "Width" + +[node name="Width" type="SpinBox" parent="SizeContainer"] +margin_left = 42.0 +margin_right = 116.0 +margin_bottom = 24.0 +min_value = 1.0 +max_value = 50.0 +value = 20.0 + +[node name="HeightLabel" type="Label" parent="SizeContainer"] +margin_left = 120.0 +margin_top = 5.0 +margin_right = 162.0 +margin_bottom = 19.0 +text = "Height" + +[node name="Height" type="SpinBox" parent="SizeContainer"] +margin_left = 166.0 +margin_right = 240.0 +margin_bottom = 24.0 +min_value = 1.0 +max_value = 50.0 +value = 20.0 + +[node name="StartContainer" type="CenterContainer" parent="."] +margin_top = 70.0 +margin_right = 1024.0 +margin_bottom = 100.0 +rect_min_size = Vector2( 0, 30 ) + +[node name="StartButton" type="Button" parent="StartContainer"] +margin_left = 491.0 +margin_top = 5.0 +margin_right = 532.0 +margin_bottom = 25.0 +disabled = true +text = "Start" + +[node name="SelectStyle" type="FileDialog" parent="."] +margin_top = 104.0 +margin_right = 700.0 +margin_bottom = 704.0 +rect_min_size = Vector2( 400, 600 ) +window_title = "Select a Style" +mode_overrides_title = false +mode = 0 +access = 2 +filters = PoolStringArray( "*.json ; Style JSON" ) +current_dir = "/home/tomas/Escritorio/Teggy's Map Maker" +current_path = "/home/tomas/Escritorio/Teggy's Map Maker/" +[connection signal="gui_input" from="PathSelection/Path" to="." method="_path_text_clicked"] +[connection signal="pressed" from="PathSelection/LoadStyle" to="." method="_select_style"] +[connection signal="pressed" from="StartContainer/StartButton" to="." method="_create_proyect"] +[connection signal="file_selected" from="SelectStyle" to="." method="_style_selected"] diff --git a/views/WorkSpace.gd b/views/WorkSpace.gd new file mode 100644 index 0000000..b45c059 --- /dev/null +++ b/views/WorkSpace.gd @@ -0,0 +1,36 @@ +extends Control + +signal new() + +func init(canvas_conf : Dictionary, style_conf : Dictionary): + _get_canvas().init(canvas_conf, style_conf) + + _get_tool_box_container().add_child(_get_canvas().get_current_tool_box()) + _get_magnifying_glass().connect("magnifying_factor_updated", _get_canvas(), "_update_scale_factor") + _get_canvas().connect("gui_input", _get_magnifying_glass(), "process_mouse_wheel") + + _get_canvas().connect_with_undo_redo(_get_undo_redo()) + +func _get_canvas(): + return get_node("VerticalDivision/HorizontalDivision/Canvas") + +func _get_tool_box_container(): + return get_node("VerticalDivision/HorizontalDivision/ToolBoxContainer/ToolBoxMargin") + +func _get_magnifying_glass(): + return get_node("VerticalDivision/TopBar/Margin/SplitTopBar/Tools/MagnifyingGlass") + +func _get_undo_redo(): + return get_node("VerticalDivision/TopBar/Margin/SplitTopBar/Tools/UndoRedo") + +func _save(): + get_node("SaveImageDialog").popup_centered() + +func _save_ok(path : String): + get_node("VerticalDivision/HorizontalDivision/Canvas").get_image().save_png(path) + +func _about(): + get_node("AboutDialog").popup_centered() + +func _new(): + emit_signal("new") diff --git a/views/WorkSpace.tscn b/views/WorkSpace.tscn new file mode 100644 index 0000000..11751b0 --- /dev/null +++ b/views/WorkSpace.tscn @@ -0,0 +1,150 @@ +[gd_scene load_steps=6 format=2] + +[ext_resource path="res://panels/UndoRedo.tscn" type="PackedScene" id=1] +[ext_resource path="res://views/WorkSpace.gd" type="Script" id=2] +[ext_resource path="res://panels/MagnifyingGlass.tscn" type="PackedScene" id=3] +[ext_resource path="res://panels/Canvas.tscn" type="PackedScene" id=4] + +[sub_resource type="Theme" id=1] +Dialogs/constants/button_margin = 32 +Dialogs/constants/margin = 10 + +[node name="WorkSpace" type="Control"] +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource( 2 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="VerticalDivision" type="VSplitContainer" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +collapsed = true +dragger_visibility = 2 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="TopBar" type="PanelContainer" parent="VerticalDivision"] +margin_right = 1024.0 +margin_bottom = 54.0 + +[node name="Margin" type="MarginContainer" parent="VerticalDivision/TopBar"] +margin_left = 7.0 +margin_top = 7.0 +margin_right = 1017.0 +margin_bottom = 47.0 + +[node name="SplitTopBar" type="HSplitContainer" parent="VerticalDivision/TopBar/Margin"] +margin_right = 1010.0 +margin_bottom = 40.0 +dragger_visibility = 2 + +[node name="Buttons" type="HBoxContainer" parent="VerticalDivision/TopBar/Margin/SplitTopBar"] +margin_right = 150.0 +margin_bottom = 40.0 + +[node name="New" type="Button" parent="VerticalDivision/TopBar/Margin/SplitTopBar/Buttons"] +margin_right = 40.0 +margin_bottom = 40.0 +text = "New" + +[node name="Export" type="Button" parent="VerticalDivision/TopBar/Margin/SplitTopBar/Buttons"] +margin_left = 44.0 +margin_right = 96.0 +margin_bottom = 40.0 +hint_tooltip = "Save" +text = "Export" +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="About" type="Button" parent="VerticalDivision/TopBar/Margin/SplitTopBar/Buttons"] +margin_left = 100.0 +margin_right = 150.0 +margin_bottom = 40.0 +text = "About" + +[node name="Tools" type="HBoxContainer" parent="VerticalDivision/TopBar/Margin/SplitTopBar"] +margin_left = 150.0 +margin_right = 1010.0 +margin_bottom = 40.0 +alignment = 2 + +[node name="UndoRedo" parent="VerticalDivision/TopBar/Margin/SplitTopBar/Tools" instance=ExtResource( 1 )] +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 460.0 +margin_right = 556.0 +margin_bottom = 40.0 + +[node name="MagnifyingGlass" parent="VerticalDivision/TopBar/Margin/SplitTopBar/Tools" instance=ExtResource( 3 )] +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 560.0 +margin_right = 860.0 +margin_bottom = 40.0 +rect_min_size = Vector2( 300, 0 ) + +[node name="HorizontalDivision" type="HSplitContainer" parent="VerticalDivision"] +margin_top = 54.0 +margin_right = 1024.0 +margin_bottom = 600.0 +collapsed = true +dragger_visibility = 2 + +[node name="ToolBoxContainer" type="PanelContainer" parent="VerticalDivision/HorizontalDivision"] +margin_right = 14.0 +margin_bottom = 546.0 +size_flags_vertical = 3 + +[node name="ToolBoxMargin" type="MarginContainer" parent="VerticalDivision/HorizontalDivision/ToolBoxContainer"] +margin_left = 7.0 +margin_top = 7.0 +margin_right = 7.0 +margin_bottom = 539.0 + +[node name="Canvas" parent="VerticalDivision/HorizontalDivision" instance=ExtResource( 4 )] +margin_left = 14.0 +margin_right = 1024.0 +margin_bottom = 546.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="SaveImageDialog" type="FileDialog" parent="."] +margin_right = 700.0 +margin_bottom = 600.0 +theme = SubResource( 1 ) +window_title = "Export Image" +access = 2 +filters = PoolStringArray( "*.png ; PNG Images" ) +current_dir = "/home/tomas/Escritorio/Teggy's Map Maker" +current_path = "/home/tomas/Escritorio/Teggy's Map Maker/" + +[node name="AboutDialog" type="AcceptDialog" parent="."] +margin_right = 700.0 +margin_bottom = 600.0 +theme = SubResource( 1 ) +window_title = "About this Project" +dialog_text = "Teggy's Map Maker: +- Created by Tomás Espejo Gómez + +Icons made by: +- Google +- Freepik +- Becris +From www.flaticon.com + +Fonts: +- Poppins +- Roboto Mono +From fonts.google.com + +Color Palette selected using coolors.co + +Built using the Godot Game Engine" +[connection signal="pressed" from="VerticalDivision/TopBar/Margin/SplitTopBar/Buttons/New" to="." method="_new"] +[connection signal="pressed" from="VerticalDivision/TopBar/Margin/SplitTopBar/Buttons/Export" to="." method="_save"] +[connection signal="pressed" from="VerticalDivision/TopBar/Margin/SplitTopBar/Buttons/About" to="." method="_about"] +[connection signal="file_selected" from="SaveImageDialog" to="." method="_save_ok"]