protected override void Start()
    {
#if !AR_ON
        AddActionPointButton.SetInteractivity(true);
        AddActionPointButton2.SetInteractivity(true);
#endif
        Base.ProjectManager.Instance.OnProjectSavedSatusChanged += OnProjectSavedStatusChanged;
        Base.GameManager.Instance.OnOpenProjectEditor           += OnOpenProjectEditor;

        SceneManager.Instance.OnSceneStateEvent += OnSceneStateEvent;

        GameManager.Instance.OnGameStateChanged            += OnGameStateChanged;
        GameManager.Instance.OnEditorStateChanged          += OnEditorStateChanged;
        SelectorMenu.Instance.OnObjectSelectedChangedEvent += OnObjectSelectedChangedEvent;

        GameManager.Instance.OnActionExecution         += OnActionExecutionEvent;
        GameManager.Instance.OnActionExecutionCanceled += OnActionExecutionEvent;
        GameManager.Instance.OnActionExecutionFinished += OnActionExecutionEvent;
    }
    protected async override Task UpdateBtns(InteractiveObject obj)
    {
        try {
            if (CanvasGroup.alpha == 0)
            {
                previousUpdateDone = true;
                return;
            }

            await base.UpdateBtns(obj);

#if UNITY_ANDROID && AR_ON
            if (!CalibrationManager.Instance.Calibrated && !TrackingManager.Instance.IsDeviceTracking())
            {
                SetActionPointParentButton.SetInteractivity(false, $"{SET_ACTION_POINT_PARENT_LABEL}\n(AR not calibrated)");
                AddActionButton.SetInteractivity(false, $"{ADD_ACTION_LABEL}\n(AR not calibrated)");
                AddActionButton2.SetInteractivity(false, $"{ADD_ACTION_LABEL}\n(AR not calibrated)");
                AddConnectionButton.SetInteractivity(false, $"{ADD_CONNECTION_LABEL}\n(AR not calibrated)");
                AddConnectionButton2.SetInteractivity(false, $"{ADD_CONNECTION_LABEL}\n(AR not calibrated)");
                RunButton.SetInteractivity(false, $"{RUN_ACTION_OR_PACKAGE_LABEL}\n(AR not calibrated)");
                RunButton2.SetInteractivity(false, $"{RUN_ACTION_OR_PACKAGE_LABEL}\n(AR not calibrated)");
                AddActionPointButton.SetInteractivity(false, $"{ADD_ACTION_POINT_LABEL}\n(AR not calibrated)");
                AddActionPointButton2.SetInteractivity(false, $"{ADD_ACTION_POINT_LABEL}\n(AR not calibrated)");
                CopyButton.SetInteractivity(false, $"{COPY_LABEL}\n(AR not calibrated");
                ActionPointAimingMenuButton.SetInteractivity(false, $"{ACTION_POINT_AIMING_LABEL}\n(AR not calibrated)");
            }
            else
#endif
            if (requestingObject || obj == null)
            {
                SetActionPointParentButton.SetInteractivity(false, $"{SET_ACTION_POINT_PARENT_LABEL}\n(no action point is selected)");
                AddActionButton.SetInteractivity(false, $"{ADD_ACTION_LABEL}\n(no action point is selected)");
                AddActionButton2.SetInteractivity(false, $"{ADD_ACTION_LABEL}\n(no action point is selected)");
                AddConnectionButton.SetInteractivity(false, $"{ADD_CONNECTION_LABEL}\n(no input / output is selected)");
                AddConnectionButton2.SetInteractivity(false, $"{ADD_CONNECTION_LABEL}\n(no input / output is selected)");
                RunButton.SetInteractivity(false, $"{RUN_ACTION_OR_PACKAGE_LABEL}\n(select action to execute it or START to run project)");
                RunButton2.SetInteractivity(false, RunButton.GetAlternativeDescription());
                AddActionPointButton.SetInteractivity(true);
                AddActionPointButton2.SetInteractivity(true);
                AddActionPointButton.SetDescription(ADD_ACTION_POINT_GLOBAL_LABEL);
                AddActionPointButton2.SetDescription(ADD_ACTION_POINT_GLOBAL_LABEL);
                CopyButton.SetInteractivity(false, $"{COPY_LABEL}\n(no object to duplicate selected)");
                ActionPointAimingMenuButton.SetInteractivity(false, $"{ACTION_POINT_AIMING_LABEL}\n(no action point selected)");
                RunDebugButton.SetInteractivity(false, $"{RUN_DEBUG_OR_TRIGGER_BREAKPOINT_LABEL}\n(select action point to trigger breakpoint or START to run debug mode)");
            }
            else if (obj.IsLocked && obj.LockOwner != LandingScreen.Instance.GetUsername())
            {
                SetActionPointParentButton.SetInteractivity(false, $"{SET_ACTION_POINT_PARENT_LABEL}\n(object is used by {obj.LockOwner})");
                AddConnectionButton.SetInteractivity(false, $"{ADD_CONNECTION_LABEL}\n(object is used by {obj.LockOwner})");
                AddConnectionButton2.SetInteractivity(false, $"{ADD_CONNECTION_LABEL}\n(object is used by {obj.LockOwner})");
                RunButton.SetInteractivity(false, $"{RUN_ACTION_OR_PACKAGE_LABEL}\n(object is used by {obj.LockOwner})");
                RunButton2.SetInteractivity(false, $"{RUN_ACTION_OR_PACKAGE_LABEL}\n(object is used by {obj.LockOwner})");
                AddActionButton.SetInteractivity(false, $"{ADD_ACTION_POINT_LABEL}\n(object is used by {obj.LockOwner})");
                AddActionButton2.SetInteractivity(false, $"{ADD_ACTION_POINT_LABEL}\n(object is used by {obj.LockOwner})");
                CopyButton.SetInteractivity(false, $"{COPY_LABEL}\n(object is used by {obj.LockOwner})");
                ActionPointAimingMenuButton.SetInteractivity(false, $"{ACTION_POINT_AIMING_LABEL}\n(object is used by {obj.LockOwner})");
                RunDebugButton.SetInteractivity(false, $"{RUN_DEBUG_OR_TRIGGER_BREAKPOINT_LABEL}\n(object is used by {obj.LockOwner})");
            }
            else
            {
                RunDebugButton.SetInteractivity(false, $"{RUN_DEBUG_OR_TRIGGER_BREAKPOINT_LABEL}\n(select action point to trigger breakpoint or START to run debug mode)");
                SetActionPointParentButton.SetInteractivity(obj is ActionPoint3D, $"{SET_ACTION_POINT_PARENT_LABEL}\n(selected object is not action point)");
                if (obj is ActionPoint3D ap)
                {
                    AddActionButton.SetInteractivity(ProjectManager.Instance.AnyAvailableAction, $"{ADD_ACTION_LABEL}\n(no actions available)");
                    AddActionButton2.SetInteractivity(ProjectManager.Instance.AnyAvailableAction, $"{ADD_ACTION_LABEL}\n(no actions available)");
                    CopyButton.SetInteractivity(false, $"{COPY_LABEL}\n(checking...)");
                    WebsocketManager.Instance.CopyActionPoint(obj.GetId(), null, obj.GetName(), CopyActionPointDryRunCallback, true);
                    RunDebugButton.SetInteractivity(true);
                    RunDebugButton.SetDescription(ap.BreakPoint ? TRIGGER_BREAKPOINT_OFF_LABEL : TRIGGER_BREAKPOINT_ON_LABEL);
                }
                else
                {
                    AddActionButton.SetInteractivity(false, $"{ADD_ACTION_LABEL}\n(selected object is not action point)");
                    AddActionButton2.SetInteractivity(false, $"{ADD_ACTION_LABEL}\n(selected object is not action point)");
                    CopyButton.SetInteractivity(obj is Base.Action && !(obj is StartEndAction), $"{COPY_LABEL}\n(selected object cannot be duplicated)");
                }

                ActionPointAimingMenuButton.SetInteractivity(obj is ActionPoint3D || obj is APOrientation, $"{ACTION_POINT_AIMING_LABEL}\n(selected object is not action point or orientation)");
                if (obj is IActionPointParent)
                {
                    AddActionPointButton.SetDescription($"Add AP relative to {obj.GetName()}");
                    AddActionPointButton.SetInteractivity(true);
                }
                else
                {
                    AddActionPointButton.SetInteractivity(false, $"{ADD_ACTION_POINT_LABEL}\n(selected object could not be parent of AP");
                }
                AddActionPointButton2.SetInteractivity(AddActionPointButton.IsInteractive(), $"{ADD_ACTION_POINT_LABEL}\n({AddActionPointButton.GetAlternativeDescription()})");
                AddActionPointButton2.SetDescription(AddActionPointButton.GetDescription());

                if (!MainSettingsMenu.Instance.ConnectionsSwitch.IsOn())
                {
                    AddConnectionButton.SetInteractivity(false, $"{ADD_CONNECTION_LABEL}\n(connections are hidden)");
                    AddConnectionButton2.SetInteractivity(false, $"{ADD_CONNECTION_LABEL}\n(connections are hidden)");
                }
                else
                {
                    if (obj is Base.Action)
                    {
                        if (obj is EndAction)
                        {
                            AddConnectionButton.SetInteractivity(false, $"{ADD_CONNECTION_LABEL}\n(end action could not be connected to anything else)");
                        }
                        else
                        {
                            AddConnectionButton.SetInteractivity(true);
                        }
                        AddConnectionButton2.SetInteractivity(AddConnectionButton.IsInteractive(), AddConnectionButton.GetAlternativeDescription());
                    }
                }
                string runBtnInteractivity = null;

                if (obj.GetType() == typeof(Action3D))
                {
                    if (!SceneManager.Instance.SceneStarted)
                    {
                        runBtnInteractivity = "scene offline";
                    }
                    else if (!string.IsNullOrEmpty(GameManager.Instance.ExecutingAction))
                    {
                        string actionName = ProjectManager.Instance.GetAction(GameManager.Instance.ExecutingAction).GetName();
                        runBtnInteractivity = $"action '{actionName}' running";
                    }
                    RunButton.SetDescription(RUN_ACTION_LABEL);
                    RunButton2.SetDescription(RUN_ACTION_LABEL);
                    RunButton.SetInteractivity(string.IsNullOrEmpty(runBtnInteractivity), $"{RUN_ACTION_LABEL}\n({runBtnInteractivity})");
                    RunButton2.SetInteractivity(string.IsNullOrEmpty(runBtnInteractivity), $"{RUN_ACTION_LABEL}\n({runBtnInteractivity})");
                }
                else if (obj.GetType() == typeof(StartAction))
                {
                    if (!ProjectManager.Instance.ProjectMeta.HasLogic)
                    {
                        runBtnInteractivity = "project without logic could not be started from editor";
                    }
                    else if (ProjectManager.Instance.ProjectChanged)
                    {
                        runBtnInteractivity = "project has unsaved changes";
                    }
                    RunButton.SetDescription(RUN_TEMP_PACKAGE_LABEL);
                    RunButton2.SetDescription(RUN_TEMP_PACKAGE_LABEL);
                    RunDebugButton.SetDescription(RUN_DEBUG_LABEL);
                    RunButton.SetInteractivity(string.IsNullOrEmpty(runBtnInteractivity), $"{RUN_TEMP_PACKAGE_LABEL}\n({runBtnInteractivity})");
                    RunButton2.SetInteractivity(string.IsNullOrEmpty(runBtnInteractivity), $"{RUN_TEMP_PACKAGE_LABEL}\n({runBtnInteractivity})");
                    RunDebugButton.SetInteractivity(string.IsNullOrEmpty(runBtnInteractivity), $"{RUN_DEBUG_LABEL}\n({runBtnInteractivity})");
                }
                else
                {
                    runBtnInteractivity = "select action to execute it or START to run project";
                    RunButton.SetInteractivity(false, $"{RUN_ACTION_OR_PACKAGE_LABEL}\n({runBtnInteractivity})");
                    RunButton2.SetInteractivity(false, $"{RUN_ACTION_OR_PACKAGE_LABEL}\n({runBtnInteractivity})");
                }
            }

            if (!SceneManager.Instance.SceneStarted)
            {
                AddActionPointUsingRobotButton.SetInteractivity(false, $"{ADD_ACTION_POINT_USING_ROBOT_LABEL}\n(scene offline");
            }
            else
            {
                AddActionPointUsingRobotButton.SetInteractivity(true);
            }
        } finally {
            previousUpdateDone = true;
        }
    }