Viewport25D.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. using Godot;
  2. // This is identical to the GDScript version, yet it doesn't work.
  3. [Tool]
  4. public partial class Viewport25D : Control
  5. {
  6. private int zoomLevel = 0;
  7. private bool isPanning = false;
  8. private Vector2 panCenter;
  9. private Vector2 viewportCenter;
  10. private int viewModeIndex = 0;
  11. // The type or namespace name 'EditorInterface' could not be found (are you missing a using directive or an assembly reference?)
  12. // No idea why this error shows up in VS Code. It builds fine...
  13. public EditorInterface editorInterface; // Set in node25d_plugin.gd
  14. private bool moving = false;
  15. private SubViewport viewport2d;
  16. private SubViewport viewportOverlay;
  17. private ButtonGroup viewModeButtonGroup;
  18. private Label zoomLabel;
  19. private PackedScene gizmo25dScene;
  20. public async override void _Ready()
  21. {
  22. // Give Godot a chance to fully load the scene. Should take two frames.
  23. await ToSignal(GetTree(), "idle_frame");
  24. await ToSignal(GetTree(), "idle_frame");
  25. var editedSceneRoot = GetTree().EditedSceneRoot;
  26. if (editedSceneRoot == null)
  27. {
  28. // Godot hasn't finished loading yet, so try loading the plugin again.
  29. //editorInterface.SetPluginEnabled("node25d", false);
  30. //editorInterface.SetPluginEnabled("node25d", true);
  31. return;
  32. }
  33. // Alright, we're loaded up. Now check if we have a valid world and assign it.
  34. var world2d = editedSceneRoot.GetViewport().World2d;
  35. if (world2d == GetViewport().World2d)
  36. {
  37. return; // This is the MainScreen25D scene opened in the editor!
  38. }
  39. viewport2d.World2d = world2d;
  40. // Onready vars.
  41. viewport2d = GetNode<SubViewport>("Viewport2D");
  42. viewportOverlay = GetNode<SubViewport>("ViewportOverlay");
  43. viewModeButtonGroup = GetParent().GetNode("TopBar").GetNode("ViewModeButtons").GetNode<Button>("45Degree").Group;
  44. zoomLabel = GetParent().GetNode("TopBar").GetNode("Zoom").GetNode<Label>("ZoomPercent");
  45. gizmo25dScene = ResourceLoader.Load<PackedScene>("res://addons/node25d/main_screen/gizmo_25d.tscn");
  46. }
  47. public override void _Process(float delta)
  48. {
  49. if (editorInterface == null) // Something's not right... bail!
  50. {
  51. return;
  52. }
  53. // View mode polling.
  54. var viewModeChangedThisFrame = false;
  55. var newViewMode = viewModeButtonGroup.GetPressedButton().GetIndex();
  56. if (viewModeIndex != newViewMode)
  57. {
  58. viewModeIndex = newViewMode;
  59. viewModeChangedThisFrame = true;
  60. RecursiveChangeViewMode(GetTree().EditedSceneRoot);
  61. }
  62. // Zooming.
  63. if (Input.IsMouseButtonPressed((int)MouseButton.WheelUp))
  64. {
  65. zoomLevel += 1;
  66. }
  67. else if (Input.IsMouseButtonPressed((int)MouseButton.WheelDown))
  68. {
  69. zoomLevel -= 1;
  70. }
  71. float zoom = GetZoomAmount();
  72. // SubViewport size.
  73. Vector2 size = GetGlobalRect().Size;
  74. viewport2d.Size = size;
  75. // SubViewport transform.
  76. Transform2D viewportTrans = Transform2D.Identity;
  77. viewportTrans.x *= zoom;
  78. viewportTrans.y *= zoom;
  79. viewportTrans.origin = viewportTrans.BasisXform(viewportCenter) + size / 2;
  80. viewport2d.CanvasTransform = viewportTrans;
  81. viewportOverlay.CanvasTransform = viewportTrans;
  82. // Delete unused gizmos.
  83. var selection = editorInterface.GetSelection().GetSelectedNodes();
  84. var overlayChildren = viewportOverlay.GetChildren();
  85. foreach (Gizmo25D overlayChild in overlayChildren)
  86. {
  87. bool contains = false;
  88. foreach (Node selected in selection)
  89. {
  90. if (selected == overlayChild.node25d && !viewModeChangedThisFrame)
  91. {
  92. contains = true;
  93. }
  94. }
  95. if (!contains)
  96. {
  97. overlayChild.QueueFree();
  98. }
  99. }
  100. // Add new gizmos.
  101. foreach (Node sel in selection)
  102. {
  103. if (sel is Node25D selected)
  104. {
  105. var newNode = true;
  106. foreach (Gizmo25D overlayChild2 in overlayChildren)
  107. {
  108. if (selected == overlayChild2.node25d)
  109. {
  110. newNode = false;
  111. }
  112. }
  113. if (newNode)
  114. {
  115. Gizmo25D gizmo = (Gizmo25D)gizmo25dScene.Instantiate();
  116. viewportOverlay.AddChild(gizmo);
  117. gizmo.node25d = selected;
  118. gizmo.Initialize();
  119. }
  120. }
  121. }
  122. }
  123. // This only accepts input when the mouse is inside of the 2.5D viewport.
  124. public override void _GuiInput(InputEvent inputEvent)
  125. {
  126. if (inputEvent is InputEventMouseButton mouseButtonEvent)
  127. {
  128. if (mouseButtonEvent.IsPressed())
  129. {
  130. if ((MouseButton)mouseButtonEvent.ButtonIndex == MouseButton.WheelUp)
  131. {
  132. zoomLevel += 1;
  133. AcceptEvent();
  134. }
  135. else if ((MouseButton)mouseButtonEvent.ButtonIndex == MouseButton.WheelDown)
  136. {
  137. zoomLevel -= 1;
  138. AcceptEvent();
  139. }
  140. else if ((MouseButton)mouseButtonEvent.ButtonIndex == MouseButton.Middle)
  141. {
  142. isPanning = true;
  143. panCenter = viewportCenter - mouseButtonEvent.Position;
  144. AcceptEvent();
  145. }
  146. else if ((MouseButton)mouseButtonEvent.ButtonIndex == MouseButton.Left)
  147. {
  148. var overlayChildren2 = viewportOverlay.GetChildren();
  149. foreach (Gizmo25D overlayChild in overlayChildren2)
  150. {
  151. overlayChild.wantsToMove = true;
  152. }
  153. AcceptEvent();
  154. }
  155. }
  156. else if ((MouseButton)mouseButtonEvent.ButtonIndex == MouseButton.Middle)
  157. {
  158. isPanning = false;
  159. AcceptEvent();
  160. }
  161. else if ((MouseButton)mouseButtonEvent.ButtonIndex == MouseButton.Left)
  162. {
  163. var overlayChildren3 = viewportOverlay.GetChildren();
  164. foreach (Gizmo25D overlayChild in overlayChildren3)
  165. {
  166. overlayChild.wantsToMove = false;
  167. }
  168. AcceptEvent();
  169. }
  170. }
  171. else if (inputEvent is InputEventMouseMotion mouseEvent)
  172. {
  173. if (isPanning)
  174. {
  175. viewportCenter = panCenter + mouseEvent.Position;
  176. AcceptEvent();
  177. }
  178. }
  179. }
  180. public void RecursiveChangeViewMode(Node currentNode)
  181. {
  182. // TODO
  183. if (currentNode.HasMethod("SetViewMode"))
  184. {
  185. //currentNode.SetViewMode(viewModeIndex);
  186. }
  187. foreach (Node child in currentNode.GetChildren())
  188. {
  189. RecursiveChangeViewMode(child);
  190. }
  191. }
  192. private float GetZoomAmount()
  193. {
  194. float zoomAmount = Mathf.Pow(1.05476607648f, zoomLevel); // 13th root of 2
  195. zoomLabel.Text = Mathf.Round(zoomAmount * 1000) / 10 + "%";
  196. return zoomAmount;
  197. }
  198. public void OnZoomOutPressed()
  199. {
  200. zoomLevel -= 1;
  201. }
  202. public void OnZoomInPressed()
  203. {
  204. zoomLevel += 1;
  205. }
  206. public void OnZoomResetPressed()
  207. {
  208. zoomLevel = 0;
  209. }
  210. }