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