Files
godot-demo-projects/mono/2.5d/addons/node25d-cs/main_screen/viewport_25d.gd

150 lines
4.7 KiB
GDScript

@tool
extends Control
var zoom_level := 0
var is_panning = false
var pan_center: Vector2
var viewport_center: Vector2
var view_mode_index := 0
var editor_interface: EditorInterface # Set in node25d_plugin.gd
var moving = false
@onready var viewport_2d = $Viewport2D
@onready var viewport_overlay = $ViewportOverlay
@onready var view_mode_button_group: ButtonGroup = $"../TopBar/ViewModeButtons/45Degree".group
@onready var zoom_label: Label = $"../TopBar/Zoom/ZoomPercent"
@onready var gizmo_25d_scene = preload("res://addons/node25d-cs/main_screen/gizmo_25d.tscn")
func _ready():
# Give Godot a chance to fully load the scene. Should take two frames.
await get_tree().process_frame
await get_tree().process_frame
var edited_scene_root = get_tree().edited_scene_root
if not edited_scene_root:
# Godot hasn't finished loading yet, so try loading the plugin again.
editor_interface.set_plugin_enabled("node25d", false)
editor_interface.set_plugin_enabled("node25d", true)
return
# Alright, we're loaded up. Now check if we have a valid world and assign it.
var world_2d = edited_scene_root.get_viewport().world_2d
if world_2d == get_viewport().world_2d:
return # This is the MainScreen25D scene opened in the editor!
viewport_2d.world_2d = world_2d
func _process(delta):
if not editor_interface: # Something's not right... bail!
return
# View mode polling.
var view_mode_changed_this_frame = false
var new_view_mode = view_mode_button_group.get_pressed_button().get_index()
if view_mode_index != new_view_mode:
view_mode_index = new_view_mode
view_mode_changed_this_frame = true
_recursive_change_view_mode(get_tree().edited_scene_root)
# Zooming.
if Input.is_mouse_button_pressed(MOUSE_BUTTON_WHEEL_UP):
zoom_level += 1
elif Input.is_mouse_button_pressed(MOUSE_BUTTON_WHEEL_DOWN):
zoom_level -= 1
var zoom = _get_zoom_amount()
# SubViewport size.
var size = get_global_rect().size
viewport_2d.size = size
# SubViewport transform.
var viewport_trans = Transform2D.IDENTITY
viewport_trans.x *= zoom
viewport_trans.y *= zoom
viewport_trans.origin = viewport_trans.basis_xform(viewport_center) + size / 2
viewport_2d.canvas_transform = viewport_trans
viewport_overlay.canvas_transform = viewport_trans
# Delete unused gizmos.
var selection = editor_interface.get_selection().get_selected_nodes()
var overlay_children = viewport_overlay.get_children()
for overlay_child in overlay_children:
var contains = false
for selected in selection:
if selected == overlay_child.get("node25d") and not view_mode_changed_this_frame:
contains = true
if not contains:
overlay_child.queue_free()
# Add new gizmos.
for selected in selection:
if selected.has_method("Node25DReady"):
var new = true
for overlay_child in overlay_children:
if selected == overlay_child.get("node25d"):
new = false
if new:
var gizmo = gizmo_25d_scene.instantiate()
viewport_overlay.add_child(gizmo)
gizmo.set("node25d", selected)
gizmo.call("Initialize")
# This only accepts input when the mouse is inside of the 2.5D viewport.
func _gui_input(event):
if event is InputEventMouseButton:
if event.is_pressed():
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
zoom_level += 1
accept_event()
elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
zoom_level -= 1
accept_event()
elif event.button_index == MOUSE_BUTTON_MIDDLE:
is_panning = true
pan_center = viewport_center - event.position
accept_event()
elif event.button_index == MOUSE_BUTTON_LEFT:
var overlay_children = viewport_overlay.get_children()
for overlay_child in overlay_children:
overlay_child.set("wantsToMove", true)
accept_event()
elif event.button_index == MOUSE_BUTTON_MIDDLE:
is_panning = false
accept_event()
elif event.button_index == MOUSE_BUTTON_LEFT:
var overlay_children = viewport_overlay.get_children()
for overlay_child in overlay_children:
overlay_child.set("wantsToMove", false)
accept_event()
elif event is InputEventMouseMotion:
if is_panning:
viewport_center = pan_center + event.position
accept_event()
func _recursive_change_view_mode(current_node):
if current_node.has_method("set_view_mode"):
current_node.set_view_mode(view_mode_index) # GDScript.
if current_node.has_method("SetViewMode"):
current_node.call("SetViewMode", view_mode_index) # C#.
for child in current_node.get_children():
_recursive_change_view_mode(child)
func _get_zoom_amount():
var zoom_amount = pow(1.05476607648, zoom_level) # 13th root of 2.
zoom_label.text = str(round(zoom_amount * 1000) / 10) + "%"
return zoom_amount
func _on_ZoomOut_pressed():
zoom_level -= 1
func _on_ZoomIn_pressed():
zoom_level += 1
func _on_ZoomReset_pressed():
zoom_level = 0