Fixed curves, and the curve editor, and added curve support for sd_shape_line.

This commit is contained in:
Relintai 2021-10-20 19:53:05 +02:00
parent 3841c50674
commit 6f2437279e
10 changed files with 224 additions and 72 deletions

View File

@ -54,7 +54,7 @@ sides = 11
radius = SubResource( 4 ) radius = SubResource( 4 )
edge = SubResource( 3 ) edge = SubResource( 3 )
[sub_resource type="Resource" id=64] [sub_resource type="Resource" id=67]
script = ExtResource( 5 ) script = ExtResource( 5 )
default_type = 5 default_type = 5
default_int = 0 default_int = 0
@ -66,7 +66,7 @@ default_color = Color( 0, 0, 0, 1 )
[sub_resource type="Resource" id=6] [sub_resource type="Resource" id=6]
script = ExtResource( 6 ) script = ExtResource( 6 )
graph_position = Vector2( 300, -400 ) graph_position = Vector2( 300, -400 )
image = SubResource( 64 ) image = SubResource( 67 )
postfix = "-test" postfix = "-test"
[sub_resource type="Resource" id=9] [sub_resource type="Resource" id=9]
@ -339,7 +339,7 @@ default_vector2 = Vector2( 0, 0 )
default_vector3 = Vector3( 0, 0, 0 ) default_vector3 = Vector3( 0, 0, 0 )
default_color = Color( 0, 0, 0, 1 ) default_color = Color( 0, 0, 0, 1 )
[sub_resource type="Resource" id=62] [sub_resource type="Resource" id=65]
script = ExtResource( 5 ) script = ExtResource( 5 )
default_type = 1 default_type = 1
default_int = 0 default_int = 0
@ -356,15 +356,15 @@ default_float = 0.0
default_vector2 = Vector2( 0, 0 ) default_vector2 = Vector2( 0, 0 )
default_vector3 = Vector3( 0, 0, 0 ) default_vector3 = Vector3( 0, 0, 0 )
default_color = Color( 0, 0, 0, 1 ) default_color = Color( 0, 0, 0, 1 )
input_property = SubResource( 62 ) input_property = SubResource( 65 )
[sub_resource type="Resource" id=49] [sub_resource type="Resource" id=49]
script = ExtResource( 13 ) script = ExtResource( 13 )
graph_position = Vector2( 1480, -680 ) graph_position = Vector2( 1480, -680 )
image = SubResource( 47 ) image = SubResource( 47 )
input = SubResource( 48 ) input = SubResource( 48 )
bevel = 0.23 bevel = 0.0
base = 0.2 base = 0.17
[sub_resource type="Resource" id=53] [sub_resource type="Resource" id=53]
script = ExtResource( 5 ) script = ExtResource( 5 )
@ -424,13 +424,7 @@ output = SubResource( 59 )
center = Vector2( 0.04, 0 ) center = Vector2( 0.04, 0 )
size = Vector2( 0.3, 0.2 ) size = Vector2( 0.3, 0.2 )
[sub_resource type="Resource" id=63] [sub_resource type="Resource" id=62]
script = ExtResource( 16 )
graph_position = Vector2( 1060, -400 )
points = PoolVector2Array( 0.2, 0.2, 0.7, 0.4, 0.858401, 0.631436, 0.672764, 0.875339, 0.396341, 0.873984, 0.25542, 0.856369, 0.143902, 0.556369 )
output = SubResource( 62 )
[sub_resource type="Resource" id=65]
script = ExtResource( 5 ) script = ExtResource( 5 )
default_type = 1 default_type = 1
default_int = 0 default_int = 0
@ -439,13 +433,20 @@ default_vector2 = Vector2( 0, 0 )
default_vector3 = Vector3( 0, 0, 0 ) default_vector3 = Vector3( 0, 0, 0 )
default_color = Color( 0, 0, 0, 1 ) default_color = Color( 0, 0, 0, 1 )
[sub_resource type="Resource" id=63]
script = ExtResource( 16 )
graph_position = Vector2( 960, -440 )
points = PoolVector2Array( 0.2, 0.2, 0.7, 0.4, 0.858401, 0.631436, 0.672764, 0.875339, 0.396341, 0.873984, 0.25542, 0.856369, 0.143902, 0.556369 )
output = SubResource( 62 )
[sub_resource type="Resource" id=66] [sub_resource type="Resource" id=66]
script = ExtResource( 17 ) script = ExtResource( 17 )
graph_position = Vector2( 1280, -280 ) graph_position = Vector2( 1260, -580 )
points = PoolRealArray( 0, 1, 0, 0, 0.154647, 0.9653, 0, 0.509482, 0.314904, 0.787066, 0, -0.181703, 0.461538, 0.768139, -2.54259, 1.21581, 0.665064, 0.839117, 4.01892, 0, 0.872596, 0.911672, 0, 0, 0.893429, 0.580442, 0, 0, 1, 1, 0, 0 )
output = SubResource( 65 ) output = SubResource( 65 )
A = Vector2( -0.3, -0.3 ) A = Vector2( -0.3, -0.36 )
B = Vector2( 0.3, 0.3 ) B = Vector2( 0.25, 0.35 )
width = 0.1 width = 0.07
[resource] [resource]
script = ExtResource( 1 ) script = ExtResource( 1 )

View File

@ -10,7 +10,7 @@ class Point:
ls = nls ls = nls
rs = nrs rs = nrs
var points = [ Point.new(0.0, 0.0, 0.0, 1.0), Point.new(1.0, 1.0, 1.0, 0.0) ] export(PoolRealArray) var points = [ 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0 ]
func to_string() -> String: func to_string() -> String:
var rv = PoolStringArray() var rv = PoolStringArray()
@ -24,37 +24,83 @@ func clear() -> void:
curve_changed() curve_changed()
func add_point(x : float, y : float, ls : float = INF, rs : float = INF) -> void: func add_point(x : float, y : float, ls : float = INF, rs : float = INF) -> void:
for i in points.size(): var indx : int = points.size() / 4
if x < points[i].p.x:
for i in indx:
var ii : int = i * 4
if x < points[ii]:
if ls == INF: if ls == INF:
ls == 0 ls == 0
if rs == INF: if rs == INF:
rs == 0 rs == 0
points.insert(i, Point.new(x, y, ls, rs)) points.insert(ii, x)
points.insert(ii + 1, y)
points.insert(ii + 2, ls)
points.insert(ii + 3, rs)
curve_changed() curve_changed()
return return
points.append(Point.new(x, y, ls, rs)) points.append(x)
points.append(y)
points.append(ls)
points.append(rs)
curve_changed() curve_changed()
func remove_point(index : int) -> bool: func remove_point(i : int) -> bool:
var index : int = i * 4
if index <= 0 or index >= points.size() - 1: if index <= 0 or index >= points.size() - 1:
return false return false
else: else:
points.remove(index) points.remove(index)
points.remove(index)
points.remove(index)
points.remove(index)
curve_changed() curve_changed()
return true return true
func get_point_count() -> int: func get_point_count() -> int:
return points.size() return points.size() / 4
func set_point(i : int, v : Point) -> void: func set_point(i : int, v : Point) -> void:
points[i] = v var indx : int = i * 4
points[indx + 0] = v.p.x
points[indx + 1] = v.p.y
points[indx + 2] = v.ls
points[indx + 3] = v.rs
curve_changed() curve_changed()
func set_poins(v : PoolRealArray) -> void: func get_point(i : int) -> Point:
#points[i] = v var indx : int = i * 4
return Point.new(points[indx + 0], points[indx + 1], points[indx + 2], points[indx + 3])
func get_points() -> Array:
var arr : Array = Array()
var c : int = get_point_count()
for i in range(c):
arr.append(get_point(i))
return arr
func set_points(arr : Array, notify : bool = true) -> void:
points.resize(0)
for p in arr:
points.append(p.p.x)
points.append(p.p.y)
points.append(p.ls)
points.append(p.rs)
if notify:
curve_changed() curve_changed()
func curve_changed() -> void: func curve_changed() -> void:

View File

@ -0,0 +1,85 @@
tool
extends Reference
const Commons = preload("res://addons/mat_maker_gd/nodes/common/commons.gd")
#Based on MaterialMaker's curve.gd
#Curve PoolRealArray: p.x, p.y, ls, rs, p.x, p.y ....
#class Point:
# var p : Vector2
# var ls : float
# var rs : float
#func get_shader(name) -> String:
# var shader
# shader = "float "+name+"_curve_fct(float x) {\n"
# for i in range(points.size()-1):
# if i < points.size()-2:
# shader += "if (x <= p_"+name+"_"+str(i+1)+"_x) "
#
# shader += "{\n"
# shader += "float dx = x - p_"+name+"_"+str(i)+"_x;\n"
# shader += "float d = p_"+name+"_"+str(i+1)+"_x - p_"+name+"_"+str(i)+"_x;\n"
# shader += "float t = dx/d;\n"
# shader += "float omt = (1.0 - t);\n"
# shader += "float omt2 = omt * omt;\n"
# shader += "float omt3 = omt2 * omt;\n"
# shader += "float t2 = t * t;\n"
# shader += "float t3 = t2 * t;\n"
# shader += "d /= 3.0;\n"
# shader += "float y1 = p_"+name+"_"+str(i)+"_y;\n"
# shader += "float yac = p_"+name+"_"+str(i)+"_y + d*p_"+name+"_"+str(i)+"_rs;\n"
# shader += "float ybc = p_"+name+"_"+str(i+1)+"_y - d*p_"+name+"_"+str(i+1)+"_ls;\n"
# shader += "float y2 = p_"+name+"_"+str(i+1)+"_y;\n"
# shader += "return y1*omt3 + yac*omt2*t*3.0 + ybc*omt*t2*3.0 + y2*t3;\n"
# shader += "}\n"
#
# shader += "}\n"
# return shader
static func curve(x : float, points : PoolRealArray) -> float:
if points.size() % 4 != 0 || points.size() < 8:
return 0.0
var ps : int = points.size() / 4
for i in range(ps - 1):
var pi : int = i * 4
var pip1 : int = (i + 1) * 4
if i < ps - 2:
# if (x <= p_"+name+"_"+str(i+1)+"_x)
if x > points[pip1]:
continue
#float dx = x - p_"+name+"_"+str(i)+"_x;
var dx : float = x - points[pi];
#var d : float = p_"+name+"_"+str(i+1)+"_x - p_"+name+"_"+str(i)+"_x;
var d : float = points[pi + 1] - points[pi];
var t : float = dx / d
var omt : float = (1.0 - t)
var omt2 : float = omt * omt
var omt3 : float = omt2 * omt
var t2 : float = t * t
var t3 : float = t2 * t
d /= 3.0
# var y1 : float = p_"+name+"_"+str(i)+"_y
var y1 : float = points[pi + 1]
# var yac : float = p_"+name+"_"+str(i)+"_y + d*p_"+name+"_"+str(i)+"_rs
var yac : float = points[pi + 1] + d * points[pi + 3]
# var ybc : float = p_"+name+"_"+str(i+1)+"_y - d*p_"+name+"_"+str(i+1)+"_ls
var ybc : float = points[pip1 + 1] - d * points[pip1 + 2]
# var y2 : float = p_"+name+"_"+str(i+1)+"_y
var y2 : float = points[pip1 + 1]
return y1 * omt3 + yac * omt2 * t * 3.0 + ybc * omt * t2 * 3.0 + y2 * t3;
return 0.0

View File

@ -3,6 +3,7 @@ extends "res://addons/mat_maker_gd/nodes/bases/curve_base.gd"
const Commons = preload("res://addons/mat_maker_gd/nodes/common/commons.gd") const Commons = preload("res://addons/mat_maker_gd/nodes/common/commons.gd")
var SDF2D = preload("res://addons/mat_maker_gd/nodes/common/sdf2d.gd") var SDF2D = preload("res://addons/mat_maker_gd/nodes/common/sdf2d.gd")
var Curves = preload("res://addons/mat_maker_gd/nodes/common/curves.gd")
export(Resource) var output : Resource export(Resource) var output : Resource
export(Vector2) var A : Vector2 = Vector2(-0.3, -0.3) export(Vector2) var A : Vector2 = Vector2(-0.3, -0.3)
@ -33,7 +34,7 @@ func get_property_value(uv : Vector2) -> float:
#$(name_uv)_sdl.x - $r * $profile($(name_uv)_sdl.y) #$(name_uv)_sdl.x - $r * $profile($(name_uv)_sdl.y)
return line.x return line.x - width * Curves.curve(line.y, points)
#a #a
func get_a() -> Vector2: func get_a() -> Vector2:
@ -65,9 +66,6 @@ func set_width(val : float) -> void:
emit_changed() emit_changed()
output.emit_changed() output.emit_changed()
func polygon_changed() -> void: func _curve_changed() -> void:
_polygon_changed()
func _polygon_changed() -> void:
emit_changed() emit_changed()
output.emit_changed() output.emit_changed()

View File

@ -3,31 +3,35 @@ extends WindowDialog
var MMCurve = preload("res://addons/mat_maker_gd/nodes/bases/curve_base.gd") var MMCurve = preload("res://addons/mat_maker_gd/nodes/bases/curve_base.gd")
var previous_value var previous_points : Array
var curve
signal curve_changed(curve) signal curve_changed(curve)
signal return_curve(curve)
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
pass # Replace with function body. pass # Replace with function body.
func _on_CurveDialog_popup_hide(): func _on_CurveDialog_popup_hide():
emit_signal("return_curve", null) queue_free()
func _on_OK_pressed(): func _on_OK_pressed():
emit_signal("return_curve", $VBoxContainer/EditorContainer/CurveEditor.curve) emit_signal("curve_changed", curve)
curve.curve_changed()
queue_free()
func _on_Cancel_pressed(): func _on_Cancel_pressed():
emit_signal("return_curve", previous_value) curve.set_points(previous_points)
emit_signal("curve_changed", curve)
func edit_curve(curve) -> Array: queue_free()
previous_value = curve.duplicate()
func edit_curve(c) -> void:
curve = c
previous_points = curve.get_points()
$VBoxContainer/EditorContainer/CurveEditor.set_curve(curve) $VBoxContainer/EditorContainer/CurveEditor.set_curve(curve)
popup_centered() popup_centered()
var result = yield(self, "return_curve")
queue_free()
return result
func _on_CurveEditor_value_changed(value): func _on_CurveEditor_value_changed(value):
emit_signal("curve_changed", value) emit_signal("curve_changed", value)

View File

@ -5,29 +5,20 @@ var MMCurve = preload("res://addons/mat_maker_gd/nodes/bases/curve_base.gd")
var value = null setget set_value var value = null setget set_value
signal updated(curve) signal updated(curve)
func _ready():
set_value(MMCurve.new())
func set_value(v) -> void: func set_value(v) -> void:
value = v.duplicate() value = v
$CurveView.curve = value $CurveView.set_curve(value)
$CurveView.update() $CurveView.update()
func _on_CurveEdit_pressed(): func _on_CurveEdit_pressed():
var dialog = preload("res://addons/mat_maker_gd/widgets/curve_edit/curve_dialog.tscn").instance() var dialog = preload("res://addons/mat_maker_gd/widgets/curve_edit/curve_dialog.tscn").instance()
add_child(dialog) add_child(dialog)
dialog.connect("curve_changed", self, "on_value_changed") dialog.connect("curve_changed", self, "on_value_changed")
var new_curve = dialog.edit_curve(value) dialog.edit_curve(value)
while new_curve is GDScriptFunctionState:
new_curve = yield(new_curve, "completed")
if new_curve != null:
set_value(new_curve)
emit_signal("updated", new_curve.duplicate())
func on_value_changed(v) -> void: func on_value_changed(v) -> void:
set_value(v) #set_value(v)
emit_signal("updated", v.duplicate()) emit_signal("updated", v)
$CurveView.update()

View File

@ -18,4 +18,5 @@ __meta__ = {
} }
[node name="CurveView" parent="." instance=ExtResource( 2 )] [node name="CurveView" parent="." instance=ExtResource( 2 )]
[connection signal="pressed" from="." to="." method="_on_CurveEdit_pressed"] [connection signal="pressed" from="." to="." method="_on_CurveEdit_pressed"]

View File

@ -12,39 +12,54 @@ func set_curve(c) -> void:
update_controls() update_controls()
func update_controls() -> void: func update_controls() -> void:
if !curve:
return
for c in get_children(): for c in get_children():
c.queue_free() c.queue_free()
for i in curve.points.size():
var p = curve.points[i] var points = curve.get_points()
for i in points.size():
var p = points[i]
var control_point = preload("res://addons/mat_maker_gd/widgets/curve_edit/control_point.tscn").instance() var control_point = preload("res://addons/mat_maker_gd/widgets/curve_edit/control_point.tscn").instance()
add_child(control_point) add_child(control_point)
control_point.initialize(p) control_point.initialize(p)
control_point.rect_position = transform_point(p.p)-control_point.OFFSET control_point.rect_position = transform_point(p.p)-control_point.OFFSET
if i == 0 or i == curve.points.size()-1:
if i == 0 or i == points.size()-1:
control_point.set_constraint(control_point.rect_position.x, control_point.rect_position.x, -control_point.OFFSET.y, rect_size.y-control_point.OFFSET.y) control_point.set_constraint(control_point.rect_position.x, control_point.rect_position.x, -control_point.OFFSET.y, rect_size.y-control_point.OFFSET.y)
if i == 0: if i == 0:
control_point.get_child(0).visible = false control_point.get_child(0).visible = false
else: else:
control_point.get_child(1).visible = false control_point.get_child(1).visible = false
else: else:
var min_x = transform_point(curve.points[i-1].p).x+1 var min_x = transform_point(points[i-1].p).x+1
var max_x = transform_point(curve.points[i+1].p).x-1 var max_x = transform_point(points[i+1].p).x-1
control_point.set_constraint(min_x, max_x, -control_point.OFFSET.y, rect_size.y-control_point.OFFSET.y) control_point.set_constraint(min_x, max_x, -control_point.OFFSET.y, rect_size.y-control_point.OFFSET.y)
control_point.connect("moved", self, "_on_ControlPoint_moved") control_point.connect("moved", self, "_on_ControlPoint_moved")
control_point.connect("removed", self, "_on_ControlPoint_removed") control_point.connect("removed", self, "_on_ControlPoint_removed")
emit_signal("value_changed", curve) emit_signal("value_changed", curve)
func _on_ControlPoint_moved(index): func _on_ControlPoint_moved(index):
var points : Array = curve.get_points()
var control_point = get_child(index) var control_point = get_child(index)
curve.points[index].p = reverse_transform_point(control_point.rect_position+control_point.OFFSET) points[index].p = reverse_transform_point(control_point.rect_position+control_point.OFFSET)
if control_point.has_node("LeftSlope"): if control_point.has_node("LeftSlope"):
var slope_vector = control_point.get_node("LeftSlope").rect_position/rect_size var slope_vector = control_point.get_node("LeftSlope").rect_position/rect_size
if slope_vector.x != 0: if slope_vector.x != 0:
curve.points[index].ls = -slope_vector.y / slope_vector.x points[index].ls = -slope_vector.y / slope_vector.x
if control_point.has_node("RightSlope"): if control_point.has_node("RightSlope"):
var slope_vector = control_point.get_node("RightSlope").rect_position/rect_size var slope_vector = control_point.get_node("RightSlope").rect_position/rect_size
if slope_vector.x != 0: if slope_vector.x != 0:
curve.points[index].rs = -slope_vector.y / slope_vector.x points[index].rs = -slope_vector.y / slope_vector.x
curve.set_points(points, false)
update() update()
emit_signal("value_changed", curve) emit_signal("value_changed", curve)

View File

@ -8,10 +8,14 @@ export var show_axes : bool = false
var curve #: MMCurve var curve #: MMCurve
func _ready() -> void: func _ready() -> void:
curve = MMCurve.new() # curve = MMCurve.new()
connect("resized", self, "_on_resize") connect("resized", self, "_on_resize")
update() update()
func set_curve(val) -> void:
curve = val
update()
func transform_point(p : Vector2) -> Vector2: func transform_point(p : Vector2) -> Vector2:
return (Vector2(0.0, 1.0)+Vector2(1.0, -1.0)*p)*rect_size return (Vector2(0.0, 1.0)+Vector2(1.0, -1.0)*p)*rect_size
@ -19,6 +23,9 @@ func reverse_transform_point(p : Vector2) -> Vector2:
return Vector2(0.0, 1.0)+Vector2(1.0, -1.0)*p/rect_size return Vector2(0.0, 1.0)+Vector2(1.0, -1.0)*p/rect_size
func _draw(): func _draw():
if !curve:
return
# var current_theme : Theme = get_node("/root/MainWindow").theme # var current_theme : Theme = get_node("/root/MainWindow").theme
# #
# var bg = current_theme.get_stylebox("panel", "Panel").bg_color # var bg = current_theme.get_stylebox("panel", "Panel").bg_color
@ -36,14 +43,17 @@ func _draw():
draw_line(Vector2(p.x, 0), Vector2(p.x, rect_size.y-1), axes_color) draw_line(Vector2(p.x, 0), Vector2(p.x, rect_size.y-1), axes_color)
draw_line(Vector2(0, p.y), Vector2(rect_size.x-1, p.y), axes_color) draw_line(Vector2(0, p.y), Vector2(rect_size.x-1, p.y), axes_color)
for i in range(curve.points.size()-1): var points = curve.get_points()
var p1 = curve.points[i].p
var p2 = curve.points[i+1].p for i in range(points.size() - 1):
var p1 = points[i].p
var p2 = points[i+1].p
var d = (p2.x-p1.x)/3.0 var d = (p2.x-p1.x)/3.0
var yac = p1.y+d*curve.points[i].rs var yac = p1.y+d*points[i].rs
var ybc = p2.y-d*curve.points[i+1].ls var ybc = p2.y-d*points[i+1].ls
var p = transform_point(p1) var p = transform_point(p1)
var count : int = max(1, int((transform_point(p2).x-p.x/5.0))) var count : int = max(1, int((transform_point(p2).x-p.x/5.0)))
for tt in range(count): for tt in range(count):
var t = (tt+1.0)/count var t = (tt+1.0)/count
var omt = (1.0 - t) var omt = (1.0 - t)

View File

@ -45,4 +45,5 @@ func _on_ControlPoint_gui_input(event):
rect_position = vector-OFFSET rect_position = vector-OFFSET
if event.control: if event.control:
get_parent().get_child(1-get_index()).rect_position = -vector-OFFSET get_parent().get_child(1-get_index()).rect_position = -vector-OFFSET
get_parent().update_tangents() get_parent().update_tangents()