New preview menu, added support for expressions in float parameters

This commit is contained in:
RodZill4 2020-04-13 09:32:59 +02:00
parent fe2c83a79a
commit bd868d8a55
18 changed files with 296 additions and 92 deletions

View File

@ -1,3 +1,9 @@
varying float elapsed_time;
void vertex() {
elapsed_time = TIME;
}
float rand(vec2 x) { float rand(vec2 x) {
return fract(cos(dot(x, vec2(13.9898, 8.141))) * 43758.5453); return fract(cos(dot(x, vec2(13.9898, 8.141))) * 43758.5453);
} }

View File

@ -130,7 +130,7 @@ func set_parameter(n : String, v) -> void:
if is_inside_tree(): if is_inside_tree():
var parameter_def : Dictionary = get_parameter_def(n) var parameter_def : Dictionary = get_parameter_def(n)
if parameter_def.has("type"): if parameter_def.has("type"):
if parameter_def.type == "float": if parameter_def.type == "float" and v is float and old_value is float:
var parameter_name = "p_o"+str(get_instance_id())+"_"+n var parameter_name = "p_o"+str(get_instance_id())+"_"+n
get_tree().call_group("preview", "on_float_parameters_changed", { parameter_name:v }) get_tree().call_group("preview", "on_float_parameters_changed", { parameter_name:v })
return return

View File

@ -149,27 +149,33 @@ func replace_input(string : String, context, input : String, type : String, src
func is_word_letter(l) -> bool: func is_word_letter(l) -> bool:
return "azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN1234567890_".find(l) != -1 return "azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN1234567890_".find(l) != -1
func replace_variable(string : String, variable : String, value : String) -> String: func replace_variables(string : String, variables : Dictionary) -> String:
string = string.replace("$(%s)" % variable, value) while true:
var keyword_size = variable.length()+1 var old_string = string
var new_string = "" for variable in variables.keys():
while !string.empty(): string = string.replace("$(%s)" % variable, variables[variable])
var pos = string.find("$"+variable) var keyword_size : int = variable.length()+1
if pos == -1: var new_string : String = ""
new_string += string while !string.empty():
var pos : int = string.find("$"+variable)
if pos == -1:
new_string += string
break
new_string += string.left(pos)
string = string.right(pos)
if string.length() > keyword_size and is_word_letter(string[keyword_size]):
new_string += string.left(keyword_size)
string = string.right(keyword_size)
continue
if string.empty() or !is_word_letter(string[0]):
new_string += variables[variable]
else:
new_string += "$"+variable
string = string.right(keyword_size)
string = new_string
if string == old_string:
break break
new_string += string.left(pos) return string
string = string.right(pos)
if string.length() > keyword_size and is_word_letter(string[keyword_size]):
new_string += string.left(keyword_size)
string = string.right(keyword_size)
continue
if string.empty() or !is_word_letter(string[0]):
new_string += value
else:
new_string += "$"+variable
string = string.right(keyword_size)
return new_string
func subst(string : String, context : MMGenContext, uv : String = "") -> Dictionary: func subst(string : String, context : MMGenContext, uv : String = "") -> Dictionary:
var genname = "o"+str(get_instance_id()) var genname = "o"+str(get_instance_id())
@ -177,13 +183,13 @@ func subst(string : String, context : MMGenContext, uv : String = "") -> Diction
var required_defs = "" var required_defs = ""
var required_code = "" var required_code = ""
var required_textures = {} var required_textures = {}
string = replace_variable(string, "name", genname) var variables = {}
variables["name"] = genname
if uv != "": if uv != "":
var genname_uv = genname+"_"+str(context.get_variant(self, uv)) var genname_uv = genname+"_"+str(context.get_variant(self, uv))
string = replace_variable(string, "name_uv", genname_uv) variables["name_uv"] = genname_uv
var tmp_string = replace_variable(string, "seed", "seed_"+genname) variables["seed"] = "seed_"+genname
if tmp_string != string: variables["node_id"] = str(get_instance_id())
string = tmp_string
if shader_model.has("parameters") and typeof(shader_model.parameters) == TYPE_ARRAY: if shader_model.has("parameters") and typeof(shader_model.parameters) == TYPE_ARRAY:
for p in shader_model.parameters: for p in shader_model.parameters:
if !p.has("name") or !p.has("type"): if !p.has("name") or !p.has("type"):
@ -191,7 +197,10 @@ func subst(string : String, context : MMGenContext, uv : String = "") -> Diction
var value = parameters[p.name] var value = parameters[p.name]
var value_string = null var value_string = null
if p.type == "float": if p.type == "float":
value_string = "p_%s_%s" % [ genname, p.name ] if parameters[p.name] is float:
value_string = "p_%s_%s" % [ genname, p.name ]
elif parameters[p.name] is String:
value_string = "("+parameters[p.name]+")"
elif p.type == "size": elif p.type == "size":
value_string = "%.9f" % pow(2, value) value_string = "%.9f" % pow(2, value)
elif p.type == "enum": elif p.type == "enum":
@ -207,9 +216,11 @@ func subst(string : String, context : MMGenContext, uv : String = "") -> Diction
else: else:
print("Cannot replace parameter of type "+p.type) print("Cannot replace parameter of type "+p.type)
if value_string != null: if value_string != null:
string = replace_variable(string, p.name, value_string) variables[p.name] = value_string
if uv != "": if uv != "":
string = replace_variable(string, "uv", "("+uv+")") variables["uv"] = "("+uv+")"
variables["time"] = "elapsed_time"
string = replace_variables(string, variables)
if shader_model.has("inputs") and typeof(shader_model.inputs) == TYPE_ARRAY: if shader_model.has("inputs") and typeof(shader_model.inputs) == TYPE_ARRAY:
var cont = true var cont = true
while cont: while cont:
@ -252,7 +263,7 @@ func _get_shader_code(uv : String, output_index : int, context : MMGenContext) -
if has_randomness(): if has_randomness():
rv.defs += "uniform int seed_%s = %d;\n" % [ genname, get_seed() ] rv.defs += "uniform int seed_%s = %d;\n" % [ genname, get_seed() ]
for p in shader_model.parameters: for p in shader_model.parameters:
if p.type == "float": if p.type == "float" and parameters[p.name] is float:
rv.defs += "uniform float p_%s_%s = %.9f;\n" % [ genname, p.name, parameters[p.name] ] rv.defs += "uniform float p_%s_%s = %.9f;\n" % [ genname, p.name, parameters[p.name] ]
elif p.type == "color": elif p.type == "color":
rv.defs += "uniform float p_%s_%s_r = %.9f;\n" % [ genname, p.name, parameters[p.name].r ] rv.defs += "uniform float p_%s_%s_r = %.9f;\n" % [ genname, p.name, parameters[p.name].r ]
@ -266,7 +277,7 @@ func _get_shader_code(uv : String, output_index : int, context : MMGenContext) -
g.deserialize(parameters[p.name]) g.deserialize(parameters[p.name])
var params = g.get_shader_params(genname+"_"+p.name) var params = g.get_shader_params(genname+"_"+p.name)
for sp in params.keys(): for sp in params.keys():
rv.defs += "uniform float "+sp+" = "+str(params[sp])+";\n" rv.defs += "uniform float %s = %.9f;\n" % [ sp, params[sp] ]
rv.defs += g.get_shader(genname+"_"+p.name) rv.defs += g.get_shader(genname+"_"+p.name)
# Generate functions for inputs # Generate functions for inputs
if shader_model.has("inputs"): if shader_model.has("inputs"):

View File

@ -31,7 +31,21 @@ func _ready() -> void:
add_valid_connection_type(42, t) add_valid_connection_type(42, t)
func _gui_input(event) -> void: func _gui_input(event) -> void:
if event is InputEventKey and event.pressed: if event.is_action_pressed("ui_library_popup") && get_rect().has_point(get_local_mouse_position()):
node_popup.rect_global_position = get_global_mouse_position()
node_popup.show_popup()
elif event is InputEventMouseButton:
if event.button_index == BUTTON_WHEEL_DOWN and event.control:
zoom *= 1.1
print(zoom)
get_tree().set_input_as_handled()
elif event.button_index == BUTTON_WHEEL_UP and event.control:
zoom /= 1.1
print(zoom)
get_tree().set_input_as_handled()
else:
call_deferred("check_last_selected")
elif event is InputEventKey and event.pressed:
var scancode_with_modifiers = event.get_scancode_with_modifiers() var scancode_with_modifiers = event.get_scancode_with_modifiers()
if scancode_with_modifiers == KEY_DELETE or scancode_with_modifiers == KEY_BACKSPACE: if scancode_with_modifiers == KEY_DELETE or scancode_with_modifiers == KEY_BACKSPACE:
remove_selection() remove_selection()
@ -390,13 +404,6 @@ func set_last_selected(node) -> void:
else: else:
last_selected = null last_selected = null
func _on_GraphEdit_gui_input(event) -> void:
if event.is_action_pressed("ui_library_popup") && get_rect().has_point(get_local_mouse_position()):
node_popup.rect_global_position = get_global_mouse_position()
node_popup.show_popup()
if event is InputEventMouseButton:
call_deferred("check_last_selected")
func request_popup(from, from_slot, release_position) -> void: func request_popup(from, from_slot, release_position) -> void:
# Check if the connector was actually dragged # Check if the connector was actually dragged
var node : GraphNode = get_node(from) var node : GraphNode = get_node(from)
@ -415,5 +422,3 @@ func check_last_selected() -> void:
if last_selected != null and !(is_instance_valid(last_selected) and last_selected.selected): if last_selected != null and !(is_instance_valid(last_selected) and last_selected.selected):
last_selected = null last_selected = null
emit_signal("node_selected", null) emit_signal("node_selected", null)

View File

@ -83,7 +83,6 @@ icon = SubResource( 4 )
[connection signal="copy_nodes_request" from="." to="." method="copy"] [connection signal="copy_nodes_request" from="." to="." method="copy"]
[connection signal="disconnection_request" from="." to="." method="disconnect_node"] [connection signal="disconnection_request" from="." to="." method="disconnect_node"]
[connection signal="duplicate_nodes_request" from="." to="." method="duplicate_selected"] [connection signal="duplicate_nodes_request" from="." to="." method="duplicate_selected"]
[connection signal="gui_input" from="." to="." method="_on_GraphEdit_gui_input"]
[connection signal="node_selected" from="." to="." method="_on_GraphEdit_node_selected"] [connection signal="node_selected" from="." to="." method="_on_GraphEdit_node_selected"]
[connection signal="paste_nodes_request" from="." to="." method="paste"] [connection signal="paste_nodes_request" from="." to="." method="paste"]
[connection signal="timeout" from="Timer" to="." method="do_send_changed_signal"] [connection signal="timeout" from="Timer" to="." method="do_send_changed_signal"]

View File

@ -147,7 +147,7 @@ func save_preview_widget() -> void:
func restore_preview_widget() -> void: func restore_preview_widget() -> void:
if preview == null: if preview == null:
preview = preload("res://material_maker/preview/preview_2d.tscn").instance() preview = preload("res://material_maker/preview/preview_2d_node.tscn").instance()
preview.shader = "uniform vec2 size;void fragment() {COLOR = preview_2d(UV);}" preview.shader = "uniform vec2 size;void fragment() {COLOR = preview_2d(UV);}"
preview.visible = false preview.visible = false
preview_position = get_child_count() preview_position = get_child_count()

View File

@ -23,17 +23,19 @@ func update_node() -> void:
var color = Color(0.0, 0.5, 0.0, 0.5) var color = Color(0.0, 0.5, 0.0, 0.5)
for p in generator.get_io_defs(): for p in generator.get_io_defs():
color = mm_io_types.types[p.type].color color = mm_io_types.types[p.type].color
set_slot(get_child_count(), generator.name != "gen_inputs", 0, color, generator.name != "gen_outputs", 0, color) var slot_type = mm_io_types.types[p.type].slot_type
set_slot(get_child_count(), generator.name != "gen_inputs", slot_type, color, generator.name != "gen_outputs", slot_type, color)
var port : Control var port : Control
if generator.is_editable(): if generator.is_editable():
port = preload("res://material_maker/nodes/ios/port.tscn").instance() port = preload("res://material_maker/nodes/ios/port.tscn").instance()
add_child(port)
if p.has("name"): if p.has("name"):
port.set_label(p.name) port.set_label(p.name)
port.set_type(p.type) port.set_type(p.type)
else: else:
port = Label.new() port = Label.new()
add_child(port)
port.text = p.name port.text = p.name
add_child(port)
if generator.is_editable(): if generator.is_editable():
var add_button : Button = preload("res://material_maker/nodes/ios/add.tscn").instance() var add_button : Button = preload("res://material_maker/nodes/ios/add.tscn").instance()
add_child(add_button) add_child(add_button)

View File

@ -2,8 +2,10 @@
[ext_resource path="res://material_maker/nodes/ios.gd" type="Script" id=1] [ext_resource path="res://material_maker/nodes/ios.gd" type="Script" id=1]
[node name="IOs" type="GraphNode"] [node name="IOs" type="GraphNode"]
margin_right = 32.0 margin_right = 32.0
margin_bottom = 29.0 margin_bottom = 29.0
script = ExtResource( 1 ) script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}

View File

@ -1,10 +1,16 @@
extends HBoxContainer extends HBoxContainer
func _ready() -> void:
$Type.clear()
for tn in mm_io_types.type_names:
var t = mm_io_types.types[tn]
$Type.add_item(t.label)
func set_label(l : String) -> void: func set_label(l : String) -> void:
$Name.set_text(l) $Name.set_text(l)
func set_type(t : String) -> void: func set_type(t : String) -> void:
$Type.selected = mm_io_types.type_names.find(t) $Type.select(mm_io_types.type_names.find(t))
func update_up_down_button() -> void: func update_up_down_button() -> void:
var parent = get_parent() var parent = get_parent()

View File

@ -4,9 +4,6 @@
[ext_resource path="res://material_maker/icons/icons.svg" type="Texture" id=2] [ext_resource path="res://material_maker/icons/icons.svg" type="Texture" id=2]
[ext_resource path="res://material_maker/widgets/linked_widgets/editable_label.tscn" type="PackedScene" id=3] [ext_resource path="res://material_maker/widgets/linked_widgets/editable_label.tscn" type="PackedScene" id=3]
[sub_resource type="AtlasTexture" id=1] [sub_resource type="AtlasTexture" id=1]
flags = 4 flags = 4
atlas = ExtResource( 2 ) atlas = ExtResource( 2 )
@ -54,12 +51,11 @@ rect_min_size = Vector2( 30, 0 )
[node name="Type" type="OptionButton" parent="."] [node name="Type" type="OptionButton" parent="."]
margin_left = 118.0 margin_left = 118.0
margin_right = 222.0 margin_right = 220.0
margin_bottom = 20.0 margin_bottom = 20.0
rect_min_size = Vector2( 102, 0 ) rect_min_size = Vector2( 102, 0 )
hint_tooltip = "Input flag" hint_tooltip = "Input flag"
text = "Greyscale" text = "Greyscale"
items = [ "Greyscale", null, false, 0, null, "Color", null, false, 1, null, "RGBA", null, false, 2, null, "SDF2D", null, false, 3, null, "SDF3D", null, false, 4, null ]
selected = 0 selected = 0
[connection signal="pressed" from="Delete" to="." method="_on_Delete_pressed"] [connection signal="pressed" from="Delete" to="." method="_on_Delete_pressed"]
[connection signal="pressed" from="Up" to="." method="_on_Up_pressed"] [connection signal="pressed" from="Up" to="." method="_on_Up_pressed"]

View File

@ -77,16 +77,24 @@ func get_value() -> Vector2:
if is_instance_valid(generator): if is_instance_valid(generator):
if is_xy: if is_xy:
if parameter_x != "": if parameter_x != "":
pos.x = generator.get_parameter(parameter_x) var p = generator.get_parameter(parameter_x)
if p is float:
pos.x = p
if parameter_y != "": if parameter_y != "":
pos.y = generator.get_parameter(parameter_y) var p = generator.get_parameter(parameter_y)
if p is float:
pos.y = p
else: else:
var r = 0.25 var r = 0.25
var a = 0 var a = 0
if parameter_r != "": if parameter_r != "":
r = generator.get_parameter(parameter_r) var p = generator.get_parameter(parameter_r)
if p is float:
r = p
if parameter_a != "": if parameter_a != "":
a = generator.get_parameter(parameter_a)*0.01745329251 var p = generator.get_parameter(parameter_a)
if p is float:
a = p*0.01745329251
pos.x = r*cos(a) pos.x = r*cos(a)
pos.y = r*sin(a) pos.y = r*sin(a)
return pos return pos
@ -101,8 +109,12 @@ func get_parent_value() -> Vector2:
func on_parameter_changed(p, v) -> void: func on_parameter_changed(p, v) -> void:
if !dragging and (p == parameter_x or p == parameter_y or p == parameter_r or p == parameter_a): if !dragging and (p == parameter_x or p == parameter_y or p == parameter_r or p == parameter_a):
update_position(get_value()) if v is float:
update() visible = true
update_position(get_value())
update()
else:
visible = false
func update_parameters(value : Vector2) -> void: func update_parameters(value : Vector2) -> void:
if !is_instance_valid(generator): if !is_instance_valid(generator):

View File

@ -13,9 +13,6 @@ func set_generator(g : MMGenBase, o : int = 0) -> void:
generator = g generator = g
output = o output = o
generator.connect("parameter_changed", self, "on_parameter_changed") generator.connect("parameter_changed", self, "on_parameter_changed")
var param_defs : Array = generator.get_parameter_defs()
for c in get_children():
c.setup_control(generator, param_defs)
var gen_output_defs = generator.get_output_defs() var gen_output_defs = generator.get_output_defs()
if ! gen_output_defs.empty(): if ! gen_output_defs.empty():
var context : MMGenContext = MMGenContext.new() var context : MMGenContext = MMGenContext.new()
@ -25,9 +22,7 @@ func set_generator(g : MMGenBase, o : int = 0) -> void:
if source.empty(): if source.empty():
source = MMGenBase.DEFAULT_GENERATED_SHADER source = MMGenBase.DEFAULT_GENERATED_SHADER
else: else:
g = null generator = null
for c in get_children():
c.setup_control(generator, [])
# Update shader # Update shader
material.shader.code = MMGenBase.generate_preview_shader(source, source.type, shader) material.shader.code = MMGenBase.generate_preview_shader(source, source.type, shader)
# Get parameter values from the shader code # Get parameter values from the shader code
@ -60,13 +55,30 @@ func on_float_parameters_changed(parameter_changes : Dictionary) -> void:
func on_resized() -> void: func on_resized() -> void:
material.set_shader_param("size", rect_size) material.set_shader_param("size", rect_size)
set_generator(generator)
func value_to_pos(value : Vector2) -> Vector2: func _on_Export_id_pressed(id):
return rect_size*0.5+value*min(rect_size.x, rect_size.y)/1.2 var dialog = FileDialog.new()
add_child(dialog)
dialog.rect_min_size = Vector2(500, 500)
dialog.access = FileDialog.ACCESS_FILESYSTEM
dialog.mode = FileDialog.MODE_SAVE_FILE
dialog.add_filter("*.png;PNG image file")
dialog.connect("file_selected", self, "export_as_png", [ 256 << id ])
dialog.popup_centered()
func value_to_offset(value : Vector2) -> Vector2: func export_as_png(file_name : String, size : int) -> void:
return value*min(rect_size.x, rect_size.y)/1.2 var previous_size = material.get_shader_param("size")
var previous_margin = material.get_shader_param("margin")
var previous_show_tiling = material.get_shader_param("show_tiling")
material.set_shader_param("size", Vector2(size, size))
material.set_shader_param("margin", 0.0)
material.set_shader_param("show_tiling", false)
var result = mm_renderer.render_material(material, size, false)
while result is GDScriptFunctionState:
result = yield(result, "completed")
result.save_to_file(file_name)
result.release()
material.set_shader_param("size", previous_size)
material.set_shader_param("margin", previous_margin)
material.set_shader_param("show_tiling", previous_show_tiling)
func pos_to_value(pos : Vector2) -> Vector2:
return (pos - rect_size*0.5)*1.2/min(rect_size.x, rect_size.y)

View File

@ -0,0 +1,9 @@
extends "res://material_maker/preview/preview_2d.gd"
func _ready():
$ContextMenu.add_submenu_item("Export", "Export")
func _on_gui_input(event):
if event is InputEventMouseButton:
if event.pressed and event.button_index == BUTTON_RIGHT:
$ContextMenu.popup(Rect2(get_global_mouse_position(), $ContextMenu.get_minimum_size()))

View File

@ -0,0 +1,27 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://material_maker/preview/preview_2d.tscn" type="PackedScene" id=1]
[ext_resource path="res://material_maker/preview/preview_2d_node.gd" type="Script" id=2]
[sub_resource type="Shader" id=1]
resource_local_to_scene = true
[sub_resource type="ShaderMaterial" id=2]
resource_local_to_scene = true
shader = SubResource( 1 )
[node name="Preview2D" instance=ExtResource( 1 )]
material = SubResource( 2 )
script = ExtResource( 2 )
shader = ""
[node name="ContextMenu" type="PopupMenu" parent="." index="0"]
margin_right = 109.0
margin_bottom = 52.0
[node name="Export" type="PopupMenu" parent="ContextMenu" index="1"]
margin_right = 91.0
margin_bottom = 88.0
items = [ "256x256", null, 0, false, false, 0, 0, null, "", false, "512x512", null, 0, false, false, 1, 0, null, "", false, "1024x1024", null, 0, false, false, 2, 0, null, "", false, "2048x2048", null, 0, false, false, 3, 0, null, "", false ]
[connection signal="gui_input" from="." to="." method="_on_gui_input"]
[connection signal="id_pressed" from="ContextMenu/Export" to="." method="_on_Export_id_pressed"]

View File

@ -0,0 +1,54 @@
extends "res://material_maker/preview/preview_2d.gd"
var shader_margin : float = 0
func _ready():
update_shader_options()
$ContextMenu.add_submenu_item("Export", "Export")
func set_generator(g : MMGenBase, o : int = 0) -> void:
.set_generator(g, o)
setup_controls()
update_shader_options()
func setup_controls() -> void:
var param_defs = generator.get_parameter_defs() if is_instance_valid(generator) else []
for c in get_children():
if c.has_method("setup_control"):
c.setup_control(generator, param_defs)
func value_to_pos(value : Vector2) -> Vector2:
return rect_size*0.5+value*min(rect_size.x, rect_size.y)/(1+shader_margin)
func value_to_offset(value : Vector2) -> Vector2:
return value*min(rect_size.x, rect_size.y)/(1+shader_margin)
func pos_to_value(pos : Vector2) -> Vector2:
return (pos - rect_size*0.5)*(1+shader_margin)/min(rect_size.x, rect_size.y)
func update_shader_options() -> void:
if $ContextMenu == null:
return
if $ContextMenu.is_item_checked(0):
shader_margin = 0.2
material.set_shader_param("show_tiling", true)
material.set_shader_param("margin", 0.2)
else:
shader_margin = 0
material.set_shader_param("show_tiling", false)
material.set_shader_param("margin", 0)
setup_controls()
func _on_gui_input(event):
if event is InputEventMouseButton:
if event.pressed and event.button_index == BUTTON_RIGHT:
$ContextMenu.popup(Rect2(get_global_mouse_position(), $ContextMenu.get_minimum_size()))
func _on_ContextMenu_id_pressed(id) -> void:
if $ContextMenu.is_item_checkable(id):
$ContextMenu.toggle_item_checked(id)
match id:
0:
update_shader_options()
_:
print("unsupported id "+str(id))

View File

@ -1,30 +1,44 @@
[gd_scene load_steps=8 format=2] [gd_scene load_steps=9 format=2]
[ext_resource path="res://material_maker/icons/icons.svg" type="Texture" id=1] [ext_resource path="res://material_maker/icons/icons.svg" type="Texture" id=1]
[ext_resource path="res://material_maker/preview/control_point.tscn" type="PackedScene" id=2] [ext_resource path="res://material_maker/preview/control_point.tscn" type="PackedScene" id=2]
[ext_resource path="res://material_maker/preview/preview_2d.tscn" type="PackedScene" id=3] [ext_resource path="res://material_maker/preview/preview_2d.tscn" type="PackedScene" id=3]
[ext_resource path="res://material_maker/preview/preview_2d_panel.gd" type="Script" id=4]
[sub_resource type="Shader" id=1] [sub_resource type="Shader" id=1]
code = "shader_type canvas_item; code = "shader_type canvas_item;
uniform sampler2D tex; uniform vec2 size = vec2(585.0, 453.0);
uniform vec2 size; uniform bool show_tiling = false;
uniform float margin = 0.2;
vec4 preview_2d(vec2 uv) {
return vec4(0.8);
}
void fragment() { void fragment() {
float ms = max(size.x, size.y); float ms = max(size.x, size.y);
vec2 uv = fract(0.5+1.2*(UV-vec2(0.5))*ms/size.yx); float margin_factor = 1.0+max(0.0, margin);
float is = min(size.x, size.y)/1.2; vec2 uv = 0.5+margin_factor*(UV-vec2(0.5))*ms/size.yx;
vec2 m2 = min(fract(uv), 1.0-fract(uv)); float is = min(size.x, size.y)/margin_factor;
vec4 image = texture(tex, uv); vec4 image = preview_2d(fract(uv));
vec3 image_with_background = mix(vec3(mod(floor(uv.x*32.0)+floor(uv.y*32.0), 2.0)), image.xyz, image.a); float checkerboard = mod(floor(uv.x*32.0)+floor(uv.y*32.0), 2.0);
float lines_color = 0.5*(cos(5.0*TIME+100.0*(uv.x+uv.y))+1.0); vec3 image_with_background = mix(vec3(checkerboard), image.xyz, image.a);
COLOR = vec4(mix(image_with_background, vec3(lines_color), step(is*min(m2.x, m2.y), 1.0)), 1.0); if (show_tiling) {
vec2 m2 = min(fract(uv), 1.0-fract(uv));
float lines_color = 0.5*(cos(5.0*TIME+100.0*(uv.x+uv.y))+1.0);
COLOR = vec4(mix(image_with_background, vec3(lines_color), step(is*min(m2.x, m2.y), 1.0)), 1.0);
} else {
vec2 outside = step(abs(uv-vec2(0.5)), vec2(0.5));
COLOR = vec4(mix(vec3(0.0), image_with_background, outside.x*outside.y), 1.0);
}
}" }"
[sub_resource type="ShaderMaterial" id=2] [sub_resource type="ShaderMaterial" id=2]
resource_local_to_scene = true
shader = SubResource( 1 ) shader = SubResource( 1 )
shader_param/size = Vector2( 585, 492 ) shader_param/size = Vector2( 585, 492 )
shader_param/show_tiling = false
shader_param/margin = 0.5
[sub_resource type="AtlasTexture" id=3] [sub_resource type="AtlasTexture" id=3]
flags = 4 flags = 4
@ -38,7 +52,32 @@ region = Rect2( 16, 64, 16, 16 )
[node name="Preview2D" instance=ExtResource( 3 )] [node name="Preview2D" instance=ExtResource( 3 )]
material = SubResource( 2 ) material = SubResource( 2 )
margin_right = -758.0
margin_bottom = -267.0
rect_min_size = Vector2( 200, 200 ) rect_min_size = Vector2( 200, 200 )
script = ExtResource( 4 )
shader = "uniform vec2 size;
uniform bool show_tiling = true;
uniform float margin = 0.5;
void fragment() {
float ms = max(size.x, size.y);
float margin_factor = 1.0+max(0.0, margin);
vec2 uv = 0.5+margin_factor*(UV-vec2(0.5))*ms/size.yx;
float is = min(size.x, size.y)/margin_factor;
vec4 image = preview_2d(fract(uv));
float checkerboard = mod(floor(uv.x*32.0)+floor(uv.y*32.0), 2.0);
vec3 image_with_background = mix(vec3(checkerboard), image.xyz, image.a);
if (show_tiling) {
vec2 m2 = min(fract(uv), 1.0-fract(uv));
float lines_color = 0.5*(cos(5.0*TIME+100.0*(uv.x+uv.y))+1.0);
COLOR = vec4(mix(image_with_background, vec3(lines_color), step(is*min(m2.x, m2.y), 1.0)), 1.0);
} else {
vec2 outside = step(abs(uv-vec2(0.5)), vec2(0.5));
COLOR = vec4(mix(vec3(0.0), image_with_background, outside.x*outside.y), 1.0);
}
}
"
[node name="P1" parent="." index="0" instance=ExtResource( 2 )] [node name="P1" parent="." index="0" instance=ExtResource( 2 )]
visible = false visible = false
@ -128,3 +167,16 @@ mouse_default_cursor_shape = 10
texture = SubResource( 4 ) texture = SubResource( 4 )
parent_control = "P1" parent_control = "P1"
control_type = 2 control_type = 2
[node name="ContextMenu" type="PopupMenu" parent="." index="8"]
margin_right = 109.0
margin_bottom = 52.0
items = [ "Show tiling", null, 1, false, false, 0, 0, null, "", false ]
[node name="Export" type="PopupMenu" parent="ContextMenu" index="1"]
margin_right = 91.0
margin_bottom = 88.0
items = [ "256x256", null, 0, false, false, 0, 0, null, "", false, "512x512", null, 0, false, false, 1, 0, null, "", false, "1024x1024", null, 0, false, false, 2, 0, null, "", false, "2048x2048", null, 0, false, false, 3, 0, null, "", false ]
[connection signal="gui_input" from="." to="." method="_on_gui_input"]
[connection signal="id_pressed" from="ContextMenu" to="." method="_on_ContextMenu_id_pressed"]
[connection signal="id_pressed" from="ContextMenu/Export" to="." method="_on_Export_id_pressed"]

View File

@ -5,6 +5,7 @@ export var value : float = 0.5 setget set_value
export var min_value : float = 0.0 setget set_min_value export var min_value : float = 0.0 setget set_min_value
export var max_value : float = 1.0 setget set_max_value export var max_value : float = 1.0 setget set_max_value
export var step : float = 0.0 setget set_step export var step : float = 0.0 setget set_step
export var float_only : bool = false
var sliding : bool = false var sliding : bool = false
var start_position : float var start_position : float
@ -17,14 +18,19 @@ var from_upper_bound : bool = false
onready var slider = $Slider onready var slider = $Slider
onready var cursor = $Slider/Cursor onready var cursor = $Slider/Cursor
signal value_changed signal value_changed(value)
func _ready() -> void: func _ready() -> void:
do_update() do_update()
func set_value(v : float) -> void: func set_value(v) -> void:
value = v if v is float:
do_update() value = v
do_update()
$Slider.visible = true
elif v is String and !float_only:
text = v
$Slider.visible = false
func set_min_value(v : float) -> void: func set_min_value(v : float) -> void:
min_value = v min_value = v
@ -39,7 +45,7 @@ func set_step(v : float) -> void:
do_update() do_update()
func do_update(update_text : bool = true) -> void: func do_update(update_text : bool = true) -> void:
if update_text: if update_text and $Slider.visible:
text = str(value) text = str(value)
if cursor != null: if cursor != null:
if max_value != min_value: if max_value != min_value:
@ -58,6 +64,8 @@ func get_modifiers(event):
return modifiers return modifiers
func _on_LineEdit_gui_input(event : InputEvent) -> void: func _on_LineEdit_gui_input(event : InputEvent) -> void:
if !$Slider.visible:
return
if event is InputEventMouseButton and event.button_index == BUTTON_LEFT: if event is InputEventMouseButton and event.button_index == BUTTON_LEFT:
if event.is_pressed(): if event.is_pressed():
last_position = event.position.x last_position = event.position.x
@ -110,9 +118,12 @@ func _on_LineEdit_text_changed(new_text : String) -> void:
func _on_LineEdit_text_entered(new_text : String) -> void: func _on_LineEdit_text_entered(new_text : String) -> void:
if new_text.is_valid_float(): if new_text.is_valid_float():
value = new_text.to_float() value = new_text.to_float()
do_update() do_update()
emit_signal("value_changed", value) emit_signal("value_changed", value)
$Slider.visible = true
else:
emit_signal("value_changed", new_text)
$Slider.visible = false
func _on_LineEdit_focus_exited() -> void: func _on_LineEdit_focus_exited() -> void:
do_update() _on_LineEdit_text_entered(text)
emit_signal("value_changed", value)

View File

@ -10,7 +10,7 @@ margin_left = -1280.0
margin_right = -1222.0 margin_right = -1222.0
margin_bottom = -696.0 margin_bottom = -696.0
text = "0.5" text = "0.5"
max_length = 20 max_length = 100
context_menu_enabled = false context_menu_enabled = false
caret_blink = true caret_blink = true
script = ExtResource( 1 ) script = ExtResource( 1 )