Added skeleton classes for mesh data resource editor's uv rect editor.

This commit is contained in:
Relintai 2022-04-11 01:42:33 +02:00
parent 2093cef963
commit 200b4b0405
11 changed files with 1348 additions and 433 deletions

View File

@ -1,218 +0,0 @@
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

View File

@ -1,8 +0,0 @@
[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 )

View File

@ -1,207 +0,0 @@
tool
extends Container
#From https://github.com/EricEzaM/godot-color-palette
# MIT License
#
# Copyright (c) 2020 Eric M
#
# 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 columns: int = 1 setget set_columns
var _min_x : int = 0
func _notification(p_what):
match p_what:
NOTIFICATION_SORT_CHILDREN:
var col_minw: Dictionary # Max of min_width of all controls in each col (indexed by col).
var row_minh: Dictionary # Max of min_height of all controls in each row (indexed by row).
var col_expanded: Array # Columns which have the SIZE_EXPAND flag set.
var row_expanded: Array # Rows which have the SIZE_EXPAND flag set.
var hsep = get_constant("hseparation", "GridContainer")
var vsep = get_constant("vseparation", "GridContainer")
var min_columns = 1
_min_x = 0
if get_child_count() > 0:
min_columns = int(floor(rect_size.x / (get_child(0).get_combined_minimum_size().x + hsep)))
self.columns = min_columns
var max_col = min(get_child_count(), columns)
var max_row = ceil(float(get_child_count()) / float(columns))
# Compute the per-column/per-row data.
var valid_controls_index = 0
for i in range(get_child_count()):
var c: Control = get_child(i)
if !c or !c.is_visible_in_tree():
continue
var row = valid_controls_index / columns
var col = valid_controls_index % columns
valid_controls_index += 1
var ms: Vector2 = c.get_combined_minimum_size()
if _min_x < ms.x:
_min_x = ms.x
if col_minw.has(col):
col_minw[col] = max(col_minw[col], ms.x)
else:
col_minw[col] = ms.x
if row_minh.has(row):
row_minh[row] = max(row_minh[row], ms.y)
else:
row_minh[row] = ms.y
if c.get_h_size_flags() & SIZE_EXPAND:
col_expanded.push_front(col)
if c.get_v_size_flags() & SIZE_EXPAND:
row_expanded.push_front(row)
# Consider all empty columns expanded.
for i in range(valid_controls_index, columns):
col_expanded.push_front(i)
# Evaluate the remaining space for expanded columns/rows.
var remaining_space: Vector2 = get_size()
for e in col_minw.keys():
if !col_expanded.has(e):
remaining_space.x -= col_minw.get(e)
for e in row_minh.keys():
if !row_expanded.has(e):
remaining_space.y -= row_minh.get(e)
remaining_space.y -= vsep * max(max_row - 1, 0)
remaining_space.x -= hsep * max(max_col - 1, 0)
var can_fit = false
while !can_fit && col_expanded.size() > 0:
# Check if all minwidth constraints are OK if we use the remaining space.
can_fit = true
var max_index = col_expanded.front()
for e in col_expanded:
if col_minw.has(e):
if col_minw[e] > col_minw[max_index]:
max_index = e
if can_fit && (remaining_space.x / col_expanded.size()) < col_minw[e]:
can_fit = false
# If not, the column with maximum minwidth is not expanded.
if (!can_fit):
col_expanded.erase(max_index)
remaining_space.x -= col_minw[max_index]
can_fit = false
while !can_fit && row_expanded.size() > 0:
# Check if all minheight constraints are OK if we use the remaining space.
can_fit = true
var max_index = row_expanded.front()
for e in row_expanded:
if row_minh[e] > row_minh[max_index]:
max_index = e
if can_fit && (remaining_space.y / row_expanded.size()) < row_minh[e]:
can_fit = false
# If not, the row with maximum minheight is not expanded.
if (!can_fit):
row_expanded.erase(max_index)
remaining_space.y -= row_minh[max_index]
# Finally, fit the nodes.
var col_expand = remaining_space.x / col_expanded.size() if col_expanded.size() > 0 else 0
var row_expand = remaining_space.y / row_expanded.size() if row_expanded.size() > 0 else 0
var col_ofs = 0
var row_ofs = 0
valid_controls_index = 0
for i in range(get_child_count()):
var c: Control = get_child(i)
if (!c || !c.is_visible_in_tree()):
continue
var row = valid_controls_index / columns
var col = valid_controls_index % columns
valid_controls_index += 1
if (col == 0):
col_ofs = 0
if (row > 0):
row_ofs += (row_expand if row_expanded.has(row - 1) else row_minh[row - 1]) + vsep
var p = Vector2(col_ofs, row_ofs)
var s = Vector2(col_expand if col_expanded.has(col) else col_minw[col], row_expand if row_expanded.has(row) else row_minh[row])
fit_child_in_rect(c, Rect2(p, s))
col_ofs += s.x + hsep
NOTIFICATION_THEME_CHANGED:
minimum_size_changed()
func _get_minimum_size():
# Only worry about max height, not width (since it does width automatically)
var row_minh: Dictionary
var vsep = get_constant("vseparation", "GridContainer")
var max_row = 0
var valid_controls_index = 0
for i in range(get_child_count()):
var c: Control = get_child(i)
if !c or !c.is_visible():
continue
var row = valid_controls_index / columns
valid_controls_index += 1
var ms = c.get_combined_minimum_size()
if row_minh.has(row):
row_minh[row] = max(row_minh[row], ms.y)
else:
row_minh[row] = ms.y
max_row = max(row, max_row)
var ms: Vector2
ms.x = _min_x
for e in row_minh.keys():
ms.y += row_minh.get(e)
ms.y += vsep * max_row
return ms
func set_columns(p_columns: int):
columns = p_columns
minimum_size_changed()

View File

@ -0,0 +1,181 @@
/*
Copyright (c) 2019-2022 Péter Magyar
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.
*/
#include "mdr_uv_rect_editor.h"
#include "editor/editor_plugin.h"
#include "../../mesh_data_resource.h"
#include "../../nodes/mesh_data_instance.h"
void MDRUVRectEditor::set_plugin(EditorPlugin *plugin) {
//$ScrollContainer/MarginContainer/RectView.set_plugin(plugin)
}
void MDRUVRectEditor::set_mesh_data_resource(Ref<MeshDataResource> a) {
//$ScrollContainer/MarginContainer/RectView.set_mesh_data_resource(a)
}
void MDRUVRectEditor::set_mesh_data_instance(MeshDataInstance *a) {
//$ScrollContainer/MarginContainer/RectView.set_mesh_data_instance(a)
}
void MDRUVRectEditor::ok_pressed() {
//$ScrollContainer/MarginContainer/RectView.ok_pressed()
}
void MDRUVRectEditor::cancel_pressed() {
//$ScrollContainer/MarginContainer/RectView.cancel_pressed()
}
MDRUVRectEditor::MDRUVRectEditor() {
/*
[gd_scene load_steps=8 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]
[ext_resource path="res://addons/mesh_data_resource_editor/icons/icon_v_mirror.png" type="Texture" id=4]
[ext_resource path="res://addons/mesh_data_resource_editor/icons/icon_h_mirror.png" type="Texture" id=5]
[ext_resource path="res://addons/mesh_data_resource_editor/icons/icon_rot_right.png" type="Texture" id=6]
[ext_resource path="res://addons/mesh_data_resource_editor/icons/icon_rot_left.png" type="Texture" id=7]
[node name="UVEditor" 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 = 700.0
margin_bottom = 700.0
custom_constants/margin_right = 50
custom_constants/margin_top = 50
custom_constants/margin_left = 50
custom_constants/margin_bottom = 50
[node name="RectView" type="Control" parent="ScrollContainer/MarginContainer"]
margin_left = 50.0
margin_top = 50.0
margin_right = 650.0
margin_bottom = 650.0
rect_min_size = Vector2( 600, 600 )
script = ExtResource( 3 )
zoom_widget_path = NodePath("../../../Control/HBoxContainer/EditorZoomWidget")
mirror_horizontal_button_path = NodePath("../../../Control/HBoxContainer/HorizontalMirror")
mirror_vertical_button_path = NodePath("../../../Control/HBoxContainer/VerticalMirror")
rotate_left_button_path = NodePath("../../../Control/HBoxContainer/RotLeft")
rotate_amount_spinbox_path = NodePath("../../../Control/HBoxContainer/SpinBox")
rotate_right_button_path = NodePath("../../../Control/HBoxContainer/RotRight")
[node name="Control" type="VBoxContainer" 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="HBoxContainer" type="HBoxContainer" parent="Control"]
margin_right = 1010.0
margin_bottom = 24.0
mouse_filter = 2
size_flags_horizontal = 3
__meta__ = {
"_edit_use_anchors_": false
}
[node name="EditorZoomWidget" parent="Control/HBoxContainer" instance=ExtResource( 2 )]
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 115.0
margin_bottom = 24.0
custom_constants/separation = -8
__meta__ = {
"_edit_use_anchors_": false
}
[node name="VSeparator2" type="VSeparator" parent="Control/HBoxContainer"]
margin_left = 119.0
margin_right = 123.0
margin_bottom = 24.0
[node name="HorizontalMirror" type="Button" parent="Control/HBoxContainer"]
margin_left = 127.0
margin_right = 155.0
margin_bottom = 24.0
hint_tooltip = "Mirror the selected island horizontally.."
icon = ExtResource( 5 )
[node name="VerticalMirror" type="Button" parent="Control/HBoxContainer"]
margin_left = 159.0
margin_right = 187.0
margin_bottom = 24.0
hint_tooltip = "Mirror the selected island vertically."
icon = ExtResource( 4 )
[node name="VSeparator" type="VSeparator" parent="Control/HBoxContainer"]
margin_left = 191.0
margin_right = 195.0
margin_bottom = 24.0
[node name="RotLeft" type="Button" parent="Control/HBoxContainer"]
margin_left = 199.0
margin_right = 227.0
margin_bottom = 24.0
hint_tooltip = "Rotate left."
icon = ExtResource( 7 )
[node name="SpinBox" type="SpinBox" parent="Control/HBoxContainer"]
margin_left = 231.0
margin_right = 305.0
margin_bottom = 24.0
hint_tooltip = "Rotate amount in degrees."
max_value = 360.0
value = 45.0
allow_greater = true
allow_lesser = true
[node name="RotRight" type="Button" parent="Control/HBoxContainer"]
margin_left = 309.0
margin_right = 337.0
margin_bottom = 24.0
hint_tooltip = "Rotate right."
icon = ExtResource( 6 )
*/
}
MDRUVRectEditor::~MDRUVRectEditor() {
}
void MDRUVRectEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("ok_pressed"), &MDRUVRectEditor::ok_pressed);
ClassDB::bind_method(D_METHOD("cancel_pressed"), &MDRUVRectEditor::cancel_pressed);
}

View File

@ -0,0 +1,50 @@
#ifndef MDR_UV_RECT_EDITOR_H
#define MDR_UV_RECT_EDITOR_H
/*
Copyright (c) 2019-2022 Péter Magyar
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.
*/
#include "core/reference.h"
#include "scene/gui/panel_container.h"
class EditorPlugin;
class MeshDataResource;
class MeshDataInstance;
class MDRUVRectEditor : public PanelContainer {
GDCLASS(MDRUVRectEditor, PanelContainer);
public:
//void set_plugin(EditorPlugin *plugin);
void set_mesh_data_resource(Ref<MeshDataResource> a);
void set_mesh_data_instance(MeshDataInstance *a);
void ok_pressed();
void cancel_pressed();
MDRUVRectEditor();
~MDRUVRectEditor();
protected:
static void _bind_methods();
};
#endif

View File

@ -0,0 +1,324 @@
/*
Copyright (c) 2019-2022 Péter Magyar
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.
*/
#include "mdr_uv_rect_view.h"
#include "scene/gui/control.h"
void MDRUVRectView::set_plugin(EditorPlugin *plugin) {
/*
_plugin = plugin
_undo_redo = _plugin.get_undo_redo()
*/
}
void MDRUVRectView::set_mesh_data_resource(Ref<MeshDataResource> a) {
/*
_mdr = a
*/
}
void MDRUVRectView::set_mesh_data_instance(MeshDataInstance *a) {
/*
_background_texture = null
if a:
_background_texture = a.texture
*/
}
void MDRUVRectView::set_selected(Control *node) {
/*
if selected_rect && is_instance_valid(selected_rect):
selected_rect.set_selected(false)
selected_rect = node
if selected_rect:
selected_rect.set_selected(true)
*/
}
void MDRUVRectView::store_uvs() {
/*
_stored_uvs.resize(0)
if !_mdr:
return
var arrays : Array = _mdr.get_array()
if arrays.size() != ArrayMesh.ARRAY_MAX:
return
if arrays[ArrayMesh.ARRAY_TEX_UV] == null:
return
# Make sure it gets copied
_stored_uvs.append_array(arrays[ArrayMesh.ARRAY_TEX_UV])
*/
}
PoolVector2Array MDRUVRectView::get_uvs(Ref<MeshDataResource> mdr) {
/*
if !_mdr:
return PoolVector2Array()
var arrays : Array = _mdr.get_array()
if arrays.size() != ArrayMesh.ARRAY_MAX:
return PoolVector2Array()
if arrays[ArrayMesh.ARRAY_TEX_UV] == null:
return PoolVector2Array()
return arrays[ArrayMesh.ARRAY_TEX_UV]
*/
}
void MDRUVRectView::apply_uvs(Ref<MeshDataResource> mdr, PoolVector2Array stored_uvs) {
/*
if !_mdr:
return
var arrays : Array = _mdr.get_array()
if arrays.size() != ArrayMesh.ARRAY_MAX:
return
if arrays[ArrayMesh.ARRAY_TEX_UV] == null:
return
arrays[ArrayMesh.ARRAY_TEX_UV] = stored_uvs
_mdr.array = arrays
*/
}
void MDRUVRectView::refresh() {
/*
clear()
var rect : Rect2 = base_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()
*/
}
void MDRUVRectView::clear() {
}
void MDRUVRectView::refresh_rects() {
/*
clear_rects()
if !_mdr:
return
var partitions : Array = MeshDecompose.partition_mesh(_mdr)
for p in partitions:
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(_mdr, p)
*/
}
void MDRUVRectView::clear_rects() {
/*
for c in get_children():
c.queue_free()
remove_child(c)
*/
}
void MDRUVRectView::_enter_tree() {
/*
*/
}
void MDRUVRectView::_draw() {
/*
draw_rect(Rect2(Vector2(), get_size()), Color(0.2, 0.2, 0.2, 1))
if _background_texture:
draw_texture_rect_region(_background_texture, Rect2(Vector2(), get_size()), Rect2(Vector2(), _background_texture.get_size()))
*/
}
void MDRUVRectView::on_mirror_horizontal_button_pressed() {
/*
if selected_rect && is_instance_valid(selected_rect) {
selected_rect.mirror_horizontal();
}*/
}
void MDRUVRectView::on_mirror_vertical_button_pressed() {
/*
if selected_rect && is_instance_valid(selected_rect):
selected_rect.mirror_vertical()
*/
}
void MDRUVRectView::on_rotate_left_button_button_pressed() {
/*
if selected_rect && is_instance_valid(selected_rect):
selected_rect.rotate_uvs(-rotation_amount)
*/
}
void MDRUVRectView::on_rotate_amount_spinbox_changed(float val) {
/*
rotation_amount = val
*/
}
void MDRUVRectView::on_rotate_right_button_button_pressed() {
/*
if selected_rect && is_instance_valid(selected_rect):
selected_rect.rotate_uvs(rotation_amount)
*/
}
void MDRUVRectView::on_edited_resource_changed() {
/*
call_deferred("refresh")
*/
}
void MDRUVRectView::on_zoom_changed(float zoom) {
/*
_rect_scale = zoom
apply_zoom()
*/
}
void MDRUVRectView::on_visibility_changed() {
/*
if is_visible_in_tree():
store_uvs()
call_deferred("refresh")
*/
}
void MDRUVRectView::ok_pressed() {
/*
_undo_redo.create_action("UV Editor Accept")
_undo_redo.add_do_method(self, "apply_uvs", _mdr, get_uvs(_mdr))
_undo_redo.add_undo_method(self, "apply_uvs", _mdr, _stored_uvs)
_undo_redo.commit_action()
*/
}
void MDRUVRectView::cancel_pressed() {
/*
if !_mdr:
return
var arrays : Array = _mdr.get_array()
if arrays.size() != ArrayMesh.ARRAY_MAX:
return
# Make sure it gets copied
var uvs : PoolVector2Array = PoolVector2Array()
uvs.append_array(_stored_uvs)
_undo_redo.create_action("UV Editor Cancel")
_undo_redo.add_do_method(self, "apply_uvs", _mdr, uvs)
_undo_redo.add_undo_method(self, "apply_uvs", _mdr, get_uvs(_mdr))
_undo_redo.commit_action()
_stored_uvs.resize(0)
*/
}
void MDRUVRectView::apply_zoom() {
/*
var rect : Rect2 = base_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)
*/
}
MDRUVRectView::MDRUVRectView() {
float _rect_scale = 1;
Rect2 base_rect = Rect2(0, 0, 600, 600);
PoolVector2Array _stored_uvs;
EditorPlugin *_plugin = nullptr;
UndoRedo *_undo_redo = nullptr;
Control *selected_rect = nullptr;
rotation_amount = 45;
/* var zoom_widget : Node = get_node_or_null(zoom_widget_path)
if zoom_widget && !zoom_widget.is_connected("zoom_changed", self, "on_zoom_changed"):
zoom_widget.connect("zoom_changed", self, "on_zoom_changed")
var mirror_horizontal_button : Button = get_node_or_null(mirror_horizontal_button_path)
if mirror_horizontal_button && !mirror_horizontal_button.is_connected("pressed", self, "on_mirror_horizontal_button_pressed"):
mirror_horizontal_button.connect("pressed", self, "on_mirror_horizontal_button_pressed")
var mirror_vertical_button : Button = get_node_or_null(mirror_vertical_button_path)
if mirror_vertical_button && !mirror_vertical_button.is_connected("pressed", self, "on_mirror_vertical_button_pressed"):
mirror_vertical_button.connect("pressed", self, "on_mirror_vertical_button_pressed")
var rotate_left_button : Button = get_node_or_null(rotate_left_button_path)
if rotate_left_button && !rotate_left_button.is_connected("pressed", self, "on_rotate_left_button_button_pressed"):
rotate_left_button.connect("pressed", self, "on_rotate_left_button_button_pressed")
var rotate_amount_spinbox : SpinBox = get_node_or_null(rotate_amount_spinbox_path)
if rotate_amount_spinbox:
rotation_amount = rotate_amount_spinbox.value
if !rotate_amount_spinbox.is_connected("value_changed", self, "on_rotate_amount_spinbox_changed"):
rotate_amount_spinbox.connect("value_changed", self, "on_rotate_amount_spinbox_changed")
var rotate_right_button : Button = get_node_or_null(rotate_right_button_path)
if rotate_right_button && !rotate_right_button.is_connected("pressed", self, "on_rotate_right_button_button_pressed"):
rotate_right_button.connect("pressed", self, "on_rotate_right_button_button_pressed")
if !is_connected("visibility_changed", self, "on_visibility_changed"):
connect("visibility_changed", self, "on_visibility_changed")
*/
}
MDRUVRectView::~MDRUVRectView() {
}
void MDRUVRectView::_bind_methods() {
}

View File

@ -0,0 +1,112 @@
#ifndef MDR_UV_RECT_VIEW_H
#define MDR_UV_RECT_VIEW_H
/*
Copyright (c) 2019-2022 Péter Magyar
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.
*/
#include "core/math/rect2.h"
#include "core/pool_vector.h"
#include "core/reference.h"
#include "scene/gui/control.h"
class MeshDataResource;
class MeshDataInstance;
class Texture;
class EditorPlugin;
class UndoRedo;
class Button;
class EditorZoomWidget;
class SpinBox;
class MDRUVRectView : public Control {
GDCLASS(MDRUVRectView, Control);
public:
void set_plugin(EditorPlugin *plugin);
void set_mesh_data_resource(Ref<MeshDataResource> a);
void set_mesh_data_instance(MeshDataInstance *a);
void set_selected(Control *node);
void store_uvs();
PoolVector2Array get_uvs(Ref<MeshDataResource> mdr);
void apply_uvs(Ref<MeshDataResource> mdr, PoolVector2Array stored_uvs);
void refresh();
void clear();
void refresh_rects();
void clear_rects();
void _enter_tree();
void _draw();
void on_mirror_horizontal_button_pressed();
void on_mirror_vertical_button_pressed();
void on_rotate_left_button_button_pressed();
void on_rotate_amount_spinbox_changed(float val);
void on_rotate_right_button_button_pressed();
void on_edited_resource_changed();
void on_zoom_changed(float zoom);
void on_visibility_changed();
void ok_pressed();
void cancel_pressed();
void apply_zoom();
MDRUVRectView();
~MDRUVRectView();
protected:
static void _bind_methods();
EditorZoomWidget *zoom_widget;
Button *mirror_horizontal_button;
Button *mirror_vertical_button;
Button *rotate_left_button;
SpinBox *rotate_amount_spinbox;
Button *rotate_right_button;
public:
float _rect_scale;
Ref<MeshDataResource> _mdr;
Ref<Texture> _background_texture;
Rect2 base_rect;
Vector2 edited_resource_current_size;
PoolVector2Array _stored_uvs;
EditorPlugin *_plugin;
UndoRedo *_undo_redo;
Control *selected_rect;
float rotation_amount;
};
#endif

View File

@ -0,0 +1,482 @@
/*
Copyright (c) 2019-2022 Péter Magyar
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.
*/
#include "mdr_uv_rect_view_node.h"
void MDRUVRectViewNode::set_edited_resource(Ref<MeshDataResource> mdr, PoolIntArray indices) {
/*
_mdr = mdr
_indices = indices
_uvs.resize(0)
var arrays : Array = _mdr.get_array()
if arrays.size() != ArrayMesh.ARRAY_MAX:
return
if arrays[ArrayMesh.ARRAY_TEX_UV] == null:
return
# Make sure it gets copied
_uvs.append_array(arrays[ArrayMesh.ARRAY_TEX_UV])
set_up_base_rect()
refresh()
*/
}
void MDRUVRectViewNode::mirror_horizontal() {
/*
var pia : PoolIntArray = PoolIntArray()
for index in _indices:
var found : bool = false
for i in pia:
if i == index:
found = true
break
if found:
continue
pia.append(index)
var uv : Vector2 = _uvs[index]
uv.x = 1.0 - uv.x
_uvs.set(index, uv)
apply_uv()
update()
*/
}
void MDRUVRectViewNode::mirror_vertical() {
/*
var pia : PoolIntArray = PoolIntArray()
for index in _indices:
var found : bool = false
for i in pia:
if i == index:
found = true
break
if found:
continue
pia.append(index)
var uv : Vector2 = _uvs[index]
uv.y = 1.0 - uv.y
_uvs.set(index, uv)
apply_uv()
update()
*/
}
void MDRUVRectViewNode::rotate_uvs(float amount) {
/*
var t : Transform2D = Transform2D(deg2rad(amount), Vector2())
var pia : PoolIntArray = PoolIntArray()
for index in _indices:
var found : bool = false
for i in pia:
if i == index:
found = true
break
if found:
continue
pia.append(index)
var uv : Vector2 = _uvs[index]
uv = t.xform(uv)
_uvs.set(index, uv)
re_normalize_uvs()
apply_uv()
update()
*/
}
void MDRUVRectViewNode::set_selected(bool val) {
/*
selected = val
update()
*/
}
void MDRUVRectViewNode::set_editor_rect_scale(float rect_scale) {
/*
_rect_scale = rect_scale
refresh()
*/
}
void MDRUVRectViewNode::set_up_base_rect() {
/*
_base_rect = Rect2()
if !_mdr:
return
if _uvs.size() == 0:
return
var vmin : Vector2 = _uvs[_indices[0]]
var vmax : Vector2 = vmin
for i in range(1, _indices.size()):
var uv : Vector2 = _uvs[_indices[i]]
if uv.x < vmin.x:
vmin.x = uv.x
if uv.x > vmax.x:
vmax.x = uv.x
if uv.y < vmin.y:
vmin.y = uv.y
if uv.y > vmax.y:
vmax.y = uv.y
_base_rect = Rect2(vmin.x, vmin.y, vmax.x - vmin.x, vmax.y - vmin.y)
_base_rect.position *= edited_resource_parent_size
_base_rect.size *= edited_resource_parent_size
_uv_min = vmin
_uv_max = vmax
normalize_uvs()
*/
}
void MDRUVRectViewNode::re_normalize_uvs() {
/*
if _uvs.size() == 0:
return
var vmin : Vector2 = _uvs[_indices[0]]
var vmax : Vector2 = vmin
for i in range(1, _indices.size()):
var uv : Vector2 = _uvs[_indices[i]]
if uv.x < vmin.x:
vmin.x = uv.x
if uv.x > vmax.x:
vmax.x = uv.x
if uv.y < vmin.y:
vmin.y = uv.y
if uv.y > vmax.y:
vmax.y = uv.y
var xmm : float = vmax.x - vmin.x
var ymm : float = vmax.y - vmin.y
if xmm == 0:
xmm = 0.0000001
if ymm == 0:
ymm = 0.0000001
for i in range(_uvs.size()):
var uv : Vector2 = _uvs[i]
uv.x -= vmin.x
uv.x /= xmm
uv.y -= vmin.y
uv.y /= ymm
_uvs[i] = uv
*/
}
void MDRUVRectViewNode::normalize_uvs() {
/*
var xmm : float = _uv_max.x - _uv_min.x
var ymm : float = _uv_max.y - _uv_min.y
if xmm == 0:
xmm = 0.0000001
if ymm == 0:
ymm = 0.0000001
for i in range(_uvs.size()):
var uv : Vector2 = _uvs[i]
uv.x -= _uv_min.x
uv.x /= xmm
uv.y -= _uv_min.y
uv.y /= ymm
_uvs[i] = uv
*/
}
void MDRUVRectViewNode::apply_uv() {
/*
if !_mdr:
return
var rect : Rect2 = get_rect()
#rect needs to be converted back
rect.position /= _rect_scale
rect.size /= _rect_scale
rect.position /= edited_resource_parent_size
rect.size /= edited_resource_parent_size
var arrays : Array = _mdr.get_array()
if arrays.size() != ArrayMesh.ARRAY_MAX:
return
if arrays[ArrayMesh.ARRAY_TEX_UV] == null:
return
var uvs : PoolVector2Array = arrays[ArrayMesh.ARRAY_TEX_UV]
for index in _indices:
var uv : Vector2 = _uvs[index]
uv = uv * rect.size + rect.position
uvs[index] = uv
_uv_min = rect.position
_uv_max = rect.position + rect.size
_base_rect = get_rect()
arrays[ArrayMesh.ARRAY_TEX_UV] = uvs
_mdr.array = arrays
*/
}
void MDRUVRectViewNode::refresh() {
/*
if !_mdr:
return
var rect : Rect2 = _base_rect
rect.position *= _rect_scale
rect.size *= _rect_scale
rect_position = rect.position
rect_size = rect.size
update()
*/
}
void MDRUVRectViewNode::_draw() {
/*
if selected:
draw_rect(Rect2(Vector2(), get_size()), _edited_resource_rect_selected_color)
draw_rect(Rect2(Vector2(), get_size()), _edited_resource_rect_selected_border_color, false, _editor_rect_border_size)
else:
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)
if _mdr && _uvs.size() > 0:
var c : Color = _edited_resource_uv_mesh_color
for i in range(0, len(_indices), 3):
draw_line(_uvs[_indices[i]] * get_size(), _uvs[_indices[i + 1]] * get_size(), c, 1, false)
draw_line(_uvs[_indices[i + 1]] * get_size(), _uvs[_indices[i + 2]] * get_size(), c, 1, false)
draw_line(_uvs[_indices[i + 2]] * get_size(), _uvs[_indices[i]] * get_size(), c, 1, false)
*/
}
//based on / ported from engine/scene/gui/dialogs.h and .cpp
void MDRUVRectViewNode::_gui_input(Ref<InputEvent> p_event) {
/*
if (p_event is InputEventMouseButton) && (p_event.get_button_index() == BUTTON_LEFT):
var mb : InputEventMouseButton = p_event as InputEventMouseButton
if (mb.is_pressed()):
get_parent().set_selected(self)
# 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.
apply_uv()
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
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)
*/
}
//based on / ported from engine/scene/gui/dialogs.h and .cpp
int MDRUVRectViewNode::_drag_hit_test(Vector2 pos) {
/*
var drag_type : int = DragType.DRAG_NONE
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
*/
}
//based on / ported from engine/scene/gui/dialogs.h and .cpp
void MDRUVRectViewNode::_notification(int p_what) {
/*
if (p_what == NOTIFICATION_MOUSE_EXIT):
# Reset the mouse cursor when leaving the resizable window border.
if (_mdr && !drag_type):
if (get_default_cursor_shape() != CURSOR_ARROW):
set_default_cursor_shape(CURSOR_ARROW)
*/
}
MDRUVRectViewNode::MDRUVRectViewNode() {
selected = false;
_base_rect = Rect2(0, 0, 100, 100);
_edited_resource_rect_border_color = Color(0.8, 0.8, 0.8, 0.5);
_edited_resource_rect_color = Color(0.5, 0.5, 0.5, 0.2);
_edited_resource_rect_selected_border_color = Color(0.9, 0.9, 0.9, 0.8);
_edited_resource_rect_selected_color = Color(0.5, 0.5, 0.5, 0.4);
_edited_resource_uv_mesh_color = Color(1, 1, 1, 1);
_editor_rect_border_size = 2;
_edited_resource_font_color = Color(0, 0, 0, 1);
drag_type = 0;
_rect_scale = 1;
/*
[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
}
*/
}
MDRUVRectViewNode::~MDRUVRectViewNode() {
}
void MDRUVRectViewNode::_bind_methods() {
}

View File

@ -0,0 +1,105 @@
#ifndef MDR_UV_RECT_VIEW_NODE_H
#define MDR_UV_RECT_VIEW_NODE_H
/*
Copyright (c) 2019-2022 Péter Magyar
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.
*/
#include "core/color.h"
#include "core/math/rect2.h"
#include "core/pool_vector.h"
#include "core/reference.h"
#include "scene/gui/margin_container.h"
class MeshDataResource;
class MDRUVRectViewNode : public MarginContainer {
GDCLASS(MDRUVRectViewNode, MarginContainer);
public:
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
};
void set_edited_resource(Ref<MeshDataResource> mdr, PoolIntArray indices);
void mirror_horizontal();
void mirror_vertical();
void rotate_uvs(float amount);
void set_selected(bool val);
void set_editor_rect_scale(float rect_scale);
void set_up_base_rect();
void re_normalize_uvs();
void normalize_uvs();
void apply_uv();
void refresh();
void _draw();
void _gui_input(Ref<InputEvent> p_event);
int _drag_hit_test(Vector2 pos);
MDRUVRectViewNode();
~MDRUVRectViewNode();
protected:
void _notification(int p_what);
static void _bind_methods();
public:
bool selected;
Ref<MeshDataResource> _mdr;
PoolIntArray _indices;
PoolVector2Array _uvs;
Rect2 _base_rect;
Vector2 _uv_min;
Vector2 _uv_max;
Vector2 edited_resource_parent_size;
Color _edited_resource_rect_border_color;
Color _edited_resource_rect_color;
Color _edited_resource_rect_selected_border_color;
Color _edited_resource_rect_selected_color;
Color _edited_resource_uv_mesh_color;
int _editor_rect_border_size;
Color _edited_resource_font_color;
String _editor_additional_text;
int drag_type;
Vector2 drag_offset;
Vector2 drag_offset_far;
float _rect_scale;
};
#endif

View File

@ -0,0 +1,51 @@
/*
Copyright (c) 2019-2022 Péter Magyar
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.
*/
#include "mdr_uv_rect_view_popup.h"
void MDRUVRectViewPopup::on_ok_pressed() {
//$UVEditor.ok_pressed()
}
void MDRUVRectViewPopup::on_cancel_pressed() {
//$UVEditor.cancel_pressed()
}
void MDRUVRectViewPopup::_notification(int p_what) {
/*
func _enter_tree():
if !is_connected("confirmed", self, "on_ok_pressed"):
connect("confirmed", self, "on_ok_pressed")
if !get_cancel().is_connected("pressed", self, "on_cancel_pressed"):
get_cancel().connect("pressed", self, "on_cancel_pressed")
*/
}
MDRUVRectViewPopup::MDRUVRectViewPopup() {
}
MDRUVRectViewPopup::~MDRUVRectViewPopup() {
}
void MDRUVRectViewPopup::_bind_methods() {
}

View File

@ -0,0 +1,43 @@
#ifndef MDR_UV_RECT_VIEW_POPUP_H
#define MDR_UV_RECT_VIEW_POPUP_H
/*
Copyright (c) 2019-2022 Péter Magyar
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.
*/
#include "scene/gui/dialogs.h"
class MDRUVRectViewPopup : public ConfirmationDialog {
GDCLASS(MDRUVRectViewPopup, ConfirmationDialog);
public:
void on_ok_pressed();
void on_cancel_pressed();
MDRUVRectViewPopup();
~MDRUVRectViewPopup();
protected:
void _notification(int p_what);
static void _bind_methods();
};
#endif