1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-02-13 09:13:07 +00:00
Pixelorama/src/UI/Dialogs/ImageEffects/ShaderEffect.gd
OverloadedOrama fe2ed42819 Use VisualServer viewport for applying shader
This comes with the benefit that we no longer need a Viewport node in the ShaderEffect dialog, which lets us have the Preview TextureRect at a fixed size. Previously, the preview was scaled based on the image's size, which would make applying shaders to large images very inconvenient, since the dialog would be way too big.
2020-08-13 01:55:31 +03:00

145 lines
4.4 KiB
GDScript

extends ConfirmationDialog
var current_cel : Image
var shader : Shader
var params := [] # String[]
onready var preview : TextureRect = $VBoxContainer/Preview
onready var shader_loaded_label : Label = $VBoxContainer/ShaderLoadedLabel
onready var shader_params : BoxContainer = $VBoxContainer/ShaderParams
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
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:
if !shader:
return
current_cel.unlock()
var viewport_texture := Image.new()
var size : Vector2 = Global.current_project.size
var vp = VisualServer.viewport_create()
var canvas = VisualServer.canvas_create()
VisualServer.viewport_attach_canvas(vp, canvas)
VisualServer.viewport_set_size(vp, size.x, size.y)
VisualServer.viewport_set_disable_3d(vp, true)
VisualServer.viewport_set_usage(vp, VisualServer.VIEWPORT_USAGE_2D)
VisualServer.viewport_set_hdr(vp, true)
VisualServer.viewport_set_active(vp, true)
VisualServer.viewport_set_transparent_background(vp, true)
var ci_rid = VisualServer.canvas_item_create()
VisualServer.viewport_set_canvas_transform(vp, canvas, Transform())
VisualServer.canvas_item_set_parent(ci_rid, canvas)
var texture = ImageTexture.new()
texture.create_from_image(current_cel)
VisualServer.canvas_item_add_texture_rect(ci_rid, Rect2(Vector2(0, 0), size), texture)
var mat_rid = VisualServer.material_create()
VisualServer.material_set_shader(mat_rid, shader.get_rid())
VisualServer.canvas_item_set_material(ci_rid, mat_rid)
for param in params:
var param_data = preview.material.get_shader_param(param)
VisualServer.material_set_param(mat_rid, param, param_data)
VisualServer.viewport_set_update_mode(vp, VisualServer.VIEWPORT_UPDATE_ONCE)
VisualServer.viewport_set_vflip(vp, true)
VisualServer.force_draw(false)
viewport_texture = VisualServer.texture_get_data(VisualServer.viewport_get_texture(vp))
VisualServer.free_rid(vp)
VisualServer.free_rid(canvas)
VisualServer.free_rid(ci_rid)
VisualServer.free_rid(mat_rid)
print(viewport_texture.data)
viewport_texture.convert(Image.FORMAT_RGBA8)
Global.canvas.handle_undo("Draw")
current_cel.copy_from(viewport_texture)
Global.canvas.handle_redo("Draw")
current_cel.lock()
func _on_ShaderEffect_popup_hide() -> void:
Global.dialog_open(false)
func _on_ChooseShader_pressed() -> void:
if OS.get_name() == "HTML5":
Html5FileExchange.load_shader()
else:
$FileDialog.popup_centered(Vector2(300, 340))
func _on_FileDialog_file_selected(path : String) -> void:
var _shader = load(path)
if !_shader is Shader:
return
change_shader(_shader, path.get_file().get_basename())
func change_shader(_shader : Shader, name : String) -> void:
shader = _shader
preview.material.shader = _shader
shader_loaded_label.text = tr("Shader loaded:") + " " + name
params.clear()
for child in shader_params.get_children():
child.queue_free()
var code = shader.code.split("\n")
var uniforms := []
for line in code:
if line.begins_with("uniform"):
uniforms.append(line)
for uniform in uniforms:
# Example uniform:
# uniform float parameter_name : hint_range(0, 255) = 100.0;
var uniform_split = uniform.split("=")
var u_value := ""
if uniform_split.size() > 1:
u_value = uniform_split[1].replace(";", "").strip_edges()
var u_left_side = uniform_split[0].split(":")
var _u_hint := ""
if u_left_side.size() > 1:
_u_hint = u_left_side[1].strip_edges()
var u_init = u_left_side[0].split(" ")
var u_type = u_init[1]
var u_name = u_init[2]
params.append(u_name)
if u_type == "float":
var label := Label.new()
label.text = u_name
var spinbox := SpinBox.new()
spinbox.min_value = 0.01
spinbox.max_value = 255
spinbox.step = 0.01
if u_value != "":
spinbox.value = float(u_value)
spinbox.connect("value_changed", self, "set_shader_param", [u_name])
var hbox := HBoxContainer.new()
hbox.add_child(label)
hbox.add_child(spinbox)
shader_params.add_child(hbox)
# print("---")
# print(uniform_split)
# print(u_type)
# print(u_name)
# print(u_hint)
# print(u_value)
# print("--")
func set_shader_param(value, param : String) -> void:
preview.material.set_shader_param(param, value)