mirror of
https://github.com/Relintai/broken_seals.git
synced 2024-11-13 20:47:19 +01:00
Copied over the rect editor from the world generator addon to med ed as a base for a uv editor.
This commit is contained in:
parent
1f48d44a5f
commit
2a6768a8ca
@ -0,0 +1,9 @@
|
|||||||
|
tool
|
||||||
|
extends PanelContainer
|
||||||
|
|
||||||
|
func _init():
|
||||||
|
# Control/EditorZoomWidget
|
||||||
|
pass
|
||||||
|
|
||||||
|
func set_edited_resource(res : WorldGenBaseResource):
|
||||||
|
$ScrollContainer/MarginContainer/RectView.set_edited_resource(res)
|
@ -0,0 +1,54 @@
|
|||||||
|
[gd_scene load_steps=4 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://addons/mesh_data_resource_editor/uv_editor/RectEditor.gd" type="Script" id=1]
|
||||||
|
[ext_resource path="res://addons/mesh_data_resource_editor/widgets/EditorZoomWidget.tscn" type="PackedScene" id=2]
|
||||||
|
[ext_resource path="res://addons/mesh_data_resource_editor/uv_editor/RectView.gd" type="Script" id=3]
|
||||||
|
|
||||||
|
[node name="RectEditor" type="PanelContainer"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
script = ExtResource( 1 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="ScrollContainer" type="ScrollContainer" parent="."]
|
||||||
|
margin_left = 7.0
|
||||||
|
margin_top = 7.0
|
||||||
|
margin_right = 1017.0
|
||||||
|
margin_bottom = 593.0
|
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="ScrollContainer"]
|
||||||
|
margin_right = 400.0
|
||||||
|
margin_bottom = 400.0
|
||||||
|
custom_constants/margin_right = 200
|
||||||
|
custom_constants/margin_top = 200
|
||||||
|
custom_constants/margin_left = 200
|
||||||
|
custom_constants/margin_bottom = 200
|
||||||
|
|
||||||
|
[node name="RectView" type="Control" parent="ScrollContainer/MarginContainer"]
|
||||||
|
margin_left = 200.0
|
||||||
|
margin_top = 200.0
|
||||||
|
margin_right = 200.0
|
||||||
|
margin_bottom = 200.0
|
||||||
|
script = ExtResource( 3 )
|
||||||
|
zoom_widget_path = NodePath("../../../Control/EditorZoomWidget")
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="."]
|
||||||
|
margin_left = 7.0
|
||||||
|
margin_top = 7.0
|
||||||
|
margin_right = 1017.0
|
||||||
|
margin_bottom = 593.0
|
||||||
|
mouse_filter = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="EditorZoomWidget" parent="Control" instance=ExtResource( 2 )]
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_right = 115.0
|
||||||
|
margin_bottom = 22.0
|
||||||
|
custom_constants/separation = -8
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
108
game/addons/mesh_data_resource_editor/uv_editor/RectView.gd
Normal file
108
game/addons/mesh_data_resource_editor/uv_editor/RectView.gd
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
tool
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
var rect_editor_node_scene : PackedScene = preload("res://addons/world_generator/ui/RectViewNode.tscn")
|
||||||
|
|
||||||
|
export(NodePath) var zoom_widget_path : NodePath = ""
|
||||||
|
|
||||||
|
var _rect_scale : float = 1
|
||||||
|
|
||||||
|
var edited_resource : WorldGenBaseResource = null
|
||||||
|
var edited_resource_current_size : Vector2 = Vector2()
|
||||||
|
|
||||||
|
func _enter_tree():
|
||||||
|
var zoom_widget : Node = get_node_or_null(zoom_widget_path)
|
||||||
|
|
||||||
|
if !zoom_widget:
|
||||||
|
return
|
||||||
|
|
||||||
|
if !zoom_widget.is_connected("zoom_changed", self, "on_zoom_changed"):
|
||||||
|
zoom_widget.connect("zoom_changed", self, "on_zoom_changed")
|
||||||
|
|
||||||
|
if !is_connected("visibility_changed", self, "on_visibility_changed"):
|
||||||
|
connect("visibility_changed", self, "on_visibility_changed")
|
||||||
|
|
||||||
|
func on_visibility_changed() -> void:
|
||||||
|
call_deferred("apply_zoom")
|
||||||
|
|
||||||
|
func apply_zoom() -> void:
|
||||||
|
if !edited_resource:
|
||||||
|
return
|
||||||
|
|
||||||
|
var rect : Rect2 = edited_resource.rect
|
||||||
|
edited_resource_current_size = rect.size
|
||||||
|
rect.position = rect.position * _rect_scale
|
||||||
|
rect.size = rect.size * _rect_scale
|
||||||
|
set_custom_minimum_size(rect.size)
|
||||||
|
|
||||||
|
var p : MarginContainer = get_parent() as MarginContainer
|
||||||
|
|
||||||
|
p.add_constant_override("margin_left", min(rect.size.x / 4.0, 50 * _rect_scale))
|
||||||
|
p.add_constant_override("margin_right", min(rect.size.x / 4.0, 50 * _rect_scale))
|
||||||
|
p.add_constant_override("margin_top", min(rect.size.y / 4.0, 50 * _rect_scale))
|
||||||
|
p.add_constant_override("margin_bottom", min(rect.size.y / 4.0, 50 * _rect_scale))
|
||||||
|
|
||||||
|
for c in get_children():
|
||||||
|
c.set_editor_rect_scale(_rect_scale)
|
||||||
|
|
||||||
|
func on_zoom_changed(zoom : float) -> void:
|
||||||
|
_rect_scale = zoom
|
||||||
|
apply_zoom()
|
||||||
|
|
||||||
|
func _draw():
|
||||||
|
draw_rect(Rect2(Vector2(), get_size()), Color(0.2, 0.2, 0.2, 1))
|
||||||
|
|
||||||
|
func refresh() -> void:
|
||||||
|
clear()
|
||||||
|
|
||||||
|
if !edited_resource:
|
||||||
|
return
|
||||||
|
|
||||||
|
var rect : Rect2 = edited_resource.rect
|
||||||
|
edited_resource_current_size = rect.size
|
||||||
|
rect.position = rect.position * _rect_scale
|
||||||
|
rect.size = rect.size * _rect_scale
|
||||||
|
set_custom_minimum_size(rect.size)
|
||||||
|
|
||||||
|
apply_zoom()
|
||||||
|
|
||||||
|
refresh_rects()
|
||||||
|
|
||||||
|
func clear() -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
func refresh_rects() -> void:
|
||||||
|
clear_rects()
|
||||||
|
|
||||||
|
if !edited_resource:
|
||||||
|
return
|
||||||
|
|
||||||
|
var cont : Array = edited_resource.get_content()
|
||||||
|
|
||||||
|
for c in cont:
|
||||||
|
if c:
|
||||||
|
var s : Node = rect_editor_node_scene.instance()
|
||||||
|
|
||||||
|
add_child(s)
|
||||||
|
s.set_editor_rect_scale(_rect_scale)
|
||||||
|
s.edited_resource_parent_size = edited_resource_current_size
|
||||||
|
s.set_edited_resource(c)
|
||||||
|
|
||||||
|
func clear_rects():
|
||||||
|
for c in get_children():
|
||||||
|
c.queue_free()
|
||||||
|
remove_child(c)
|
||||||
|
|
||||||
|
func set_edited_resource(res : WorldGenBaseResource):
|
||||||
|
if edited_resource:
|
||||||
|
edited_resource.disconnect("changed", self, "on_edited_resource_changed")
|
||||||
|
|
||||||
|
edited_resource = res
|
||||||
|
|
||||||
|
refresh()
|
||||||
|
|
||||||
|
if edited_resource:
|
||||||
|
edited_resource.connect("changed", self, "on_edited_resource_changed")
|
||||||
|
|
||||||
|
func on_edited_resource_changed() -> void:
|
||||||
|
call_deferred("refresh")
|
202
game/addons/mesh_data_resource_editor/uv_editor/RectViewNode.gd
Normal file
202
game/addons/mesh_data_resource_editor/uv_editor/RectViewNode.gd
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
tool
|
||||||
|
extends MarginContainer
|
||||||
|
|
||||||
|
enum DragType {
|
||||||
|
DRAG_NONE = 0,
|
||||||
|
DRAG_MOVE = 1,
|
||||||
|
DRAG_RESIZE_TOP = 1 << 1,
|
||||||
|
DRAG_RESIZE_RIGHT = 1 << 2,
|
||||||
|
DRAG_RESIZE_BOTTOM = 1 << 3,
|
||||||
|
DRAG_RESIZE_LEFT = 1 << 4
|
||||||
|
};
|
||||||
|
|
||||||
|
var edited_resource : WorldGenBaseResource = null
|
||||||
|
var edited_resource_parent_size : Vector2 = Vector2()
|
||||||
|
|
||||||
|
var _edited_resource_rect_border_color : Color = Color(1, 1, 1, 1)
|
||||||
|
var _edited_resource_rect_color : Color = Color(0.8, 0.8, 0.8, 0.9)
|
||||||
|
var _editor_rect_border_size : int = 2
|
||||||
|
var _edited_resource_font_color : Color = Color(0, 0, 0, 1)
|
||||||
|
var _editor_additional_text : String = ""
|
||||||
|
|
||||||
|
var drag_type : int
|
||||||
|
var drag_offset : Vector2
|
||||||
|
var drag_offset_far : Vector2
|
||||||
|
|
||||||
|
var _rect_scale : float = 1
|
||||||
|
|
||||||
|
func _draw():
|
||||||
|
draw_rect(Rect2(Vector2(), get_size()), _edited_resource_rect_color)
|
||||||
|
draw_rect(Rect2(Vector2(), get_size()), _edited_resource_rect_border_color, false, _editor_rect_border_size)
|
||||||
|
|
||||||
|
var font : Font = get_font("font")
|
||||||
|
|
||||||
|
var res_name : String = "NULL"
|
||||||
|
|
||||||
|
if edited_resource:
|
||||||
|
res_name = edited_resource.resource_name
|
||||||
|
|
||||||
|
var res_cls : String = ""
|
||||||
|
|
||||||
|
if edited_resource:
|
||||||
|
res_cls = edited_resource.get_editor_class()
|
||||||
|
|
||||||
|
draw_string(font, Vector2(_editor_rect_border_size, font.get_height()), res_name, _edited_resource_font_color)
|
||||||
|
draw_string(font, Vector2(_editor_rect_border_size, font.get_height() * 2), _editor_additional_text, _edited_resource_font_color, get_rect().size.x)
|
||||||
|
|
||||||
|
if res_cls != "":
|
||||||
|
draw_string(font, Vector2(_editor_rect_border_size, font.get_height() * 3), res_cls, _edited_resource_font_color, get_rect().size.x)
|
||||||
|
|
||||||
|
func refresh() -> void:
|
||||||
|
if !edited_resource:
|
||||||
|
return
|
||||||
|
|
||||||
|
#anchor is bottom left here
|
||||||
|
var rect : Rect2 = edited_resource.get_rect()
|
||||||
|
rect.position *= _rect_scale
|
||||||
|
rect.size *= _rect_scale
|
||||||
|
|
||||||
|
#anchor needs to be on top left here
|
||||||
|
var rp : Vector2 = rect.position
|
||||||
|
rp.y = edited_resource_parent_size.y * _rect_scale - rect.size.y - rect.position.y
|
||||||
|
rect_position = rp
|
||||||
|
rect_size = rect.size
|
||||||
|
|
||||||
|
update()
|
||||||
|
|
||||||
|
func set_editor_rect_scale(rect_scale) -> void:
|
||||||
|
_rect_scale = rect_scale
|
||||||
|
|
||||||
|
refresh()
|
||||||
|
|
||||||
|
func set_edited_resource(res : WorldGenBaseResource):
|
||||||
|
edited_resource = res
|
||||||
|
|
||||||
|
if edited_resource:
|
||||||
|
_edited_resource_rect_border_color = edited_resource.get_editor_rect_border_color()
|
||||||
|
_edited_resource_rect_color = edited_resource.get_editor_rect_color()
|
||||||
|
_editor_rect_border_size = edited_resource.get_editor_rect_border_size()
|
||||||
|
_edited_resource_font_color = edited_resource.get_editor_font_color()
|
||||||
|
_editor_additional_text = edited_resource.get_editor_additional_text()
|
||||||
|
|
||||||
|
refresh()
|
||||||
|
|
||||||
|
#based on / ported from engine/scene/gui/dialogs.h and .cpp
|
||||||
|
func _notification(p_what : int) -> void:
|
||||||
|
if (p_what == NOTIFICATION_MOUSE_EXIT):
|
||||||
|
# Reset the mouse cursor when leaving the resizable window border.
|
||||||
|
if (edited_resource && !edited_resource.locked && !drag_type):
|
||||||
|
if (get_default_cursor_shape() != CURSOR_ARROW):
|
||||||
|
set_default_cursor_shape(CURSOR_ARROW)
|
||||||
|
|
||||||
|
#based on / ported from engine/scene/gui/dialogs.h and .cpp
|
||||||
|
func _gui_input(p_event : InputEvent) -> void:
|
||||||
|
if (p_event is InputEventMouseButton) && (p_event.get_button_index() == BUTTON_LEFT):
|
||||||
|
var mb : InputEventMouseButton = p_event as InputEventMouseButton
|
||||||
|
|
||||||
|
if (mb.is_pressed()):
|
||||||
|
# Begin a possible dragging operation.
|
||||||
|
drag_type = _drag_hit_test(Vector2(mb.get_position().x, mb.get_position().y))
|
||||||
|
|
||||||
|
if (drag_type != DragType.DRAG_NONE):
|
||||||
|
drag_offset = get_global_mouse_position() - get_position()
|
||||||
|
|
||||||
|
drag_offset_far = get_position() + get_size() - get_global_mouse_position()
|
||||||
|
|
||||||
|
elif (drag_type != DragType.DRAG_NONE && !mb.is_pressed()):
|
||||||
|
# End a dragging operation.
|
||||||
|
drag_type = DragType.DRAG_NONE
|
||||||
|
|
||||||
|
if p_event is InputEventMouseMotion:
|
||||||
|
var mm : InputEventMouseMotion = p_event as InputEventMouseMotion
|
||||||
|
|
||||||
|
if (drag_type == DragType.DRAG_NONE):
|
||||||
|
# Update the cursor while moving along the borders.
|
||||||
|
var cursor = CURSOR_ARROW
|
||||||
|
if (!edited_resource.locked):
|
||||||
|
var preview_drag_type : int = _drag_hit_test(Vector2(mm.get_position().x, mm.get_position().y))
|
||||||
|
|
||||||
|
var top_left : int = DragType.DRAG_RESIZE_TOP + DragType.DRAG_RESIZE_LEFT
|
||||||
|
var bottom_right : int = DragType.DRAG_RESIZE_BOTTOM + DragType.DRAG_RESIZE_RIGHT
|
||||||
|
var top_right : int = DragType.DRAG_RESIZE_TOP + DragType.DRAG_RESIZE_RIGHT
|
||||||
|
var bottom_left : int = DragType.DRAG_RESIZE_BOTTOM + DragType.DRAG_RESIZE_LEFT
|
||||||
|
|
||||||
|
match (preview_drag_type):
|
||||||
|
DragType.DRAG_RESIZE_TOP:
|
||||||
|
cursor = CURSOR_VSIZE
|
||||||
|
DragType.DRAG_RESIZE_BOTTOM:
|
||||||
|
cursor = CURSOR_VSIZE
|
||||||
|
DragType.DRAG_RESIZE_LEFT:
|
||||||
|
cursor = CURSOR_HSIZE
|
||||||
|
DragType.DRAG_RESIZE_RIGHT:
|
||||||
|
cursor = CURSOR_HSIZE
|
||||||
|
top_left:
|
||||||
|
cursor = CURSOR_FDIAGSIZE
|
||||||
|
bottom_right:
|
||||||
|
cursor = CURSOR_FDIAGSIZE
|
||||||
|
top_right:
|
||||||
|
cursor = CURSOR_BDIAGSIZE
|
||||||
|
bottom_left:
|
||||||
|
cursor = CURSOR_BDIAGSIZE
|
||||||
|
|
||||||
|
if (get_cursor_shape() != cursor):
|
||||||
|
set_default_cursor_shape(cursor);
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Update while in a dragging operation.
|
||||||
|
var global_pos : Vector2 = get_global_mouse_position()
|
||||||
|
|
||||||
|
var rect : Rect2 = get_rect()
|
||||||
|
var min_size : Vector2 = get_combined_minimum_size()
|
||||||
|
|
||||||
|
if (drag_type == DragType.DRAG_MOVE):
|
||||||
|
rect.position = global_pos - drag_offset
|
||||||
|
else:
|
||||||
|
if (drag_type & DragType.DRAG_RESIZE_TOP):
|
||||||
|
var bottom : int = rect.position.y + rect.size.y
|
||||||
|
var max_y : int = bottom - min_size.y
|
||||||
|
rect.position.y = min(global_pos.y - drag_offset.y, max_y)
|
||||||
|
rect.size.y = bottom - rect.position.y
|
||||||
|
elif (drag_type & DragType.DRAG_RESIZE_BOTTOM):
|
||||||
|
rect.size.y = global_pos.y - rect.position.y + drag_offset_far.y
|
||||||
|
|
||||||
|
if (drag_type & DragType.DRAG_RESIZE_LEFT):
|
||||||
|
var right : int = rect.position.x + rect.size.x
|
||||||
|
var max_x : int = right - min_size.x
|
||||||
|
rect.position.x = min(global_pos.x - drag_offset.x, max_x)
|
||||||
|
rect.size.x = right - rect.position.x
|
||||||
|
elif (drag_type & DragType.DRAG_RESIZE_RIGHT):
|
||||||
|
rect.size.x = global_pos.x - rect.position.x + drag_offset_far.x
|
||||||
|
|
||||||
|
set_size(rect.size)
|
||||||
|
set_position(rect.position)
|
||||||
|
|
||||||
|
#rect needs to be converted back
|
||||||
|
rect.position.y = edited_resource_parent_size.y * _rect_scale - rect.size.y - rect.position.y
|
||||||
|
rect.position /= _rect_scale
|
||||||
|
rect.size /= _rect_scale
|
||||||
|
edited_resource.set_rect(rect)
|
||||||
|
|
||||||
|
#based on / ported from engine/scene/gui/dialogs.h and .cpp
|
||||||
|
func _drag_hit_test(pos : Vector2) -> int:
|
||||||
|
var drag_type : int = DragType.DRAG_NONE
|
||||||
|
|
||||||
|
if (!edited_resource.locked):
|
||||||
|
var scaleborder_size : int = 5 #get_constant("scaleborder_size", "WindowDialog")
|
||||||
|
|
||||||
|
var rect : Rect2 = get_rect()
|
||||||
|
|
||||||
|
if (pos.y < (scaleborder_size)):
|
||||||
|
drag_type = DragType.DRAG_RESIZE_TOP
|
||||||
|
elif (pos.y >= (rect.size.y - scaleborder_size)):
|
||||||
|
drag_type = DragType.DRAG_RESIZE_BOTTOM
|
||||||
|
|
||||||
|
if (pos.x < scaleborder_size):
|
||||||
|
drag_type |= DragType.DRAG_RESIZE_LEFT
|
||||||
|
elif (pos.x >= (rect.size.x - scaleborder_size)):
|
||||||
|
drag_type |= DragType.DRAG_RESIZE_RIGHT
|
||||||
|
|
||||||
|
if (drag_type == DragType.DRAG_NONE):
|
||||||
|
drag_type = DragType.DRAG_MOVE
|
||||||
|
|
||||||
|
return drag_type
|
@ -0,0 +1,11 @@
|
|||||||
|
[gd_scene load_steps=2 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://addons/mesh_data_resource_editor/uv_editor/RectViewNode.gd" type="Script" id=1]
|
||||||
|
|
||||||
|
[node name="RectViewNode" type="MarginContainer"]
|
||||||
|
margin_right = 1024.0
|
||||||
|
margin_bottom = 600.0
|
||||||
|
script = ExtResource( 1 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
@ -0,0 +1,218 @@
|
|||||||
|
tool
|
||||||
|
extends HBoxContainer
|
||||||
|
|
||||||
|
#This is a port of godot 4.0's EditorZoomWidget
|
||||||
|
|
||||||
|
#/*************************************************************************/
|
||||||
|
#/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||||
|
#/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
#/* */
|
||||||
|
#/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
#/* a copy of this software and associated documentation files (the */
|
||||||
|
#/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
#/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
#/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
#/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
#/* the following conditions: */
|
||||||
|
#/* */
|
||||||
|
#/* 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. */
|
||||||
|
#/*************************************************************************/
|
||||||
|
|
||||||
|
var zoom_minus : Button
|
||||||
|
var zoom_reset : Button
|
||||||
|
var zoom_plus : Button
|
||||||
|
|
||||||
|
var EDSCALE : float = 1
|
||||||
|
|
||||||
|
export(float) var zoom : float = 1.0 setget set_zoom, get_zoom
|
||||||
|
|
||||||
|
signal zoom_changed(zoom)
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
# Zoom buttons
|
||||||
|
zoom_minus = Button.new()
|
||||||
|
zoom_minus.set_flat(true)
|
||||||
|
add_child(zoom_minus)
|
||||||
|
zoom_minus.connect("pressed", self, "_button_zoom_minus")
|
||||||
|
zoom_minus.set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_minus", tr("Zoom Out"), KEY_MASK_CMD | KEY_MINUS))
|
||||||
|
zoom_minus.set_focus_mode(FOCUS_NONE)
|
||||||
|
|
||||||
|
zoom_reset = Button.new()
|
||||||
|
zoom_reset.set_flat(true)
|
||||||
|
add_child(zoom_reset)
|
||||||
|
zoom_reset.add_constant_override("outline_size", 1)
|
||||||
|
zoom_reset.add_color_override("font_outline_color", Color(0, 0, 0))
|
||||||
|
zoom_reset.add_color_override("font_color", Color(1, 1, 1))
|
||||||
|
zoom_reset.connect("pressed", self, "_button_zoom_reset")
|
||||||
|
zoom_reset.set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", tr("Zoom Reset"), KEY_MASK_CMD | KEY_0))
|
||||||
|
zoom_reset.set_focus_mode(FOCUS_NONE)
|
||||||
|
#Prevent the button's size from changing when the text size changes
|
||||||
|
zoom_reset.set_custom_minimum_size(Vector2(75, 0))
|
||||||
|
|
||||||
|
zoom_plus = Button.new()
|
||||||
|
zoom_plus.set_flat(true)
|
||||||
|
add_child(zoom_plus)
|
||||||
|
zoom_plus.connect("pressed", self, "_button_zoom_plus")
|
||||||
|
zoom_plus.set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_plus", tr("Zoom In"), KEY_MASK_CMD | KEY_EQUAL)) # Usually direct access key for PLUS
|
||||||
|
zoom_plus.set_focus_mode(FOCUS_NONE)
|
||||||
|
|
||||||
|
_update_zoom_label()
|
||||||
|
|
||||||
|
add_constant_override("separation", round(-8))
|
||||||
|
|
||||||
|
func get_zoom() -> float:
|
||||||
|
return zoom
|
||||||
|
|
||||||
|
func set_zoom(p_zoom : float) -> void:
|
||||||
|
if (p_zoom > 0 && p_zoom != zoom):
|
||||||
|
zoom = p_zoom;
|
||||||
|
_update_zoom_label();
|
||||||
|
|
||||||
|
func set_zoom_by_increments(p_increment_count : int, p_integer_only : bool) -> void:
|
||||||
|
# Remove editor scale from the index computation.
|
||||||
|
var zoom_noscale : float = zoom / max(1, EDSCALE)
|
||||||
|
var CMP_EPSILON : float = 0.00001
|
||||||
|
|
||||||
|
if (p_integer_only):
|
||||||
|
# Only visit integer scaling factors above 100%, and fractions with an integer denominator below 100%
|
||||||
|
# (1/2 = 50%, 1/3 = 33.33%, 1/4 = 25%, …).
|
||||||
|
# This is useful when working on pixel art projects to avoid distortion.
|
||||||
|
# This algorithm is designed to handle fractional start zoom values correctly
|
||||||
|
# (e.g. 190% will zoom up to 200% and down to 100%).
|
||||||
|
if (zoom_noscale + p_increment_count * 0.001 >= 1.0 - CMP_EPSILON):
|
||||||
|
# New zoom is certain to be above 100%.
|
||||||
|
if (p_increment_count >= 1):
|
||||||
|
# Zooming.
|
||||||
|
set_zoom(floor(zoom_noscale + p_increment_count) * max(1, EDSCALE))
|
||||||
|
else:
|
||||||
|
# Dezooming.
|
||||||
|
set_zoom(ceil(zoom_noscale + p_increment_count) * max(1, EDSCALE))
|
||||||
|
else:
|
||||||
|
if (p_increment_count >= 1):
|
||||||
|
# Zooming. Convert the current zoom into a denominator.
|
||||||
|
var new_zoom : float = 1.0 / ceil(1.0 / zoom_noscale - p_increment_count)
|
||||||
|
if (is_equal_approx(zoom_noscale, new_zoom)):
|
||||||
|
# New zoom is identical to the old zoom, so try again.
|
||||||
|
# This can happen due to floating-point precision issues.
|
||||||
|
new_zoom = 1.0 / ceil(1.0 / zoom_noscale - p_increment_count - 1)
|
||||||
|
|
||||||
|
set_zoom(new_zoom * max(1, EDSCALE));
|
||||||
|
else:
|
||||||
|
# Dezooming. Convert the current zoom into a denominator.
|
||||||
|
var new_zoom : float = 1.0 / floor(1.0 / zoom_noscale - p_increment_count)
|
||||||
|
if (is_equal_approx(zoom_noscale, new_zoom)):
|
||||||
|
# New zoom is identical to the old zoom, so try again.
|
||||||
|
# This can happen due to floating-point precision issues.
|
||||||
|
new_zoom = 1.0 / floor(1.0 / zoom_noscale - p_increment_count + 1)
|
||||||
|
|
||||||
|
set_zoom(new_zoom * max(1, EDSCALE))
|
||||||
|
else:
|
||||||
|
# Base increment factor defined as the twelveth root of two.
|
||||||
|
# This allow a smooth geometric evolution of the zoom, with the advantage of
|
||||||
|
# visiting all integer power of two scale factors.
|
||||||
|
# note: this is analogous to the 'semitones' interval in the music world
|
||||||
|
# In order to avoid numerical imprecisions, we compute and edit a zoom index
|
||||||
|
# with the following relation: zoom = 2 ^ (index / 12)
|
||||||
|
|
||||||
|
if (zoom < CMP_EPSILON || p_increment_count == 0):
|
||||||
|
return
|
||||||
|
|
||||||
|
# zoom = 2**(index/12) => log2(zoom) = index/12
|
||||||
|
var closest_zoom_index : float = round(log(zoom_noscale) * 12.0 / log(2.0))
|
||||||
|
|
||||||
|
var new_zoom_index : float = closest_zoom_index + p_increment_count
|
||||||
|
var new_zoom : float = pow(2.0, new_zoom_index / 12.0)
|
||||||
|
|
||||||
|
# Restore Editor scale transformation
|
||||||
|
new_zoom *= max(1, EDSCALE)
|
||||||
|
|
||||||
|
set_zoom(new_zoom)
|
||||||
|
|
||||||
|
|
||||||
|
func _update_zoom_label() -> void:
|
||||||
|
var zoom_text : String = ""
|
||||||
|
|
||||||
|
# The zoom level displayed is relative to the editor scale
|
||||||
|
# (like in most image editors). Its lower bound is clamped to 1 as some people
|
||||||
|
# lower the editor scale to increase the available real estate,
|
||||||
|
# even if their display doesn't have a particularly low DPI.
|
||||||
|
|
||||||
|
if (zoom >= 10):
|
||||||
|
# Don't show a decimal when the zoom level is higher than 1000 %.
|
||||||
|
#zoom_text = (rtos(round((zoom / max(1, EDSCALE)) * 100))) + " %"
|
||||||
|
zoom_text = (String(round((zoom / max(1, EDSCALE)) * 100))) + " %"
|
||||||
|
else:
|
||||||
|
var v : float = (zoom / max(1, EDSCALE)) * 100
|
||||||
|
var val : float = floor(v / 0.1 + 0.5) * 0.1
|
||||||
|
|
||||||
|
# zoom_text = (rtos(val)) + " %"
|
||||||
|
zoom_text = (String(val)) + " %"
|
||||||
|
|
||||||
|
zoom_reset.set_text(zoom_text)
|
||||||
|
|
||||||
|
func _button_zoom_minus() -> void:
|
||||||
|
set_zoom_by_increments(-6, Input.is_key_pressed(KEY_ALT));
|
||||||
|
emit_signal("zoom_changed", zoom);
|
||||||
|
|
||||||
|
func _button_zoom_reset() -> void:
|
||||||
|
set_zoom(1.0 * max(1, EDSCALE));
|
||||||
|
emit_signal("zoom_changed", zoom);
|
||||||
|
|
||||||
|
func _button_zoom_plus() -> void:
|
||||||
|
set_zoom_by_increments(6, Input.is_key_pressed(KEY_ALT));
|
||||||
|
emit_signal("zoom_changed", zoom);
|
||||||
|
|
||||||
|
func _notification(p_what : int) -> void:
|
||||||
|
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED):
|
||||||
|
zoom_minus.icon = get_icon("ZoomLess", "EditorIcons")
|
||||||
|
zoom_plus.icon = get_icon("ZoomMore", "EditorIcons")
|
||||||
|
|
||||||
|
#from godot editor/editor_Settings.cpp
|
||||||
|
func ED_SHORTCUT(p_path : String, p_name : String, p_keycode : int, editor_settings : EditorSettings = null) -> ShortCut:
|
||||||
|
if OS.get_name() == "OSX":
|
||||||
|
# Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS
|
||||||
|
if (p_keycode == KEY_DELETE):
|
||||||
|
p_keycode = KEY_MASK_CMD | KEY_BACKSPACE
|
||||||
|
|
||||||
|
var ie : InputEventKey = null
|
||||||
|
if (p_keycode):
|
||||||
|
ie = InputEventKey.new()
|
||||||
|
|
||||||
|
ie.set_unicode(p_keycode & KEY_CODE_MASK)
|
||||||
|
ie.set_scancode(p_keycode & KEY_CODE_MASK)
|
||||||
|
ie.set_shift(bool(p_keycode & KEY_MASK_SHIFT))
|
||||||
|
ie.set_alt(bool(p_keycode & KEY_MASK_ALT))
|
||||||
|
ie.set_control(bool(p_keycode & KEY_MASK_CTRL))
|
||||||
|
ie.set_metakey(bool(p_keycode & KEY_MASK_META))
|
||||||
|
|
||||||
|
if (!editor_settings):
|
||||||
|
var sc : ShortCut
|
||||||
|
sc = ShortCut.new()
|
||||||
|
sc.set_name(p_name)
|
||||||
|
sc.set_shortcut(ie)
|
||||||
|
sc.set_meta("original", ie)
|
||||||
|
return sc
|
||||||
|
|
||||||
|
var sc : ShortCut = editor_settings.get_shortcut(p_path)
|
||||||
|
if (sc.is_valid()):
|
||||||
|
sc.set_name(p_name); #keep name (the ones that come from disk have no name)
|
||||||
|
sc.set_meta("original", ie); #to compare against changes
|
||||||
|
return sc;
|
||||||
|
|
||||||
|
sc = ShortCut.new()
|
||||||
|
sc.set_name(p_name)
|
||||||
|
sc.set_shortcut(ie)
|
||||||
|
sc.set_meta("original", ie) #to compare against changes
|
||||||
|
editor_settings.add_shortcut(p_path, sc)
|
||||||
|
|
||||||
|
return sc
|
||||||
|
|
@ -0,0 +1,8 @@
|
|||||||
|
[gd_scene load_steps=2 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://addons/world_generator/widgets/EditorZoomWidget.gd" type="Script" id=1]
|
||||||
|
|
||||||
|
[node name="EditorZoomWidget" type="HBoxContainer"]
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
script = ExtResource( 1 )
|
Loading…
Reference in New Issue
Block a user