public void Initialize(Cockpit cockpit)
        {
            cockpit.Name = "modelCockpit";


            // Configure how the cockpit moves

            cockpit.PositionMode = Cockpit.MovementMode.TrackPosition;
            // [RMS] use orientation mode to make cockpit follow view orientation.
            //  (however default widgets below are off-screen!)
            //cockpit.PositionMode = Cockpit.MovementMode.TrackOrientation;



            FScene       Scene                     = cockpit.Scene;
            BoxContainer screenContainer           = new BoxContainer(new Cockpit2DContainerProvider(cockpit));
            PinnedBoxes2DLayoutSolver screenLayout = new PinnedBoxes2DLayoutSolver(screenContainer);
            PinnedBoxesLayout         layout       = new PinnedBoxesLayout(cockpit, screenLayout)
            {
                StandardDepth = 1.5f
            };

            cockpit.AddLayout(layout, "2D", true);


            Func <string, float, HUDLabel> MakeButtonF = (label, buttonW) => {
                HUDLabel button = new HUDLabel()
                {
                    Shape             = OrthogenUI.MakeMenuButtonRect(buttonW, OrthogenUI.MenuButtonHeight),
                    TextHeight        = OrthogenUI.MenuButtonTextHeight,
                    AlignmentHorz     = HorizontalAlignment.Center,
                    BackgroundColor   = OrthogenUI.ButtonBGColor,
                    TextColor         = OrthogenUI.ButtonTextColor,
                    DisabledTextColor = OrthogenUI.DisabledButtonTextColor,
                    Text         = label,
                    EnableBorder = true, BorderWidth = OrthogenUI.StandardButtonBorderWidth, BorderColor = OrthogenUI.ButtonTextColor
                };
                button.Create();
                button.Name    = label;
                button.Enabled = true;
                return(button);
            };
            Func <string, float, float, HUDSpacer> MakeSpacerF = (label, spacerw, spacerh) => {
                HUDSpacer spacer = new HUDSpacer()
                {
                    Shape = new HUDShape(HUDShapeType.Rectangle, spacerw, spacerh)
                };
                spacer.Create();
                spacer.Name = label;
                return(spacer);
            };


            HUDElementList button_list = new HUDElementList()
            {
                Width     = OrthogenUI.MenuButtonWidth,
                Height    = 5 * OrthogenUI.MenuButtonHeight,
                Spacing   = 10 * OrthogenUI.PixelScale,
                Direction = HUDElementList.ListDirection.Vertical
            };



            HUDLabel trim_scan_button = MakeButtonF("Trim Scan", OrthogenUI.MenuButtonWidth);

            trim_scan_button.OnClicked += (sender, e) => {
                OG.Transition(OGWorkflow.TrimScanStartT);
            };
            button_list.AddListItem(trim_scan_button);

            HUDLabel align_scan_button = MakeButtonF("Align Scan", OrthogenUI.MenuButtonWidth);

            align_scan_button.OnClicked += (sender, e) => {
                OG.Transition(OGWorkflow.AlignScanStartT);
            };
            button_list.AddListItem(align_scan_button);


            HUDLabel accept_scan_button = MakeButtonF("Done Scan", OrthogenUI.MenuButtonWidth);

            accept_scan_button.OnClicked += (sender, e) => {
                OG.TransitionToState(RectifyState.Identifier);
            };
            button_list.AddListItem(accept_scan_button);



            button_list.AddListItem(MakeSpacerF("space", OrthogenUI.MenuButtonWidth, 0.5f * OrthogenUI.MenuButtonHeight));


            HUDLabel draw_offset_area_button = MakeButtonF("Offset Area", OrthogenUI.MenuButtonWidth);

            draw_offset_area_button.OnClicked += (sender, e) => {
                OGActions.CurrentLegDeformType = LegModel.LegDeformationTypes.Offset;
                OG.Transition(OGWorkflow.DrawAreaStartT);
            };
            button_list.AddListItem(draw_offset_area_button);

            HUDLabel draw_smooth_area_button = MakeButtonF("Smooth Area", OrthogenUI.MenuButtonWidth);

            draw_smooth_area_button.OnClicked += (sender, e) => {
                OGActions.CurrentLegDeformType = LegModel.LegDeformationTypes.Smooth;
                OG.Transition(OGWorkflow.DrawAreaStartT);
            };
            button_list.AddListItem(draw_smooth_area_button);


            HUDLabel add_plane_button = MakeButtonF("Add Plane", OrthogenUI.MenuButtonWidth);

            add_plane_button.OnClicked += (sender, e) => {
                OG.Transition(OGWorkflow.AddDeformRingStartT);
            };
            button_list.AddListItem(add_plane_button);

            HUDLabel add_lengthen_button = MakeButtonF("Add Lengthen", OrthogenUI.MenuButtonWidth);

            add_lengthen_button.OnClicked += (sender, e) => {
                if (OGActions.CanAddLengthenOp())
                {
                    OGActions.AddLengthenOp();
                }
            };
            button_list.AddListItem(add_lengthen_button);


            HUDLabel       sculpt_curve_button = MakeButtonF("Sculpt Curve", OrthogenUI.MenuButtonWidth);
            WorkflowRouter sculpt_router       = WorkflowRouter.Build(new[] {
                OGWorkflow.RectifyState, OGWorkflow.SculptAreaStartT,
                OGWorkflow.SocketState, OGWorkflow.SculptTrimlineStartT
            });

            sculpt_curve_button.OnClicked += (sender, e) => {
                sculpt_router.Apply(OG.Model.Workflow);
            };
            button_list.AddListItem(sculpt_curve_button);


            HUDLabel accept_rectify_button = MakeButtonF("Begin Socket", OrthogenUI.MenuButtonWidth);

            accept_rectify_button.OnClicked += (sender, e) => {
                OG.Leg.SetOpWidgetVisibility(false);
                OG.TransitionToState(SocketDesignState.Identifier);
            };
            button_list.AddListItem(accept_rectify_button);



            button_list.AddListItem(MakeSpacerF("space", OrthogenUI.MenuButtonWidth, 0.5f * OrthogenUI.MenuButtonHeight));



            HUDLabel draw_trim_line_button = MakeButtonF("Draw Trimline", OrthogenUI.MenuButtonWidth);

            draw_trim_line_button.OnClicked += (sender, e) => {
                OG.Transition(OGWorkflow.DrawTrimlineStartT);
            };
            button_list.AddListItem(draw_trim_line_button);

            HUDLabel plane_trim_line_button = MakeButtonF("Plane Trimline", OrthogenUI.MenuButtonWidth);

            plane_trim_line_button.OnClicked += (sender, e) => {
                OG.Transition(OGWorkflow.PlaneTrimlineStartT);
            };
            button_list.AddListItem(plane_trim_line_button);

            HUDLabel add_socket_button = MakeButtonF("Add Socket", OrthogenUI.MenuButtonWidth);

            add_socket_button.OnClicked += (sender, e) => {
                if (OGActions.CanAddSocket())
                {
                    OGActions.AddSocket();
                }
            };
            button_list.AddListItem(add_socket_button);

            HUDLabel export_socket_button = MakeButtonF("Export", OrthogenUI.MenuButtonWidth);

            export_socket_button.OnClicked += (sender, e) => {
                if (OGActions.CanExportSocket())
                {
                    OGActions.ExportSocket();
                }
            };
            button_list.AddListItem(export_socket_button);



            button_list.AddListItem(MakeSpacerF("space", OrthogenUI.MenuButtonWidth, 1.0f * OrthogenUI.MenuButtonHeight));


            HUDLabel accept_button = MakeButtonF("Accept", OrthogenUI.MenuButtonWidth);

            accept_button.OnClicked += (sender, e) => {
                OGActions.AcceptCurrentTool();
            };


            HUDLabel cancel_button = MakeButtonF("Cancel", OrthogenUI.MenuButtonWidth);

            cancel_button.OnClicked += (sender, e) => {
                OGActions.CancelCurrentTool();
            };
            button_list.AddListItem(accept_button);
            button_list.AddListItem(cancel_button);



            button_list.Create();
            button_list.Name = "button_bar";

            // align button list to center of timeline
            layout.Add(button_list, new LayoutOptions()
            {
                Flags            = LayoutFlags.None,
                PinSourcePoint2D = LayoutUtil.BoxPointF(button_list, BoxPosition.TopLeft),
                PinTargetPoint2D = LayoutUtil.BoxPointF(screenContainer, BoxPosition.TopLeft, 10 * OrthogenUI.PixelScale * (Vector2f.AxisX - Vector2f.AxisY))
            });

            screenLayout.RecomputeLayout();



            // Configure interaction behaviors
            //   - below we add behaviors for mouse, gamepad, and spatial devices (oculus touch, etc)
            //   - keep in mind that Tool objects will register their own behaviors when active

            // setup key handlers (need to move to behavior...)
            cockpit.AddKeyHandler(new OrthoGenKeyHandler(cockpit.Context));

            // these behaviors let us interact with UIElements (ie left-click/trigger, or either triggers for Touch)
            cockpit.InputBehaviors.Add(new Mouse2DCockpitUIBehavior(cockpit.Context)
            {
                Priority = 0
            });
            cockpit.InputBehaviors.Add(new VRMouseUIBehavior(cockpit.Context)
            {
                Priority = 1
            });

            // selection / multi-selection behaviors
            // Note: this custom behavior implements some selection redirects that we use in various parts of Archform
            cockpit.InputBehaviors.Add(new MouseMultiSelectBehavior(cockpit.Context)
            {
                Priority = 10
            });

            // left click-drag to tumble, and left click-release to de-select
            cockpit.InputBehaviors.Add(new MouseClickDragSuperBehavior()
            {
                Priority     = 100,
                DragBehavior = new MouseViewRotateBehavior(cockpit.Context)
                {
                    Priority = 100, RotateSpeed = 3.0f
                },
                ClickBehavior = new MouseDeselectBehavior(cockpit.Context)
                {
                    Priority = 999
                }
            });

            // also right-click-drag to tumble
            cockpit.InputBehaviors.Add(new MouseViewRotateBehavior(cockpit.Context)
            {
                Priority  = 100, RotateSpeed = 3.0f,
                ActivateF = MouseBehaviors.RightButtonPressedF, ContinueF = MouseBehaviors.RightButtonDownF
            });

            // middle-click-drag to pan
            cockpit.InputBehaviors.Add(new MouseViewPanBehavior(cockpit.Context)
            {
                Priority  = 100, PanSpeed = 10.0f,
                ActivateF = MouseBehaviors.MiddleButtonPressedF, ContinueF = MouseBehaviors.MiddleButtonDownF
            });


            cockpit.OverrideBehaviors.Add(new MouseWheelZoomBehavior(cockpit)
            {
                Priority = 100, ZoomScale = 100.0f
            });

            // touch input
            cockpit.InputBehaviors.Add(new TouchUIBehavior(cockpit.Context)
            {
                Priority = 1
            });
            cockpit.InputBehaviors.Add(new Touch2DCockpitUIBehavior(cockpit.Context)
            {
                Priority = 0
            });
            cockpit.InputBehaviors.Add(new TouchViewManipBehavior(cockpit.Context)
            {
                Priority = 999, TouchZoomSpeed = 1.0f, TouchPanSpeed = 0.3f
            });


            // update buttons enable/disable on state transitions, selection changes
            Action updateStateChangeButtons = () => {
                trim_scan_button.Enabled   = OG.CanTransition(OGWorkflow.TrimScanStartT);
                align_scan_button.Enabled  = OG.CanTransition(OGWorkflow.AlignScanStartT);
                accept_scan_button.Enabled =
                    OG.IsInState(ScanState.Identifier) && OG.CanTransitionToState(RectifyState.Identifier);

                draw_offset_area_button.Enabled = OG.CanTransition(OGWorkflow.DrawAreaStartT);
                draw_smooth_area_button.Enabled = OG.CanTransition(OGWorkflow.DrawAreaStartT);
                add_plane_button.Enabled        = OG.CanTransition(OGWorkflow.AddDeformRingStartT);
                add_lengthen_button.Enabled     = OGActions.CanAddLengthenOp();
                accept_rectify_button.Enabled   = OG.IsInState(RectifyState.Identifier) &&
                                                  OG.CanTransitionToState(SocketDesignState.Identifier);

                draw_trim_line_button.Enabled  = OG.CanTransition(OGWorkflow.DrawTrimlineStartT);
                plane_trim_line_button.Enabled = OG.CanTransition(OGWorkflow.PlaneTrimlineStartT);
                add_socket_button.Enabled      = OGActions.CanAddSocket();
                export_socket_button.Enabled   = OGActions.CanExportSocket();

                sculpt_curve_button.Enabled = sculpt_router.CanApply(OG.Model.Workflow);
            };

            OG.OnWorfklowInitialized            += (o, e) => { updateStateChangeButtons(); };
            OG.OnStateTransition                += (from, to) => { updateStateChangeButtons(); };
            OG.OnDataModelModified              += (from, to) => { updateStateChangeButtons(); };
            cockpit.Scene.SelectionChangedEvent += (o, e) => { if (OG.WorkflowInitialized)
                                                               {
                                                                   updateStateChangeButtons();
                                                               }
            };
            cockpit.Scene.ChangedEvent += (scene, so, type) => { if (OG.WorkflowInitialized)
                                                                 {
                                                                     updateStateChangeButtons();
                                                                 }
            };

            // accept/cancel buttons need to be checked every frame because the CanApply state
            // could change at any time, and there is no event about it
            cockpit.Context.RegisterEveryFrameAction("update_buttons", () => {
                if (cockpit.Context.ToolManager.ActiveRightTool != null)
                {
                    cancel_button.Enabled = true;
                    accept_button.Enabled = cockpit.Context.ToolManager.ActiveRightTool.CanApply;
                }
                else
                {
                    cancel_button.Enabled = accept_button.Enabled = false;
                }

                // [RMS] currently this state changes outside workflow state changes...
                add_socket_button.Enabled = OGActions.CanAddSocket();
            });
        }
Beispiel #2
0
    public void Initialize(Cockpit cockpit)
    {
        cockpit.Name = "sampleCockpit";

        // Configure how the cockpit moves
        cockpit.PositionMode = Cockpit.MovementMode.TrackPosition;


        // initialize layout
        BoxContainer screenContainer           = new BoxContainer(new Cockpit2DContainerProvider(cockpit));
        PinnedBoxes2DLayoutSolver screenLayout = new PinnedBoxes2DLayoutSolver(screenContainer);
        PinnedBoxesLayout         layout       = new PinnedBoxesLayout(cockpit, screenLayout)
        {
            StandardDepth = 1.0f
        };

        cockpit.AddLayout(layout, "2D", true);



        float pixelScale = cockpit.GetPixelScale();
        float buttonDiam = 150 * pixelScale;

        HUDElementList primitives_list = new HUDElementList()
        {
            Width     = 5 * buttonDiam,
            Height    = buttonDiam,
            Spacing   = 25 * pixelScale,
            Direction = HUDElementList.ListDirection.Horizontal
        };


        // Add some UI elements to the cockpit
        //   - cylinder & box buttons - double-click or drag/drop into scene
        //   - button to start and cancel draw-primitives tool

        Color    bgColor    = new Color(0.7f, 0.7f, 1.0f, 0.7f);
        Material bgMaterial = (bgColor.a == 1.0f) ?
                              MaterialUtil.CreateStandardMaterial(bgColor) : MaterialUtil.CreateTransparentMaterial(bgColor);
        Material primMaterial = MaterialUtil.CreateStandardMaterial(Color.yellow);

        DropPrimitiveButton cylinderButton =
            create_primitive_button(cockpit, "create_cylinder", buttonDiam / 2,
                                    PrimitiveType.Cylinder, SOTypes.Cylinder, 0.7f, bgMaterial, primMaterial,
                                    () => { return(new CylinderSO().Create(cockpit.Scene.DefaultSOMaterial)); });

        primitives_list.AddListItem(cylinderButton);

        DropPrimitiveButton boxButton =
            create_primitive_button(cockpit, "create_box", buttonDiam / 2,
                                    PrimitiveType.Cube, SOTypes.Box, 0.8f, bgMaterial, primMaterial,
                                    () => { return(new BoxSO().Create(cockpit.Scene.DefaultSOMaterial)); });

        primitives_list.AddListItem(boxButton);


        primitives_list.Create();
        primitives_list.Name = "button_bar";

        // align primitives_list to bottom-left
        layout.Add(primitives_list, new LayoutOptions()
        {
            Flags            = LayoutFlags.None,
            PinSourcePoint2D = LayoutUtil.BoxPointF(primitives_list, BoxPosition.BottomLeft),
            PinTargetPoint2D = LayoutUtil.BoxPointF(screenContainer, BoxPosition.BottomLeft, 25 * pixelScale * Vector2f.One)
        });


        //float fToolsX = 35.0f;
        //float fToolButtonRadius = 0.08f;

        // buttons for draw-primitive tool and cancel-tool button

        //ActivateToolButton drawPrimButton = add_tool_button(cockpit, DrawPrimitivesTool.Identifier, fHUDRadius,
        //    fToolsX - fButtonsSpacing, fButtonsY, fToolButtonRadius, bgMaterial, primMaterial,
        //    new toolInfo() { identifier = DrawPrimitivesTool.Identifier, sMeshPath = "draw_primitive", fMeshScaleFudge = 1.2f });
        //cockpit.AddUIElement(drawPrimButton);

        //ActivateToolButton cancelButton = add_tool_button(cockpit, "cancel", fHUDRadius,
        //    fToolsX, fButtonsY, fToolButtonRadius, bgMaterial, primMaterial,
        //    new toolInfo() { identifier = "cancel", sMeshPath = "cancel", fMeshScaleFudge = 1.2f });
        //cockpit.AddUIElement(cancelButton);



        // Configure interaction behaviors
        //   - below we add behaviors for mouse, gamepad, and spatial devices (oculus touch, etc)
        //   - keep in mind that Tool objects will register their own behaviors when active

        // setup key handlers (need to move to behavior...)
        cockpit.AddKeyHandler(new BasicShapesDemo_KeyHandler(cockpit.Context));

        // these behaviors let us interact with UIElements (ie left-click/trigger, or either triggers for Touch)
        cockpit.InputBehaviors.Add(new Mouse2DCockpitUIBehavior(cockpit.Context)
        {
            Priority = 0
        });
        cockpit.InputBehaviors.Add(new VRMouseUIBehavior(cockpit.Context)
        {
            Priority = 1
        });

        // selection / multi-selection behaviors
        cockpit.InputBehaviors.Add(new MouseMultiSelectBehavior(cockpit.Context)
        {
            Priority = 10
        });
        cockpit.InputBehaviors.Add(new GamepadMultiSelectBehavior(cockpit.Context)
        {
            Priority = 10
        });

        // left click-drag to tumble, and left click-release to de-select
        cockpit.InputBehaviors.Add(new MouseClickDragSuperBehavior()
        {
            Priority     = 100,
            DragBehavior = new MouseViewRotateBehavior(cockpit.Context)
            {
                Priority = 100, RotateSpeed = 3.0f
            },
            ClickBehavior = new MouseDeselectBehavior(cockpit.Context)
            {
                Priority = 999
            }
        });

        // also right-click-drag to tumble
        cockpit.InputBehaviors.Add(new MouseViewRotateBehavior(cockpit.Context)
        {
            Priority  = 100, RotateSpeed = 3.0f,
            ActivateF = MouseBehaviors.RightButtonPressedF, ContinueF = MouseBehaviors.RightButtonDownF
        });

        // middle-click-drag to pan
        cockpit.InputBehaviors.Add(new MouseViewPanBehavior(cockpit.Context)
        {
            Priority  = 100, PanSpeed = 1.0f,
            ActivateF = MouseBehaviors.MiddleButtonPressedF, ContinueF = MouseBehaviors.MiddleButtonDownF
        });

        cockpit.OverrideBehaviors.Add(new MouseWheelZoomBehavior(cockpit)
        {
            Priority = 100, ZoomScale = 10.0f
        });

        // touch input
        cockpit.InputBehaviors.Add(new TouchUIBehavior(cockpit.Context)
        {
            Priority = 1
        });
        cockpit.InputBehaviors.Add(new Touch2DCockpitUIBehavior(cockpit.Context)
        {
            Priority = 0
        });
        cockpit.InputBehaviors.Add(new TouchViewManipBehavior(cockpit.Context)
        {
            Priority = 999, TouchZoomSpeed = 0.1f, TouchPanSpeed = 0.03f
        });
    }
Beispiel #3
0
        public void Initialize(Cockpit cockpit)
        {
            cockpit.Name = "modelCockpit";


            // Configure how the cockpit moves

            //cockpit.PositionMode = Cockpit.MovementMode.TrackPosition;
            // [RMS] use orientation mode to make cockpit follow view orientation.
            //  (however default widgets below are off-screen!)
            cockpit.PositionMode = Cockpit.MovementMode.TrackOrientation;



            BoxContainer screenContainer           = new BoxContainer(new Cockpit2DContainerProvider(cockpit));
            PinnedBoxes2DLayoutSolver screenLayout = new PinnedBoxes2DLayoutSolver(screenContainer);
            PinnedBoxesLayout         layout       = new PinnedBoxesLayout(cockpit, screenLayout)
            {
                StandardDepth = 2.0f
            };

            cockpit.AddLayout(layout, "2D", true);



            Func <string, float, HUDLabel> MakeButtonF = (label, buttonW) => {
                HUDLabel button = new HUDLabel()
                {
                    Shape           = CotangentUI.MakeMenuButtonRect(buttonW, CotangentUI.MenuButtonHeight),
                    TextHeight      = CotangentUI.MenuButtonTextHeight,
                    AlignmentHorz   = HorizontalAlignment.Center,
                    BackgroundColor = CotangentUI.ButtonBGColor, TextColor = CotangentUI.ButtonTextColor, Text = label,
                    EnableBorder    = true, BorderWidth = CotangentUI.StandardButtonBorderWidth, BorderColor = CotangentUI.ButtonTextColor
                };
                button.Create();
                button.Name    = label;
                button.Enabled = true;
                return(button);
            };



            Vector2f          progressOffsetY = 4 * CotangentUI.PixelScale * Vector2f.AxisY;
            HUDRadialProgress slicerProgress  = new HUDRadialProgress()
            {
                Radius = 18 * CotangentUI.PixelScale
            };

            slicerProgress.Create();
            slicerProgress.Name = "slicer_progress";
            int MAX_PROGRESS = 1000;

            slicerProgress.MaxProgress = MAX_PROGRESS;
            CC.SlicingProgressEvent   += (status) => {
                if (status.bFailed)
                {
                    double t = 0.5 * (double)status.curProgress / (double)status.maxProgress;
                    slicerProgress.Progress       = (int)(t * MAX_PROGRESS);
                    slicerProgress.CompletedColor = Colorf.VideoRed;
                }
                else
                {
                    double t = 0.5 * (double)status.curProgress / (double)status.maxProgress;
                    slicerProgress.Progress       = (int)(t * MAX_PROGRESS);
                    slicerProgress.CompletedColor = Colorf.BlueMetal;
                }
            };
            CC.ToolpathProgressEvent += (status) => {
                if (status.bFailed)
                {
                    double t = 0.5 + 0.5 * (double)status.curProgress / (double)status.maxProgress;
                    slicerProgress.Progress       = (int)(t * MAX_PROGRESS);
                    slicerProgress.CompletedColor = Colorf.VideoRed;
                }
                else
                {
                    double t = 0.5 + 0.5 * (double)status.curProgress / (double)status.maxProgress;
                    if (status.curProgress == 0 && status.maxProgress == 1)
                    {
                        t = 0;
                    }
                    slicerProgress.Progress       = (int)(t * MAX_PROGRESS);
                    slicerProgress.CompletedColor = (status.curProgress == status.maxProgress) ? Colorf.LightGreen : Colorf.BlueMetal;
                }
            };
            layout.Add(slicerProgress, new LayoutOptions()
            {
                Flags            = LayoutFlags.None,
                PinSourcePoint2D = LayoutUtil.BoxPointF(slicerProgress, BoxPosition.CenterBottom),
                PinTargetPoint2D = LayoutUtil.BoxPointF(screenContainer, BoxPosition.CenterBottom, progressOffsetY)
            });



            HUDButton progressClick = new HUDButton()
            {
                Shape = new HUDShape(HUDShapeType.Disc, slicerProgress.Radius)
            };
            fMaterial normalMaterial = MaterialUtil.CreateFlatMaterialF(Colorf.White, 0);
            fMaterial pauseMaterial  = MaterialUtil.CreateTransparentImageMaterialF("icons/progress_pause");
            fMaterial pausedMaterial = MaterialUtil.CreateTransparentImageMaterialF("icons/progress_play");

            if (CCPreferences.ActiveSlicingUpdateMode == CCPreferences.SlicingUpdateModes.ImmediateSlicing)
            {
                progressClick.Create(normalMaterial, null, pauseMaterial);
            }
            else
            {
                progressClick.Create(pausedMaterial, null, null);
            }
            progressClick.Name = "progress_click";
            layout.Add(progressClick, new LayoutOptions()
            {
                Flags            = LayoutFlags.None,
                DepthShift       = -0.1f,
                PinSourcePoint2D = LayoutUtil.BoxPointF(progressClick, BoxPosition.CenterBottom),
                PinTargetPoint2D = LayoutUtil.BoxPointF(screenContainer, BoxPosition.CenterBottom, progressOffsetY)
            });
            progressClick.OnClicked += (o, e) => {
                if (CCPreferences.ActiveSlicingUpdateMode == CCPreferences.SlicingUpdateModes.ImmediateSlicing)
                {
                    CCPreferences.ActiveSlicingUpdateMode = CCPreferences.SlicingUpdateModes.SliceOnDemand;
                    progressClick.StandardMaterial        = pausedMaterial;
                    progressClick.HoverMaterial           = null;
                }
                else
                {
                    CCPreferences.ActiveSlicingUpdateMode = CCPreferences.SlicingUpdateModes.ImmediateSlicing;
                    progressClick.StandardMaterial        = normalMaterial;
                    progressClick.HoverMaterial           = pauseMaterial;
                }
                if (CC.Toolpather.ToolpathsValid == false)
                {
                    // not sure why we have to invalidate slicing here, but if we don't toolpath
                    // computation will not stop when we pause...
                    CC.Slicer.InvalidateSlicing();
                    //CC.InvalidateToolPaths();
                }
            };


            CotangentUI.PrintViewHUDItems = new List <HUDStandardItem>()
            {
                slicerProgress, progressClick
            };

            screenLayout.RecomputeLayout();


            // Configure interaction behaviors
            //   - below we add behaviors for mouse, gamepad, and spatial devices (oculus touch, etc)
            //   - keep in mind that Tool objects will register their own behaviors when active

            // setup key handlers (need to move to behavior...)
            cockpit.AddKeyHandler(new CotangentKeyHandler(cockpit.Context));

            // these behaviors let us interact with UIElements (ie left-click/trigger, or either triggers for Touch)
            cockpit.InputBehaviors.Add(new Mouse2DCockpitUIBehavior(cockpit.Context)
            {
                Priority = 0
            });
            cockpit.InputBehaviors.Add(new VRMouseUIBehavior(cockpit.Context)
            {
                Priority = 1
            });

            // selection / multi-selection behaviors
            // Note: this custom behavior implements some selection redirects that we use in various parts of Archform
            cockpit.InputBehaviors.Add(new MouseMultiSelectBehavior(cockpit.Context)
            {
                Priority = 10
            });

            // left click-drag to tumble, and left click-release to de-select
            cockpit.InputBehaviors.Add(new MouseClickDragSuperBehavior()
            {
                Priority     = 100,
                DragBehavior = new MouseViewRotateBehavior(cockpit.Context)
                {
                    Priority = 100, RotateSpeed = 3.0f
                },
                ClickBehavior = new MouseDeselectBehavior(cockpit.Context)
                {
                    Priority = 999
                }
            });

            // also right-click-drag to tumble
            cockpit.InputBehaviors.Add(new MouseViewRotateBehavior(cockpit.Context)
            {
                Priority  = 100, RotateSpeed = 3.0f,
                ActivateF = MouseBehaviors.RightButtonPressedF, ContinueF = MouseBehaviors.RightButtonDownF
            });

            // middle-click-drag to pan
            cockpit.InputBehaviors.Add(new MouseViewPanBehavior(cockpit.Context)
            {
                Priority  = 100, PanSpeed = 0.01f, Adaptive = true,
                ActivateF = MouseBehaviors.MiddleButtonPressedF, ContinueF = MouseBehaviors.MiddleButtonDownF
            });


            cockpit.OverrideBehaviors.Add(new MouseWheelZoomBehavior(cockpit)
            {
                Priority = 100, ZoomScale = 0.2f, Adaptive = true
            });

            // touch input
            cockpit.InputBehaviors.Add(new TouchUIBehavior(cockpit.Context)
            {
                Priority = 1
            });
            cockpit.InputBehaviors.Add(new Touch2DCockpitUIBehavior(cockpit.Context)
            {
                Priority = 0
            });
            cockpit.InputBehaviors.Add(new TouchViewManipBehavior(cockpit.Context)
            {
                Priority = 999, TouchZoomSpeed = 0.1f, TouchPanSpeed = 0.03f
            });
        }