1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-02-22 21:43:13 +00:00

Users can now color code their layers in the timeline

This commit is contained in:
Emmanouil Papadeas 2025-02-21 18:11:58 +02:00
parent b5da73e2c2
commit 999c6742a9
5 changed files with 64 additions and 10 deletions

View file

@ -6,6 +6,7 @@ extends RefCounted
signal name_changed ## Emits when [member name] is changed.
signal visibility_changed ## Emits when [member visible] is changed.
signal effects_added_removed ## Emits when an effect is added or removed to/from [member effects].
signal ui_color_changed ## Emits when [member ui_color] is changed.
## All currently supported layer blend modes between two layers. The upper layer
## is the blend layer, and the bottom layer is the base layer.
@ -13,7 +14,7 @@ signal effects_added_removed ## Emits when an effect is added or removed to/fro
enum BlendModes {
PASS_THROUGH = -2, ## Only for group layers. Ignores group blending, like it doesn't exist.
NORMAL = 0, ## The blend layer colors are simply placed on top of the base colors.
ERASE, ## Subtracts the numerical value of alpha from the base alpha.
ERASE, ## Erases the non-transparent areas of the upper layer from the lower layer's alpha.
DARKEN, ## Keeps the darker colors between the blend and the base layers.
MULTIPLY, ## Multiplies the numerical values of the two colors, giving a darker result.
COLOR_BURN, ## Darkens by increasing the contrast between the blend and base colors.
@ -55,6 +56,11 @@ var cel_link_sets: Array[Dictionary] = [] ## Each Dictionary represents a cel's
var effects: Array[LayerEffect] ## An array for non-destructive effects of the layer.
var effects_enabled := true ## If [code]true[/code], the effects are being applied.
var user_data := "" ## User defined data, set in the layer properties.
## The color of the layer's button in the timeline. By default, it's the theme button color.
var ui_color := Color(0, 0, 0, 0):
set(value):
ui_color = value
ui_color_changed.emit()
## Returns true if this is a direct or indirect parent of layer
@ -236,8 +242,9 @@ func display_effects(cel: BaseCel, image_override: Image = null) -> Image:
if not effect.enabled or not is_instance_valid(effect.shader):
continue
var params := effect.params
params["PXO_time"] = cel.get_frame(project).position_in_seconds(project)
params["PXO_frame_index"] = project.frames.find(cel.get_frame(project))
var frame := cel.get_frame(project)
params["PXO_time"] = frame.position_in_seconds(project)
params["PXO_frame_index"] = project.frames.find(frame)
params["PXO_layer_index"] = index
var shader_image_effect := ShaderImageEffect.new()
shader_image_effect.generate_image(image, effect.shader, params, image_size)
@ -259,6 +266,17 @@ func emit_effects_added_removed() -> void:
effects_added_removed.emit()
## Returns the final color of the layer button,
## iterating through the layer's ancestors, if it has any.
## If the layer has no UI color, it inherits from its parents, otherwise it overwrites it.
func get_ui_color() -> Color:
if not is_zero_approx(ui_color.a):
return ui_color
for ancestor in get_ancestors():
return ancestor.get_ui_color()
return ui_color
# Methods to Override:
@ -275,6 +293,7 @@ func serialize() -> Dictionary:
"blend_mode": blend_mode,
"clipping_mask": clipping_mask,
"opacity": opacity,
"ui_color": ui_color,
"parent": parent.index if is_instance_valid(parent) else -1,
"effects": effect_data
}
@ -301,6 +320,7 @@ func deserialize(dict: Dictionary) -> void:
clipping_mask = dict.get("clipping_mask", false)
opacity = dict.get("opacity", 1.0)
user_data = dict.get("user_data", user_data)
ui_color = str_to_var("Color" + dict.get("ui_color", "(0, 0, 0, 0)"))
if dict.get("parent", -1) != -1:
parent = project.layers[dict.parent]
if dict.has("linked_cels") and not dict["linked_cels"].is_empty(): # Backwards compatibility

View file

@ -35,6 +35,7 @@ var audio_player: AudioStreamPlayer
@onready var hierarchy_spacer := %HierarchySpacer as Control
@onready var layer_fx_texture_rect := %LayerFXTextureRect as TextureRect
@onready var layer_type_texture_rect := %LayerTypeTextureRect as TextureRect
@onready var layer_ui_color := $LayerMainButton/LayerUIColor as ColorRect
@onready var linked_button := %LinkButton as BaseButton
@onready var clipping_mask_icon := %ClippingMask as TextureRect
@onready var popup_menu := $PopupMenu as PopupMenu
@ -47,6 +48,9 @@ func _ready() -> void:
var layer := Global.current_project.layers[layer_index]
layer.name_changed.connect(func(): label.text = layer.name)
layer.visibility_changed.connect(_on_layer_visibility_changed)
layer.ui_color_changed.connect(func(): layer_ui_color.color = layer.get_ui_color())
for ancestor in layer.get_ancestors():
ancestor.ui_color_changed.connect(func(): layer_ui_color.color = layer.get_ui_color())
if layer is PixelLayer:
linked_button.visible = true
elif layer is GroupLayer:
@ -62,6 +66,7 @@ func _ready() -> void:
custom_minimum_size.y = Global.animation_timeline.cel_size
label.text = layer.name
line_edit.text = layer.name
layer_ui_color.color = layer.get_ui_color()
layer_fx_texture_rect.visible = layer.effects.size() > 0
layer_type_texture_rect.texture = ARRAY_TEXTURE_TYPES[layer.get_layer_type()]
layer.effects_added_removed.connect(

View file

@ -127,6 +127,16 @@ theme_type_variation = &"LayerFrameButton"
toggle_mode = true
script = ExtResource("6_n8q6b")
[node name="LayerUIColor" type="ColorRect" parent="LayerMainButton"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
color = Color(0, 0, 0, 0)
[node name="LayerName" type="HBoxContainer" parent="LayerMainButton"]
layout_mode = 1
anchors_preset = 15

View file

@ -10,6 +10,7 @@ var layer_indices: PackedInt32Array
@onready var blend_modes_button := $GridContainer/BlendModeOptionButton as OptionButton
@onready var play_at_frame_slider := $GridContainer/PlayAtFrameSlider as ValueSlider
@onready var user_data_text_edit := $GridContainer/UserDataTextEdit as TextEdit
@onready var ui_color_picker_button := $GridContainer/UIColorPickerButton as ColorPickerButton
@onready var tileset_option_button := $GridContainer/TilesetOptionButton as OptionButton
@onready var audio_file_dialog := $AudioFileDialog as FileDialog
@ -34,6 +35,7 @@ func _on_visibility_changed() -> void:
play_at_frame_slider.value = first_layer.playback_frame + 1
play_at_frame_slider.max_value = project.frames.size()
user_data_text_edit.text = first_layer.user_data
ui_color_picker_button.color = first_layer.ui_color
get_tree().set_group(&"VisualLayers", "visible", first_layer is not AudioLayer)
get_tree().set_group(&"TilemapLayers", "visible", first_layer is LayerTileMap)
get_tree().set_group(&"AudioLayers", "visible", first_layer is AudioLayer)
@ -130,6 +132,12 @@ func _on_user_data_text_edit_text_changed() -> void:
layer.user_data = user_data_text_edit.text
func _on_ui_color_picker_button_color_changed(color: Color) -> void:
for layer_index in layer_indices:
var layer := Global.current_project.layers[layer_index]
layer.ui_color = color
func _emit_layer_property_signal() -> void:
layer_property_changed.emit()

View file

@ -6,14 +6,14 @@
[node name="LayerProperties" type="AcceptDialog"]
title = "Layer properties"
position = Vector2i(0, 36)
size = Vector2i(300, 270)
size = Vector2i(425, 300)
script = ExtResource("1_54q1t")
[node name="GridContainer" type="GridContainer" parent="."]
offset_left = 8.0
offset_top = 8.0
offset_right = 292.0
offset_bottom = 221.0
offset_right = 417.0
offset_bottom = 251.0
columns = 2
[node name="NameLabel" type="Label" parent="GridContainer"]
@ -81,6 +81,16 @@ stretch_margin_right = 3
stretch_margin_bottom = 3
script = ExtResource("2_bwpwc")
[node name="TilesetLabel" type="Label" parent="GridContainer" groups=["TilemapLayers"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 0
text = "Tileset:"
[node name="TilesetOptionButton" type="OptionButton" parent="GridContainer" groups=["TilemapLayers"]]
layout_mode = 2
mouse_default_cursor_shape = 2
[node name="UserDataLabel" type="Label" parent="GridContainer"]
layout_mode = 2
size_flags_horizontal = 3
@ -92,13 +102,13 @@ layout_mode = 2
size_flags_horizontal = 3
scroll_fit_content_height = true
[node name="TilesetLabel" type="Label" parent="GridContainer" groups=["TilemapLayers"]]
[node name="UIColorLabel" type="Label" parent="GridContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 0
text = "Tileset:"
text = "Color:"
[node name="TilesetOptionButton" type="OptionButton" parent="GridContainer" groups=["TilemapLayers"]]
[node name="UIColorPickerButton" type="ColorPickerButton" parent="GridContainer"]
layout_mode = 2
mouse_default_cursor_shape = 2
@ -117,6 +127,7 @@ filters = PackedStringArray("*.mp3 ; MP3 Audio")
[connection signal="item_selected" from="GridContainer/BlendModeOptionButton" to="." method="_on_blend_mode_option_button_item_selected"]
[connection signal="pressed" from="GridContainer/AudioFileButton" to="." method="_on_audio_file_button_pressed"]
[connection signal="value_changed" from="GridContainer/PlayAtFrameSlider" to="." method="_on_play_at_frame_slider_value_changed"]
[connection signal="text_changed" from="GridContainer/UserDataTextEdit" to="." method="_on_user_data_text_edit_text_changed"]
[connection signal="item_selected" from="GridContainer/TilesetOptionButton" to="." method="_on_tileset_option_button_item_selected"]
[connection signal="text_changed" from="GridContainer/UserDataTextEdit" to="." method="_on_user_data_text_edit_text_changed"]
[connection signal="color_changed" from="GridContainer/UIColorPickerButton" to="." method="_on_ui_color_picker_button_color_changed"]
[connection signal="file_selected" from="AudioFileDialog" to="." method="_on_audio_file_dialog_file_selected"]