diff --git a/README.md b/README.md index cbe9a36..e2e92db 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -

GlitchApp

+

Fragmented

![screenshot](./screenshot.png) @@ -9,30 +9,39 @@ - Linux -You can find the latest releases [here](https://github.com/ChaoticByte/GlitchApp/releases/latest). +You can find the latest releases [here](https://github.com/ChaoticByte/Fragmented/releases/latest). ## Usage -The application includes presets. You can use them as a starting-point to write your own filters. -Just load an image, apply a preset, edit the code and hit `F5` to see the changes. +The repo includes examples. You can use them as a starting-point to write your own filters. +Just load an image using `//!load`, edit the shader code and hit `F5` to see the changes. -### Load additional images using the `//!load` directive +### Load TEXTURE using the `//!load` directive + +```glsl +//!load +``` + +The image file will be read and available as the `TEXTURE` variable. + +#### Load additional images ```glsl //!load uniform sampler2D ; ``` -With this you can load additional images into your shader. -Have a look at the `Mix` preset: +Have a look at the `mix.gdshader` example: ```glsl shader_type canvas_item; -//!load img2 ./icon.png +//!load ./swamp.jpg + +//!load+ img2 ./overlay.jpg uniform sampler2D img2: repeat_enable, filter_nearest; void fragment() { - COLOR = mix(COLOR, texture(img2, UV), .5); + COLOR = mix(COLOR, texture(img2, UV), .2); } ``` diff --git a/examples/CREDITS.md b/examples/CREDITS.md new file mode 100644 index 0000000..99df0e2 --- /dev/null +++ b/examples/CREDITS.md @@ -0,0 +1,5 @@ + +# Example Images + +- swamp.jpg by [clfr21](https://pixabay.com/de/users/clfr21-6530007/) +- overlay.jpg by [Humusak](https://pixabay.com/de/users/humusak-137455/) diff --git a/src/presets/shaders/channel_offset.gdshader b/examples/channel_offset.gdshader similarity index 94% rename from src/presets/shaders/channel_offset.gdshader rename to examples/channel_offset.gdshader index e3ac188..73915ea 100644 --- a/src/presets/shaders/channel_offset.gdshader +++ b/examples/channel_offset.gdshader @@ -1,5 +1,7 @@ shader_type canvas_item; +//!load ./swamp.jpg + const vec2 offset_r = vec2(-0.002, -0.002); const vec2 offset_g = vec2(0., 0.); const vec2 offset_b = vec2(0.002, 0.002); diff --git a/src/presets/shaders/greyscale.gdshader b/examples/greyscale.gdshader similarity index 71% rename from src/presets/shaders/greyscale.gdshader rename to examples/greyscale.gdshader index cd70a78..921c591 100644 --- a/src/presets/shaders/greyscale.gdshader +++ b/examples/greyscale.gdshader @@ -1,10 +1,10 @@ shader_type canvas_item; +//!load ./swamp.jpg + void fragment() { - vec4 tex = texture(TEXTURE , UV); float b = (COLOR.r + COLOR.g + COLOR.b) / 3.0; COLOR.r = b; COLOR.g = b; COLOR.b = b; - COLOR.a = tex.a; } diff --git a/src/presets/shaders/lowpass.gdshader b/examples/lowpass.gdshader similarity index 92% rename from src/presets/shaders/lowpass.gdshader rename to examples/lowpass.gdshader index 9dc44f7..d2d82c5 100644 --- a/src/presets/shaders/lowpass.gdshader +++ b/examples/lowpass.gdshader @@ -1,5 +1,7 @@ shader_type canvas_item; +//!load ./swamp.jpg + // Settings const float threshold = 0.5; // diff --git a/src/presets/shaders/mix.gdshader b/examples/mix.gdshader similarity index 52% rename from src/presets/shaders/mix.gdshader rename to examples/mix.gdshader index 53ed562..a043856 100644 --- a/src/presets/shaders/mix.gdshader +++ b/examples/mix.gdshader @@ -1,8 +1,10 @@ shader_type canvas_item; -//!load img2 ./icon.png +//!load ./swamp.jpg + +//!load+ img2 ./overlay.jpg uniform sampler2D img2: repeat_enable, filter_nearest; void fragment() { - COLOR = mix(COLOR, texture(img2, UV), .5); + COLOR = mix(COLOR, texture(img2, UV), .2); } diff --git a/examples/overlay.jpg b/examples/overlay.jpg new file mode 100644 index 0000000..b305379 Binary files /dev/null and b/examples/overlay.jpg differ diff --git a/examples/overlay.jpg.import b/examples/overlay.jpg.import new file mode 100644 index 0000000..7d189f0 --- /dev/null +++ b/examples/overlay.jpg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://8101nnc8cx4o" +path="res://.godot/imported/overlay.jpg-b6d13e0def59877969c9eda02fa4244e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://examples/overlay.jpg" +dest_files=["res://.godot/imported/overlay.jpg-b6d13e0def59877969c9eda02fa4244e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/src/presets/shaders/rgb_uv_distort.gdshader b/examples/rgb_uv_distort.gdshader similarity index 91% rename from src/presets/shaders/rgb_uv_distort.gdshader rename to examples/rgb_uv_distort.gdshader index c07466b..1b65816 100644 --- a/src/presets/shaders/rgb_uv_distort.gdshader +++ b/examples/rgb_uv_distort.gdshader @@ -1,5 +1,7 @@ shader_type canvas_item; +//!load ./swamp.jpg + const float strength = 0.1; void fragment() { diff --git a/examples/swamp.jpg b/examples/swamp.jpg new file mode 100644 index 0000000..d7bdf3c Binary files /dev/null and b/examples/swamp.jpg differ diff --git a/examples/swamp.jpg.import b/examples/swamp.jpg.import new file mode 100644 index 0000000..3cc2a0b --- /dev/null +++ b/examples/swamp.jpg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ckjb0agn5btv7" +path="res://.godot/imported/swamp.jpg-8e3eac7e7aacce65638e712310cdb35c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://examples/swamp.jpg" +dest_files=["res://.godot/imported/swamp.jpg-8e3eac7e7aacce65638e712310cdb35c.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/export_presets.cfg b/export_presets.cfg index df6f7ca..d1be5f0 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -8,7 +8,7 @@ custom_features="" export_filter="all_resources" include_filter="" exclude_filter="" -export_path="dist/GlitchApp.x86_64" +export_path="dist/Fragmented.x86_64" encryption_include_filters="" encryption_exclude_filters="" encrypt_pck=false diff --git a/project.godot b/project.godot index df98a4f..cee024d 100644 --- a/project.godot +++ b/project.godot @@ -10,16 +10,15 @@ config_version=5 [application] -config/name="Glitch" -config/version="v4.0" +config/name="Fragmented" +config/version="v5.0" run/main_scene="res://scenes/main.tscn" -config/features=PackedStringArray("4.2", "Mobile") +config/features=PackedStringArray("4.3", "Mobile") run/low_processor_mode=true config/icon="res://icon.png" [autoload] -ShaderPresets="*res://src/presets/Presets.gd" Globals="*res://src/Globals.gd" [display] @@ -28,6 +27,7 @@ window/size/viewport_width=1280 window/size/viewport_height=720 window/size/mode=2 window/energy_saving/keep_screen_on=false +window/vsync/vsync_mode=0 [editor_plugins] @@ -38,15 +38,15 @@ enabled=PackedStringArray() zoom_out={ "deadzone": 0.5, "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":16,"position":Vector2(244, 15),"global_position":Vector2(248, 56),"factor":1.0,"button_index":5,"canceled":false,"pressed":true,"double_click":false,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":45,"physical_keycode":0,"key_label":0,"unicode":45,"echo":false,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194435,"key_label":0,"unicode":45,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":45,"physical_keycode":0,"key_label":0,"unicode":45,"location":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194435,"key_label":0,"unicode":45,"location":0,"echo":false,"script":null) ] } zoom_in={ "deadzone": 0.5, "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":8,"position":Vector2(270, 19),"global_position":Vector2(274, 60),"factor":1.0,"button_index":4,"canceled":false,"pressed":true,"double_click":false,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":43,"physical_keycode":0,"key_label":0,"unicode":43,"echo":false,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194437,"key_label":0,"unicode":43,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":43,"physical_keycode":0,"key_label":0,"unicode":43,"location":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194437,"key_label":0,"unicode":43,"location":0,"echo":false,"script":null) ] } drag={ @@ -56,12 +56,12 @@ drag={ } apply_shader={ "deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194336,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194336,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) ] } save_shader={ "deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":false,"pressed":false,"keycode":83,"physical_keycode":0,"key_label":0,"unicode":115,"echo":false,"script":null) +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":false,"pressed":false,"keycode":83,"physical_keycode":0,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) ] } @@ -70,4 +70,5 @@ save_shader={ renderer/rendering_method="mobile" textures/vram_compression/import_etc2_astc=true textures/lossless_compression/force_png=true +shader_compiler/shader_cache/enabled=false environment/defaults/default_clear_color=Color(0, 0, 0, 1) diff --git a/scenes/main.tscn b/scenes/main.tscn index 2ba507d..6792ecb 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -2,7 +2,7 @@ [ext_resource type="Script" path="res://src/Main.gd" id="1_2625y"] [ext_resource type="Script" path="res://src/ImageViewport.gd" id="2_hvo65"] -[ext_resource type="Script" path="res://src/ImageViewportDisplays.gd" id="3_n4itb"] +[ext_resource type="Script" path="res://src/ImageViewportDisplay.gd" id="3_n4itb"] [ext_resource type="Shader" path="res://src/ui_background.gdshader" id="4_ty3qx"] [ext_resource type="Script" path="res://src/UIAppVersion.gd" id="5_o1ggv"] [ext_resource type="Script" path="res://src/Editor.gd" id="7_g8bap"] @@ -18,6 +18,7 @@ shader = ExtResource("4_ty3qx") script = ExtResource("1_2625y") [node name="ImageViewport" type="SubViewport" parent="."] +unique_name_in_owner = true disable_3d = true transparent_bg = true canvas_item_default_texture_filter = 0 @@ -25,8 +26,10 @@ render_target_update_mode = 4 script = ExtResource("2_hvo65") [node name="ImageSprite" type="Sprite2D" parent="ImageViewport"] +unique_name_in_owner = true [node name="ImageViewportDisplay" type="Sprite2D" parent="."] +unique_name_in_owner = true texture = SubResource("ViewportTexture_lct1c") script = ExtResource("3_n4itb") @@ -42,6 +45,7 @@ grow_vertical = 2 focus_mode = 2 [node name="UserInterfaceContainer" type="Control" parent="UI_Layer"] +unique_name_in_owner = true layout_mode = 3 anchor_right = 0.225 anchor_bottom = 1.0 @@ -63,87 +67,32 @@ color = Color(1, 1, 1, 0) [node name="AppName" type="Label" parent="UI_Layer/UserInterfaceContainer"] layout_mode = 0 offset_left = 24.0 -offset_top = 24.0 +offset_top = 16.0 offset_right = 208.0 -offset_bottom = 56.0 +offset_bottom = 48.0 theme_override_font_sizes/font_size = 20 -text = "GlitchApp -" +text = "Fragmented" vertical_alignment = 2 [node name="AppVersion" type="Label" parent="UI_Layer/UserInterfaceContainer"] layout_mode = 0 -offset_left = 128.0 -offset_top = 24.0 +offset_left = 152.0 +offset_top = 17.0 offset_right = 208.0 -offset_bottom = 56.0 +offset_bottom = 47.0 theme_override_font_sizes/font_size = 14 text = "v0 " vertical_alignment = 2 script = ExtResource("5_o1ggv") -[node name="OpenImageDialog" type="FileDialog" parent="UI_Layer/UserInterfaceContainer"] -title = "Load Image" -size = Vector2i(521, 159) -ok_button_text = "Open" -mode_overrides_title = false -file_mode = 0 -access = 2 -use_native_dialog = true - -[node name="SaveImageDialog" type="FileDialog" parent="UI_Layer/UserInterfaceContainer"] -title = "Export Image" -size = Vector2i(661, 159) -ok_button_text = "Save" -mode_overrides_title = false -access = 2 -filters = PackedStringArray("*.png") -use_native_dialog = true - -[node name="OpenImageButton" type="Button" parent="UI_Layer/UserInterfaceContainer"] -layout_mode = 1 -anchors_preset = 1 -anchor_left = 1.0 -anchor_right = 1.0 -offset_left = -360.0 -offset_top = 24.0 -offset_right = -248.0 -offset_bottom = 56.0 -grow_horizontal = 0 -text = "Load Image" - -[node name="SaveImageButton" type="Button" parent="UI_Layer/UserInterfaceContainer"] -layout_mode = 1 -anchors_preset = 1 -anchor_left = 1.0 -anchor_right = 1.0 -offset_left = -240.0 -offset_top = 23.0 -offset_right = -120.0 -offset_bottom = 55.0 -grow_horizontal = 0 -text = "Export Image" - -[node name="FitImageButton" type="Button" parent="UI_Layer/UserInterfaceContainer"] -layout_mode = 1 -anchors_preset = 1 -anchor_left = 1.0 -anchor_right = 1.0 -offset_left = -112.0 -offset_top = 24.0 -offset_right = -24.0 -offset_bottom = 56.0 -grow_horizontal = 0 -text = "Fit Image" - [node name="Editor" type="Control" parent="UI_Layer/UserInterfaceContainer"] layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 offset_left = 24.0 -offset_top = 80.0 +offset_top = 64.0 offset_right = -24.0 offset_bottom = -24.0 grow_horizontal = 2 @@ -151,8 +100,9 @@ grow_vertical = 2 script = ExtResource("7_g8bap") [node name="OpenShaderDialog" type="FileDialog" parent="UI_Layer/UserInterfaceContainer/Editor"] +unique_name_in_owner = true title = "Load Shader" -size = Vector2i(521, 159) +size = Vector2i(521, 175) ok_button_text = "Open" mode_overrides_title = false file_mode = 0 @@ -161,28 +111,27 @@ filters = PackedStringArray("*.gdshader") use_native_dialog = true [node name="SaveShaderDialog" type="FileDialog" parent="UI_Layer/UserInterfaceContainer/Editor"] +unique_name_in_owner = true title = "Save Shader" -size = Vector2i(661, 159) +size = Vector2i(661, 175) ok_button_text = "Save" mode_overrides_title = false access = 2 filters = PackedStringArray("*.gdshader") use_native_dialog = true -[node name="Label" type="Label" parent="UI_Layer/UserInterfaceContainer/Editor"] -layout_mode = 0 -offset_right = 104.0 -offset_bottom = 32.0 -text = "Load Preset: " -vertical_alignment = 1 - -[node name="PresetOptions" type="OptionButton" parent="UI_Layer/UserInterfaceContainer/Editor"] -layout_mode = 0 -offset_left = 104.0 -offset_right = 240.0 -offset_bottom = 32.0 +[node name="SaveImageDialog" type="FileDialog" parent="UI_Layer/UserInterfaceContainer/Editor"] +unique_name_in_owner = true +title = "Export Image" +size = Vector2i(661, 175) +ok_button_text = "Save" +mode_overrides_title = false +access = 2 +filters = PackedStringArray("*.png") +use_native_dialog = true [node name="CodeEdit" type="CodeEdit" parent="UI_Layer/UserInterfaceContainer/Editor"] +unique_name_in_owner = true layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 @@ -208,48 +157,55 @@ auto_brace_completion_highlight_matching = true [node name="OpenShaderButton" type="Button" parent="UI_Layer/UserInterfaceContainer/Editor"] layout_mode = 1 -anchors_preset = 1 -anchor_left = 1.0 -anchor_right = 1.0 -offset_left = -216.0 -offset_right = -160.0 +offset_right = 56.0 offset_bottom = 32.0 -grow_horizontal = 0 text = "Open" [node name="SaveShaderButton" type="Button" parent="UI_Layer/UserInterfaceContainer/Editor"] layout_mode = 1 -anchors_preset = 1 -anchor_left = 1.0 -anchor_right = 1.0 -offset_left = -152.0 -offset_right = -96.0 +offset_left = 64.0 +offset_right = 120.0 offset_bottom = 32.0 -grow_horizontal = 0 text = "Save" [node name="ApplyShaderButton" type="Button" parent="UI_Layer/UserInterfaceContainer/Editor"] layout_mode = 1 +offset_left = 128.0 +offset_right = 216.0 +offset_bottom = 32.0 +text = "Apply (F5)" + +[node name="SaveImageButton" type="Button" parent="UI_Layer/UserInterfaceContainer/Editor"] +layout_mode = 1 anchors_preset = 1 anchor_left = 1.0 anchor_right = 1.0 -offset_left = -88.0 +offset_left = -120.0 offset_bottom = 32.0 grow_horizontal = 0 -text = "Apply (F5)" +text = "Export Image" + +[node name="FitImageButton" type="Button" parent="UI_Layer/UserInterfaceContainer/Editor"] +layout_mode = 1 +anchors_preset = 1 +anchor_left = 1.0 +anchor_right = 1.0 +offset_left = -216.0 +offset_right = -128.0 +offset_bottom = 32.0 +grow_horizontal = 0 +text = "Fit Image" [node name="Camera" type="Camera2D" parent="."] +unique_name_in_owner = true script = ExtResource("8_mls06") -[connection signal="file_selected" from="UI_Layer/UserInterfaceContainer/OpenImageDialog" to="." method="_on_open_image_dialog_file_selected"] -[connection signal="file_selected" from="UI_Layer/UserInterfaceContainer/SaveImageDialog" to="." method="_on_save_image_dialog_file_selected"] -[connection signal="pressed" from="UI_Layer/UserInterfaceContainer/OpenImageButton" to="." method="_on_open_image_button_pressed"] -[connection signal="pressed" from="UI_Layer/UserInterfaceContainer/SaveImageButton" to="." method="_on_save_image_button_pressed"] -[connection signal="pressed" from="UI_Layer/UserInterfaceContainer/FitImageButton" to="Camera" method="_on_fit_image_button_pressed"] [connection signal="file_selected" from="UI_Layer/UserInterfaceContainer/Editor/OpenShaderDialog" to="UI_Layer/UserInterfaceContainer/Editor" method="_on_open_shader_dialog_file_selected"] [connection signal="file_selected" from="UI_Layer/UserInterfaceContainer/Editor/SaveShaderDialog" to="UI_Layer/UserInterfaceContainer/Editor" method="_on_save_shader_dialog_file_selected"] -[connection signal="item_selected" from="UI_Layer/UserInterfaceContainer/Editor/PresetOptions" to="UI_Layer/UserInterfaceContainer/Editor" method="_on_preset_options_item_selected"] +[connection signal="file_selected" from="UI_Layer/UserInterfaceContainer/Editor/SaveImageDialog" to="." method="_on_save_image_dialog_file_selected"] [connection signal="code_completion_requested" from="UI_Layer/UserInterfaceContainer/Editor/CodeEdit" to="UI_Layer/UserInterfaceContainer/Editor" method="_on_code_edit_code_completion_requested"] [connection signal="pressed" from="UI_Layer/UserInterfaceContainer/Editor/OpenShaderButton" to="UI_Layer/UserInterfaceContainer/Editor" method="_on_open_shader_button_pressed"] [connection signal="pressed" from="UI_Layer/UserInterfaceContainer/Editor/SaveShaderButton" to="UI_Layer/UserInterfaceContainer/Editor" method="_on_save_shader_button_pressed"] [connection signal="pressed" from="UI_Layer/UserInterfaceContainer/Editor/ApplyShaderButton" to="UI_Layer/UserInterfaceContainer/Editor" method="_on_apply_shader_button_pressed"] +[connection signal="pressed" from="UI_Layer/UserInterfaceContainer/Editor/SaveImageButton" to="." method="_on_save_image_button_pressed"] +[connection signal="pressed" from="UI_Layer/UserInterfaceContainer/Editor/FitImageButton" to="Camera" method="_on_fit_image_button_pressed"] diff --git a/screenshot.png b/screenshot.png index 5595ae5..551bf4d 100644 Binary files a/screenshot.png and b/screenshot.png differ diff --git a/src/Camera.gd b/src/Camera.gd index 231add8..1bc16f4 100644 --- a/src/Camera.gd +++ b/src/Camera.gd @@ -2,8 +2,9 @@ extends Camera2D var drag = false -@onready var user_interface_container = get_parent().get_node("UI_Layer/UserInterfaceContainer") -@onready var image_viewport = get_parent().get_node("ImageViewport") +@onready var user_interface_container = %UserInterfaceContainer +@onready var image_viewport = %ImageViewport +@onready var image_viewport_display = %ImageViewportDisplay func _input(event): if event.is_action_pressed("zoom_out") && !Globals.camera_freeze: @@ -32,11 +33,13 @@ func zoom_in(): var old_mouse_pos = get_global_mouse_position() zoom *= 1.2 global_position += old_mouse_pos - get_global_mouse_position() + image_viewport_display.update_zoom_texture_filter(zoom) func zoom_out(): var old_mouse_pos = get_global_mouse_position() zoom *= 1/1.2 global_position += old_mouse_pos - get_global_mouse_position() + image_viewport_display.update_zoom_texture_filter(zoom) func _on_fit_image_button_pressed(): fit_image() diff --git a/src/Editor.gd b/src/Editor.gd index a22d5c8..ae8ed61 100644 --- a/src/Editor.gd +++ b/src/Editor.gd @@ -1,11 +1,8 @@ extends Control -@onready var preset_options = $PresetOptions -@onready var code_editor = $CodeEdit -@onready var open_shader_dialog = $OpenShaderDialog -@onready var save_shader_dialog = $SaveShaderDialog -var selected_preset_name = ShaderPresets.default_preset -var last_save_filepath = "" +@onready var code_editor = %CodeEdit +@onready var open_shader_dialog = %OpenShaderDialog +@onready var save_shader_dialog = %SaveShaderDialog # # # # # # # # # # # # GDShader keywords # @@ -189,35 +186,17 @@ func _input(event): accept_event() # Event is now handled. _on_save_shader_button_pressed() -func _on_preset_options_item_selected(index): - selected_preset_name = preset_options.get_item_text(index) - Globals.shader = ShaderPresets.presets[selected_preset_name] - Globals.target_viewport.update() - update() - last_save_filepath = "" - func update(): - preset_options.clear() - # the following lines are weird af - var presets: Array[String] = [] - var current_p_idx = 0 - for p in ShaderPresets.presets: - presets.append(p) - if p == selected_preset_name: - current_p_idx = len(presets) - 1 - preset_options.add_item(p) - preset_options.select(current_p_idx) - # weirdness ends here code_editor.text = Globals.shader.code func _on_open_shader_button_pressed(): open_shader_dialog.show() func _on_save_shader_button_pressed(): - if last_save_filepath == "": - save_shader_dialog.current_file = selected_preset_name + "_custom.gdshader" + if Globals.last_shader_savepath == "": + save_shader_dialog.current_file = "shader.gdshader" else: - save_shader_dialog.current_path = last_save_filepath + save_shader_dialog.current_path = Globals.last_shader_savepath save_shader_dialog.show() func _on_open_shader_dialog_file_selected(path: String): @@ -231,7 +210,7 @@ func _on_open_shader_dialog_file_selected(path: String): Globals.cwd = path.substr(0, path.rfind("/")) Globals.target_viewport.update() update() - last_save_filepath = path + Globals.last_shader_savepath = path func _on_save_shader_dialog_file_selected(path): print("Save ", path) @@ -240,7 +219,7 @@ func _on_save_shader_dialog_file_selected(path): file.store_string(content) if "/" in path: # update current working directory Globals.cwd = path.substr(0, path.rfind("/")) - last_save_filepath = path + Globals.last_shader_savepath = path func _on_apply_shader_button_pressed(): var shader = Shader.new() diff --git a/src/Globals.gd b/src/Globals.gd index 44e8681..0351452 100644 --- a/src/Globals.gd +++ b/src/Globals.gd @@ -1,6 +1,8 @@ extends Node var camera_freeze = false -@onready var shader: Shader = ShaderPresets.presets[ShaderPresets.default_preset] +@onready var shader: Shader = load("res://src/shaders/empty.gdshader") var target_viewport: SubViewport var cwd = "." +var last_image_savepath = "" +var last_shader_savepath = "" diff --git a/src/ImageViewport.gd b/src/ImageViewport.gd index 1db1e55..207d283 100644 --- a/src/ImageViewport.gd +++ b/src/ImageViewport.gd @@ -1,46 +1,71 @@ extends SubViewport -@onready var image_sprite = $ImageSprite +@onready var camera = %Camera +@onready var image_sprite = %ImageSprite var image_original_tex: ImageTexture var image_result: Image -var load_uniform_regex: RegEx +var load_regex: RegEx +var load_additional_regex: RegEx +var last_tex_path = "" func _ready(): - load_uniform_regex = RegEx.new() - load_uniform_regex.compile(r'\/\/!load\s(\w*)\s(.*)') + load_regex = RegEx.new() + load_additional_regex = RegEx.new() + load_regex.compile(r'\/\/!load\s(.*)') + load_additional_regex.compile(r'\/\/!load\+\s(\w*)\s(.*)') -func set_original_image(image: Image): - image_original_tex = ImageTexture.create_from_image(image) - image_sprite.texture = image_original_tex - image_sprite.offset = image_original_tex.get_size() / 2 - size = image_original_tex.get_size() +func load_texture(path): + print("Load ", path) + var img = Image.new() + var err = img.load(path) + if err == OK: + image_original_tex = ImageTexture.create_from_image(img) + image_sprite.texture = image_original_tex + image_sprite.offset = image_original_tex.get_size() / 2 + size = image_original_tex.get_size() + else: + print("An error occured!") + +func get_absolute_path(p: String) -> String: + if !p.begins_with("/"): + return Globals.cwd + "/" + p.lstrip("./") + return p func update(): - if image_original_tex != null: - image_sprite.texture = image_original_tex - var mat = ShaderMaterial.new() - mat.shader = Globals.shader - # load images from //!load directives and apply them to - # the material as shader parameters - for m in load_uniform_regex.search_all(Globals.shader.code): - # this only works for Linux! - var img_path = m.strings[2] - if !img_path.begins_with("/"): - img_path = Globals.cwd + "/" + img_path.lstrip("./") - # - print("Load ", img_path) - var u_image = Image.load_from_file(img_path) - mat.set_shader_parameter( - m.strings[1], # uniform param name - ImageTexture.create_from_image(u_image)) - # assign material - image_sprite.material = mat - # Get viewport texture - await RenderingServer.frame_post_draw # for good measure - image_result = get_texture().get_image() - image_sprite.material = null - image_sprite.texture = ImageTexture.create_from_image(image_result) + # load images from //!load directive -> TEXTURE + var regex_match = load_regex.search(Globals.shader.code) + if regex_match == null: # Error! + print("Didn't find any load directives!") + return + var tex_path = get_absolute_path(regex_match.strings[1]) + load_texture(tex_path) # load every time + if tex_path != last_tex_path: + camera.fit_image() + last_tex_path = tex_path + if Globals.last_image_savepath == "": + Globals.last_image_savepath = tex_path + image_sprite.texture = image_original_tex + var mat = ShaderMaterial.new() + mat.shader = Globals.shader + # load images from //!load+ directives and apply them to + # the material as shader parameters + for m in load_additional_regex.search_all(Globals.shader.code): + # this only works for Linux! + var img_path = get_absolute_path(m.strings[2]) + # + print("Load ", img_path) + var u_image = Image.load_from_file(img_path) + mat.set_shader_parameter( + m.strings[1], # uniform param name + ImageTexture.create_from_image(u_image)) + # assign material + image_sprite.material = mat + # Get viewport texture + await RenderingServer.frame_post_draw # for good measure + image_result = get_texture().get_image() + image_sprite.material = null + image_sprite.texture = ImageTexture.create_from_image(image_result) func get_result(): return image_result diff --git a/src/ImageViewportDisplays.gd b/src/ImageViewportDisplay.gd similarity index 53% rename from src/ImageViewportDisplays.gd rename to src/ImageViewportDisplay.gd index d4817ca..9edcf83 100644 --- a/src/ImageViewportDisplays.gd +++ b/src/ImageViewportDisplay.gd @@ -1,9 +1,7 @@ extends Sprite2D -@onready var camera = get_parent().get_node("Camera") - -func _process(_delta): - if camera.zoom.x >= 1.5: +func update_zoom_texture_filter(zoom: Vector2): + if zoom.x >= 1.5: texture_filter = TEXTURE_FILTER_NEAREST_WITH_MIPMAPS else: texture_filter = TEXTURE_FILTER_LINEAR diff --git a/src/Main.gd b/src/Main.gd index b930536..42be43b 100644 --- a/src/Main.gd +++ b/src/Main.gd @@ -1,33 +1,16 @@ extends Node2D -@onready var camera = $Camera -@onready var image_viewport = $ImageViewport -@onready var ui_container = $UI_Layer/UserInterfaceContainer -@onready var ui_control_fileopen = $UI_Layer/UserInterfaceContainer/OpenImageDialog -@onready var ui_control_filesave = $UI_Layer/UserInterfaceContainer/SaveImageDialog -var last_save_filepath = "" +@onready var image_viewport = %ImageViewport +@onready var ui_control_filesave = %SaveImageDialog + func _ready(): + DisplayServer.window_set_min_size(Vector2i(900, 500)) Globals.target_viewport = image_viewport -func _on_open_image_button_pressed(): - ui_control_fileopen.show() - -func _on_open_image_dialog_file_selected(path): - print("Load ", path) - var img = Image.new() - var err = img.load(path) - if err == OK: - image_viewport.set_original_image(img) - image_viewport.update() - camera.fit_image() - last_save_filepath = path - else: - print("An error occured!") - func _on_save_image_button_pressed(): if image_viewport.get_result() != null: - ui_control_filesave.current_path = last_save_filepath + ui_control_filesave.current_path = Globals.last_image_savepath ui_control_filesave.show() func _on_save_image_dialog_file_selected(path): @@ -36,4 +19,4 @@ func _on_save_image_dialog_file_selected(path): if err != OK: print("An error occured!") else: - last_save_filepath = path + Globals.last_image_savepath = path diff --git a/src/presets/Presets.gd b/src/presets/Presets.gd deleted file mode 100644 index c009bd2..0000000 --- a/src/presets/Presets.gd +++ /dev/null @@ -1,14 +0,0 @@ -extends Node - -const dir = "res://src/presets/shaders/" - -@onready var presets = { - "Empty": load(dir + "empty.gdshader"), - "Greyscale": load(dir + "greyscale.gdshader"), - "Lowpass": load(dir + "lowpass.gdshader"), - "Channel Offset": load(dir + "channel_offset.gdshader"), - "RGB -> UV Distort": load(dir + "rgb_uv_distort.gdshader"), - "Mix": load(dir + "mix.gdshader") -} - -var default_preset: String = "Empty" diff --git a/src/presets/shaders/empty.gdshader b/src/shaders/empty.gdshader similarity index 77% rename from src/presets/shaders/empty.gdshader rename to src/shaders/empty.gdshader index 0cb1281..be6c5cc 100644 --- a/src/presets/shaders/empty.gdshader +++ b/src/shaders/empty.gdshader @@ -1,5 +1,7 @@ shader_type canvas_item; +//!load /path/to/your/image + void fragment() { // Called for every pixel the material is visible on. }