diff --git a/src/Autoload/HTML5FileExchange.gd b/src/Autoload/HTML5FileExchange.gd
index 19d4fad9c..96b380271 100644
--- a/src/Autoload/HTML5FileExchange.gd
+++ b/src/Autoload/HTML5FileExchange.gd
@@ -69,6 +69,27 @@ func _define_js() -> void:
}
});
}
+ function upload_shader() {
+ canceled = true;
+ var input = document.createElement('INPUT');
+ input.setAttribute("type", "file");
+ input.setAttribute("accept", ".shader");
+ input.click();
+ input.addEventListener('change', event => {
+ if (event.target.files.length > 0){
+ canceled = false;}
+ var file = event.target.files[0];
+ var reader = new FileReader();
+ fileType = file.type;
+ fileName = file.name;
+ reader.readAsText(file);
+ reader.onloadend = function (evt) {
+ if (evt.target.readyState == FileReader.DONE) {
+ fileData = evt.target.result;
+ }
+ }
+ });
+ }
function download(fileName, byte, type) {
var buffer = Uint8Array.from(byte);
var blob = new Blob([buffer], { type: type});
@@ -174,3 +195,37 @@ func save_image(image : Image, file_name : String = "export") -> void:
var png_data = Array(image.save_png_to_buffer())
JavaScript.eval("download('%s', %s, 'image/png');" % [file_name, str(png_data)], true)
+
+
+func load_shader() -> void:
+ if OS.get_name() != "HTML5" or !OS.has_feature('JavaScript'):
+ return
+
+ # Execute JS function
+ JavaScript.eval("upload_shader();", true) # Opens prompt for choosing file
+
+ yield(self, "InFocus") # Wait until JS prompt is closed
+
+ yield(get_tree().create_timer(0.5), "timeout") # Give some time for async JS data load
+
+ if JavaScript.eval("canceled;", true): # If File Dialog closed w/o file
+ return
+
+ # Use data from png data
+ var file_data
+ while true:
+ file_data = JavaScript.eval("fileData;", true)
+ if file_data != null:
+ break
+ yield(get_tree().create_timer(1.0), "timeout") # Need more time to load data
+
+# var file_type = JavaScript.eval("fileType;", true)
+ var file_name = JavaScript.eval("fileName;", true)
+
+ var shader = Shader.new()
+ shader.code = file_data
+
+ var shader_effect_dialog = Global.control.get_node("Dialogs/ImageEffects/ShaderEffect")
+ shader_effect_dialog.preview.material.shader = shader
+ shader_effect_dialog.shader_loaded_label.text = tr("Shader loaded:") + " " + file_name.get_basename()
+
diff --git a/src/Main.tscn b/src/Main.tscn
index 3f386476c..eaee70651 100644
--- a/src/Main.tscn
+++ b/src/Main.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=21 format=2]
+[gd_scene load_steps=22 format=2]
[ext_resource path="res://assets/themes/dark/theme.tres" type="Theme" id=1]
[ext_resource path="res://src/Main.gd" type="Script" id=2]
@@ -9,6 +9,7 @@
[ext_resource path="res://src/UI/Dialogs/ResizeCanvas.tscn" type="PackedScene" id=7]
[ext_resource path="res://src/UI/Dialogs/SaveSpriteHTML5.tscn" type="PackedScene" id=8]
[ext_resource path="res://src/UI/Dialogs/GradientDialog.tscn" type="PackedScene" id=9]
+[ext_resource path="res://src/UI/Dialogs/ShaderEffect.tscn" type="PackedScene" id=10]
[ext_resource path="res://src/UI/Dialogs/SaveSprite.tscn" type="PackedScene" id=11]
[ext_resource path="res://src/UI/Dialogs/OpenSprite.tscn" type="PackedScene" id=12]
[ext_resource path="res://src/UI/Dialogs/SplashDialog.tscn" type="PackedScene" id=27]
@@ -45,17 +46,16 @@ __meta__ = {
[node name="UI" parent="MenuAndUI" instance=ExtResource( 4 )]
[node name="Dialogs" type="Control" parent="."]
-margin_right = 40.0
-margin_bottom = 40.0
mouse_filter = 2
__meta__ = {
"_edit_use_anchors_": false
}
[node name="ImageEffects" type="Control" parent="Dialogs"]
-margin_right = 40.0
-margin_bottom = 40.0
mouse_filter = 2
+__meta__ = {
+"_edit_use_anchors_": false
+}
[node name="ScaleImage" parent="Dialogs/ImageEffects" instance=ExtResource( 31 )]
margin_bottom = 127.0
@@ -75,6 +75,8 @@ margin_bottom = 106.0
[node name="GradientDialog" parent="Dialogs/ImageEffects" instance=ExtResource( 9 )]
margin_bottom = 214.0
+[node name="ShaderEffect" parent="Dialogs/ImageEffects" instance=ExtResource( 10 )]
+
[node name="BrushesPopup" parent="Dialogs" instance=ExtResource( 6 )]
[node name="PatternsPopup" parent="Dialogs" instance=ExtResource( 5 )]
diff --git a/src/UI/Dialogs/ShaderEffect.gd b/src/UI/Dialogs/ShaderEffect.gd
new file mode 100644
index 000000000..b9a161dd5
--- /dev/null
+++ b/src/UI/Dialogs/ShaderEffect.gd
@@ -0,0 +1,56 @@
+extends ConfirmationDialog
+
+
+var current_cel : Image
+
+onready var viewport : Viewport = $VBoxContainer/ViewportContainer/Viewport
+onready var preview : TextureRect = viewport.get_node("Preview")
+onready var shader_loaded_label : Label = $VBoxContainer/ShaderLoadedLabel
+
+
+func _on_ShaderEffect_about_to_show() -> void:
+ current_cel = Global.current_project.frames[Global.current_project.current_frame].cels[Global.current_project.current_layer].image
+ current_cel.unlock()
+ viewport.size = current_cel.get_size()
+ var viewport_texture = viewport.get_texture().get_data()
+ viewport_texture.convert(Image.FORMAT_RGBA8)
+
+ var preview_image := Image.new()
+ preview_image.copy_from(current_cel)
+ var preview_texture = ImageTexture.new()
+ preview_texture.create_from_image(preview_image, 0)
+ preview.texture = preview_texture
+
+
+func _on_ShaderEffect_confirmed() -> void:
+ var viewport_texture = viewport.get_texture().get_data()
+ viewport_texture.flip_y()
+ viewport_texture.convert(Image.FORMAT_RGBA8)
+ print(viewport_texture.get_size())
+ Global.canvas.handle_undo("Draw")
+ current_cel.copy_from(viewport_texture)
+ Global.canvas.handle_redo("Draw")
+
+
+func _on_ShaderEffect_popup_hide() -> void:
+ current_cel.lock()
+ Global.dialog_open(false)
+ yield(get_tree().create_timer(0.2), "timeout")
+ preview.texture = null
+ viewport.size = Vector2.ONE
+ rect_size = Vector2.ONE
+
+
+func _on_ChooseShader_pressed() -> void:
+ if OS.get_name() == "HTML5":
+ Html5FileExchange.load_shader()
+ else:
+ $FileDialog.popup_centered(Vector2(200, 340))
+
+
+func _on_FileDialog_file_selected(path : String) -> void:
+ var shader = load(path)
+ if !shader is Shader:
+ return
+ preview.material.shader = shader
+ shader_loaded_label.text = tr("Shader loaded:") + " " + path.get_file().get_basename()
diff --git a/src/UI/Dialogs/ShaderEffect.tscn b/src/UI/Dialogs/ShaderEffect.tscn
new file mode 100644
index 000000000..f34128008
--- /dev/null
+++ b/src/UI/Dialogs/ShaderEffect.tscn
@@ -0,0 +1,86 @@
+[gd_scene load_steps=3 format=2]
+
+[ext_resource path="res://src/UI/Dialogs/ShaderEffect.gd" type="Script" id=2]
+
+[sub_resource type="ShaderMaterial" id=1]
+
+[node name="ShaderEffect" type="ConfirmationDialog"]
+margin_right = 200.0
+margin_bottom = 228.0
+rect_min_size = Vector2( 0, 0 )
+resizable = true
+script = ExtResource( 2 )
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="VBoxContainer" type="VBoxContainer" parent="."]
+anchor_right = 1.0
+anchor_bottom = 1.0
+margin_left = 8.0
+margin_top = 8.0
+margin_right = -8.0
+margin_bottom = -36.0
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="Label" type="Label" parent="VBoxContainer"]
+margin_right = 255.0
+margin_bottom = 48.0
+text = "This is an experimental feature and may not be included in the stable version"
+autowrap = true
+
+[node name="ViewportContainer" type="ViewportContainer" parent="VBoxContainer"]
+margin_top = 52.0
+margin_right = 255.0
+margin_bottom = 53.0
+__meta__ = {
+"_edit_use_anchors_": false
+}
+
+[node name="Viewport" type="Viewport" parent="VBoxContainer/ViewportContainer"]
+size = Vector2( 1, 1 )
+transparent_bg = true
+handle_input_locally = false
+disable_3d = true
+usage = 0
+render_target_update_mode = 0
+gui_disable_input = true
+
+[node name="Preview" type="TextureRect" parent="VBoxContainer/ViewportContainer/Viewport"]
+material = SubResource( 1 )
+anchor_right = 1.0
+anchor_bottom = 1.0
+
+[node name="ChooseShader" type="Button" parent="VBoxContainer"]
+margin_top = 57.0
+margin_right = 255.0
+margin_bottom = 77.0
+mouse_default_cursor_shape = 2
+text = "Choose Shader"
+
+[node name="ShaderLoadedLabel" type="Label" parent="VBoxContainer"]
+margin_top = 81.0
+margin_right = 255.0
+margin_bottom = 95.0
+text = "No shader loaded!"
+autowrap = true
+
+[node name="FileDialog" type="FileDialog" parent="."]
+margin_left = 8.0
+margin_top = 8.0
+margin_right = 263.0
+margin_bottom = 192.0
+window_title = "Open a File"
+resizable = true
+mode = 0
+access = 2
+filters = PoolStringArray( "*shader" )
+current_dir = "/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/Pixelorama"
+current_path = "/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/Pixelorama/"
+[connection signal="about_to_show" from="." to="." method="_on_ShaderEffect_about_to_show"]
+[connection signal="confirmed" from="." to="." method="_on_ShaderEffect_confirmed"]
+[connection signal="popup_hide" from="." to="." method="_on_ShaderEffect_popup_hide"]
+[connection signal="pressed" from="VBoxContainer/ChooseShader" to="." method="_on_ChooseShader_pressed"]
+[connection signal="file_selected" from="FileDialog" to="." method="_on_FileDialog_file_selected"]
diff --git a/src/UI/TopMenuContainer.gd b/src/UI/TopMenuContainer.gd
index 3bdaf5c79..534eab882 100644
--- a/src/UI/TopMenuContainer.gd
+++ b/src/UI/TopMenuContainer.gd
@@ -94,7 +94,8 @@ func setup_image_menu() -> void:
"Desaturation" : 0,
"Outline" : 0,
"Adjust Hue/Saturation/Value" : 0,
- "Gradient" : 0
+ "Gradient" : 0,
+ "Shader" : 0
}
var image_menu : PopupMenu = Global.image_menu.get_popup()
@@ -333,6 +334,9 @@ func image_menu_id_pressed(id : int) -> void:
10: # Gradient
Global.control.get_node("Dialogs/ImageEffects/GradientDialog").popup_centered()
Global.dialog_open(true)
+ 11: # Shader
+ Global.control.get_node("Dialogs/ImageEffects/ShaderEffect").popup_centered()
+ Global.dialog_open(true)
func show_scale_image_popup() -> void: