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

Compare commits

...

3 commits

Author SHA1 Message Date
Emmanouil Papadeas 1f6998e723 Add support for gradient presets 2025-01-16 22:11:02 +02:00
Emmanouil Papadeas 48130809c9 Update ObjParse.gd
Updated to c3156e2105/obj-parse/ObjParse.gd. Should fix #1165.
2025-01-16 20:17:21 +02:00
Emmanouil Papadeas 952498a2b8 Fix crash when importing a model in a 3D layer 2025-01-16 19:37:43 +02:00
5 changed files with 191 additions and 128 deletions

View file

@ -1,105 +1,111 @@
class_name ObjParse class_name ObjParse
extends Object
## Obj parser made by Ezcha, updated by Deakcor const DEBUG: bool = false
## Created on 7/11/2018
## https://ezcha.net
## https://github.com/Ezcha/gd-obj
## MIT License
## https://github.com/Ezcha/gd-obj/blob/master/LICENSE
## Returns an array of materials from a MTL file
const DEBUG := false # gd-obj
#
# Public methods # Created on 7/11/2018
#
# Originally made by Ezcha
# Contributors: deakcor, kb173, jeffgamedev
#
# https://ezcha.net
# https://github.com/Ezcha/gd-obj
#
# MIT License
# https://github.com/Ezcha/gd-obj/blob/master/LICENSE
## Create mesh from obj and mtl paths # Create mesh from obj and mtl paths
static func load_obj(obj_path: String, mtl_path: String = "") -> Mesh: static func load_obj(obj_path: String, mtl_path: String = "") -> Mesh:
var obj_str: String = _read_file_str(obj_path)
if mtl_path == "": if mtl_path == "":
mtl_path = search_mtl_path(obj_path) var mtl_filename: String = _get_mtl_filename(obj_str)
var obj := get_data(obj_path) mtl_path = "%s/%s" % [obj_path.get_base_dir(), mtl_filename]
var mats := {} var mats: Dictionary = {}
if mtl_path != "": if mtl_path != "":
mats = _create_mtl(get_data(mtl_path), get_mtl_tex(mtl_path)) mats = _create_mtl(_read_file_str(mtl_path), _get_mtl_tex(mtl_path))
return _create_obj(obj, mats) if obj and mats else null if obj_str.is_empty():
return null
return _create_obj(obj_str, mats)
## Create mesh from obj, materials. Materials should be {"matname":data} # Create mesh from obj, materials. Materials should be { "matname": data }
static func load_obj_from_buffer(obj_data: String, materials: Dictionary) -> Mesh: static func load_obj_from_buffer(obj_data: String, materials: Dictionary) -> Mesh:
return _create_obj(obj_data, materials) return _create_obj(obj_data, materials)
## Create materials # Create materials
static func load_mtl_from_buffer(mtl_data: String, textures: Dictionary) -> Dictionary: static func load_mtl_from_buffer(mtl_data: String, textures: Dictionary) -> Dictionary:
return _create_mtl(mtl_data, textures) return _create_mtl(mtl_data, textures)
## Get data from file path # Get data from file path
static func get_data(path: String) -> String: static func _read_file_str(path: String) -> String:
if path != "": if path == "":
var file := FileAccess.open(path, FileAccess.READ) return ""
if FileAccess.get_open_error() == OK: var file: FileAccess = FileAccess.open(path, FileAccess.READ)
var res := file.get_as_text() if file == null:
file.close() return ""
return res return file.get_as_text()
return ""
## Get textures from mtl path (return {"tex_path":data}) # Internal functions
static func get_mtl_tex(mtl_path: String) -> Dictionary:
var file_paths := get_mtl_tex_paths(mtl_path)
var textures := {} # Get textures from mtl path (returns { "tex_path": data })
static func _get_mtl_tex(mtl_path: String) -> Dictionary:
var file_paths: Array[String] = _get_mtl_tex_paths(mtl_path)
var textures: Dictionary = {}
for k in file_paths: for k in file_paths:
textures[k] = _get_image(mtl_path, k).save_png_to_buffer() textures[k] = _get_image(mtl_path, k).save_png_to_buffer()
return textures return textures
## Get textures paths from mtl path # Get textures paths from mtl path
static func get_mtl_tex_paths(mtl_path: String) -> Array: static func _get_mtl_tex_paths(mtl_path: String) -> Array[String]:
var file := FileAccess.open(mtl_path, FileAccess.READ) var file: FileAccess = FileAccess.open(mtl_path, FileAccess.READ)
var paths := [] if file == null:
if FileAccess.get_open_error() == OK: return []
var lines := file.get_as_text().split("\n", false)
file.close() var paths: Array[String] = []
for line in lines: var lines: PackedStringArray = file.get_as_text().split("\n", false)
var parts := line.split(" ", false, 1) for line in lines:
if parts[0] in ["map_Kd", "map_Ks", "map_Ka"]: var parts: PackedStringArray = line.split(" ", false, 1)
if !parts[1] in paths: if ["map_Kd", "map_Ks", "map_Ka"].has(parts[0]):
paths.push_back(parts[1]) if !paths.has(parts[1]):
paths.push_back(parts[1])
return paths return paths
## Try to find mtl path from obj path static func _get_mtl_filename(obj: String) -> String:
static func search_mtl_path(obj_path: String) -> String: var lines: PackedStringArray = obj.split("\n")
var mtl_path := obj_path.get_base_dir().path_join( for line in lines:
obj_path.get_file().rsplit(".", false, 1)[0] + ".mtl" var split: PackedStringArray = line.split(" ", false)
) if split.size() < 2:
if !FileAccess.file_exists(mtl_path): continue
mtl_path = obj_path.get_base_dir().path_join(obj_path.get_file() + ".mtl") if split[0] != "mtllib":
if !FileAccess.file_exists(mtl_path): continue
return "" return split[1].strip_edges()
return mtl_path return ""
# Private methods
static func _create_mtl(obj: String, textures: Dictionary) -> Dictionary: static func _create_mtl(obj: String, textures: Dictionary) -> Dictionary:
var mats := {} var mats: Dictionary = {}
var current_mat: StandardMaterial3D = null var current_mat: StandardMaterial3D = null
var lines := obj.split("\n", false) var lines: PackedStringArray = obj.split("\n", false)
for line in lines: for line in lines:
var parts := line.split(" ", false) var parts: PackedStringArray = line.split(" ", false)
match parts[0]: match parts[0]:
"#": "#":
# Comment # Comment
#print("Comment: "+line)
pass pass
"newmtl": "newmtl":
# Create a new material # Create a new material
if DEBUG: if DEBUG:
print("Adding new material " + parts[1]) prints("Adding new material", parts[1])
current_mat = StandardMaterial3D.new() current_mat = StandardMaterial3D.new()
mats[parts[1]] = current_mat mats[parts[1]] = current_mat
"Ka": "Ka":
@ -108,117 +114,134 @@ static func _create_mtl(obj: String, textures: Dictionary) -> Dictionary:
pass pass
"Kd": "Kd":
# Diffuse color # Diffuse color
current_mat.albedo_color = Color(float(parts[1]), float(parts[2]), float(parts[3])) current_mat.albedo_color = Color(
parts[1].to_float(), parts[2].to_float(), parts[3].to_float()
)
if DEBUG: if DEBUG:
print("Setting material color " + str(current_mat.albedo_color)) prints("Setting material color", str(current_mat.albedo_color))
_: _:
if parts[0] in ["map_Kd", "map_Ks", "map_Ka"]: if parts[0] in ["map_Kd", "map_Ks", "map_Ka"]:
var path := line.split(" ", false, 1)[1] var path: String = line.split(" ", false, 1)[1]
if textures.has(path): if textures.has(path):
current_mat.albedo_texture = _create_texture(textures[path]) current_mat.albedo_texture = _create_texture(textures[path])
return mats return mats
static func _parse_mtl_file(path) -> Dictionary:
return _create_mtl(_read_file_str(path), _get_mtl_tex(path))
static func _get_image(mtl_filepath: String, tex_filename: String) -> Image: static func _get_image(mtl_filepath: String, tex_filename: String) -> Image:
if DEBUG: if DEBUG:
print(" Debug: Mapping texture file " + tex_filename) prints("Debug: Mapping texture file", tex_filename)
var texfilepath := tex_filename var tex_filepath: String = tex_filename
if tex_filename.is_relative_path(): if tex_filename.is_relative_path():
texfilepath = mtl_filepath.get_base_dir().path_join(tex_filename) tex_filepath = "%s/%s" % [mtl_filepath.get_base_dir(), tex_filename]
var filetype := texfilepath.get_extension() var file_type: String = tex_filepath.get_extension()
if DEBUG: if DEBUG:
print(" Debug: texture file path: " + texfilepath + " of type " + filetype) prints("Debug: texture file path:", tex_filepath, "of type", file_type)
var img := Image.new() var img: Image = Image.new()
img.load(texfilepath) img.load(tex_filepath)
return img return img
static func _create_texture(data: PackedByteArray) -> ImageTexture: static func _create_texture(data: PackedByteArray) -> ImageTexture:
var img := Image.new() var img: Image = Image.new()
img.load_png_from_buffer(data) img.load_png_from_buffer(data)
return ImageTexture.create_from_image(img) return ImageTexture.create_from_image(img)
static func _get_texture(mtl_filepath, tex_filename) -> ImageTexture:
var tex = ImageTexture.create_from_image(_get_image(mtl_filepath, tex_filename))
if DEBUG:
prints("Debug: texture is", str(tex))
return tex
static func _create_obj(obj: String, mats: Dictionary) -> Mesh: static func _create_obj(obj: String, mats: Dictionary) -> Mesh:
# Setup # Setup
var mesh := ArrayMesh.new() var mesh: ArrayMesh = ArrayMesh.new()
var vertices := PackedVector3Array() var vertices: PackedVector3Array = PackedVector3Array()
var normals := PackedVector3Array() var normals: PackedVector3Array = PackedVector3Array()
var uvs := PackedVector2Array() var uvs: PackedVector2Array = PackedVector2Array()
var faces := {} var faces: Dictionary = {}
var mat_name := "default" var mat_name: String = "default"
var count_mtl := 0 var count_mtl: int = 0
# Parse # Parse
var lines := obj.split("\n", false) var lines: PackedStringArray = obj.split("\n", false)
for line in lines: for line in lines:
var parts := line.split(" ", false) var parts: PackedStringArray = line.split(" ", false)
match parts[0]: match parts[0]:
"#": "#":
# Comment # Comment
#print("Comment: "+line)
pass pass
"v": "v":
# Vertex # Vertice
var n_v := Vector3(float(parts[1]), float(parts[2]), float(parts[3])) var n_v: Vector3 = Vector3(
parts[1].to_float(), parts[2].to_float(), parts[3].to_float()
)
vertices.append(n_v) vertices.append(n_v)
"vn": "vn":
# Normal # Normal
var n_vn := Vector3(float(parts[1]), float(parts[2]), float(parts[3])) var n_vn: Vector3 = Vector3(
parts[1].to_float(), parts[2].to_float(), parts[3].to_float()
)
normals.append(n_vn) normals.append(n_vn)
"vt": "vt":
# UV # UV
var n_uv := Vector2(float(parts[1]), 1 - float(parts[2])) var n_uv: Vector2 = Vector2(parts[1].to_float(), 1 - parts[2].to_float())
uvs.append(n_uv) uvs.append(n_uv)
"usemtl": "usemtl":
# Material group # Material group
count_mtl += 1 count_mtl += 1
mat_name = parts[1] mat_name = parts[1].strip_edges()
if not faces.has(mat_name): if !faces.has(mat_name):
var mats_keys := mats.keys() var mats_keys: Array = mats.keys()
if !mats.has(mat_name): if !mats.has(mat_name):
if mats_keys.size() > count_mtl: if mats_keys.size() > count_mtl:
mat_name = mats_keys[count_mtl] mat_name = mats_keys[count_mtl]
faces[mat_name] = [] faces[mat_name] = []
"f": "f":
if not faces.has(mat_name): if !faces.has(mat_name):
var mats_keys := mats.keys() var mats_keys: Array = mats.keys()
if mats_keys.size() > count_mtl: if mats_keys.size() > count_mtl:
mat_name = mats_keys[count_mtl] mat_name = mats_keys[count_mtl]
faces[mat_name] = [] faces[mat_name] = []
# Face # Face
if parts.size() == 4: if parts.size() == 4:
# Tri # Tri
var face := {"v": [], "vt": [], "vn": []} var face: Dictionary = {"v": [], "vt": [], "vn": []}
for map in parts: for map in parts:
var vertices_index := map.split("/") var vertices_index: PackedStringArray = map.split("/")
if str(vertices_index[0]) != "f": if vertices_index[0] != "f":
face["v"].append(int(vertices_index[0]) - 1) face["v"].append(vertices_index[0].to_int() - 1)
face["vt"].append(int(vertices_index[1]) - 1) if vertices_index.size() > 1:
if vertices_index.size() > 2: face["vt"].append(vertices_index[1].to_int() - 1)
face["vn"].append(int(vertices_index[2]) - 1) if vertices_index.size() > 2:
face["vn"].append(vertices_index[2].to_int() - 1)
if faces.has(mat_name): if faces.has(mat_name):
faces[mat_name].append(face) faces[mat_name].append(face)
elif parts.size() > 4: elif parts.size() > 4:
# Triangulate # Triangulate
var points: Array[PackedInt64Array] = [] var points: Array[Array] = []
for map in parts: for map in parts:
var vertices_index = map.split("/") var vertices_index: PackedStringArray = map.split("/")
if str(vertices_index[0]) != "f": if vertices_index[0] != "f":
var point: PackedInt64Array = [] var point: Array[int] = []
point.append(int(vertices_index[0]) - 1) point.append(vertices_index[0].to_int() - 1)
point.append(int(vertices_index[1]) - 1) point.append(vertices_index[1].to_int() - 1)
if vertices_index.size() > 2: if vertices_index.size() > 2:
point.append(int(vertices_index[2]) - 1) point.append(vertices_index[2].to_int() - 1)
points.append(point) points.append(point)
for i in points.size(): for i in points.size():
if i != 0: if i != 0:
var face = {"v": [], "vt": [], "vn": []} var face = {"v": [], "vt": [], "vn": []}
var point0 := points[0] var point0: Array[int] = points[0]
var point1 := points[i] var point1: Array[int] = points[i]
var point2 := points[i - 1] var point2: Array[int] = points[i - 1]
face["v"].append(point0[0]) face["v"].append(point0[0])
face["v"].append(point2[0]) face["v"].append(point2[0])
face["v"].append(point1[0]) face["v"].append(point1[0])
@ -236,18 +259,16 @@ static func _create_obj(obj: String, mats: Dictionary) -> Mesh:
# Make tri # Make tri
for matgroup in faces.keys(): for matgroup in faces.keys():
if DEBUG: if DEBUG:
print( prints(
( "Creating surface for matgroup",
"Creating surface for matgroup " matgroup,
+ matgroup "with",
+ " with " str(faces[matgroup].size()),
+ str(faces[matgroup].size()) "faces"
+ " faces"
)
) )
# Mesh Assembler # Mesh Assembler
var st := SurfaceTool.new() var st: SurfaceTool = SurfaceTool.new()
st.begin(Mesh.PRIMITIVE_TRIANGLES) st.begin(Mesh.PRIMITIVE_TRIANGLES)
if !mats.has(matgroup): if !mats.has(matgroup):
mats[matgroup] = StandardMaterial3D.new() mats[matgroup] = StandardMaterial3D.new()
@ -255,37 +276,38 @@ static func _create_obj(obj: String, mats: Dictionary) -> Mesh:
for face in faces[matgroup]: for face in faces[matgroup]:
if face["v"].size() == 3: if face["v"].size() == 3:
# Vertices # Vertices
var fan_v := PackedVector3Array() var fan_v: PackedVector3Array = PackedVector3Array()
fan_v.append(vertices[face["v"][0]]) fan_v.append(vertices[face["v"][0]])
fan_v.append(vertices[face["v"][2]]) fan_v.append(vertices[face["v"][2]])
fan_v.append(vertices[face["v"][1]]) fan_v.append(vertices[face["v"][1]])
# Normals # Normals
var fan_vn := PackedVector3Array() var fan_vn: PackedVector3Array = PackedVector3Array()
if face["vn"].size() > 0: if face["vn"].size() > 0:
fan_vn.append(normals[face["vn"][0]]) fan_vn.append(normals[face["vn"][0]])
fan_vn.append(normals[face["vn"][2]]) fan_vn.append(normals[face["vn"][2]])
fan_vn.append(normals[face["vn"][1]]) fan_vn.append(normals[face["vn"][1]])
# Textures # Textures
var fan_vt := PackedVector2Array() var fan_vt: PackedVector2Array = PackedVector2Array()
if face["vt"].size() > 0: if face["vt"].size() > 0:
for k in [0, 2, 1]: for k in [0, 2, 1]:
var f = face["vt"][k] var f = face["vt"][k]
if f > -1: if f > -1:
var uv = uvs[f] var uv = uvs[f]
fan_vt.append(uv) fan_vt.append(uv)
st.add_triangle_fan( st.add_triangle_fan(
fan_v, fan_vt, PackedColorArray(), PackedVector2Array(), fan_vn, [] fan_v, fan_vt, PackedColorArray(), PackedVector2Array(), fan_vn, []
) )
mesh = st.commit(mesh) mesh = st.commit(mesh)
for k in mesh.get_surface_count(): for k in mesh.get_surface_count():
var mat := mesh.surface_get_material(k) var mat: Material = mesh.surface_get_material(k)
mat_name = "" mat_name = ""
for m in mats: for m in mats:
if mats[m] == mat: if mats[m] == mat:
mat_name = m mat_name = m
mesh.surface_set_name(k, mat_name) mesh.surface_set_name(k, mat_name)
# Finish # Finish
return mesh return mesh

View file

@ -367,7 +367,7 @@ func _set_node_values(to_edit: Object, properties: Dictionary) -> void:
if property_path.ends_with("v2"): if property_path.ends_with("v2"):
property_path = property_path.replace("v2", "") property_path = property_path.replace("v2", "")
var value = to_edit.get_indexed(property_path) var value = to_edit.get_indexed(property_path)
if value == null: if not is_instance_valid(value):
continue continue
if "scale" in prop: if "scale" in prop:
value *= 100 value *= 100

View file

@ -2,7 +2,7 @@
[ext_resource type="PackedScene" uid="uid://ctfgfelg0sho8" path="res://src/Tools/BaseTool.tscn" id="1"] [ext_resource type="PackedScene" uid="uid://ctfgfelg0sho8" path="res://src/Tools/BaseTool.tscn" id="1"]
[ext_resource type="Script" path="res://src/Tools/3DTools/3DShapeEdit.gd" id="2"] [ext_resource type="Script" path="res://src/Tools/3DTools/3DShapeEdit.gd" id="2"]
[ext_resource type="PackedScene" path="res://src/UI/Nodes/Sliders/ValueSliderV2.tscn" id="3"] [ext_resource type="PackedScene" uid="uid://bbnqcxa20a5a5" path="res://src/UI/Nodes/Sliders/ValueSliderV2.tscn" id="3"]
[ext_resource type="PackedScene" uid="uid://yjhp0ssng2mp" path="res://src/UI/Nodes/Sliders/ValueSlider.tscn" id="4"] [ext_resource type="PackedScene" uid="uid://yjhp0ssng2mp" path="res://src/UI/Nodes/Sliders/ValueSlider.tscn" id="4"]
[ext_resource type="Script" path="res://src/UI/Nodes/Sliders/ValueSlider.gd" id="5"] [ext_resource type="Script" path="res://src/UI/Nodes/Sliders/ValueSlider.gd" id="5"]
[ext_resource type="Script" path="res://src/UI/Nodes/CollapsibleContainer.gd" id="6"] [ext_resource type="Script" path="res://src/UI/Nodes/CollapsibleContainer.gd" id="6"]
@ -521,7 +521,6 @@ unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
selected = 0
[node name="MeshPixelSizeLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="24"] [node name="MeshPixelSizeLabel" type="Label" parent="ObjectOptions/MeshOptions/GridContainer" index="24"]
layout_mode = 2 layout_mode = 2

View file

@ -19,9 +19,14 @@ var active_cursor: GradientCursor: ## Showing a color picker popup to change a
i.queue_redraw() i.queue_redraw()
var texture := GradientTexture2D.new() var texture := GradientTexture2D.new()
var gradient := Gradient.new() var gradient := Gradient.new()
var presets: Array[Gradient] = []
@onready var x_offset: float = size.x - GradientCursor.WIDTH @onready var x_offset: float = size.x - GradientCursor.WIDTH
@onready var offset_value_slider := %OffsetValueSlider as ValueSlider @onready var offset_value_slider := %OffsetValueSlider as ValueSlider
@onready var interpolation_option_button: OptionButton = %InterpolationOptionButton
@onready var color_space_option_button: OptionButton = %ColorSpaceOptionButton
@onready var tools_menu_button: MenuButton = %ToolsMenuButton
@onready var presets_menu_button: MenuButton = %PresetsMenuButton
@onready var texture_rect := $TextureRect as TextureRect @onready var texture_rect := $TextureRect as TextureRect
@onready var color_picker := $Popup.get_node("ColorPicker") as ColorPicker @onready var color_picker := $Popup.get_node("ColorPicker") as ColorPicker
@onready var divide_dialog := $DivideConfirmationDialog as ConfirmationDialog @onready var divide_dialog := $DivideConfirmationDialog as ConfirmationDialog
@ -131,14 +136,23 @@ class GradientCursor:
func _init() -> void: func _init() -> void:
texture.gradient = gradient texture.gradient = gradient
presets.append(Gradient.new()) # Left to right
presets.append(Gradient.new()) # Left to transparent
presets.append(Gradient.new()) # Black to white
func _ready() -> void: func _ready() -> void:
texture_rect.texture = texture texture_rect.texture = texture
_create_cursors() _create_cursors()
%InterpolationOptionButton.select(gradient.interpolation_mode) interpolation_option_button.select(gradient.interpolation_mode)
%ColorSpaceOptionButton.select(gradient.interpolation_color_space) color_space_option_button.select(gradient.interpolation_color_space)
%ToolsMenuButton.get_popup().index_pressed.connect(_on_tools_menu_button_index_pressed) tools_menu_button.get_popup().index_pressed.connect(_on_tools_menu_button_index_pressed)
presets_menu_button.get_popup().index_pressed.connect(_on_presets_menu_button_index_pressed)
for preset in presets:
var grad_texture := GradientTexture2D.new()
grad_texture.height = 32
grad_texture.gradient = preset
presets_menu_button.get_popup().add_icon_item(grad_texture, "")
func _create_cursors() -> void: func _create_cursors() -> void:
@ -256,6 +270,22 @@ func _on_tools_menu_button_index_pressed(index: int) -> void:
divide_dialog.popup_centered() divide_dialog.popup_centered()
func _on_presets_menu_button_about_to_popup() -> void:
# Update left to right and left to transparent gradients
presets[0].set_color(0, Tools.get_assigned_color(MOUSE_BUTTON_LEFT))
presets[0].set_color(1, Tools.get_assigned_color(MOUSE_BUTTON_RIGHT))
presets[1].set_color(0, Tools.get_assigned_color(MOUSE_BUTTON_LEFT))
presets[1].set_color(1, Color(0, 0, 0, 0))
func _on_presets_menu_button_index_pressed(index: int) -> void:
var item_icon := presets_menu_button.get_popup().get_item_icon(index) as GradientTexture2D
gradient = item_icon.gradient.duplicate()
texture.gradient = gradient
_create_cursors()
updated.emit(gradient, continuous_change)
func _on_DivideConfirmationDialog_confirmed() -> void: func _on_DivideConfirmationDialog_confirmed() -> void:
var add_point_to_end := add_point_end_check_box.button_pressed var add_point_to_end := add_point_end_check_box.button_pressed
var parts := number_of_parts_spin_box.value var parts := number_of_parts_spin_box.value

View file

@ -15,6 +15,7 @@ layout_mode = 2
[node name="OffsetValueSlider" type="TextureProgressBar" parent="InterpolationContainer"] [node name="OffsetValueSlider" type="TextureProgressBar" parent="InterpolationContainer"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(64, 0)
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
focus_mode = 2 focus_mode = 2
@ -38,6 +39,7 @@ size_flags_horizontal = 3
tooltip_text = "Interpolation" tooltip_text = "Interpolation"
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
selected = 0 selected = 0
fit_to_longest_item = false
item_count = 3 item_count = 3
popup/item_0/text = "Linear" popup/item_0/text = "Linear"
popup/item_1/text = "Constant" popup/item_1/text = "Constant"
@ -52,6 +54,7 @@ size_flags_horizontal = 3
tooltip_text = "Color space" tooltip_text = "Color space"
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
selected = 0 selected = 0
fit_to_longest_item = false
item_count = 3 item_count = 3
popup/item_0/text = "sRGB" popup/item_0/text = "sRGB"
popup/item_1/text = "Linear sRGB" popup/item_1/text = "Linear sRGB"
@ -74,6 +77,14 @@ popup/item_1/id = 1
popup/item_2/text = "Divide into equal parts" popup/item_2/text = "Divide into equal parts"
popup/item_2/id = 2 popup/item_2/id = 2
[node name="PresetsMenuButton" type="MenuButton" parent="InterpolationContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
mouse_default_cursor_shape = 2
text = "Presets"
flat = false
[node name="TextureRect" type="TextureRect" parent="."] [node name="TextureRect" type="TextureRect" parent="."]
custom_minimum_size = Vector2(0, 30) custom_minimum_size = Vector2(0, 30)
layout_mode = 2 layout_mode = 2
@ -129,5 +140,6 @@ text = "Add point at the end"
[connection signal="value_changed" from="InterpolationContainer/OffsetValueSlider" to="." method="_on_offset_value_slider_value_changed"] [connection signal="value_changed" from="InterpolationContainer/OffsetValueSlider" to="." method="_on_offset_value_slider_value_changed"]
[connection signal="item_selected" from="InterpolationContainer/InterpolationOptionButton" to="." method="_on_InterpolationOptionButton_item_selected"] [connection signal="item_selected" from="InterpolationContainer/InterpolationOptionButton" to="." method="_on_InterpolationOptionButton_item_selected"]
[connection signal="item_selected" from="InterpolationContainer/ColorSpaceOptionButton" to="." method="_on_color_space_option_button_item_selected"] [connection signal="item_selected" from="InterpolationContainer/ColorSpaceOptionButton" to="." method="_on_color_space_option_button_item_selected"]
[connection signal="about_to_popup" from="InterpolationContainer/PresetsMenuButton" to="." method="_on_presets_menu_button_about_to_popup"]
[connection signal="color_changed" from="Popup/ColorPicker" to="." method="_on_ColorPicker_color_changed"] [connection signal="color_changed" from="Popup/ColorPicker" to="." method="_on_ColorPicker_color_changed"]
[connection signal="confirmed" from="DivideConfirmationDialog" to="." method="_on_DivideConfirmationDialog_confirmed"] [connection signal="confirmed" from="DivideConfirmationDialog" to="." method="_on_DivideConfirmationDialog_confirmed"]