1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-18 17:19:50 +00:00

[EXPERIMENTAL] Added ability to load a shader as an image effect

This new feature allows users to load a .shader file (must be a GLES2 Godot shader) that will modify the image itself. This feature is experimental and possibly buggy, not all shaders are working properly and I'm not sure yet why. As such, this feature may not be included in v0.8 stable.
This commit is contained in:
OverloadedOrama 2020-07-25 16:26:57 +03:00
parent 59122f6a13
commit 186e2259ac
5 changed files with 209 additions and 6 deletions

View file

@ -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()

View file

@ -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 )]

View file

@ -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()

View file

@ -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"]

View file

@ -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: