private void DrawGizmo(EditorPanel sender) { if (ready) { ImGuizmo.SetOrthographic(_viewportPanel.ProjectioMode == ViewportPanel.ViewMode.Orthographic); _viewportPanel.EnableSelect = !ImGuizmo.IsOver(); ImGuizmo.SetRect(_viewportPanel.WindowContentAreaMin.X, _viewportPanel.WindowContentAreaMin.Y, _viewportPanel.WindowContentAreaMax.X - _viewportPanel.WindowContentAreaMin.X, _viewportPanel.WindowContentAreaMax.Y - _viewportPanel.WindowContentAreaMin.Y); //ref *(float*)(void*)null ImGuizmo.SetDrawlist(); if (ImGuizmo.Manipulate(ref cameraView.M11, ref cameraProjection.M11, currentGizmoOperation, (currentGizmoOperation != OPERATION.SCALE) ? currentGizmoMode : MODE.LOCAL, ref transformMat.M11)) { // safety feature if (!Matrix4x4Extension.HasNaNElement(transformMat)) { Context.ActiveEntity.Transform.SetWorldTransform(transformMat); } } } }
public override void OnGUI() { ImGui.Begin("Viewport"); if (ECSScene.Camera == null) { ImGui.Text("Camera missing."); ImGui.End(); } var l = ImGui.GetWindowContentRegionMin(); var h = ImGui.GetWindowContentRegionMax(); var size = h - l; ECSScene.RenderTexture.Size = size; ImGui.Image(new IntPtr(ECSScene.RenderTexture.ResolveTex), size, new(0, 1), new(1, 0)); // This renders the texture technically upside-down how OpenGL sees it // but since OpenGL textures are already upside-down it's uno reverse carding opengl's flip and it's normal now var wp = ImGui.GetWindowPos(); ImGuizmo.Enable(ImGui.IsMouseHoveringRect(wp, wp + size)); // Gizmos var dl = ImGui.GetForegroundDrawList(); ImGuizmo.SetOrthographic(false); var cr = ImGui.GetWindowContentRegionMax(); ImGuizmo.SetRect(wp.X, wp.Y, cr.X, cr.Y); ImGuizmo.SetDrawlist(dl); if (Editor.SelectedObject != null && Editor.ObjectSelected) { var v = ECSScene.Camera.View(); var p = ECSScene.Camera.Projection(); var a = Editor.SelectedObject.ModelMatrix; var op = Toolbar.ActiveMode switch { MovementMode.Translate => OPERATION.TRANSLATE, MovementMode.Rotate => OPERATION.ROTATE, _ => OPERATION.TRANSLATE }; var m = ImGuizmo.Manipulate(ref v.Row0.X, ref p.Row0.X, op, MODE.LOCAL, ref a.Row0.X); if (m) { Editor.SelectedObject.ModelMatrix = a; } } ImGui.End(); } }
public void ProcessGizmos() { var selected = _guiService.SelectedEntity; if (selected != default && selected.Has <TransformComponent>()) { foreach (var camera in _cameras) { ref var cam = ref _cameras.Get1(camera); if (cam.Camera.Active && _guiService.GizmoType.HasValue) { if (duplicated && (!InputManager.Instance.GetKeyDown(KeyCodes.AltLeft) || InputManager.Instance.GetMouseButtonUp(MouseButtonCodes.Left))) { duplicated = false; } ImGuizmo.SetID(camera); ImGuizmo.SetOrthographic(cam.Camera.ProjectionType == BootEngine.Renderer.Cameras.ProjectionType.Orthographic); ImGuizmo.SetDrawlist(ImGui.GetWindowDrawList()); float windowWidth = ImGui.GetWindowWidth(); float windowHeight = ImGui.GetWindowHeight(); ImGuizmo.SetRect(ImGui.GetWindowPos().X, ImGui.GetWindowPos().Y, windowWidth, windowHeight); bool snap = InputManager.Instance.GetKeyDown(KeyCodes.LControl); float snapValue = .1f; if (_guiService.GizmoType == OPERATION.ROTATE) { snapValue = 45f; } float[] snapValues = new float[] { snapValue, snapValue, snapValue }; ref var tc = ref selected.Get <TransformComponent>(); var rotTmp = MathUtil.Rad2Deg(tc.Rotation); float[] pos = new float[] { tc.Translation.X, tc.Translation.Y, tc.Translation.Z }; float[] rot = new float[] { rotTmp.X, rotTmp.Y, rotTmp.Z }; float[] sca = new float[] { tc.Scale.X, tc.Scale.Y, tc.Scale.Z }; float[] transform = new float[16]; ImGuizmo.RecomposeMatrixFromComponents(ref pos[0], ref rot[0], ref sca[0], ref transform[0]); // using the component's transform breaks guizmos for some reason // TODO: investigate //transform = tc.Transform.ToFloatArray(); ref var cameraTc = ref _cameras.Get2(camera); Matrix4x4.Invert(cameraTc.Transform, out Matrix4x4 cameraViewMat); float[] cameraView = cameraViewMat.ToFloatArray(); float[] cameraProj; if (cam.Camera.SwapYAxis) { // de-swapping Y axis for gizmo rendering cameraProj = (cam.Camera.ProjectionMatrix * new Matrix4x4( 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)).ToFloatArray(); } else { cameraProj = cam.Camera.ProjectionMatrix.ToFloatArray(); } float[] deltaTransform = new float[16]; if (snap) { ImGuizmo.Manipulate(ref cameraView[0], ref cameraProj[0], _guiService.GizmoType.Value, MODE.LOCAL, ref transform[0], ref deltaTransform[0], ref snapValues[0]); } else { ImGuizmo.Manipulate(ref cameraView[0], ref cameraProj[0], _guiService.GizmoType.Value, MODE.LOCAL, ref transform[0], ref deltaTransform[0]); } if (ImGuizmo.IsOver() && ImGuizmo.IsUsing()) { if (InputManager.Instance.GetKeyDown(KeyCodes.AltLeft) && !duplicated) { // copy current entity _guiService.SelectedEntity = _guiService.SelectedEntity.Copy(); ref var tag = ref _guiService.SelectedEntity.Get <TagComponent>(); #pragma warning disable S1643 // Strings should not be concatenated using '+' in a loop tag.Tag += " (Copy)"; #pragma warning restore S1643 // Strings should not be concatenated using '+' in a loop duplicated = true; } float[] translation = new float[3]; float[] rotation = new float[3]; float[] scale = new float[3]; switch (_guiService.GizmoType) { case OPERATION.TRANSLATE: ImGuizmo.DecomposeMatrixToComponents(ref deltaTransform[0], ref translation[0], ref rotation[0], ref scale[0]); tc.Translation += new Vector3(translation[0], translation[1], translation[2]); break; case OPERATION.ROTATE: ImGuizmo.DecomposeMatrixToComponents(ref deltaTransform[0], ref translation[0], ref rotation[0], ref scale[0]); tc.Rotation -= MathUtil.Deg2Rad(new Vector3(rotation[0], rotation[1], rotation[2])); break; case OPERATION.SCALE: // for some reason, scale part from deltaTransform does not return deltaScale ImGuizmo.DecomposeMatrixToComponents(ref transform[0], ref translation[0], ref rotation[0], ref scale[0]); tc.Scale = new Vector3(scale[0], scale[1], scale[2]); break; } }
private void OnImGui() { //dockspace ImGui.DockSpaceOverViewport(); if (ImGui.BeginMainMenuBar()) { pc.DrawFileMenu(); ImGui.EndMainMenuBar(); } ImGui.PushStyleVar(ImGuiStyleVar.WindowMinSize, new System.Numerics.Vector2(160f, 90f)); if (ImGui.Begin("Viewport")) { cm.Focus = ImGui.IsWindowFocused(); var cPos = ImGui.GetCursorScreenPos(); var vSize = ImGui.GetContentRegionAvail(); Renderer.ViewportSize = new Vector2i((int)vSize.X, (int)vSize.Y); //display framebuffer texture on window ImGui.GetWindowDrawList().AddImage( (IntPtr)Renderer.FramebufferTexture, cPos, cPos + vSize, new System.Numerics.Vector2(0f, 1f), new System.Numerics.Vector2(1f, 0f)); //gizmos ImGui.PushClipRect(cPos, cPos + vSize, false); if (SceneHierachy.SelectedEntity != null) { var entity = SceneHierachy.SelectedEntity; ImGuizmo.SetOrthographic(false); ImGuizmo.SetDrawlist(); ImGuizmo.SetRect(cPos.X, cPos.Y, vSize.X, vSize.Y); Camera.Main.CalculateViewProjection(out var view, out var projection); var transform = entity.Transform.GlobalTransform; ImGuizmo.Manipulate(ref view.Row0.X, ref projection.Row0.X, operation, MODE.LOCAL, ref transform.Row0.X); if (ImGuizmo.IsUsing()) { var parentGlobal = entity.Parent != null ? entity.Parent.Transform.GlobalTransform : Matrix4.Identity; var local = transform * parentGlobal.Inverted(); entity.Transform.Position = local.ExtractTranslation(); entity.Transform.Rotation = local.ExtractRotation(); entity.Transform.Scale = local.ExtractScale(); } } ImGui.SetCursorScreenPos(cPos + new System.Numerics.Vector2(4f)); ImGui.SetNextItemWidth(240f); if (ImGui.BeginCombo("Gizmo", operation == OPERATION.TRANSLATE ? "Translate" : (operation == OPERATION.ROTATE ? "Rotate" : "Scale"))) { if (ImGui.Selectable("Translate", operation == OPERATION.TRANSLATE)) { operation = OPERATION.TRANSLATE; } if (ImGui.Selectable("Rotate", operation == OPERATION.ROTATE)) { operation = OPERATION.ROTATE; } if (ImGui.Selectable("Scale", operation == OPERATION.SCALE)) { operation = OPERATION.SCALE; } } ImGui.PopClipRect(); //mouse select with raycast if (ImGui.IsWindowHovered() && ImGui.IsWindowFocused() && ImGui.IsMouseClicked(ImGuiMouseButton.Left) && !ImGuizmo.IsUsing()) { Ray ray; ray.Origin = Camera.Main.BaseTransform.GlobalTransform.ExtractTranslation(); //get cam position var mPos = (ImGui.GetMousePos() - cPos) / vSize; //get mouse pos in [0, 1] Vector2 mousePos = new Vector2(mPos.X, mPos.Y) * new Vector2(2f) - new Vector2(1f); //convert to [-1, 1] Camera.Main.CalculateViewProjection(out var view, out var proj); //get view and proj Vector4 unprojected = new Vector4(mousePos.X, -mousePos.Y, 1f, 1f) * Matrix4.Invert(view * proj); //what the f**k? ray.Direction = Vector3.Normalize(unprojected.Xyz); MouseSelect(ray); } ImGui.End(); } ImGui.PopStyleVar(); if (ImGui.Begin("Debug")) { ImGui.Text($"Frametime: {MathF.Floor(Time.UnscaledDeltaTime * 100000f) / 100f}ms"); ImGui.Text($"Framerate: {MathF.Floor(1f / Time.UnscaledDeltaTime)}"); #if DEBUG ImGui.DragFloat("Exposure", ref ((ForwardRenderer)Engine.Renderer).Exposure, 0.1f); #endif ImGui.End(); } }