viewport_25d.gd 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. @tool
  2. extends Control
  3. var zoom_level := 0
  4. var is_panning = false
  5. var pan_center: Vector2
  6. var viewport_center: Vector2
  7. var view_mode_index := 0
  8. var editor_interface: EditorInterface # Set in node25d_plugin.gd
  9. var moving = false
  10. @onready var viewport_2d = $Viewport2D
  11. @onready var viewport_overlay = $ViewportOverlay
  12. @onready var view_mode_button_group: ButtonGroup = $"../TopBar/ViewModeButtons/45Degree".group
  13. @onready var zoom_label: Label = $"../TopBar/Zoom/ZoomPercent"
  14. @onready var gizmo_25d_scene = preload("res://addons/node25d-cs/main_screen/gizmo_25d.tscn")
  15. func _ready():
  16. # Give Godot a chance to fully load the scene. Should take two frames.
  17. await get_tree().process_frame
  18. await get_tree().process_frame
  19. var edited_scene_root = get_tree().edited_scene_root
  20. if not edited_scene_root:
  21. # Godot hasn't finished loading yet, so try loading the plugin again.
  22. editor_interface.set_plugin_enabled("node25d", false)
  23. editor_interface.set_plugin_enabled("node25d", true)
  24. return
  25. # Alright, we're loaded up. Now check if we have a valid world and assign it.
  26. var world_2d = edited_scene_root.get_viewport().world_2d
  27. if world_2d == get_viewport().world_2d:
  28. return # This is the MainScreen25D scene opened in the editor!
  29. viewport_2d.world_2d = world_2d
  30. func _process(delta):
  31. if not editor_interface: # Something's not right... bail!
  32. return
  33. # View mode polling.
  34. var view_mode_changed_this_frame = false
  35. var new_view_mode = view_mode_button_group.get_pressed_button().get_index()
  36. if view_mode_index != new_view_mode:
  37. view_mode_index = new_view_mode
  38. view_mode_changed_this_frame = true
  39. _recursive_change_view_mode(get_tree().edited_scene_root)
  40. # Zooming.
  41. if Input.is_mouse_button_pressed(MOUSE_BUTTON_WHEEL_UP):
  42. zoom_level += 1
  43. elif Input.is_mouse_button_pressed(MOUSE_BUTTON_WHEEL_DOWN):
  44. zoom_level -= 1
  45. var zoom = _get_zoom_amount()
  46. # SubViewport size.
  47. var size = get_global_rect().size
  48. viewport_2d.size = size
  49. # SubViewport transform.
  50. var viewport_trans = Transform2D.IDENTITY
  51. viewport_trans.x *= zoom
  52. viewport_trans.y *= zoom
  53. viewport_trans.origin = viewport_trans.basis_xform(viewport_center) + size / 2
  54. viewport_2d.canvas_transform = viewport_trans
  55. viewport_overlay.canvas_transform = viewport_trans
  56. # Delete unused gizmos.
  57. var selection = editor_interface.get_selection().get_selected_nodes()
  58. var overlay_children = viewport_overlay.get_children()
  59. for overlay_child in overlay_children:
  60. var contains = false
  61. for selected in selection:
  62. if selected == overlay_child.get("node25d") and not view_mode_changed_this_frame:
  63. contains = true
  64. if not contains:
  65. overlay_child.queue_free()
  66. # Add new gizmos.
  67. for selected in selection:
  68. if selected.has_method("Node25DReady"):
  69. var new = true
  70. for overlay_child in overlay_children:
  71. if selected == overlay_child.get("node25d"):
  72. new = false
  73. if new:
  74. var gizmo = gizmo_25d_scene.instantiate()
  75. viewport_overlay.add_child(gizmo)
  76. gizmo.set("node25d", selected)
  77. gizmo.call("Initialize")
  78. # This only accepts input when the mouse is inside of the 2.5D viewport.
  79. func _gui_input(event):
  80. if event is InputEventMouseButton:
  81. if event.is_pressed():
  82. if event.button_index == MOUSE_BUTTON_WHEEL_UP:
  83. zoom_level += 1
  84. accept_event()
  85. elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
  86. zoom_level -= 1
  87. accept_event()
  88. elif event.button_index == MOUSE_BUTTON_MIDDLE:
  89. is_panning = true
  90. pan_center = viewport_center - event.position
  91. accept_event()
  92. elif event.button_index == MOUSE_BUTTON_LEFT:
  93. var overlay_children = viewport_overlay.get_children()
  94. for overlay_child in overlay_children:
  95. overlay_child.set("wantsToMove", true)
  96. accept_event()
  97. elif event.button_index == MOUSE_BUTTON_MIDDLE:
  98. is_panning = false
  99. accept_event()
  100. elif event.button_index == MOUSE_BUTTON_LEFT:
  101. var overlay_children = viewport_overlay.get_children()
  102. for overlay_child in overlay_children:
  103. overlay_child.set("wantsToMove", false)
  104. accept_event()
  105. elif event is InputEventMouseMotion:
  106. if is_panning:
  107. viewport_center = pan_center + event.position
  108. accept_event()
  109. func _recursive_change_view_mode(current_node):
  110. if current_node.has_method("set_view_mode"):
  111. current_node.set_view_mode(view_mode_index) # GDScript.
  112. if current_node.has_method("SetViewMode"):
  113. current_node.call("SetViewMode", view_mode_index) # C#.
  114. for child in current_node.get_children():
  115. _recursive_change_view_mode(child)
  116. func _get_zoom_amount():
  117. var zoom_amount = pow(1.05476607648, zoom_level) # 13th root of 2.
  118. zoom_label.text = str(round(zoom_amount * 1000) / 10) + "%"
  119. return zoom_amount
  120. func _on_ZoomOut_pressed():
  121. zoom_level -= 1
  122. func _on_ZoomIn_pressed():
  123. zoom_level += 1
  124. func _on_ZoomReset_pressed():
  125. zoom_level = 0