crabs-game/addons/aseprite_importer/interface/spritesheet_inspector/SpritesheetView.gd

316 lines
7.4 KiB
GDScript

tool
extends Container
onready var h_scroll_bar : HScrollBar = $HScrollBar
onready var v_scroll_bar : VScrollBar = $VScrollBar
export(Texture) var texture : Texture setget set_texture
export(int, 1, 8) var zoom := 1 setget set_zoom
export(Vector2) var offset := Vector2.ZERO setget set_offset
export(bool)var zoom_to_fit := true
var frames = []
var selected_frames := [] setget set_selected_frames
var frame_border_color := Color.red
var frame_border_visibility := true
var selection_border_color := Color.yellow
var selection_border_visibility := true
var border_width := 2
var texture_background_color := Color.green
var texture_background_visibility := true
var background_color := Color.blue
var _full_rect := Rect2(Vector2.ZERO, rect_size)
var _render_rect : Rect2
var _texture_size : Vector2
var _min_offset : Vector2
var _max_offset : Vector2
var _zoom_pivot : Vector2
var _updating_scroll_bars := false
var _panning := false
signal zoom_changed(new_zoom)
func _ready() -> void:
h_scroll_bar.value = .5
v_scroll_bar.value = .5
connect("resized", self, "_on_resized")
h_scroll_bar.connect("value_changed", self, "_on_HScrollBar_value_changed")
v_scroll_bar.connect("value_changed", self, "_on_VScrollBar_value_changed")
update()
func _draw() -> void:
draw_rect(_full_rect, background_color)
if not texture:
return
if texture_background_visibility:
draw_rect(_render_rect, texture_background_color)
draw_texture_rect(texture, _render_rect, false)
if frame_border_visibility:
for frame_idx in range(frames.size()):
if (not selection_border_visibility) or (not frame_idx in selected_frames):
_draw_frame_border(frame_idx)
if selection_border_visibility:
for frame_idx in selected_frames:
_draw_frame_border(frame_idx, true)
func _draw_frame_border(frame_idx : int, selected := false) -> void:
var sprite_region = frames[frame_idx].frame
var frame_rect := _render_rect
frame_rect.position += Vector2(sprite_region.x, sprite_region.y) * zoom
frame_rect.size = Vector2(sprite_region.w, sprite_region.h) * zoom
var border_color
if frame_idx in selected_frames:
border_color = selection_border_color
else:
border_color = frame_border_color
draw_rect(frame_rect, border_color, false, border_width)
func _gui_input(event: InputEvent) -> void:
if event is InputEventMouseButton:
match event.button_index:
BUTTON_MIDDLE:
_panning = event.pressed
if _panning:
mouse_default_cursor_shape = CURSOR_DRAG
else:
mouse_default_cursor_shape = CURSOR_ARROW
BUTTON_WHEEL_UP, BUTTON_WHEEL_DOWN:
if event.pressed:
_zoom_pivot = get_local_mouse_position()
if event.button_index == BUTTON_WHEEL_UP:
self.zoom += 1
else:
self.zoom -= 1
_zoom_pivot = _full_rect.size / 2
elif event is InputEventMouseMotion:
if _panning:
self.offset += event.relative
func load_settings(settings : Dictionary) -> void:
frame_border_color = settings.frame_border.color
frame_border_visibility = settings.frame_border.visibility
selection_border_color = settings.selection_border.color
selection_border_visibility = settings.selection_border.visibility
texture_background_color = settings.texture_background.color
texture_background_visibility = settings.texture_background.visibility
background_color = settings.inspector_background.color
update()
func _update_offset_limits() -> void:
var full_rect_width := _full_rect.size.x
var render_rect_width := _render_rect.size.x
if render_rect_width <= full_rect_width:
_min_offset.x = 0
_max_offset.x = full_rect_width - render_rect_width
else:
_min_offset.x = -(render_rect_width - full_rect_width)
_max_offset.x = 0
var full_rect_height := _full_rect.size.y
var render_rect_height := _render_rect.size.y
if render_rect_height <= full_rect_height:
_min_offset.y = 0
_max_offset.y = full_rect_height - render_rect_height
else:
_min_offset.y = -(render_rect_height - full_rect_height)
_max_offset.y = 0
func _update_scrollbars() ->void:
_updating_scroll_bars = true
if h_scroll_bar:
var full_width:= _full_rect.size.x
var render_width:= _render_rect.size.x
if render_width > full_width:
var h_page := full_width / render_width
h_scroll_bar.page = h_page
h_scroll_bar.max_value = 1 + h_page
var value := inverse_lerp(_max_offset.x, _min_offset.x, offset.x)
h_scroll_bar.value = value
h_scroll_bar.show()
else:
h_scroll_bar.hide()
if v_scroll_bar:
var full_height:= _full_rect.size.y
var render_height:= _render_rect.size.y
if render_height > full_height:
var v_page := full_height / render_height
v_scroll_bar.page = v_page
v_scroll_bar.max_value = 1 + v_page
var value := inverse_lerp(_max_offset.y, _min_offset.y, offset.y)
v_scroll_bar.value = value
v_scroll_bar.show()
else:
v_scroll_bar.hide()
_updating_scroll_bars = false
# Setters and Getters
func set_offset(new_offset : Vector2) -> void:
new_offset.x = clamp(new_offset.x, _min_offset.x, _max_offset.x)
new_offset.y = clamp(new_offset.y, _min_offset.y, _max_offset.y)
if new_offset == offset:
return
offset = new_offset
_render_rect.position = offset
if not _updating_scroll_bars:
_update_scrollbars()
update()
func set_selected_frames(selection : Array) -> void:
selected_frames = selection
update()
func set_texture(new_texture) -> void:
texture = new_texture
if texture == null:
return
_texture_size = texture.get_size()
var full_rect_size := _full_rect.size
if zoom_to_fit:
var ratio : Vector2
ratio.x = floor(full_rect_size.x / _texture_size.x)
ratio.y = floor(full_rect_size.y / _texture_size.y)
self.zoom = min(ratio.x, ratio.y)
else:
self.zoom = 1
_update_offset_limits()
self.offset = (_max_offset - _min_offset) / 2
func set_zoom(new_zoom : int) -> void:
zoom = clamp(new_zoom, 1, 8)
var new_render_rect_size := _texture_size * zoom
var relative_pivot := _zoom_pivot - offset
var pivot_weight : Vector2
if _render_rect.size.x and _render_rect.size.y:
pivot_weight.x = relative_pivot.x / _render_rect.size.x
pivot_weight.y = relative_pivot.y / _render_rect.size.y
var render_rect_size_diff := new_render_rect_size - _render_rect.size
var offset_diff := render_rect_size_diff * pivot_weight
_render_rect.size = new_render_rect_size
_update_offset_limits()
_update_scrollbars()
self.offset = offset - offset_diff
emit_signal("zoom_changed", zoom)
# Signal Callbacks
func _on_resized() -> void:
_full_rect.size = rect_size
_zoom_pivot = _full_rect.size / 2
_update_offset_limits()
_update_scrollbars()
self.offset = offset
var rect := Rect2()
rect.position.x = 0
rect.position.y = (rect_size.y - h_scroll_bar.rect_size.y)
rect.size.x = (rect_size.x - v_scroll_bar.rect_size.x)
rect.size.y = h_scroll_bar.rect_size.y
fit_child_in_rect(h_scroll_bar, rect)
rect.position.x = (rect_size.x - v_scroll_bar.rect_size.x)
rect.position.y = 0
rect.size.x = v_scroll_bar.rect_size.x
rect.size.y = (rect_size.y - h_scroll_bar.rect_size.y)
fit_child_in_rect(v_scroll_bar, rect)
func _on_HScrollBar_value_changed(value : float) -> void:
if _updating_scroll_bars:
return
_updating_scroll_bars = true
self.offset.x = lerp(_max_offset.x, _min_offset.x, value)
_updating_scroll_bars = false
func _on_VScrollBar_value_changed(value : float) -> void:
if _updating_scroll_bars:
return
_updating_scroll_bars = true
self.offset.y = lerp(_max_offset.y, _min_offset.y, value)
_updating_scroll_bars = false