@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