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

New UI system using Dockable Containers (#640)

* Add dockable container plugin

Experimenting with it, also added a tabs_visible property to the DockableContainer. Removed some code about Tallscreen from Main.gd, but not all of it.

* Add a panel behind the UI, temporarily restore the dark theme

* Remove tallscreen code

* Add edit mode, toggles DockableContainer's tab visibility on and off

* Split tool options into color pickers, left and right tool options

* Remove alternate_transparent_background

* Re-order tool buttons on resize

* Clip content in timeline

* Changes to the tool panel

* Removed some old unused node variables

* Restore Zen mode

* Set tabs_visible = false by default

* Better way to set tabs_visible = false by default

* Added the license of godot-dockable-container

* Remove unneeded lines

* Update README.md

* Restore window transparency with the canvas

It makes all of the TabContainers transparent however, which may not be what we actually want.

* Change tab names of the UI elements

* Remove unneeded nodes from ColorPickers.tscn

* Update default.tres

* Let the user hide elements individually

* Add some checks in HandleThemes

* Center tool icons

* Remove unneeded custom panel in SplashDialog

* Bump version to v0.10-dev and some other minor changes

* Fix crash on Zen Mode

* Added a hacky way to fix the issue with the palette panel size
This commit is contained in:
Manolis Papadeas 2022-01-30 00:47:25 +02:00 committed by GitHub
parent 2649f0e2b8
commit e2bb0b8440
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 2749 additions and 864 deletions

View file

@ -4,7 +4,13 @@
- Upstream: https://github.com/jegor377/godot-gdgifexporter
- Version: git (b6a6628dc253acb5c2955bc9ca5c8eaa2eaf2e1a, 2021)
- License: MIT
- License: [MIT](https://github.com/jegor377/godot-gdgifexporter/blob/master/LICENSE)
Files extracted from source:
- `gdgifexporter/quantization/enhanced_uniform_quantization.gd`
## godot-dockable-container
- Upstream: https://github.com/gilzoide/godot-dockable-container
- Version: git (c0c631d27178923d28d8631b0116f4efad2cb360, 2022)
- License: [CC0-1.0](https://github.com/gilzoide/godot-dockable-container/blob/main/LICENSE)

View file

@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

View file

@ -0,0 +1,427 @@
tool
extends Container
const SplitHandle = preload("split_handle.gd")
const DockablePanel = preload("dockable_panel.gd")
const DragNDropPanel = preload("drag_n_drop_panel.gd")
const Layout = preload("layout.gd")
# gdlint: ignore=max-line-length
export(int, "Left", "Center", "Right") var tab_align = TabContainer.ALIGN_CENTER setget set_tab_align, get_tab_align
export(bool) var tabs_visible := true setget set_tabs_visible, get_tabs_visible
# gdlint: ignore=max-line-length
export(bool) var use_hidden_tabs_for_min_size: bool setget set_use_hidden_tabs_for_min_size, get_use_hidden_tabs_for_min_size
export(int) var rearrange_group = 0
export(Resource) var layout = Layout.new() setget set_layout, get_layout
# If `clone_layout_on_ready` is true, `layout` will be cloned on `_ready`.
# This is useful for leaving layout Resources untouched in case you want to
# restore layout to its default later.
export(bool) var clone_layout_on_ready = true
var _layout = Layout.new()
var _panel_container = Container.new()
var _split_container = Container.new()
var _drag_n_drop_panel = DragNDropPanel.new()
var _drag_panel: DockablePanel
var _tab_align = TabContainer.ALIGN_CENTER
var _tabs_visible = true
var _use_hidden_tabs_for_min_size = false
var _current_panel_index = 0
var _current_split_index = 0
var _children_names = {}
var _layout_dirty = false
func _ready() -> void:
set_process_input(false)
_panel_container.name = "_panel_container"
.add_child(_panel_container)
move_child(_panel_container, 0)
_split_container.name = "_split_container"
_split_container.mouse_filter = MOUSE_FILTER_PASS
_panel_container.add_child(_split_container)
_drag_n_drop_panel.name = "_drag_n_drop_panel"
_drag_n_drop_panel.mouse_filter = MOUSE_FILTER_PASS
_drag_n_drop_panel.set_drag_forwarding(self)
_drag_n_drop_panel.visible = false
.add_child(_drag_n_drop_panel)
if not _layout:
set_layout(null)
elif clone_layout_on_ready and not Engine.editor_hint:
set_layout(_layout.clone())
func _notification(what: int) -> void:
if what == NOTIFICATION_SORT_CHILDREN:
_resort()
elif (
what == NOTIFICATION_DRAG_BEGIN
and _can_handle_drag_data(get_viewport().gui_get_drag_data())
):
_drag_n_drop_panel.visible = true
set_process_input(true)
elif what == NOTIFICATION_DRAG_END:
_drag_n_drop_panel.visible = false
set_process_input(false)
func _input(event: InputEvent) -> void:
assert(get_viewport().gui_is_dragging(), "FIXME: should only be called when dragging")
if event is InputEventMouseMotion:
var local_position = get_local_mouse_position()
var panel
for i in range(1, _panel_container.get_child_count()):
var p = _panel_container.get_child(i)
if p.get_rect().has_point(local_position):
panel = p
break
_drag_panel = panel
if not panel:
return
fit_child_in_rect(_drag_n_drop_panel, panel.get_child_rect())
func add_child(node: Node, legible_unique_name: bool = false) -> void:
.add_child(node, legible_unique_name)
_drag_n_drop_panel.raise()
_track_and_add_node(node)
func add_child_below_node(node: Node, child_node: Node, legible_unique_name: bool = false) -> void:
.add_child_below_node(node, child_node, legible_unique_name)
_drag_n_drop_panel.raise()
_track_and_add_node(child_node)
func remove_child(node: Node) -> void:
.remove_child(node)
_untrack_node(node)
func can_drop_data_fw(_position: Vector2, data, from_control) -> bool:
return from_control == _drag_n_drop_panel and _can_handle_drag_data(data)
func drop_data_fw(_position: Vector2, data, from_control) -> void:
assert(from_control == _drag_n_drop_panel, "FIXME")
var from_node: DockablePanel = get_node(data.from_path)
if _drag_panel == null or (from_node == _drag_panel and _drag_panel.get_child_count() == 1):
return
var moved_tab = from_node.get_tab_control(data.tabc_element)
var moved_reference = moved_tab.reference_to
var margin = _drag_n_drop_panel.get_hover_margin()
_layout.split_leaf_with_node(_drag_panel.leaf, moved_reference, margin)
_layout_dirty = true
queue_sort()
func set_control_as_current_tab(control: Control) -> void:
assert(
control.get_parent_control() == self,
"Trying to focus a control not managed by this container"
)
if is_control_hidden(control):
push_warning("Trying to focus a hidden control")
return
var leaf = _layout.get_leaf_for_node(control)
if not leaf:
return
var position_in_leaf = leaf.find_node(control)
if position_in_leaf < 0:
return
var panel
for i in range(1, _panel_container.get_child_count()):
var p = _panel_container.get_child(i)
if p.leaf == leaf:
panel = p
break
if not panel:
return
panel.current_tab = clamp(position_in_leaf, 0, panel.get_tab_count() - 1)
func set_layout(value: Layout) -> void:
if value == null:
value = Layout.new()
if value == _layout:
return
if _layout and _layout.is_connected("changed", self, "queue_sort"):
_layout.disconnect("changed", self, "queue_sort")
_layout = value
_layout.connect("changed", self, "queue_sort")
_layout_dirty = true
queue_sort()
func get_layout() -> Layout:
return _layout
func set_tab_align(value: int) -> void:
_tab_align = value
for i in range(1, _panel_container.get_child_count()):
var panel = _panel_container.get_child(i)
panel.tab_align = value
func get_tab_align() -> int:
return _tab_align
func set_tabs_visible(value: bool) -> void:
_tabs_visible = value
for i in range(1, _panel_container.get_child_count()):
var panel = _panel_container.get_child(i)
panel.tabs_visible = value
func get_tabs_visible() -> bool:
return _tabs_visible
func set_use_hidden_tabs_for_min_size(value: bool) -> void:
_use_hidden_tabs_for_min_size = value
for i in range(1, _panel_container.get_child_count()):
var panel = _panel_container.get_child(i)
panel.use_hidden_tabs_for_min_size = value
func get_use_hidden_tabs_for_min_size() -> bool:
return _use_hidden_tabs_for_min_size
func set_control_hidden(child: Control, hidden: bool) -> void:
_layout.set_node_hidden(child, hidden)
func is_control_hidden(child: Control) -> bool:
return _layout.is_node_hidden(child)
func get_tabs() -> Array:
var tabs = []
for i in get_child_count():
var child = get_child(i)
if _is_managed_node(child):
tabs.append(child)
return tabs
func get_tab_count() -> int:
var count = 0
for i in get_child_count():
var child = get_child(i)
if _is_managed_node(child):
count += 1
return count
func _can_handle_drag_data(data):
if data is Dictionary and data.get("type") == "tabc_element":
var tabc = get_node_or_null(data.get("from_path"))
return (
tabc
and tabc.has_method("get_tabs_rearrange_group")
and tabc.get_tabs_rearrange_group() == rearrange_group
)
return false
func _is_managed_node(node: Node) -> bool:
return (
node != _panel_container
and node != _drag_n_drop_panel
and node is Control
and not node.is_set_as_toplevel()
)
func _update_layout_with_children() -> void:
var names = PoolStringArray()
_children_names.clear()
for i in range(1, get_child_count() - 1):
var c = get_child(i)
if _track_node(c):
names.append(c.name)
_layout.update_nodes(names)
_layout_dirty = false
func _track_node(node: Node) -> bool:
if not _is_managed_node(node):
return false
_children_names[node] = node.name
_children_names[node.name] = node
if not node.is_connected("renamed", self, "_on_child_renamed"):
node.connect("renamed", self, "_on_child_renamed", [node])
if not node.is_connected("tree_exiting", self, "_untrack_node"):
node.connect("tree_exiting", self, "_untrack_node", [node])
return true
func _track_and_add_node(node: Node) -> void:
var tracked_name = _children_names.get(node)
if not _track_node(node):
return
if tracked_name and tracked_name != node.name:
_layout.rename_node(tracked_name, node.name)
_layout_dirty = true
func _untrack_node(node: Node) -> void:
_children_names.erase(node)
_children_names.erase(node.name)
if node.is_connected("renamed", self, "_on_child_renamed"):
node.disconnect("renamed", self, "_on_child_renamed")
if node.is_connected("tree_exiting", self, "_untrack_node"):
node.disconnect("tree_exiting", self, "_untrack_node")
_layout_dirty = true
func _resort() -> void:
assert(_panel_container, "FIXME: resorting without _panel_container")
if _panel_container.get_position_in_parent() != 0:
move_child(_panel_container, 0)
if _drag_n_drop_panel.get_position_in_parent() < get_child_count() - 1:
_drag_n_drop_panel.raise()
if _layout_dirty:
_update_layout_with_children()
var rect = Rect2(Vector2.ZERO, rect_size)
fit_child_in_rect(_panel_container, rect)
_panel_container.fit_child_in_rect(_split_container, rect)
_current_panel_index = 1
_current_split_index = 0
var children_list = []
_calculate_panel_and_split_list(children_list, _layout.root)
_fit_panel_and_split_list_to_rect(children_list, rect)
_untrack_children_after(_panel_container, _current_panel_index)
_untrack_children_after(_split_container, _current_split_index)
# Calculate DockablePanel and SplitHandle minimum sizes, skipping empty
# branches.
#
# Returns a DockablePanel on non-empty leaves, a SplitHandle on non-empty
# splits, `null` if the whole branch is empty and no space should be used.
#
# `result` will be filled with the non-empty nodes in this post-order tree
# traversal.
func _calculate_panel_and_split_list(result: Array, layout_node: Layout.LayoutNode):
if layout_node is Layout.LayoutPanel:
var nodes = []
for n in layout_node.names:
var node: Control = _children_names.get(n)
if node:
assert(node is Control, "FIXME: node is not a control %s" % node)
assert(
node.get_parent_control() == self,
"FIXME: node is not child of container %s" % node
)
if is_control_hidden(node):
node.visible = false
else:
nodes.append(node)
if nodes.empty():
return null
else:
var panel = _get_panel(_current_panel_index)
_current_panel_index += 1
panel.track_nodes(nodes, layout_node)
result.append(panel)
return panel
elif layout_node is Layout.LayoutSplit:
# by processing `second` before `first`, traversing `result` from back
# to front yields a nice pre-order tree traversal
var second_result = _calculate_panel_and_split_list(result, layout_node.second)
var first_result = _calculate_panel_and_split_list(result, layout_node.first)
if first_result and second_result:
var split = _get_split(_current_split_index)
_current_split_index += 1
split.layout_split = layout_node
split.first_minimum_size = first_result.get_layout_minimum_size()
split.second_minimum_size = second_result.get_layout_minimum_size()
result.append(split)
return split
elif first_result:
return first_result
else: # NOTE: this returns null if `second_result` is null
return second_result
else:
push_warning("FIXME: invalid Resource, should be branch or leaf, found %s" % layout_node)
# Traverse list from back to front fitting controls where they belong.
#
# Be sure to call this with the result from `_calculate_split_minimum_sizes`.
func _fit_panel_and_split_list_to_rect(panel_and_split_list: Array, rect: Rect2) -> void:
var control = panel_and_split_list.pop_back()
if control is DockablePanel:
_panel_container.fit_child_in_rect(control, rect)
elif control is SplitHandle:
var split_rects = control.get_split_rects(rect)
_split_container.fit_child_in_rect(control, split_rects.self)
_fit_panel_and_split_list_to_rect(panel_and_split_list, split_rects.first)
_fit_panel_and_split_list_to_rect(panel_and_split_list, split_rects.second)
func _get_panel(idx: int) -> DockablePanel:
"""Get the idx'th DockablePanel, reusing an instanced one if possible"""
assert(_panel_container, "FIXME: creating panel without _panel_container")
if idx < _panel_container.get_child_count():
return _panel_container.get_child(idx)
var panel = DockablePanel.new()
panel.tab_align = _tab_align
panel.tabs_visible = _tabs_visible
panel.use_hidden_tabs_for_min_size = _use_hidden_tabs_for_min_size
panel.set_tabs_rearrange_group(max(0, rearrange_group))
_panel_container.add_child(panel)
panel.connect("tab_layout_changed", self, "_on_panel_tab_layout_changed", [panel])
return panel
func _get_split(idx: int) -> SplitHandle:
"""Get the idx'th SplitHandle, reusing an instanced one if possible"""
assert(_split_container, "FIXME: creating split without _split_container")
if idx < _split_container.get_child_count():
return _split_container.get_child(idx)
var split = SplitHandle.new()
_split_container.add_child(split)
return split
static func _untrack_children_after(node, idx: int) -> void:
"""Helper for removing and freeing all remaining children from node"""
for i in range(idx, node.get_child_count()):
var child = node.get_child(idx)
node.remove_child(child)
child.queue_free()
func _on_panel_tab_layout_changed(tab: int, panel: DockablePanel) -> void:
"""Handler for `DockablePanel.tab_layout_changed`, update its LayoutPanel"""
_layout_dirty = true
var tab_reference = panel.get_tab_control(tab)
_layout.move_node_to_leaf(tab_reference.reference_to, panel.leaf, tab)
queue_sort()
func _on_child_renamed(child: Node) -> void:
"""Handler for `Node.renamed` signal, updates tracked name for node"""
var old_name = _children_names.get(child)
if not old_name:
return
_children_names.erase(old_name)
_children_names[child] = child.name
_children_names[child.name] = child
_layout.rename_node(old_name, child.name)

View file

@ -0,0 +1,80 @@
tool
extends TabContainer
signal tab_layout_changed(tab)
const ReferenceControl = preload("dockable_panel_reference_control.gd")
const Layout = preload("layout.gd")
var leaf: Layout.LayoutPanel setget set_leaf, get_leaf
var _leaf: Layout.LayoutPanel
func _ready() -> void:
drag_to_rearrange_enabled = true
func _enter_tree() -> void:
connect("tab_selected", self, "_on_tab_selected")
connect("tab_changed", self, "_on_tab_changed")
func _exit_tree() -> void:
disconnect("tab_selected", self, "_on_tab_selected")
disconnect("tab_changed", self, "_on_tab_changed")
func track_nodes(nodes: Array, new_leaf: Layout.LayoutPanel) -> void:
_leaf = null # avoid using previous leaf in tab_changed signals
var min_size = min(nodes.size(), get_child_count())
# remove spare children
for i in range(min_size, get_child_count()):
var child = get_child(min_size)
child.reference_to = null
remove_child(child)
child.queue_free()
# add missing children
for i in range(min_size, nodes.size()):
var ref_control = ReferenceControl.new()
add_child(ref_control)
assert(nodes.size() == get_child_count(), "FIXME")
# setup children
for i in nodes.size():
var ref_control: ReferenceControl = get_child(i)
ref_control.reference_to = nodes[i]
set_tab_title(i, nodes[i].name)
set_leaf(new_leaf)
func get_child_rect() -> Rect2:
var control = get_current_tab_control()
return Rect2(rect_position + control.rect_position, control.rect_size)
func set_leaf(value: Layout.LayoutPanel) -> void:
if get_tab_count() > 0 and value:
current_tab = clamp(value.current_tab, 0, get_tab_count() - 1)
_leaf = value
func get_leaf() -> Layout.LayoutPanel:
return _leaf
func get_layout_minimum_size() -> Vector2:
return get_combined_minimum_size()
func _on_tab_selected(tab: int) -> void:
if _leaf:
_leaf.current_tab = tab
func _on_tab_changed(tab: int) -> void:
if not _leaf:
return
var tab_name = get_tab_control(tab).name
var name_index_in_leaf = _leaf.find_name(tab_name)
if name_index_in_leaf != tab: # NOTE: this handles added tabs (index == -1)
emit_signal("tab_layout_changed", tab)

View file

@ -0,0 +1,49 @@
tool
extends Container
# Control that mimics its own visibility and rect into another Control.
signal moved_in_parent(control)
var reference_to: Control setget set_reference_to, get_reference_to
var _reference_to: Control = null
func _ready() -> void:
mouse_filter = MOUSE_FILTER_IGNORE
func _notification(what: int) -> void:
if what == NOTIFICATION_VISIBILITY_CHANGED and _reference_to:
_reference_to.visible = visible
elif what == NOTIFICATION_SORT_CHILDREN and _reference_to:
_reposition_reference()
func _get_minimum_size() -> Vector2:
return _reference_to.get_combined_minimum_size() if _reference_to else Vector2.ZERO
func set_reference_to(control: Control) -> void:
if _reference_to != control:
if _reference_to:
_reference_to.disconnect("renamed", self, "_on_reference_to_renamed")
_reference_to = control
minimum_size_changed()
if not _reference_to:
return
_reference_to.connect("renamed", self, "_on_reference_to_renamed")
_reference_to.visible = visible
func get_reference_to() -> Control:
return _reference_to
func _reposition_reference() -> void:
_reference_to.rect_global_position = rect_global_position
_reference_to.rect_size = rect_size
func _on_reference_to_renamed() -> void:
name = _reference_to.name

View file

@ -0,0 +1,65 @@
tool
extends Control
const MARGIN_NONE = -1
var _hover_margin = MARGIN_NONE
func _notification(what: int) -> void:
if what == NOTIFICATION_MOUSE_EXIT:
_hover_margin = MARGIN_NONE
elif what == NOTIFICATION_DRAG_BEGIN:
_hover_margin = MARGIN_NONE
func _gui_input(event: InputEvent) -> void:
if event is InputEventMouseMotion:
_find_hover_margin(event.position)
update()
func _draw() -> void:
var rect
if _hover_margin == MARGIN_NONE:
return
elif _hover_margin == MARGIN_LEFT:
rect = Rect2(0, 0, rect_size.x * 0.5, rect_size.y)
elif _hover_margin == MARGIN_TOP:
rect = Rect2(0, 0, rect_size.x, rect_size.y * 0.5)
elif _hover_margin == MARGIN_RIGHT:
var half_width = rect_size.x * 0.5
rect = Rect2(half_width, 0, half_width, rect_size.y)
elif _hover_margin == MARGIN_BOTTOM:
var half_height = rect_size.y * 0.5
rect = Rect2(0, half_height, rect_size.x, half_height)
var stylebox = get_stylebox("panel", "TooltipPanel")
draw_style_box(stylebox, rect)
func get_hover_margin() -> int:
return _hover_margin
func _find_hover_margin(point: Vector2):
var half_size = rect_size * 0.5
var left = point.distance_squared_to(Vector2(0, half_size.y))
var lesser = left
var lesser_margin = MARGIN_LEFT
var top = point.distance_squared_to(Vector2(half_size.x, 0))
if lesser > top:
lesser = top
lesser_margin = MARGIN_TOP
var right = point.distance_squared_to(Vector2(rect_size.x, half_size.y))
if lesser > right:
lesser = right
lesser_margin = MARGIN_RIGHT
var bottom = point.distance_squared_to(Vector2(half_size.x, rect_size.y))
if lesser > bottom:
#lesser = bottom # unused result
lesser_margin = MARGIN_BOTTOM
_hover_margin = lesser_margin

View file

@ -0,0 +1,17 @@
extends EditorInspectorPlugin
const DockableContainer = preload("../dockable_container.gd")
const LayoutEditorProperty = preload("layout_editor_property.gd")
func can_handle(object: Object) -> bool:
return object is DockableContainer
func parse_property(
_object: Object, _type: int, path: String, _hint: int, _hint_text: String, _usage: int
) -> bool:
if path == "layout":
var editor_property = LayoutEditorProperty.new()
add_property_editor("layout", editor_property)
return false

View file

@ -0,0 +1,71 @@
extends EditorProperty
const DockableContainer = preload("../dockable_container.gd")
const Layout = preload("../layout.gd")
var _container = DockableContainer.new()
var _hidden_menu_button = MenuButton.new()
var _hidden_menu_popup: PopupMenu
var _hidden_menu_list: PoolStringArray
func _ready() -> void:
rect_min_size = Vector2(128, 256)
_hidden_menu_button.text = "Visible nodes"
add_child(_hidden_menu_button)
_hidden_menu_popup = _hidden_menu_button.get_popup()
_hidden_menu_popup.hide_on_checkable_item_selection = false
_hidden_menu_popup.connect("about_to_show", self, "_on_hidden_menu_popup_about_to_show")
_hidden_menu_popup.connect("id_pressed", self, "_on_hidden_menu_popup_id_pressed")
_container.clone_layout_on_ready = false
_container.rect_min_size = rect_min_size
var original_container: DockableContainer = get_edited_object()
var value = original_container.get(get_edited_property())
_container.set(get_edited_property(), value)
for n in value.get_names():
var child = _create_child_control(n)
_container.add_child(child)
add_child(_container)
set_bottom_editor(_container)
func update_property() -> void:
var value = _get_layout()
_container.set(get_edited_property(), value)
func _get_layout() -> Layout:
var original_container: DockableContainer = get_edited_object()
return original_container.get(get_edited_property())
func _create_child_control(named: String) -> Control:
var new_control = Label.new()
new_control.name = named
new_control.align = Label.ALIGN_CENTER
new_control.valign = Label.VALIGN_CENTER
new_control.clip_text = true
new_control.text = named
return new_control
func _on_hidden_menu_popup_about_to_show() -> void:
var layout = _get_layout()
_hidden_menu_popup.clear()
_hidden_menu_list = layout.get_names()
for i in _hidden_menu_list.size():
var tab_name = _hidden_menu_list[i]
_hidden_menu_popup.add_check_item(tab_name, i)
_hidden_menu_popup.set_item_checked(i, not layout.is_tab_hidden(tab_name))
func _on_hidden_menu_popup_id_pressed(id: int) -> void:
var layout = _get_layout()
var tab_name = _hidden_menu_list[id]
var new_hidden = not layout.is_tab_hidden(tab_name)
layout.set_tab_hidden(tab_name, new_hidden)
_hidden_menu_popup.set_item_checked(id, not new_hidden)
emit_changed(get_edited_property(), layout)

View file

@ -0,0 +1,247 @@
tool
extends Resource
# Layout Resource definition, holding the root LayoutNode and hidden tabs.
#
# LayoutSplit are binary trees with nested LayoutSplit subtrees and LayoutPanel
# leaves. Both of them inherit from LayoutNode to help with type annotation and
# define common funcionality.
#
# Hidden tabs are marked in the `hidden_tabs` Dictionary by name.
const LayoutNode = preload("layout_node.gd")
const LayoutPanel = preload("layout_panel.gd")
const LayoutSplit = preload("layout_split.gd")
export(Resource) var root = LayoutPanel.new() setget set_root, get_root
export(Dictionary) var hidden_tabs = {} setget set_hidden_tabs, get_hidden_tabs
var _changed_signal_queued = false
var _first_leaf: LayoutPanel
var _hidden_tabs: Dictionary
var _leaf_by_node_name: Dictionary
var _root: LayoutNode = LayoutPanel.new()
func _init() -> void:
resource_name = "Layout"
func set_root(value: LayoutNode, should_emit_changed = true) -> void:
if not value:
value = LayoutPanel.new()
if _root == value:
return
if _root and _root.is_connected("changed", self, "_on_root_changed"):
_root.disconnect("changed", self, "_on_root_changed")
_root = value
_root.parent = null
_root.connect("changed", self, "_on_root_changed")
if should_emit_changed:
_on_root_changed()
func get_root() -> LayoutNode:
return _root
func set_hidden_tabs(value: Dictionary) -> void:
if value != _hidden_tabs:
_hidden_tabs = value
emit_signal("changed")
func get_hidden_tabs() -> Dictionary:
return _hidden_tabs
func clone():
var new_layout = get_script().new()
new_layout.root = _root.clone()
new_layout._hidden_tabs = _hidden_tabs.duplicate()
return new_layout
func get_names() -> PoolStringArray:
return _root.get_names()
# Add missing nodes on first leaf and remove nodes outside indices from leaves.
#
# _leaf_by_node_name = {
# (string keys) = respective Leaf that holds the node name,
# }
func update_nodes(names: PoolStringArray) -> void:
_leaf_by_node_name.clear()
_first_leaf = null
var empty_leaves = []
_ensure_names_in_node(_root, names, empty_leaves)
for l in empty_leaves:
_remove_leaf(l)
if not _first_leaf:
_first_leaf = LayoutPanel.new()
set_root(_first_leaf)
for n in names:
if not _leaf_by_node_name.has(n):
_first_leaf.push_name(n)
_leaf_by_node_name[n] = _first_leaf
_on_root_changed()
func move_node_to_leaf(node: Node, leaf: LayoutPanel, relative_position: int) -> void:
var node_name = node.name
var previous_leaf = _leaf_by_node_name.get(node_name)
if not previous_leaf:
return
previous_leaf.remove_node(node)
if previous_leaf.empty():
_remove_leaf(previous_leaf)
leaf.insert_node(relative_position, node)
_leaf_by_node_name[node_name] = leaf
_on_root_changed()
func get_leaf_for_node(node: Node) -> LayoutPanel:
return _leaf_by_node_name.get(node.name)
func split_leaf_with_node(leaf, node: Node, margin: int) -> void:
var root_branch = leaf.parent
var new_leaf = LayoutPanel.new()
var new_branch = LayoutSplit.new()
if margin == MARGIN_LEFT or margin == MARGIN_RIGHT:
new_branch.direction = LayoutSplit.Direction.HORIZONTAL
else:
new_branch.direction = LayoutSplit.Direction.VERTICAL
if margin == MARGIN_LEFT or margin == MARGIN_TOP:
new_branch.first = new_leaf
new_branch.second = leaf
else:
new_branch.first = leaf
new_branch.second = new_leaf
if _root == leaf:
set_root(new_branch, false)
elif root_branch:
if leaf == root_branch.first:
root_branch.first = new_branch
else:
root_branch.second = new_branch
move_node_to_leaf(node, new_leaf, 0)
func add_node(node: Node) -> void:
var node_name = node.name
if _leaf_by_node_name.has(node_name):
return
_first_leaf.push_name(node_name)
_leaf_by_node_name[node_name] = _first_leaf
_on_root_changed()
func remove_node(node: Node) -> void:
var node_name = node.name
var leaf: LayoutPanel = _leaf_by_node_name.get(node_name)
if not leaf:
return
leaf.remove_node(node)
_leaf_by_node_name.erase(node_name)
if leaf.empty():
_remove_leaf(leaf)
_on_root_changed()
func rename_node(previous_name: String, new_name: String) -> void:
var leaf = _leaf_by_node_name.get(previous_name)
if not leaf:
return
leaf.rename_node(previous_name, new_name)
_leaf_by_node_name.erase(previous_name)
_leaf_by_node_name[new_name] = leaf
_on_root_changed()
func set_tab_hidden(name: String, hidden: bool) -> void:
if not _leaf_by_node_name.has(name):
return
if hidden:
_hidden_tabs[name] = true
else:
_hidden_tabs.erase(name)
_on_root_changed()
func is_tab_hidden(name: String) -> bool:
return _hidden_tabs.get(name, false)
func set_node_hidden(node: Node, hidden: bool) -> void:
set_tab_hidden(node.name, hidden)
func is_node_hidden(node: Node) -> bool:
return is_tab_hidden(node.name)
func _on_root_changed() -> void:
if _changed_signal_queued:
return
_changed_signal_queued = true
set_deferred("_changed_signal_queued", false)
call_deferred("emit_signal", "changed")
func _ensure_names_in_node(node: LayoutNode, names: PoolStringArray, empty_leaves: Array) -> void:
if node is LayoutPanel:
node.update_nodes(names, _leaf_by_node_name)
if node.empty():
empty_leaves.append(node)
if not _first_leaf:
_first_leaf = node
elif node is LayoutSplit:
_ensure_names_in_node(node.first, names, empty_leaves)
_ensure_names_in_node(node.second, names, empty_leaves)
else:
assert(false, "Invalid Resource, should be branch or leaf, found %s" % node)
func _remove_leaf(leaf: LayoutPanel) -> void:
assert(leaf.empty(), "FIXME: trying to remove a leaf with nodes")
if _root == leaf:
return
var collapsed_branch = leaf.parent
assert(collapsed_branch is LayoutSplit, "FIXME: leaf is not a child of branch")
var kept_branch = (
collapsed_branch.first
if leaf == collapsed_branch.second
else collapsed_branch.second
)
var root_branch = collapsed_branch.parent
if collapsed_branch == _root:
set_root(kept_branch, true)
elif root_branch:
if collapsed_branch == root_branch.first:
root_branch.first = kept_branch
else:
root_branch.second = kept_branch
func _print_tree() -> void:
print("TREE")
_print_tree_step(_root, 0, 0)
print("")
func _print_tree_step(tree_or_leaf, level, idx) -> void:
if tree_or_leaf is LayoutPanel:
print(" |".repeat(level), "- (%d) = " % idx, tree_or_leaf.names)
else:
print(
" |".repeat(level),
"-+ (%d) = " % idx,
tree_or_leaf.direction,
" ",
tree_or_leaf.percent
)
_print_tree_step(tree_or_leaf.first, level + 1, 1)
_print_tree_step(tree_or_leaf.second, level + 1, 2)

View file

@ -0,0 +1,30 @@
tool
extends Resource
# Base class for Layout tree nodes
var parent = null
func emit_tree_changed() -> void:
var node = self
while node:
node.emit_signal("changed")
node = node.parent
# Returns a deep copy of the layout.
#
# Use this instead of `Resource.duplicate(true)` to ensure objects have the
# right script and parenting is correctly set for each node.
func clone():
assert(false, "FIXME: implement on child")
# Returns whether there are any nodes
func empty() -> bool:
return true
# Returns all tab names in this node
func get_names() -> PoolStringArray:
return PoolStringArray()

View file

@ -0,0 +1,97 @@
tool
extends "layout_node.gd"
# Layout leaf nodes, defining tabs
export(PoolStringArray) var names: PoolStringArray setget set_names, get_names
export(int) var current_tab: int setget set_current_tab, get_current_tab
var _names := PoolStringArray()
var _current_tab := 0
func _init() -> void:
resource_name = "Tabs"
func clone():
var new_panel = get_script().new()
new_panel._names = _names
new_panel._current_tab = _current_tab
return new_panel
func set_current_tab(value: int) -> void:
if value != _current_tab:
_current_tab = value
emit_tree_changed()
func get_current_tab() -> int:
return int(clamp(_current_tab, 0, _names.size() - 1))
func set_names(value: PoolStringArray) -> void:
_names = value
emit_tree_changed()
func get_names() -> PoolStringArray:
return _names
func push_name(name: String) -> void:
_names.append(name)
emit_tree_changed()
func insert_node(position: int, node: Node) -> void:
_names.insert(position, node.name)
emit_tree_changed()
func find_name(node_name: String) -> int:
for i in _names.size():
if _names[i] == node_name:
return i
return -1
func find_node(node: Node):
return find_name(node.name)
func remove_node(node: Node) -> void:
var i = find_node(node)
if i >= 0:
_names.remove(i)
emit_tree_changed()
else:
push_warning("Remove failed, node '%s' was not found" % node)
func rename_node(previous_name: String, new_name: String) -> void:
var i = find_name(previous_name)
if i >= 0:
_names.set(i, new_name)
emit_tree_changed()
else:
push_warning("Rename failed, name '%s' was not found" % previous_name)
func empty() -> bool:
return _names.empty()
func update_nodes(node_names: PoolStringArray, data: Dictionary):
var i = 0
var removed_any = false
while i < _names.size():
var current = _names[i]
if not current in node_names or data.has(current):
_names.remove(i)
removed_any = true
else:
data[current] = self
i += 1
if removed_any:
emit_tree_changed()

View file

@ -0,0 +1,98 @@
tool
extends "layout_node.gd"
# Layout binary tree nodes, defining subtrees and leaf panels
enum Direction {
HORIZONTAL,
VERTICAL,
}
const LayoutPanel = preload("layout_panel.gd")
export(Direction) var direction = Direction.HORIZONTAL setget set_direction, get_direction
export(float, 0, 1) var percent = 0.5 setget set_percent, get_percent
export(Resource) var first = LayoutPanel.new() setget set_first, get_first
export(Resource) var second = LayoutPanel.new() setget set_second, get_second
var _direction = Direction.HORIZONTAL
var _percent = 0.5
var _first
var _second
func _init() -> void:
resource_name = "Split"
func clone():
var new_split = get_script().new()
new_split._direction = _direction
new_split._percent = _percent
new_split.first = _first.clone()
new_split.second = _second.clone()
return new_split
func set_first(value) -> void:
if value == null:
_first = LayoutPanel.new()
else:
_first = value
_first.parent = self
emit_tree_changed()
func get_first():
return _first
func set_second(value) -> void:
if value == null:
_second = LayoutPanel.new()
else:
_second = value
_second.parent = self
emit_tree_changed()
func get_second():
return _second
func set_direction(value: int) -> void:
if value != _direction:
_direction = value
emit_tree_changed()
func get_direction() -> int:
return _direction
func set_percent(value: float) -> void:
var clamped_value = clamp(value, 0, 1)
if not is_equal_approx(_percent, clamped_value):
_percent = clamped_value
emit_tree_changed()
func get_percent() -> float:
return _percent
func get_names() -> PoolStringArray:
var names = _first.get_names()
names.append_array(_second.get_names())
return names
func empty() -> bool:
return _first.empty() and _second.empty()
func is_horizontal() -> bool:
return _direction == Direction.HORIZONTAL
func is_vertical() -> bool:
return _direction == Direction.VERTICAL

View file

@ -0,0 +1,13 @@
[plugin]
name="Dockable Container"
description="Container script that manages docking/tiling UI panels.
Panels are composed of tabs that can be dragged around and dropped to split another panel or compose its tabs.
Layout information is stored in Resource objects, so they can be saved/loaded from disk easily.
This plugin also offers a replica of the Container layout to be edited directly in the inspector."
author="gilzoide"
version="0.4.0"
script="plugin.gd"

View file

@ -0,0 +1,19 @@
tool
extends EditorPlugin
const DockableContainer = preload("dockable_container.gd")
const LayoutInspectorPlugin = preload("inspector_plugin/editor_inspector_plugin.gd")
var _layout_inspector_plugin
func _enter_tree() -> void:
_layout_inspector_plugin = LayoutInspectorPlugin.new()
add_custom_type("DockableContainer", "Container", DockableContainer, null)
add_inspector_plugin(_layout_inspector_plugin)
func _exit_tree() -> void:
remove_inspector_plugin(_layout_inspector_plugin)
remove_custom_type("DockableContainer")
_layout_inspector_plugin = null

View file

@ -0,0 +1,63 @@
extends VBoxContainer
const SAVED_LAYOUT_PATH = "user://layout.tres"
onready var _container = $DockableContainer
onready var _clone_control = $HBoxContainer/ControlPrefab
onready var _checkbox_container = $HBoxContainer
func _ready() -> void:
if not OS.is_userfs_persistent():
$HBoxContainer/SaveLayoutButton.visible = false
$HBoxContainer/LoadLayoutButton.visible = false
var tabs = _container.get_tabs()
for i in tabs.size():
var checkbox = CheckBox.new()
checkbox.text = str(i)
checkbox.pressed = not _container.is_control_hidden(tabs[i])
checkbox.connect("toggled", self, "_on_CheckButton_toggled", [tabs[i]])
_checkbox_container.add_child(checkbox)
func _on_add_pressed() -> void:
var control = _clone_control.duplicate()
control.get_node("Buttons/Rename").connect(
"pressed", self, "_on_control_rename_button_pressed", [control]
)
control.get_node("Buttons/Remove").connect(
"pressed", self, "_on_control_remove_button_pressed", [control]
)
control.color = Color(randf(), randf(), randf())
control.name = "Control0"
_container.add_child(control, true)
yield(_container, "sort_children")
_container.set_control_as_current_tab(control)
func _on_save_pressed() -> void:
if ResourceSaver.save(SAVED_LAYOUT_PATH, _container.get_layout()) != OK:
print("ERROR")
func _on_load_pressed() -> void:
var res = load(SAVED_LAYOUT_PATH)
if res:
_container.set_layout(res.clone())
else:
print("Error")
func _on_control_rename_button_pressed(control: Control) -> void:
control.name += " =D"
func _on_control_remove_button_pressed(control: Control) -> void:
_container.remove_child(control)
control.queue_free()
func _on_CheckButton_toggled(button_pressed: bool, tab: Control) -> void:
_container.set_control_hidden(tab, not button_pressed)

View file

@ -0,0 +1,238 @@
[gd_scene load_steps=18 format=2]
[ext_resource path="res://addons/dockable_container/dockable_container.gd" type="Script" id=1]
[ext_resource path="res://addons/dockable_container/layout.gd" type="Script" id=2]
[ext_resource path="res://addons/dockable_container/layout_split.gd" type="Script" id=3]
[ext_resource path="res://addons/dockable_container/samples/TestScene.gd" type="Script" id=4]
[ext_resource path="res://addons/dockable_container/layout_panel.gd" type="Script" id=5]
[sub_resource type="Resource" id=1]
resource_name = "Tabs"
script = ExtResource( 5 )
names = PoolStringArray( "Control0" )
current_tab = 0
[sub_resource type="Resource" id=2]
resource_name = "Tabs"
script = ExtResource( 5 )
names = PoolStringArray( "Control2" )
current_tab = 0
[sub_resource type="Resource" id=3]
resource_name = "Tabs"
script = ExtResource( 5 )
names = PoolStringArray( "Control3" )
current_tab = 0
[sub_resource type="Resource" id=4]
resource_name = "Split"
script = ExtResource( 3 )
direction = 1
percent = 0.5
first = SubResource( 2 )
second = SubResource( 3 )
[sub_resource type="Resource" id=5]
resource_name = "Split"
script = ExtResource( 3 )
direction = 1
percent = 0.333
first = SubResource( 1 )
second = SubResource( 4 )
[sub_resource type="Resource" id=6]
resource_name = "Tabs"
script = ExtResource( 5 )
names = PoolStringArray( "Control1" )
current_tab = 0
[sub_resource type="Resource" id=7]
resource_name = "Tabs"
script = ExtResource( 5 )
names = PoolStringArray( "Control4" )
current_tab = 0
[sub_resource type="Resource" id=8]
resource_name = "Split"
script = ExtResource( 3 )
direction = 1
percent = 0.5
first = SubResource( 6 )
second = SubResource( 7 )
[sub_resource type="Resource" id=9]
resource_name = "Tabs"
script = ExtResource( 5 )
names = PoolStringArray( "Control5", "Control6" )
current_tab = 1
[sub_resource type="Resource" id=10]
resource_name = "Split"
script = ExtResource( 3 )
direction = 0
percent = 0.649798
first = SubResource( 8 )
second = SubResource( 9 )
[sub_resource type="Resource" id=11]
resource_name = "Split"
script = ExtResource( 3 )
direction = 0
percent = 0.230294
first = SubResource( 5 )
second = SubResource( 10 )
[sub_resource type="Resource" id=12]
resource_name = "Layout"
script = ExtResource( 2 )
root = SubResource( 11 )
hidden_tabs = {
}
[node name="SampleScene" type="VBoxContainer"]
anchor_right = 1.0
anchor_bottom = 1.0
script = ExtResource( 4 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="HBoxContainer" type="HBoxContainer" parent="."]
margin_right = 1024.0
margin_bottom = 20.0
custom_constants/separation = 16
alignment = 1
[node name="AddControlButton" type="Button" parent="HBoxContainer"]
margin_left = 345.0
margin_right = 472.0
margin_bottom = 20.0
size_flags_horizontal = 0
size_flags_vertical = 4
text = "(+) ADD CONTROL"
[node name="SaveLayoutButton" type="Button" parent="HBoxContainer"]
margin_left = 488.0
margin_right = 575.0
margin_bottom = 20.0
size_flags_horizontal = 0
size_flags_vertical = 4
text = "Save Layout"
[node name="LoadLayoutButton" type="Button" parent="HBoxContainer"]
margin_left = 591.0
margin_right = 679.0
margin_bottom = 20.0
size_flags_horizontal = 0
size_flags_vertical = 4
text = "Load Layout"
[node name="ControlPrefab" type="ColorRect" parent="HBoxContainer"]
visible = false
margin_left = 677.0
margin_right = 697.0
margin_bottom = 20.0
rect_min_size = Vector2( 20, 20 )
color = Color( 0.129412, 0.121569, 0.121569, 1 )
[node name="Buttons" type="VBoxContainer" parent="HBoxContainer/ControlPrefab"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -65.5
margin_top = -22.0
margin_right = 65.5
margin_bottom = 22.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Rename" type="Button" parent="HBoxContainer/ControlPrefab/Buttons"]
margin_right = 131.0
margin_bottom = 20.0
text = "Rename"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Remove" type="Button" parent="HBoxContainer/ControlPrefab/Buttons"]
margin_top = 24.0
margin_right = 131.0
margin_bottom = 44.0
text = "REMOVE"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="DockableContainer" type="Container" parent="."]
margin_top = 24.0
margin_right = 1024.0
margin_bottom = 600.0
size_flags_horizontal = 3
size_flags_vertical = 3
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
layout = SubResource( 12 )
[node name="Control0" type="ColorRect" parent="DockableContainer"]
margin_left = 4.0
margin_top = 32.0
margin_right = 225.821
margin_bottom = 180.476
rect_min_size = Vector2( 64, 64 )
[node name="Control1" type="ColorRect" parent="DockableContainer"]
margin_left = 245.821
margin_top = 32.0
margin_right = 740.079
margin_bottom = 276.0
rect_min_size = Vector2( 128, 128 )
color = Color( 0.141176, 0.0745098, 0.603922, 1 )
[node name="Control2" type="ColorRect" parent="DockableContainer"]
margin_left = 4.0
margin_top = 228.476
margin_right = 225.821
margin_bottom = 374.238
rect_min_size = Vector2( 64, 64 )
color = Color( 0.533333, 0.380392, 0.380392, 1 )
[node name="Control3" type="ColorRect" parent="DockableContainer"]
margin_left = 4.0
margin_top = 422.238
margin_right = 225.821
margin_bottom = 568.0
rect_min_size = Vector2( 64, 64 )
color = Color( 0.741176, 0.188235, 0.188235, 1 )
[node name="Control4" type="ColorRect" parent="DockableContainer"]
margin_left = 245.821
margin_top = 324.0
margin_right = 740.079
margin_bottom = 568.0
rect_min_size = Vector2( 128, 128 )
color = Color( 0.129412, 0.121569, 0.121569, 1 )
[node name="Control5" type="ColorRect" parent="DockableContainer"]
margin_left = 760.079
margin_top = 32.0
margin_right = 1020.0
margin_bottom = 568.0
rect_min_size = Vector2( 64, 64 )
color = Color( 0.333333, 0.862745, 0.8, 1 )
[node name="Control6" type="ColorRect" parent="DockableContainer"]
visible = false
margin_left = 760.079
margin_top = 32.0
margin_right = 1020.0
margin_bottom = 568.0
rect_min_size = Vector2( 64, 64 )
color = Color( 0.898039, 0.921569, 0.188235, 1 )
[connection signal="pressed" from="HBoxContainer/AddControlButton" to="." method="_on_add_pressed"]
[connection signal="pressed" from="HBoxContainer/SaveLayoutButton" to="." method="_on_save_pressed"]
[connection signal="pressed" from="HBoxContainer/LoadLayoutButton" to="." method="_on_load_pressed"]

View file

@ -0,0 +1,131 @@
tool
extends Control
const Layout = preload("layout.gd")
const SPLIT_THEME_CLASS = [
"HSplitContainer", # SPLIT_THEME_CLASS[LayoutSplit.Direction.HORIZONTAL]
"VSplitContainer", # SPLIT_THEME_CLASS[LayoutSplit.Direction.VERTICAL]
]
const SPLIT_MOUSE_CURSOR_SHAPE = [
Control.CURSOR_HSPLIT, # SPLIT_MOUSE_CURSOR_SHAPE[LayoutSplit.Direction.HORIZONTAL]
Control.CURSOR_VSPLIT, # SPLIT_MOUSE_CURSOR_SHAPE[LayoutSplit.Direction.VERTICAL]
]
var layout_split: Layout.LayoutSplit
var first_minimum_size: Vector2
var second_minimum_size: Vector2
var _parent_rect
var _mouse_hovering = false
var _dragging = false
func _draw() -> void:
var theme_class = SPLIT_THEME_CLASS[layout_split.direction]
var icon = get_icon("grabber", theme_class)
var autohide = bool(get_constant("autohide", theme_class))
if not icon or (autohide and not _mouse_hovering):
return
draw_texture(icon, (rect_size - icon.get_size()) * 0.5)
func _gui_input(event: InputEvent) -> void:
if event is InputEventMouseButton and event.button_index == BUTTON_LEFT:
_dragging = event.is_pressed()
if event.doubleclick:
layout_split.percent = 0.5
elif _dragging and event is InputEventMouseMotion:
var mouse_in_parent = get_parent_control().get_local_mouse_position()
if layout_split.is_horizontal():
layout_split.percent = (
(mouse_in_parent.x - _parent_rect.position.x)
/ _parent_rect.size.x
)
else:
layout_split.percent = (
(mouse_in_parent.y - _parent_rect.position.y)
/ _parent_rect.size.y
)
func _notification(what: int) -> void:
if what == NOTIFICATION_MOUSE_ENTER:
_mouse_hovering = true
set_split_cursor(true)
if bool(get_constant("autohide", SPLIT_THEME_CLASS[layout_split.direction])):
update()
elif what == NOTIFICATION_MOUSE_EXIT:
_mouse_hovering = false
set_split_cursor(false)
if bool(get_constant("autohide", SPLIT_THEME_CLASS[layout_split.direction])):
update()
elif what == NOTIFICATION_FOCUS_EXIT:
_dragging = false
func get_layout_minimum_size() -> Vector2:
if not layout_split:
return Vector2.ZERO
var separation = get_constant("separation", SPLIT_THEME_CLASS[layout_split.direction])
if layout_split.is_horizontal():
return Vector2(
first_minimum_size.x + separation + second_minimum_size.x,
max(first_minimum_size.y, second_minimum_size.y)
)
else:
return Vector2(
max(first_minimum_size.x, second_minimum_size.x),
first_minimum_size.y + separation + second_minimum_size.y
)
func set_split_cursor(value: bool) -> void:
if value:
mouse_default_cursor_shape = SPLIT_MOUSE_CURSOR_SHAPE[layout_split.direction]
else:
mouse_default_cursor_shape = CURSOR_ARROW
func get_split_rects(rect: Rect2) -> Dictionary:
_parent_rect = rect
var separation = get_constant("separation", SPLIT_THEME_CLASS[layout_split.direction])
var origin = rect.position
var size = rect.size
var percent = layout_split.percent
if layout_split.is_horizontal():
var first_width = max((size.x - separation) * percent, first_minimum_size.x)
var split_offset = clamp(
size.x * percent - separation * 0.5,
first_minimum_size.x,
size.x - second_minimum_size.x - separation
)
var second_width = size.x - split_offset - separation
return {
"first": Rect2(origin.x, origin.y, split_offset, size.y),
"self": Rect2(origin.x + split_offset, origin.y, separation, size.y),
"second": Rect2(origin.x + split_offset + separation, origin.y, second_width, size.y),
}
else:
var first_height = max((size.y - separation) * percent, first_minimum_size.y)
var split_offset = clamp(
size.y * percent - separation * 0.5,
first_minimum_size.y,
size.y - second_minimum_size.y - separation
)
var second_height = size.y - split_offset - separation
return {
"first": Rect2(origin.x, origin.y, size.x, split_offset),
"self": Rect2(origin.x, origin.y + split_offset, size.x, separation),
"second": Rect2(origin.x, origin.y + split_offset + separation, size.x, second_height),
}
static func get_separation_with_control(control: Control) -> Vector2:
var hseparation = control.get_constant("separation", "HSplitContainer")
var vseparation = control.get_constant("separation", "VSplitContainer")
return Vector2(hseparation, vseparation)

116
assets/layouts/default.tres Normal file
View file

@ -0,0 +1,116 @@
[gd_resource type="Resource" load_steps=19 format=2]
[ext_resource path="res://addons/dockable_container/layout_panel.gd" type="Script" id=1]
[ext_resource path="res://addons/dockable_container/layout_split.gd" type="Script" id=2]
[ext_resource path="res://addons/dockable_container/layout.gd" type="Script" id=3]
[sub_resource type="Resource" id=1]
resource_name = "Tabs"
script = ExtResource( 1 )
names = PoolStringArray( "Tools" )
current_tab = 0
[sub_resource type="Resource" id=8]
resource_name = "Tabs"
script = ExtResource( 1 )
names = PoolStringArray( "Main Canvas" )
current_tab = 0
[sub_resource type="Resource" id=9]
resource_name = "Tabs"
script = ExtResource( 1 )
names = PoolStringArray( "Animation Timeline" )
current_tab = 0
[sub_resource type="Resource" id=10]
resource_name = "Split"
script = ExtResource( 2 )
direction = 1
percent = 0.90625
first = SubResource( 8 )
second = SubResource( 9 )
[sub_resource type="Resource" id=11]
resource_name = "Tabs"
script = ExtResource( 1 )
names = PoolStringArray( "Canvas Preview" )
current_tab = 0
[sub_resource type="Resource" id=20]
resource_name = "Tabs"
script = ExtResource( 1 )
names = PoolStringArray( "Color Pickers" )
current_tab = 0
[sub_resource type="Resource" id=21]
resource_name = "Split"
script = ExtResource( 2 )
direction = 1
percent = 0.911765
first = SubResource( 11 )
second = SubResource( 20 )
[sub_resource type="Resource" id=22]
resource_name = "Tabs"
script = ExtResource( 1 )
names = PoolStringArray( "Left tool options" )
current_tab = 0
[sub_resource type="Resource" id=23]
resource_name = "Tabs"
script = ExtResource( 1 )
names = PoolStringArray( "Right tool options" )
current_tab = 0
[sub_resource type="Resource" id=24]
resource_name = "Split"
script = ExtResource( 2 )
direction = 0
percent = 0.5
first = SubResource( 22 )
second = SubResource( 23 )
[sub_resource type="Resource" id=13]
resource_name = "Tabs"
script = ExtResource( 1 )
names = PoolStringArray( "Palette Panel" )
current_tab = 0
[sub_resource type="Resource" id=14]
resource_name = "Split"
script = ExtResource( 2 )
direction = 1
percent = 0.754808
first = SubResource( 24 )
second = SubResource( 13 )
[sub_resource type="Resource" id=15]
resource_name = "Split"
script = ExtResource( 2 )
direction = 1
percent = 0.332031
first = SubResource( 21 )
second = SubResource( 14 )
[sub_resource type="Resource" id=16]
resource_name = "Split"
script = ExtResource( 2 )
direction = 0
percent = 0.962785
first = SubResource( 10 )
second = SubResource( 15 )
[sub_resource type="Resource" id=5]
resource_name = "Split"
script = ExtResource( 2 )
direction = 0
percent = 0.0
first = SubResource( 1 )
second = SubResource( 16 )
[resource]
resource_name = "Layout"
script = ExtResource( 3 )
root = SubResource( 5 )
hidden_tabs = {
}

View file

@ -149,7 +149,7 @@ boot_splash/bg_color=Color( 0.145098, 0.145098, 0.164706, 1 )
config/icon="res://assets/graphics/icons/icon.png"
config/macos_native_icon="res://assets/graphics/icons/icon.icns"
config/windows_native_icon="res://assets/graphics/icons/icon.ico"
config/Version="v0.9.2-stable"
config/Version="v0.10-dev"
run/low_processor_mode.Android=false
[audio]
@ -183,6 +183,10 @@ window/per_pixel_transparency/enabled.HTML5=false
window/per_pixel_transparency/allowed.Android=false
window/per_pixel_transparency/enabled.Android=false
[editor_plugins]
enabled=PoolStringArray( "res://addons/dockable_container/plugin.cfg" )
[gui]
theme/use_hidpi.clickable=true
@ -608,6 +612,11 @@ new_brush={
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":true,"meta":false,"command":true,"pressed":false,"scancode":66,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
edit_mode={
"deadzone": 0.5,
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777252,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
]
}
[locale]

View file

@ -4,7 +4,6 @@ enum GridTypes { CARTESIAN, ISOMETRIC, ALL }
enum PressureSensitivity { NONE, ALPHA, SIZE, ALPHA_AND_SIZE }
enum ThemeTypes { DARK, BLUE, CARAMEL, LIGHT }
enum TileMode { NONE, BOTH, X_AXIS, Y_AXIS }
enum PanelLayout { AUTO, WIDESCREEN, TALLSCREEN }
enum IconColorFrom { THEME, CUSTOM }
enum ButtonSize { SMALL, BIG }
@ -18,7 +17,6 @@ var projects := [] # Array of Projects
var current_project: Project
var current_project_index := 0 setget _project_changed
var panel_layout = PanelLayout.AUTO
var ui_tooltips := {}
# Canvas related stuff
@ -89,7 +87,6 @@ var draw_grid := false
var draw_pixel_grid := false
var show_rulers := true
var show_guides := true
var show_animation_timeline := true
# Onion skinning options
var onion_skinning := false
@ -112,21 +109,23 @@ onready var canvas: Canvas = control.find_node("Canvas")
onready var tabs: Tabs = control.find_node("Tabs")
onready var main_viewport: ViewportContainer = control.find_node("ViewportContainer")
onready var second_viewport: ViewportContainer = control.find_node("ViewportContainer2")
onready var canvas_preview_container: Container = control.find_node("CanvasPreviewContainer")
onready var canvas_preview_container: Container = control.find_node("Canvas Preview")
onready var small_preview_viewport: ViewportContainer = canvas_preview_container.find_node(
"PreviewViewportContainer"
)
onready var camera: Camera2D = main_viewport.find_node("Camera2D")
onready var camera2: Camera2D = control.find_node("Camera2D2")
onready var camera_preview: Camera2D = control.find_node("CameraPreview")
onready var cameras = [camera, camera2, camera_preview]
onready var cameras := [camera, camera2, camera_preview]
onready var horizontal_ruler: BaseButton = control.find_node("HorizontalRuler")
onready var vertical_ruler: BaseButton = control.find_node("VerticalRuler")
onready var transparent_checker: ColorRect = control.find_node("TransparentChecker")
onready var preview_zoom_slider: VSlider = control.find_node("PreviewZoomSlider")
onready var tool_panel: Panel = control.find_node("ToolPanel")
onready var right_panel: Panel = control.find_node("RightPanel")
onready var tool_panel: Panel = control.find_node("Tools")
onready var color_pickers: Container = control.find_node("Color Pickers")
onready var left_tool_options_scroll: ScrollContainer = control.find_node("Left Tool Options")
onready var right_tool_options_scroll: ScrollContainer = control.find_node("Right Tool Options")
onready var brushes_popup: Popup = control.find_node("BrushesPopup")
onready var patterns_popup: Popup = control.find_node("PatternsPopup")
onready var palette_panel: PalettePanel = control.find_node("Palette Panel")
@ -177,8 +176,6 @@ func _ready() -> void:
# Load settings from the config file
config_cache.load("user://cache.ini")
panel_layout = config_cache.get_value("window", "panel_layout", PanelLayout.AUTO)
default_width = config_cache.get_value("preferences", "default_width", default_width)
default_height = config_cache.get_value("preferences", "default_height", default_height)
default_fill_color = config_cache.get_value(

View file

@ -153,7 +153,6 @@ func set_button_size(button_size: int) -> void:
if button_size == Global.ButtonSize.SMALL:
for t in _tool_buttons.get_children():
t.rect_min_size = Vector2(24, 24)
t.get_node("ToolIcon").rect_position = Vector2.ONE
t.get_node("BackgroundLeft").rect_size.x = 12
t.get_node("BackgroundRight").rect_size.x = 12
t.get_node("BackgroundRight").rect_position = Vector2(24, 24)
@ -161,7 +160,6 @@ func set_button_size(button_size: int) -> void:
else:
for t in _tool_buttons.get_children():
t.rect_min_size = Vector2(32, 32)
t.get_node("ToolIcon").rect_position = Vector2.ONE * 5
t.get_node("BackgroundLeft").rect_size.x = 16
t.get_node("BackgroundRight").rect_size.x = 16
t.get_node("BackgroundRight").rect_position = Vector2(32, 32)
@ -169,8 +167,6 @@ func set_button_size(button_size: int) -> void:
# It doesn't actually set the size to zero, it just resets it
_tool_buttons.get_parent().rect_size = Vector2.ZERO
_tool_buttons.columns = 1
_tool_buttons.get_parent().get_parent().get_parent().get_parent().split_offset = 0
func update_tool_buttons() -> void:

View file

@ -3,45 +3,18 @@ extends Control
var opensprite_file_selected := false
var redone := false
var is_quitting_on_save := false
var tallscreen_is_active = false
var alternate_transparent_background := ColorRect.new()
var cursor_image = preload("res://assets/graphics/cursor.png")
onready var ui := $MenuAndUI/UI
onready var tools_and_canvas: HSplitContainer = $MenuAndUI/UI/ToolsAndCanvas
onready var tallscreen_hsplit: HSplitContainer = tools_and_canvas.get_node(
"CanvasAndTimeline/TallscreenHSplitContainer"
)
onready var bottom_panel: VSplitContainer = tallscreen_hsplit.get_node("BottomPanel")
onready var right_panel := $MenuAndUI/UI/RightPanel
onready var canvas_preview_container := right_panel.get_node(
"MarginContainer/PreviewAndPalettes/CanvasPreviewContainer"
)
onready var tool_and_palette_vsplit := right_panel.get_node(
"MarginContainer/PreviewAndPalettes/ToolAndPaletteVSplit"
)
onready var color_and_tool_options := tool_and_palette_vsplit.get_node("ColorAndToolOptions")
onready var scroll_container := tool_and_palette_vsplit.get_node(
"ColorAndToolOptions/ScrollContainer"
)
onready var tool_panel := $MenuAndUI/UI/ToolsAndCanvas/ToolPanel
onready var ui := $MenuAndUI/UI/DockableContainer
onready var canvas_preview_container := ui.find_node("CanvasPreviewContainer")
onready var scroll_container := ui.find_node("ColorAndToolOptions/ScrollContainer")
onready var quit_dialog: ConfirmationDialog = find_node("QuitDialog")
func _ready() -> void:
randomize()
add_child(alternate_transparent_background)
move_child(alternate_transparent_background, 0)
alternate_transparent_background.visible = false
alternate_transparent_background.anchor_left = ANCHOR_BEGIN
alternate_transparent_background.anchor_top = ANCHOR_BEGIN
alternate_transparent_background.anchor_right = ANCHOR_END
alternate_transparent_background.anchor_bottom = ANCHOR_END
get_tree().set_auto_accept_quit(false)
_setup_application_window_size()
handle_resize()
get_tree().get_root().connect("size_changed", self, "handle_resize")
if OS.get_name() == "OSX":
_use_osx_shortcuts()
@ -99,131 +72,11 @@ func _ready() -> void:
_show_splash_screen()
func handle_resize() -> void:
var aspect_ratio = (
get_viewport_rect().size.x
/ (0.00001 if get_viewport_rect().size.y == 0 else get_viewport_rect().size.y)
)
if (
(aspect_ratio <= 3.0 / 4.0 and Global.panel_layout != Global.PanelLayout.WIDESCREEN)
or Global.panel_layout == Global.PanelLayout.TALLSCREEN
):
_change_ui_layout("tallscreen")
else:
_change_ui_layout("widescreen")
func _change_ui_layout(mode: String) -> void:
var colorpicker_is_switched = (
true
if tool_and_palette_vsplit.has_node("ScrollContainer")
else false
)
if mode == "tallscreen" and not tallscreen_is_active:
tallscreen_is_active = true
# changing visibility and re-parenting of nodes for tall screen
if !Global.top_menu_container.zen_mode:
tallscreen_hsplit.visible = true
tallscreen_hsplit.split_offset = tools_and_canvas.split_offset
_reparent_node_to(Global.animation_timeline, tallscreen_hsplit.get_node("BottomPanel"), 0)
_reparent_node_to(right_panel, bottom_panel, 0)
right_panel.rect_min_size.y = 322
_reparent_node_to(canvas_preview_container, tool_and_palette_vsplit, 1)
tool_and_palette_vsplit = _replace_node_with(tool_and_palette_vsplit, HBoxContainer.new())
tool_and_palette_vsplit.set("custom_constants/separation", 8)
color_and_tool_options.rect_min_size.x = 280
_reparent_node_to(tool_panel, tallscreen_hsplit, 0)
var right_panel_margin: MarginContainer = right_panel.find_node(
"MarginContainer", true, false
)
right_panel_margin.set("custom_constants/margin_top", 8)
right_panel_margin.set("custom_constants/margin_left", 0)
right_panel_margin.set("custom_constants/margin_right", 0)
right_panel.find_node("PalettePanel", true, false).size_flags_horizontal = SIZE_FILL
elif mode == "widescreen" and tallscreen_is_active:
tallscreen_is_active = false
# Reparenting and hiding nodes to adjust wide-screen
_reparent_node_to(
Global.animation_timeline, ui.get_node("ToolsAndCanvas/CanvasAndTimeline"), 1
)
tallscreen_hsplit.visible = false
tools_and_canvas.split_offset = tallscreen_hsplit.split_offset
_reparent_node_to(right_panel, ui, -1)
right_panel.rect_min_size.y = 0
_reparent_node_to(canvas_preview_container, right_panel.find_node("PreviewAndPalettes"), 0)
tool_and_palette_vsplit = _replace_node_with(tool_and_palette_vsplit, VSplitContainer.new())
color_and_tool_options.rect_min_size.x = 0
canvas_preview_container.visible = true
_reparent_node_to(tool_panel, ui.find_node("ToolsAndCanvas"), 0)
var right_panel_margin: MarginContainer = right_panel.find_node(
"MarginContainer", true, false
)
right_panel_margin.set("custom_constants/margin_top", 0)
right_panel_margin.set("custom_constants/margin_left", 8)
right_panel_margin.set("custom_constants/margin_right", 8)
right_panel.find_node("PalettePanel", true, false).size_flags_horizontal = SIZE_EXPAND_FILL
if get_viewport_rect().size.x < 908 and mode == "tallscreen":
canvas_preview_container.visible = false
else:
canvas_preview_container.visible = true
if not colorpicker_is_switched and canvas_preview_container.visible and mode == "tallscreen":
_reparent_node_to(scroll_container, tool_and_palette_vsplit, 0)
scroll_container.rect_min_size = Vector2(268, 196)
color_and_tool_options.set("custom_constants/separation", 20)
_reparent_node_to(canvas_preview_container, color_and_tool_options, -1)
elif colorpicker_is_switched and (not canvas_preview_container.visible or mode != "tallscreen"):
_reparent_node_to(scroll_container, color_and_tool_options, -1)
scroll_container.rect_min_size = Vector2(0, 0)
color_and_tool_options.set("custom_constants/separation", 8)
if mode == "widescreen":
_reparent_node_to(
canvas_preview_container,
right_panel.find_node("PreviewAndPalettes", true, false),
0
)
else:
_reparent_node_to(canvas_preview_container, tool_and_palette_vsplit, 1)
# helper function (_change_ui_layout)
# warning: this doesn't really copy any sort of attributes, except a few that
# were needed in my particular case
func _replace_node_with(old: Node, new: Node) -> Node:
var tempname = old.name
old.name = "old"
new.name = tempname
new.size_flags_vertical = old.size_flags_horizontal
new.size_flags_vertical = old.size_flags_vertical
# new.set("custom_constants/autohide", old.get("custom_constants/autohide"))
if new is HBoxContainer:
new.set_alignment(HBoxContainer.ALIGN_CENTER)
new.set("custom_constants/separation", 20)
old.get_parent().add_child(new)
for n in old.get_children():
_reparent_node_to(n, new, -1)
old.get_parent().remove_child(old)
old.queue_free()
return new
# helper function (_change_ui_layout)
func _reparent_node_to(node: Node, dest: Node, pos: int) -> bool:
if dest is Node and node is Node:
node.get_parent().remove_child(node)
dest.add_child(node)
node.set_owner(dest)
if pos >= 0:
dest.move_child(node, pos)
return true
else:
return false
# Hacky way to update the panel's size... Unsure why this happens.
yield(get_tree(), "idle_frame")
ui.set_control_hidden(Global.palette_panel, true)
yield(get_tree(), "idle_frame")
ui.set_control_hidden(Global.palette_panel, false)
func _input(event: InputEvent) -> void:
@ -510,7 +363,6 @@ func _use_osx_shortcuts() -> void:
func _exit_tree() -> void:
Global.config_cache.set_value("window", "panel_layout", Global.panel_layout)
Global.config_cache.set_value("window", "screen", OS.current_screen)
Global.config_cache.set_value(
"window", "maximized", OS.window_maximized || OS.window_fullscreen

View file

@ -40,6 +40,11 @@ __meta__ = {
[node name="TopMenuContainer" parent="MenuAndUI" instance=ExtResource( 3 )]
[node name="UI" parent="MenuAndUI" instance=ExtResource( 4 )]
anchor_right = 0.0
anchor_bottom = 0.0
margin_top = 28.0
margin_right = 1280.0
margin_bottom = 720.0
[node name="Dialogs" type="Control" parent="."]
mouse_filter = 2

View file

@ -27,9 +27,12 @@ func _ready() -> void:
buttons_container.add_child(button)
button.connect("pressed", self, "_on_Theme_pressed", [button.get_index()])
var panel_stylebox: StyleBox = theme[0].get_stylebox("panel", "Panel")
var panel_container_stylebox: StyleBox = theme[0].get_stylebox("panel", "PanelContainer")
if panel_stylebox is StyleBoxFlat and panel_container_stylebox is StyleBoxFlat:
var theme_color_preview: ColorRect = theme_color_preview_scene.instance()
var color1 = theme[0].get_stylebox("panel", "Panel").bg_color
var color2 = theme[0].get_stylebox("panel", "PanelContainer").bg_color
var color1 = panel_stylebox.bg_color
var color2 = panel_container_stylebox.bg_color
theme_color_preview.get_child(0).color = color1
theme_color_preview.get_child(1).color = color2
colors_container.add_child(theme_color_preview)
@ -57,7 +60,6 @@ func _on_Theme_pressed(index: int) -> void:
func change_theme(id: int) -> void:
var font = Global.control.theme.default_font
theme_index = id
var main_theme: Theme = themes[id][0]
@ -74,35 +76,13 @@ func change_theme(id: int) -> void:
Global.modulate_icon_color = themes[id][2]
Global.control.theme = main_theme
Global.control.theme.default_font = font
Global.default_clear_color = main_theme.get_stylebox("panel", "PanelContainer").bg_color
var panel_stylebox: StyleBox = main_theme.get_stylebox("panel", "PanelContainer")
if panel_stylebox is StyleBoxFlat:
Global.default_clear_color = panel_stylebox.bg_color
else:
Global.default_clear_color = themes[id][2]
VisualServer.set_default_clear_color(Color(Global.default_clear_color))
if Global.control.alternate_transparent_background:
# Also change color of alternate_transparent_background
var new_color = Global.default_clear_color
new_color.a = Global.control.alternate_transparent_background.color.a
Global.control.alternate_transparent_background.color = new_color
Global.animation_timeline.get_stylebox("panel", "Panel").bg_color = main_theme.get_stylebox(
"panel", "Panel"
).bg_color
var fake_vsplit_grabber: TextureRect = Global.animation_timeline.find_node(
"FakeVSplitContainerGrabber"
)
fake_vsplit_grabber.texture = main_theme.get_icon("grabber", "VSplitContainer")
# Theming for left tools panel
var fake_hsplit_grabber: TextureRect = Global.tool_panel.get_node("FakeHSplitGrabber")
fake_hsplit_grabber.texture = main_theme.get_icon("grabber", "HSplitContainer")
Global.tool_panel.get_stylebox("panel", "Panel").bg_color = main_theme.get_stylebox(
"panel", "Panel"
).bg_color
var layer_button_pcont: PanelContainer = Global.animation_timeline.find_node(
"LayerButtonPanelContainer"
)
var lbpc_stylebox: StyleBoxFlat = layer_button_pcont.get_stylebox("panel", "PanelContainer")
lbpc_stylebox.bg_color = Global.default_clear_color
var top_menu_style = main_theme.get_stylebox("TopMenu", "Panel")
var ruler_style = main_theme.get_stylebox("Ruler", "Button")

View file

@ -50,9 +50,7 @@ margin_bottom = 79.0
custom_constants/separation = 44
alignment = 1
[node name="Horizontal" type="TextureButton" parent="Mirror" groups=[
"UIButtons",
]]
[node name="Horizontal" type="TextureButton" parent="Mirror" groups=["UIButtons"]]
margin_left = 20.0
margin_right = 35.0
margin_bottom = 17.0
@ -62,9 +60,7 @@ toggle_mode = true
texture_normal = ExtResource( 3 )
texture_pressed = ExtResource( 2 )
[node name="Vertical" type="TextureButton" parent="Mirror" groups=[
"UIButtons",
]]
[node name="Vertical" type="TextureButton" parent="Mirror" groups=["UIButtons"]]
margin_left = 79.0
margin_right = 96.0
margin_bottom = 17.0

View file

@ -22,7 +22,6 @@ shader_param/follow_scale = false
[node name="CanvasPreviewContainer" type="PanelContainer"]
margin_right = 328.0
margin_bottom = 174.0
rect_min_size = Vector2( 318, 0 )
size_flags_vertical = 0
script = ExtResource( 3 )
__meta__ = {
@ -93,7 +92,6 @@ __meta__ = {
margin_left = 24.0
margin_right = 314.0
margin_bottom = 160.0
rect_min_size = Vector2( 290, 160 )
size_flags_horizontal = 3
size_flags_vertical = 3
stretch = true

View file

@ -1,120 +0,0 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://assets/graphics/misc/color_switch.png" type="Texture" id=1]
[ext_resource path="res://assets/graphics/misc/color_defaults.png" type="Texture" id=2]
[ext_resource path="res://src/UI/ColorAndToolOptions.gd" type="Script" id=8]
[sub_resource type="ShortCut" id=1]
[node name="ColorAndToolOptions" type="VBoxContainer"]
margin_right = 300.0
margin_bottom = 255.0
rect_min_size = Vector2( 318, 0 )
size_flags_vertical = 3
custom_constants/separation = 8
script = ExtResource( 8 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="ColorPickersHorizontal" type="HBoxContainer" parent="."]
margin_right = 318.0
margin_bottom = 32.0
custom_constants/separation = 13
alignment = 1
[node name="LeftColorPickerButton" type="ColorPickerButton" parent="ColorPickersHorizontal"]
margin_left = 69.0
margin_right = 133.0
margin_bottom = 32.0
rect_min_size = Vector2( 64, 32 )
hint_tooltip = "Choose a color for the left tool"
mouse_default_cursor_shape = 2
size_flags_horizontal = 0
size_flags_vertical = 0
[node name="ColorButtonsVertical" type="VBoxContainer" parent="ColorPickersHorizontal"]
margin_left = 146.0
margin_right = 171.0
margin_bottom = 32.0
custom_constants/separation = 2
alignment = 1
[node name="ColorSwitchCenter" type="CenterContainer" parent="ColorPickersHorizontal/ColorButtonsVertical"]
margin_top = 6.0
margin_right = 25.0
margin_bottom = 13.0
[node name="ColorSwitch" type="TextureButton" parent="ColorPickersHorizontal/ColorButtonsVertical/ColorSwitchCenter" groups=["UIButtons"]]
margin_right = 25.0
margin_bottom = 7.0
hint_tooltip = "Switch left and right colors
(%s)"
mouse_default_cursor_shape = 2
shortcut_in_tooltip = false
shortcut = SubResource( 1 )
texture_normal = ExtResource( 1 )
[node name="ColorPickersCenter" type="CenterContainer" parent="ColorPickersHorizontal/ColorButtonsVertical"]
margin_top = 15.0
margin_right = 25.0
margin_bottom = 15.0
[node name="ColorDefaultsCenter" type="CenterContainer" parent="ColorPickersHorizontal/ColorButtonsVertical"]
margin_top = 17.0
margin_right = 25.0
margin_bottom = 25.0
size_flags_horizontal = 3
[node name="ColorDefaults" type="TextureButton" parent="ColorPickersHorizontal/ColorButtonsVertical/ColorDefaultsCenter"]
margin_right = 25.0
margin_bottom = 8.0
hint_tooltip = "Reset the colors to their default state (black for left, white for right)"
mouse_default_cursor_shape = 2
texture_normal = ExtResource( 2 )
[node name="RightColorPickerButton" type="ColorPickerButton" parent="ColorPickersHorizontal"]
margin_left = 184.0
margin_right = 248.0
margin_bottom = 32.0
rect_min_size = Vector2( 64, 32 )
hint_tooltip = "Choose a color for the right tool"
mouse_default_cursor_shape = 2
size_flags_horizontal = 0
size_flags_vertical = 0
color = Color( 1, 1, 1, 1 )
[node name="ScrollContainer" type="ScrollContainer" parent="."]
margin_top = 40.0
margin_right = 318.0
margin_bottom = 255.0
size_flags_vertical = 3
[node name="ToolOptions" type="HBoxContainer" parent="ScrollContainer"]
margin_right = 318.0
margin_bottom = 215.0
size_flags_horizontal = 3
size_flags_vertical = 3
custom_constants/separation = 8
[node name="LeftPanelContainer" type="PanelContainer" parent="ScrollContainer/ToolOptions"]
margin_right = 155.0
margin_bottom = 215.0
rect_min_size = Vector2( 130, 0 )
size_flags_horizontal = 3
[node name="RightPanelContainer" type="PanelContainer" parent="ScrollContainer/ToolOptions"]
margin_left = 163.0
margin_right = 318.0
margin_bottom = 215.0
rect_min_size = Vector2( 130, 0 )
size_flags_horizontal = 3
[connection signal="color_changed" from="ColorPickersHorizontal/LeftColorPickerButton" to="." method="_on_ColorPickerButton_color_changed" binds= [ false ]]
[connection signal="popup_closed" from="ColorPickersHorizontal/LeftColorPickerButton" to="." method="_on_ColorPickerButton_popup_closed"]
[connection signal="pressed" from="ColorPickersHorizontal/LeftColorPickerButton" to="." method="_on_ColorPickerButton_pressed"]
[connection signal="pressed" from="ColorPickersHorizontal/ColorButtonsVertical/ColorSwitchCenter/ColorSwitch" to="." method="_on_ColorSwitch_pressed"]
[connection signal="pressed" from="ColorPickersHorizontal/ColorButtonsVertical/ColorDefaultsCenter/ColorDefaults" to="." method="_on_ColorDefaults_pressed"]
[connection signal="color_changed" from="ColorPickersHorizontal/RightColorPickerButton" to="." method="_on_ColorPickerButton_color_changed" binds= [ true ]]
[connection signal="popup_closed" from="ColorPickersHorizontal/RightColorPickerButton" to="." method="_on_ColorPickerButton_popup_closed"]
[connection signal="pressed" from="ColorPickersHorizontal/RightColorPickerButton" to="." method="_on_ColorPickerButton_pressed"]

View file

@ -1,7 +1,7 @@
extends VBoxContainer
extends HBoxContainer
onready var left_picker := $ColorPickersHorizontal/LeftColorPickerButton
onready var right_picker := $ColorPickersHorizontal/RightColorPickerButton
onready var left_picker := $LeftColorPickerButton
onready var right_picker := $RightColorPickerButton
func _ready() -> void:

76
src/UI/ColorPickers.tscn Normal file
View file

@ -0,0 +1,76 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://assets/graphics/misc/color_defaults.png" type="Texture" id=1]
[ext_resource path="res://assets/graphics/misc/color_switch.png" type="Texture" id=2]
[ext_resource path="res://src/UI/ColorPickers.gd" type="Script" id=3]
[sub_resource type="ShortCut" id=19]
[node name="ColorPickersHorizontal" type="HBoxContainer"]
margin_left = 958.0
margin_top = 170.0
margin_right = 1276.0
margin_bottom = 229.062
custom_constants/separation = 13
alignment = 1
script = ExtResource( 3 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="LeftColorPickerButton" type="ColorPickerButton" parent="."]
margin_left = 69.0
margin_top = 13.0
margin_right = 133.0
margin_bottom = 45.0
rect_min_size = Vector2( 64, 32 )
hint_tooltip = "Choose a color for the left tool"
mouse_default_cursor_shape = 2
size_flags_horizontal = 0
size_flags_vertical = 4
[node name="ColorButtonsVertical" type="VBoxContainer" parent="."]
margin_left = 146.0
margin_right = 171.0
margin_bottom = 59.0
alignment = 1
[node name="ColorSwitch" type="TextureButton" parent="ColorButtonsVertical" groups=["UIButtons"]]
margin_top = 20.0
margin_right = 25.0
margin_bottom = 27.0
hint_tooltip = "Switch left and right colors
(%s)"
mouse_default_cursor_shape = 2
shortcut_in_tooltip = false
shortcut = SubResource( 19 )
texture_normal = ExtResource( 2 )
[node name="ColorDefaults" type="TextureButton" parent="ColorButtonsVertical"]
margin_top = 31.0
margin_right = 25.0
margin_bottom = 39.0
hint_tooltip = "Reset the colors to their default state (black for left, white for right)"
mouse_default_cursor_shape = 2
texture_normal = ExtResource( 1 )
[node name="RightColorPickerButton" type="ColorPickerButton" parent="."]
margin_left = 184.0
margin_top = 13.0
margin_right = 248.0
margin_bottom = 45.0
rect_min_size = Vector2( 64, 32 )
hint_tooltip = "Choose a color for the right tool"
mouse_default_cursor_shape = 2
size_flags_horizontal = 0
size_flags_vertical = 4
color = Color( 1, 1, 1, 1 )
[connection signal="color_changed" from="LeftColorPickerButton" to="." method="_on_ColorPickerButton_color_changed" binds= [ false ]]
[connection signal="popup_closed" from="LeftColorPickerButton" to="." method="_on_ColorPickerButton_popup_closed"]
[connection signal="pressed" from="LeftColorPickerButton" to="." method="_on_ColorPickerButton_pressed"]
[connection signal="pressed" from="ColorButtonsVertical/ColorSwitch" to="." method="_on_ColorSwitch_pressed"]
[connection signal="pressed" from="ColorButtonsVertical/ColorDefaults" to="." method="_on_ColorDefaults_pressed"]
[connection signal="color_changed" from="RightColorPickerButton" to="." method="_on_ColorPickerButton_color_changed" binds= [ true ]]
[connection signal="popup_closed" from="RightColorPickerButton" to="." method="_on_ColorPickerButton_popup_closed"]
[connection signal="pressed" from="RightColorPickerButton" to="." method="_on_ColorPickerButton_pressed"]

View file

@ -40,7 +40,128 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." ]
THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", "Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN \"AS-IS\" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an \"owner\") of an original work of
authorship and/or a database (each, a \"Work\").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works (\"Commons\") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the \"Affirmer\"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights (\"Copyright and
Related Rights\"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the \"Waiver\"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
\"License\"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.
" ]
[node name="AboutUI" type="VBoxContainer" parent="."]
anchor_right = 1.0
@ -220,19 +341,19 @@ size_flags_horizontal = 3
[node name="LicenseText" type="TextEdit" parent="AboutUI/Credits/Licenses"]
margin_right = 444.0
margin_bottom = 241.0
margin_bottom = 213.0
size_flags_vertical = 3
readonly = true
wrap_enabled = true
[node name="LicenseButtonsContainer" type="GridContainer" parent="AboutUI/Credits/Licenses"]
margin_top = 245.0
margin_top = 217.0
margin_right = 444.0
margin_bottom = 269.0
columns = 4
columns = 3
[node name="PixeloramaLicense" type="CheckBox" parent="AboutUI/Credits/Licenses/LicenseButtonsContainer"]
margin_right = 99.0
margin_right = 153.0
margin_bottom = 24.0
mouse_default_cursor_shape = 2
pressed = true
@ -240,29 +361,38 @@ group = SubResource( 1 )
text = "Pixelorama"
[node name="GodotLicense" type="CheckBox" parent="AboutUI/Credits/Licenses/LicenseButtonsContainer"]
margin_left = 103.0
margin_right = 170.0
margin_left = 157.0
margin_right = 348.0
margin_bottom = 24.0
mouse_default_cursor_shape = 2
group = SubResource( 1 )
text = "Godot Engine"
[node name="FreeTypeLicense" type="CheckBox" parent="AboutUI/Credits/Licenses/LicenseButtonsContainer"]
margin_left = 174.0
margin_right = 260.0
margin_left = 352.0
margin_right = 438.0
margin_bottom = 24.0
mouse_default_cursor_shape = 2
group = SubResource( 1 )
text = "FreeType"
[node name="godot-gdgifexporterLicense" type="CheckBox" parent="AboutUI/Credits/Licenses/LicenseButtonsContainer"]
margin_left = 264.0
margin_right = 417.0
margin_bottom = 24.0
margin_top = 28.0
margin_right = 153.0
margin_bottom = 52.0
mouse_default_cursor_shape = 2
group = SubResource( 1 )
text = "godot-gdgifexporter"
[node name="godot-dockable-containerLicense" type="CheckBox" parent="AboutUI/Credits/Licenses/LicenseButtonsContainer"]
margin_left = 157.0
margin_top = 28.0
margin_right = 348.0
margin_bottom = 52.0
mouse_default_cursor_shape = 2
group = SubResource( 1 )
text = "godot-dockable-container"
[node name="HSeparator2" type="HSeparator" parent="AboutUI"]
margin_top = 349.0
margin_right = 576.0

View file

@ -36,12 +36,6 @@ func _on_SplashDialog_about_to_show() -> void:
chosen_artwork = randi() % artworks.size()
change_artwork(0)
get_stylebox("panel", "WindowDialog").bg_color = Global.control.theme.get_stylebox(
"panel", "WindowDialog"
).bg_color
get_stylebox("panel", "WindowDialog").border_color = Global.control.theme.get_stylebox(
"panel", "WindowDialog"
).border_color
if OS.get_name() == "HTML5":
$Contents/ButtonsPatronsLogos/Buttons/OpenLastBtn.visible = false

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=13 format=2]
[gd_scene load_steps=12 format=2]
[ext_resource path="res://src/UI/Dialogs/SplashDialog.gd" type="Script" id=1]
[ext_resource path="res://assets/graphics/splash_screen/artworks/wishdream.png" type="Texture" id=2]
@ -8,12 +8,6 @@
[ext_resource path="res://assets/graphics/splash_screen/github_32px.png" type="Texture" id=10]
[ext_resource path="res://assets/graphics/splash_screen/patreon_mark_white.png" type="Texture" id=11]
[sub_resource type="StyleBoxFlat" id=1]
bg_color = Color( 0.0705882, 0.0705882, 0.0705882, 1 )
border_width_top = 20
border_color = Color( 0.403922, 0.403922, 0.403922, 1 )
expand_margin_top = 20.0
[sub_resource type="StyleBoxFlat" id=4]
bg_color = Color( 0.6, 0.6, 0.6, 0 )
@ -30,7 +24,6 @@ bg_color = Color( 0.6, 0.6, 0.6, 0 )
margin_right = 640.0
margin_bottom = 583.0
rect_min_size = Vector2( 640, 583 )
custom_styles/panel = SubResource( 1 )
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false

View file

@ -20,10 +20,9 @@ func set_window_opacity(value: float) -> void:
spinbox.value = value
value = value / 100.0
Global.control.alternate_transparent_background.visible = value < 1.0
Global.default_clear_color.a = value
Global.control.alternate_transparent_background.color = Global.default_clear_color
Global.control.ui.get_parent().self_modulate.a = value
for container in Global.control.ui._panel_container.get_children():
container.self_modulate.a = value
Global.transparent_checker.transparency(value)

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=45 format=2]
[gd_scene load_steps=44 format=2]
[ext_resource path="res://src/UI/Timeline/AnimationTimeline.gd" type="Script" id=1]
[ext_resource path="res://assets/graphics/layers/new.png" type="Texture" id=2]
@ -25,10 +25,6 @@
[ext_resource path="res://assets/graphics/timeline/loop.png" type="Texture" id=31]
[ext_resource path="res://src/UI/Timeline/FrameTagDialog.tscn" type="PackedScene" id=42]
[sub_resource type="StyleBoxFlat" id=1]
bg_color = Color( 0.0627451, 0.0627451, 0.0627451, 1 )
expand_margin_top = 6.0
[sub_resource type="StyleBoxFlat" id=2]
content_margin_left = 4.5
content_margin_right = 4.5
@ -107,50 +103,40 @@ HScrollBar/styles/scroll = SubResource( 18 )
HScrollBar/styles/scroll_focus = SubResource( 19 )
[node name="AnimationTimeline" type="Panel"]
margin_top = 438.0
margin_right = 902.0
margin_bottom = 638.0
margin_bottom = 160.0
rect_min_size = Vector2( 0, 160 )
size_flags_horizontal = 3
custom_styles/panel = SubResource( 1 )
rect_clip_content = true
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="MarginContainer" type="MarginContainer" parent="."]
[node name="AnimationContainer" type="HBoxContainer" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
custom_constants/margin_top = 2
custom_constants/margin_bottom = 8
margin_right = -10.0
margin_bottom = -8.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="AnimationContainer" type="HBoxContainer" parent="MarginContainer"]
margin_top = 2.0
margin_right = 902.0
margin_bottom = 192.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="TimelineContainer" type="VBoxContainer" parent="MarginContainer/AnimationContainer"]
margin_right = 902.0
margin_bottom = 190.0
[node name="TimelineContainer" type="VBoxContainer" parent="AnimationContainer"]
margin_right = 892.0
margin_bottom = 152.0
size_flags_horizontal = 3
[node name="TimelineButtons" type="HBoxContainer" parent="MarginContainer/AnimationContainer/TimelineContainer"]
margin_right = 902.0
[node name="TimelineButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer"]
margin_right = 892.0
margin_bottom = 38.0
size_flags_horizontal = 3
[node name="LayerButtonPanelContainer" type="PanelContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons"]
[node name="LayerButtonPanelContainer" type="PanelContainer" parent="AnimationContainer/TimelineContainer/TimelineButtons"]
margin_right = 186.0
margin_bottom = 38.0
custom_styles/panel = SubResource( 2 )
[node name="LayerButtons" type="HBoxContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer"]
[node name="LayerButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer"]
margin_left = 4.5
margin_top = 3.0
margin_right = 181.5
@ -158,7 +144,7 @@ margin_bottom = 25.0
size_flags_vertical = 0
custom_constants/separation = 9
[node name="AddLayer" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]]
[node name="AddLayer" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]]
margin_right = 22.0
margin_bottom = 22.0
rect_min_size = Vector2( 22, 22 )
@ -166,7 +152,7 @@ hint_tooltip = "Create a new layer"
focus_mode = 0
mouse_default_cursor_shape = 2
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/AddLayer"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/AddLayer"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -182,7 +168,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="RemoveLayer" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]]
[node name="RemoveLayer" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]]
margin_left = 31.0
margin_right = 53.0
margin_bottom = 22.0
@ -192,7 +178,7 @@ focus_mode = 0
mouse_default_cursor_shape = 8
disabled = true
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/RemoveLayer"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/RemoveLayer"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -208,7 +194,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="MoveUpLayer" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]]
[node name="MoveUpLayer" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]]
margin_left = 62.0
margin_right = 84.0
margin_bottom = 22.0
@ -218,7 +204,7 @@ focus_mode = 0
mouse_default_cursor_shape = 8
disabled = true
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MoveUpLayer"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MoveUpLayer"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -234,7 +220,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="MoveDownLayer" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]]
[node name="MoveDownLayer" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]]
margin_left = 93.0
margin_right = 115.0
margin_bottom = 22.0
@ -244,7 +230,7 @@ focus_mode = 0
mouse_default_cursor_shape = 8
disabled = true
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MoveDownLayer"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MoveDownLayer"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -260,7 +246,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="CloneLayer" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]]
[node name="CloneLayer" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]]
margin_left = 124.0
margin_right = 146.0
margin_bottom = 22.0
@ -269,7 +255,7 @@ hint_tooltip = "Clone current layer"
focus_mode = 0
mouse_default_cursor_shape = 2
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/CloneLayer"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/CloneLayer"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -285,7 +271,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="MergeDownLayer" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]]
[node name="MergeDownLayer" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons" groups=["UIButtons"]]
margin_left = 155.0
margin_right = 177.0
margin_bottom = 22.0
@ -295,7 +281,7 @@ focus_mode = 0
mouse_default_cursor_shape = 8
disabled = true
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MergeDownLayer"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MergeDownLayer"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -311,18 +297,18 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="Control" type="Control" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons"]
[node name="Control" type="Control" parent="AnimationContainer/TimelineContainer/TimelineButtons"]
margin_left = 190.0
margin_right = 386.0
margin_right = 376.0
margin_bottom = 38.0
size_flags_horizontal = 3
[node name="PanelContainer" type="PanelContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons"]
margin_left = 390.0
margin_right = 902.0
[node name="PanelContainer" type="PanelContainer" parent="AnimationContainer/TimelineContainer/TimelineButtons"]
margin_left = 380.0
margin_right = 892.0
margin_bottom = 38.0
[node name="AnimationButtons" type="HBoxContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer"]
[node name="AnimationButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer"]
margin_left = 7.0
margin_top = 7.0
margin_right = 505.0
@ -332,11 +318,11 @@ size_flags_horizontal = 3
custom_constants/separation = 40
alignment = 2
[node name="FrameButtons" type="HBoxContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons"]
[node name="FrameButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons"]
margin_right = 140.0
margin_bottom = 24.0
[node name="AddFrame" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons" groups=["UIButtons"]]
[node name="AddFrame" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons" groups=["UIButtons"]]
margin_top = 2.0
margin_right = 20.0
margin_bottom = 22.0
@ -347,7 +333,7 @@ mouse_default_cursor_shape = 2
size_flags_horizontal = 0
size_flags_vertical = 4
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/AddFrame"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/AddFrame"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -361,7 +347,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="DeleteFrame" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons" groups=["UIButtons"]]
[node name="DeleteFrame" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons" groups=["UIButtons"]]
margin_left = 24.0
margin_top = 2.0
margin_right = 44.0
@ -373,7 +359,7 @@ mouse_default_cursor_shape = 2
size_flags_horizontal = 0
size_flags_vertical = 4
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/DeleteFrame"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/DeleteFrame"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -389,7 +375,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="CopyFrame" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons" groups=["UIButtons"]]
[node name="CopyFrame" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons" groups=["UIButtons"]]
margin_left = 48.0
margin_top = 2.0
margin_right = 68.0
@ -401,7 +387,7 @@ mouse_default_cursor_shape = 2
size_flags_horizontal = 0
size_flags_vertical = 4
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/CopyFrame"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/CopyFrame"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -415,7 +401,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="FrameTagButton" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons" groups=["UIButtons"]]
[node name="FrameTagButton" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons" groups=["UIButtons"]]
margin_left = 72.0
margin_top = 2.0
margin_right = 92.0
@ -427,7 +413,7 @@ mouse_default_cursor_shape = 2
size_flags_horizontal = 0
size_flags_vertical = 4
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/FrameTagButton"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/FrameTagButton"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -441,7 +427,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="MoveLeft" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons" groups=["UIButtons"]]
[node name="MoveLeft" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons" groups=["UIButtons"]]
margin_left = 96.0
margin_top = 2.0
margin_right = 116.0
@ -453,7 +439,7 @@ mouse_default_cursor_shape = 2
size_flags_horizontal = 0
size_flags_vertical = 4
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/MoveLeft"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/MoveLeft"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -468,7 +454,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="MoveRight" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons" groups=["UIButtons"]]
[node name="MoveRight" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons" groups=["UIButtons"]]
margin_left = 120.0
margin_top = 2.0
margin_right = 140.0
@ -480,7 +466,7 @@ mouse_default_cursor_shape = 2
size_flags_horizontal = 0
size_flags_vertical = 4
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/MoveRight"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/MoveRight"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -494,12 +480,12 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="PlaybackButtons" type="HBoxContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons"]
[node name="PlaybackButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons"]
margin_left = 180.0
margin_right = 320.0
margin_bottom = 24.0
[node name="FirstFrame" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons" groups=["UIButtons"]]
[node name="FirstFrame" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons" groups=["UIButtons"]]
margin_top = 2.0
margin_right = 20.0
margin_bottom = 22.0
@ -512,7 +498,7 @@ size_flags_vertical = 4
shortcut_in_tooltip = false
shortcut = SubResource( 4 )
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/FirstFrame"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/FirstFrame"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -526,7 +512,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="PreviousFrame" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons" groups=["UIButtons"]]
[node name="PreviousFrame" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons" groups=["UIButtons"]]
margin_left = 24.0
margin_top = 2.0
margin_right = 44.0
@ -540,7 +526,7 @@ size_flags_vertical = 4
shortcut_in_tooltip = false
shortcut = SubResource( 6 )
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/PreviousFrame"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/PreviousFrame"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -554,7 +540,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="PlayBackwards" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons" groups=["UIButtons"]]
[node name="PlayBackwards" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons" groups=["UIButtons"]]
margin_left = 48.0
margin_top = 2.0
margin_right = 68.0
@ -569,7 +555,7 @@ toggle_mode = true
shortcut_in_tooltip = false
shortcut = SubResource( 8 )
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/PlayBackwards"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/PlayBackwards"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -583,7 +569,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="PlayForward" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons" groups=["UIButtons"]]
[node name="PlayForward" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons" groups=["UIButtons"]]
margin_left = 72.0
margin_top = 2.0
margin_right = 92.0
@ -599,7 +585,7 @@ toggle_mode = true
shortcut_in_tooltip = false
shortcut = SubResource( 10 )
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/PlayForward"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/PlayForward"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -613,7 +599,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="NextFrame" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons" groups=["UIButtons"]]
[node name="NextFrame" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons" groups=["UIButtons"]]
margin_left = 96.0
margin_top = 2.0
margin_right = 116.0
@ -627,7 +613,7 @@ size_flags_vertical = 4
shortcut_in_tooltip = false
shortcut = SubResource( 12 )
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/NextFrame"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/NextFrame"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -641,7 +627,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="LastFrame" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons" groups=["UIButtons"]]
[node name="LastFrame" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons" groups=["UIButtons"]]
margin_left = 120.0
margin_top = 2.0
margin_right = 140.0
@ -655,7 +641,7 @@ size_flags_vertical = 4
shortcut_in_tooltip = false
shortcut = SubResource( 14 )
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/LastFrame"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/LastFrame"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -669,12 +655,12 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="LoopButtons" type="HBoxContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons"]
[node name="LoopButtons" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons"]
margin_left = 360.0
margin_right = 498.0
margin_bottom = 24.0
[node name="OnionSkinningSettings" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons" groups=["UIButtons"]]
[node name="OnionSkinningSettings" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons" groups=["UIButtons"]]
margin_top = 2.0
margin_right = 12.0
margin_bottom = 22.0
@ -684,7 +670,7 @@ mouse_default_cursor_shape = 2
size_flags_horizontal = 0
size_flags_vertical = 4
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons/OnionSkinningSettings"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons/OnionSkinningSettings"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -700,7 +686,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="OnionSkinning" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons" groups=["UIButtons"]]
[node name="OnionSkinning" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons" groups=["UIButtons"]]
margin_left = 16.0
margin_top = 2.0
margin_right = 36.0
@ -711,7 +697,7 @@ focus_mode = 0
mouse_default_cursor_shape = 2
size_flags_vertical = 4
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons/OnionSkinning"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons/OnionSkinning"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -727,7 +713,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="LoopAnim" type="Button" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons" groups=["UIButtons"]]
[node name="LoopAnim" type="Button" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons" groups=["UIButtons"]]
margin_left = 40.0
margin_top = 2.0
margin_right = 60.0
@ -738,7 +724,7 @@ focus_mode = 0
mouse_default_cursor_shape = 2
size_flags_vertical = 4
[node name="TextureRect" type="TextureRect" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons/LoopAnim"]
[node name="TextureRect" type="TextureRect" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons/LoopAnim"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
@ -752,7 +738,7 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="FPSValue" type="SpinBox" parent="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons"]
[node name="FPSValue" type="SpinBox" parent="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons"]
margin_left = 64.0
margin_right = 138.0
margin_bottom = 24.0
@ -766,24 +752,24 @@ value = 6.0
align = 1
suffix = "FPS"
[node name="OpacityAndTagContainer" type="HBoxContainer" parent="MarginContainer/AnimationContainer/TimelineContainer"]
[node name="OpacityAndTagContainer" type="HBoxContainer" parent="AnimationContainer/TimelineContainer"]
margin_top = 42.0
margin_right = 902.0
margin_right = 892.0
margin_bottom = 74.0
custom_constants/separation = 2
[node name="SpacerControl" type="Control" parent="MarginContainer/AnimationContainer/TimelineContainer/OpacityAndTagContainer"]
[node name="SpacerControl" type="Control" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer"]
margin_right = 4.0
margin_bottom = 32.0
rect_min_size = Vector2( 4, 0 )
[node name="OpacityContainer" type="HBoxContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/OpacityAndTagContainer"]
[node name="OpacityContainer" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer"]
margin_left = 6.0
margin_right = 186.0
margin_bottom = 32.0
rect_min_size = Vector2( 180, 0 )
[node name="OpacityLabel" type="Label" parent="MarginContainer/AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer"]
[node name="OpacityLabel" type="Label" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer"]
margin_right = 53.0
margin_bottom = 14.0
size_flags_horizontal = 0
@ -791,7 +777,7 @@ size_flags_vertical = 0
text = "Opacity:"
valign = 1
[node name="OpacitySlider" type="HSlider" parent="MarginContainer/AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer"]
[node name="OpacitySlider" type="HSlider" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer"]
margin_left = 57.0
margin_right = 102.0
margin_bottom = 32.0
@ -802,7 +788,7 @@ size_flags_vertical = 1
value = 100.0
ticks_on_borders = true
[node name="OpacitySpinBox" type="SpinBox" parent="MarginContainer/AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer"]
[node name="OpacitySpinBox" type="SpinBox" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer"]
margin_left = 106.0
margin_top = 4.0
margin_right = 180.0
@ -812,15 +798,15 @@ size_flags_vertical = 4
value = 100.0
align = 1
[node name="SpacerControl2" type="Control" parent="MarginContainer/AnimationContainer/TimelineContainer/OpacityAndTagContainer"]
[node name="SpacerControl2" type="Control" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer"]
margin_left = 188.0
margin_right = 217.0
margin_bottom = 32.0
rect_min_size = Vector2( 29, 0 )
[node name="TagScroll" type="ScrollContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/OpacityAndTagContainer"]
[node name="TagScroll" type="ScrollContainer" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer"]
margin_left = 219.0
margin_right = 902.0
margin_right = 892.0
margin_bottom = 32.0
rect_min_size = Vector2( 0, 32 )
mouse_filter = 2
@ -828,31 +814,30 @@ size_flags_horizontal = 3
theme = SubResource( 20 )
scroll_vertical_enabled = false
[node name="TagContainer" type="Control" parent="MarginContainer/AnimationContainer/TimelineContainer/OpacityAndTagContainer/TagScroll"]
[node name="TagContainer" type="Control" parent="AnimationContainer/TimelineContainer/OpacityAndTagContainer/TagScroll"]
[node name="PanelContainer" type="PanelContainer" parent="MarginContainer/AnimationContainer/TimelineContainer"]
[node name="PanelContainer" type="PanelContainer" parent="AnimationContainer/TimelineContainer"]
margin_top = 78.0
margin_right = 902.0
margin_bottom = 190.0
margin_right = 892.0
margin_bottom = 152.0
size_flags_vertical = 3
[node name="TimelineScroll" type="ScrollContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/PanelContainer"]
[node name="TimelineScroll" type="ScrollContainer" parent="AnimationContainer/TimelineContainer/PanelContainer"]
margin_left = 7.0
margin_top = 7.0
margin_right = 895.0
margin_bottom = 105.0
size_flags_vertical = 3
margin_right = 885.0
margin_bottom = 67.0
[node name="LayersAndFrames" type="HBoxContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll"]
[node name="LayersAndFrames" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll"]
margin_right = 252.0
margin_bottom = 98.0
margin_bottom = 60.0
size_flags_vertical = 3
[node name="LayerVBoxCont" type="VBoxContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll/LayersAndFrames"]
[node name="LayerVBoxCont" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll/LayersAndFrames"]
margin_right = 212.0
margin_bottom = 98.0
margin_bottom = 60.0
[node name="LayerLabel" type="Label" parent="MarginContainer/AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll/LayersAndFrames/LayerVBoxCont"]
[node name="LayerLabel" type="Label" parent="AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll/LayersAndFrames/LayerVBoxCont"]
margin_right = 212.0
margin_bottom = 16.0
rect_min_size = Vector2( 0, 16 )
@ -860,29 +845,29 @@ text = "Layers"
align = 1
valign = 1
[node name="LayersContainer" type="VBoxContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll/LayersAndFrames/LayerVBoxCont"]
[node name="LayersContainer" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll/LayersAndFrames/LayerVBoxCont"]
margin_top = 20.0
margin_right = 212.0
margin_bottom = 56.0
[node name="LayerContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll/LayersAndFrames/LayerVBoxCont/LayersContainer" instance=ExtResource( 18 )]
[node name="LayerContainer" parent="AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll/LayersAndFrames/LayerVBoxCont/LayersContainer" instance=ExtResource( 18 )]
margin_right = 212.0
[node name="FrameButtonsAndIds" type="VBoxContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll/LayersAndFrames"]
[node name="FrameButtonsAndIds" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll/LayersAndFrames"]
margin_left = 216.0
margin_right = 252.0
margin_bottom = 98.0
margin_bottom = 60.0
[node name="FrameIDs" type="HBoxContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll/LayersAndFrames/FrameButtonsAndIds"]
[node name="FrameIDs" type="HBoxContainer" parent="AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll/LayersAndFrames/FrameButtonsAndIds"]
margin_right = 36.0
margin_bottom = 20.0
rect_min_size = Vector2( 0, 16 )
[node name="FrameButton" parent="MarginContainer/AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll/LayersAndFrames/FrameButtonsAndIds/FrameIDs" instance=ExtResource( 9 )]
[node name="FrameButton" parent="AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll/LayersAndFrames/FrameButtonsAndIds/FrameIDs" instance=ExtResource( 9 )]
margin_right = 36.0
rect_min_size = Vector2( 36, 0 )
[node name="FramesContainer" type="VBoxContainer" parent="MarginContainer/AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll/LayersAndFrames/FrameButtonsAndIds"]
[node name="FramesContainer" type="VBoxContainer" parent="AnimationContainer/TimelineContainer/PanelContainer/TimelineScroll/LayersAndFrames/FrameButtonsAndIds"]
margin_top = 24.0
margin_right = 36.0
margin_bottom = 24.0
@ -1001,42 +986,30 @@ autowrap = true
[node name="FrameTagDialog" parent="." instance=ExtResource( 42 )]
[node name="FakeVSplitContainerGrabber" type="TextureRect" parent="."]
anchor_left = 0.5
anchor_right = 0.5
margin_left = -24.0
margin_top = -6.0
margin_right = 24.0
margin_bottom = -4.76837e-07
mouse_filter = 2
__meta__ = {
"_edit_use_anchors_": false
}
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/AddLayer" to="." method="add_layer" binds= [ true ]]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/RemoveLayer" to="." method="_on_RemoveLayer_pressed"]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MoveUpLayer" to="." method="change_layer_order" binds= [ 1 ]]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MoveDownLayer" to="." method="change_layer_order" binds= [ -1 ]]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/CloneLayer" to="." method="add_layer" binds= [ false ]]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MergeDownLayer" to="." method="_on_MergeDownLayer_pressed"]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/AddFrame" to="." method="add_frame"]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/DeleteFrame" to="." method="_on_DeleteFrame_pressed"]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/CopyFrame" to="." method="_on_CopyFrame_pressed"]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/FrameTagButton" to="." method="_on_FrameTagButton_pressed"]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/MoveLeft" to="." method="_on_MoveLeft_pressed"]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/MoveRight" to="." method="_on_MoveRight_pressed"]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/FirstFrame" to="." method="_on_FirstFrame_pressed"]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/PreviousFrame" to="." method="_on_PreviousFrame_pressed"]
[connection signal="toggled" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/PlayBackwards" to="." method="_on_PlayBackwards_toggled"]
[connection signal="toggled" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/PlayForward" to="." method="_on_PlayForward_toggled"]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/NextFrame" to="." method="_on_NextFrame_pressed"]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/LastFrame" to="." method="_on_LastFrame_pressed"]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons/OnionSkinningSettings" to="." method="_on_OnionSkinningSettings_pressed"]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons/OnionSkinning" to="." method="_on_OnionSkinning_pressed"]
[connection signal="pressed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons/LoopAnim" to="." method="_on_LoopAnim_pressed"]
[connection signal="value_changed" from="MarginContainer/AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons/FPSValue" to="." method="_on_FPSValue_value_changed"]
[connection signal="value_changed" from="MarginContainer/AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer/OpacitySlider" to="." method="_on_OpacitySlider_value_changed"]
[connection signal="value_changed" from="MarginContainer/AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer/OpacitySpinBox" to="." method="_on_OpacitySlider_value_changed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/AddLayer" to="." method="add_layer" binds= [ true ]]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/RemoveLayer" to="." method="_on_RemoveLayer_pressed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MoveUpLayer" to="." method="change_layer_order" binds= [ 1 ]]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MoveDownLayer" to="." method="change_layer_order" binds= [ -1 ]]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/CloneLayer" to="." method="add_layer" binds= [ false ]]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/LayerButtonPanelContainer/LayerButtons/MergeDownLayer" to="." method="_on_MergeDownLayer_pressed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/AddFrame" to="." method="add_frame"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/DeleteFrame" to="." method="_on_DeleteFrame_pressed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/CopyFrame" to="." method="_on_CopyFrame_pressed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/FrameTagButton" to="." method="_on_FrameTagButton_pressed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/MoveLeft" to="." method="_on_MoveLeft_pressed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/FrameButtons/MoveRight" to="." method="_on_MoveRight_pressed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/FirstFrame" to="." method="_on_FirstFrame_pressed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/PreviousFrame" to="." method="_on_PreviousFrame_pressed"]
[connection signal="toggled" from="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/PlayBackwards" to="." method="_on_PlayBackwards_toggled"]
[connection signal="toggled" from="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/PlayForward" to="." method="_on_PlayForward_toggled"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/NextFrame" to="." method="_on_NextFrame_pressed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/PlaybackButtons/LastFrame" to="." method="_on_LastFrame_pressed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons/OnionSkinningSettings" to="." method="_on_OnionSkinningSettings_pressed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons/OnionSkinning" to="." method="_on_OnionSkinning_pressed"]
[connection signal="pressed" from="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons/LoopAnim" to="." method="_on_LoopAnim_pressed"]
[connection signal="value_changed" from="AnimationContainer/TimelineContainer/TimelineButtons/PanelContainer/AnimationButtons/LoopButtons/FPSValue" to="." method="_on_FPSValue_value_changed"]
[connection signal="value_changed" from="AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer/OpacitySlider" to="." method="_on_OpacitySlider_value_changed"]
[connection signal="value_changed" from="AnimationContainer/TimelineContainer/OpacityAndTagContainer/OpacityContainer/OpacitySpinBox" to="." method="_on_OpacitySlider_value_changed"]
[connection signal="timeout" from="AnimationTimer" to="." method="_on_AnimationTimer_timeout"]
[connection signal="popup_hide" from="OnionSkinningSettings" to="." method="_on_OnionSkinningSettings_popup_hide"]
[connection signal="value_changed" from="OnionSkinningSettings/OnionSkinningButtons/PastOnionSkinning" to="." method="_on_PastOnionSkinning_value_changed"]

View file

@ -30,7 +30,7 @@ func _ready() -> void:
tooltips.append(t[0].hint_tooltip)
# Resize tools panel when window gets resized
get_tree().get_root().connect("size_changed", self, "_on_ToolsAndCanvas_dragged")
get_tree().get_root().connect("size_changed", self, "_on_Tools_resized")
func update_hintooltips() -> void:
@ -68,8 +68,8 @@ func _on_Tool_pressed(tool_pressed: BaseButton) -> void:
Tools.assign_tool(tool_pressed.name, button)
func _on_ToolsAndCanvas_dragged(_offset: int = 0) -> void:
var tool_panel_size: Vector2 = get_parent().get_parent().get_parent().rect_size
func _on_Tools_resized() -> void:
var tool_panel_size: Vector2 = get_parent().get_parent().rect_size
if Global.tool_button_size == Global.ButtonSize.SMALL:
columns = tool_panel_size.x / 28.5
else:

View file

@ -5,13 +5,13 @@ enum EditMenuId { UNDO, REDO, COPY, CUT, PASTE, DELETE, NEW_BRUSH, PREFERENCES }
enum ViewMenuId {
TILE_MODE,
WINDOW_OPACITY,
PANEL_LAYOUT,
MIRROR_VIEW,
SHOW_GRID,
SHOW_PIXEL_GRID,
SHOW_RULERS,
SHOW_GUIDES,
SHOW_ANIMATION_TIMELINE,
DOCKERS,
EDIT_MODE,
ZEN_MODE,
FULLSCREEN_MODE
}
@ -44,6 +44,7 @@ var view_menu: PopupMenu
var zen_mode := false
var recent_projects := []
onready var ui_elements: Array = Global.control.find_node("DockableContainer").get_children()
onready var file_menu_button: MenuButton = find_node("FileMenu")
onready var edit_menu_button: MenuButton = find_node("EditMenu")
onready var view_menu_button: MenuButton = find_node("ViewMenu")
@ -54,6 +55,7 @@ onready var help_menu_button: MenuButton = find_node("HelpMenu")
onready var new_image_dialog: ConfirmationDialog = Global.control.find_node("CreateNewImage")
onready var window_opacity_dialog: AcceptDialog = Global.control.find_node("WindowOpacityDialog")
onready var tile_mode_submenu := PopupMenu.new()
onready var dockers_submenu := PopupMenu.new()
onready var panel_layout_submenu := PopupMenu.new()
onready var recent_projects_submenu := PopupMenu.new()
@ -136,14 +138,14 @@ func _setup_view_menu() -> void:
var view_menu_items := { # order as in ViewMenuId enum
"Tile Mode": 0,
"Window Opacity": 0,
"Panel Layout": 0,
"Mirror View": InputMap.get_action_list("mirror_view")[0].get_scancode_with_modifiers(),
"Show Grid": InputMap.get_action_list("show_grid")[0].get_scancode_with_modifiers(),
"Show Pixel Grid":
InputMap.get_action_list("show_pixel_grid")[0].get_scancode_with_modifiers(),
"Show Rulers": InputMap.get_action_list("show_rulers")[0].get_scancode_with_modifiers(),
"Show Guides": InputMap.get_action_list("show_guides")[0].get_scancode_with_modifiers(),
"Show Animation Timeline": 0,
"Dockers": 0,
"Edit Mode": InputMap.get_action_list("edit_mode")[0].get_scancode_with_modifiers(),
"Zen Mode": InputMap.get_action_list("zen_mode")[0].get_scancode_with_modifiers(),
"Fullscreen Mode":
InputMap.get_action_list("toggle_fullscreen")[0].get_scancode_with_modifiers(),
@ -154,16 +156,15 @@ func _setup_view_menu() -> void:
for item in view_menu_items.keys():
if item == "Tile Mode":
_setup_tile_mode_submenu(item)
elif item == "Dockers":
_setup_dockers_submenu(item)
elif item == "Window Opacity":
view_menu.add_item(item, i, view_menu_items[item])
elif item == "Panel Layout":
_setup_panel_layout_submenu(item)
else:
view_menu.add_check_item(item, i, view_menu_items[item])
i += 1
view_menu.set_item_checked(ViewMenuId.SHOW_RULERS, true)
view_menu.set_item_checked(ViewMenuId.SHOW_GUIDES, true)
view_menu.set_item_checked(ViewMenuId.SHOW_ANIMATION_TIMELINE, true)
view_menu.hide_on_checkable_item_selection = false
view_menu.connect("id_pressed", self, "view_menu_id_pressed")
# Disable window opacity item if per pixel transparency is not allowed
@ -187,17 +188,16 @@ func _setup_tile_mode_submenu(item: String) -> void:
view_menu.add_submenu_item(item, tile_mode_submenu.get_name())
func _setup_panel_layout_submenu(item: String) -> void:
panel_layout_submenu.set_name("panel_layout_submenu")
panel_layout_submenu.add_radio_check_item("Auto", Global.PanelLayout.AUTO)
panel_layout_submenu.add_radio_check_item("Widescreen", Global.PanelLayout.WIDESCREEN)
panel_layout_submenu.add_radio_check_item("Tallscreen", Global.PanelLayout.TALLSCREEN)
panel_layout_submenu.hide_on_checkable_item_selection = false
panel_layout_submenu.set_item_checked(Global.panel_layout, true)
func _setup_dockers_submenu(item: String) -> void:
dockers_submenu.set_name("dockers_submenu")
dockers_submenu.hide_on_checkable_item_selection = false
for element in ui_elements:
dockers_submenu.add_check_item(element.name)
dockers_submenu.set_item_checked(ui_elements.find(element), true)
panel_layout_submenu.connect("id_pressed", self, "_panel_layout_submenu_id_pressed")
view_menu.add_child(panel_layout_submenu)
view_menu.add_submenu_item(item, panel_layout_submenu.get_name())
dockers_submenu.connect("id_pressed", self, "_dockers_submenu_id_pressed")
view_menu.add_child(dockers_submenu)
view_menu.add_submenu_item(item, dockers_submenu.get_name())
func _setup_image_menu() -> void:
@ -384,8 +384,9 @@ func view_menu_id_pressed(id: int) -> void:
_toggle_show_rulers()
ViewMenuId.SHOW_GUIDES:
_toggle_show_guides()
ViewMenuId.SHOW_ANIMATION_TIMELINE:
_toggle_show_anim_timeline()
ViewMenuId.EDIT_MODE:
Global.control.ui.tabs_visible = !Global.control.ui.tabs_visible
view_menu.set_item_checked(ViewMenuId.EDIT_MODE, Global.control.ui.tabs_visible)
ViewMenuId.ZEN_MODE:
_toggle_zen_mode()
ViewMenuId.FULLSCREEN_MODE:
@ -403,11 +404,12 @@ func _tile_mode_submenu_id_pressed(id: int) -> void:
Global.canvas.grid.update()
func _panel_layout_submenu_id_pressed(id: int) -> void:
Global.panel_layout = id
for i in Global.PanelLayout.values():
panel_layout_submenu.set_item_checked(i, i == id)
get_tree().get_root().get_node("Control").handle_resize()
func _dockers_submenu_id_pressed(id: int) -> void:
if zen_mode:
return
var element_visible = dockers_submenu.is_item_checked(id)
Global.control.ui.set_control_hidden(ui_elements[id], element_visible)
dockers_submenu.set_item_checked(id, !element_visible)
func _toggle_mirror_view() -> void:
@ -457,22 +459,15 @@ func _toggle_show_guides() -> void:
guide.visible = Global.show_y_symmetry_axis and Global.show_guides
func _toggle_show_anim_timeline() -> void:
if zen_mode:
return
Global.show_animation_timeline = !Global.show_animation_timeline
view_menu.set_item_checked(ViewMenuId.SHOW_ANIMATION_TIMELINE, Global.show_animation_timeline)
Global.animation_timeline.visible = Global.show_animation_timeline
func _toggle_zen_mode() -> void:
if Global.show_animation_timeline:
Global.animation_timeline.visible = zen_mode
Global.tool_panel.visible = zen_mode
Global.right_panel.visible = zen_mode
Global.control.ui.set_control_hidden(Global.animation_timeline, !zen_mode)
Global.control.ui.set_control_hidden(Global.tool_panel, !zen_mode)
Global.control.ui.set_control_hidden(Global.canvas_preview_container, !zen_mode)
Global.control.ui.set_control_hidden(Global.color_pickers, !zen_mode)
Global.control.ui.set_control_hidden(Global.left_tool_options_scroll, !zen_mode)
Global.control.ui.set_control_hidden(Global.right_tool_options_scroll, !zen_mode)
Global.control.ui.set_control_hidden(Global.palette_panel, !zen_mode)
Global.control.find_node("TabsContainer").visible = zen_mode
if Global.panel_layout == Global.PanelLayout.TALLSCREEN:
Global.control.tallscreen_hsplit.visible = zen_mode
zen_mode = !zen_mode
view_menu.set_item_checked(ViewMenuId.ZEN_MODE, zen_mode)

File diff suppressed because it is too large Load diff