Example #1
0
        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;
                            }
                        }
Example #2
0
        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();
            }
        }