private static AnimatorState CreateInitState(AnimatorStateMachine stateMachine,
                                                     IReadOnlyList <BitActionSwitchItem> actionSwitchItems, int groupIndex)
        {
            var state = stateMachine.AddStateDefaultParam("Init", Style.InitStatePosition);
            var avatarParameterDriver = state.AddStateMachineBehaviour <VRCAvatarParameterDriver>();

            avatarParameterDriver.parameters = new List <VRC_AvatarParameterDriver.Parameter>
            {
                new VRC_AvatarParameterDriver.Parameter
                {
                    name  = ActionSwitchParameters.InitializedParameterName,
                    value = 1.0f
                }
            };

            avatarParameterDriver.parameters.AddRange(actionSwitchItems.Select((value, index) =>
                                                                               new VRC_AvatarParameterDriver.Parameter
            {
                name  = ActionSwitchParameters.GetObjectFloatStatusParameterName(index + 1 + groupIndex * 9),
                value = 0.0f
            }));

            avatarParameterDriver.parameters.AddRange(actionSwitchItems.Select((value, index) =>
                                                                               new VRC_AvatarParameterDriver.Parameter
            {
                name  = ActionSwitchParameters.GetObjectActiveStatusParameterName(index + 1 + groupIndex * 9),
                value = 0.0f
            }));

            return(state);
        }
        public static void Create(AnimatorStateMachine stateMachine, int index, BitActionSwitchGroup bitActionSwitchGroup,
                                  ActivationAnimationClipItem animationClip, int groupIndex)
        {
            stateMachine.entryPosition    = Style.EntryPosition;
            stateMachine.anyStatePosition = Style.AnyStatePosition;
            stateMachine.exitPosition     = Style.ExitPosition;

            var initState              = stateMachine.AddStateDefaultParam("Init", Style.InitStatePosition);
            var staticBitActiveState   = stateMachine.AddStateDefaultParam("Static Bit Active", Style.StaticBitActiveStatePosition);
            var staticBitInactiveState = stateMachine.AddStateDefaultParam("Static Bit Inactive", Style.StaticBitInactiveStatePosition);
            var bitActiveState         = stateMachine.AddStateDefaultParam("Bit Active", Style.BitActiveStatePosition);
            var bitInactiveState       = stateMachine.AddStateDefaultParam("Bit Inactive", Style.BitInactiveStatePosition);

            // set motion
            var bitActionSwitchItem = bitActionSwitchGroup.bitActionSwitchItems[index];

            if (bitActionSwitchItem.registerType == BitActionSwitchItem.RegisterType.GameObject)
            {
                staticBitActiveState.motion   = animationClip.NonDefaultClip;
                staticBitInactiveState.motion = animationClip.DefaultClip;

                bitActiveState.motion   = staticBitActiveState.motion;
                bitInactiveState.motion = staticBitInactiveState.motion;
            }
            else
            {
                staticBitActiveState.motion   = bitActionSwitchItem.staticNonDefaultClip;
                staticBitInactiveState.motion = bitActionSwitchItem.staticDefaultClip;

                bitActiveState.motion   = bitActionSwitchItem.defaultClip == null ? staticBitActiveState.motion : bitActionSwitchItem.nonDefaultClip;
                bitInactiveState.motion = bitActionSwitchItem.nonDefaultClip == null ? staticBitInactiveState.motion : bitActionSwitchItem.defaultClip;
            }

            // transition
            stateMachine.AddAnyTransitionDefaultParam(initState, AnimatorConditionMode.If, 0.0f, ActionSwitchParameters.InitializedParameterName);

            staticBitActiveState.AddTransitionDefaultParam(bitInactiveState, AnimatorConditionMode.Equals, index + 1 + groupIndex * 9,
                                                           ActionSwitchParameters.ObjectNumParameterName);

            staticBitInactiveState.AddTransitionDefaultParam(bitActiveState, AnimatorConditionMode.Equals, index + 1 + groupIndex * 9,
                                                             ActionSwitchParameters.ObjectNumParameterName);

            var activeToInactive = bitActiveState.AddTransitionDefaultParam(bitInactiveState, AnimatorConditionMode.Less, 0.5f,
                                                                            ActionSwitchParameters.GetObjectFloatStatusParameterName(index + 1 + groupIndex * 9));

            activeToInactive.hasExitTime = true;
            activeToInactive.exitTime    = 1.0f;

            var inactiveToActive = bitInactiveState.AddTransitionDefaultParam(bitActiveState, AnimatorConditionMode.Greater, 0.5f,
                                                                              ActionSwitchParameters.GetObjectFloatStatusParameterName(index + 1 + groupIndex * 9));

            inactiveToActive.hasExitTime = true;
            inactiveToActive.exitTime    = 1.0f;


            var conditions = new List <AnimatorCondition>();

            for (var i = 0; i < 1 << bitActionSwitchGroup.bitActionSwitchItems.Count; i++)
            {
                var targetDigit = ((1 << index) & i) != 0;
                if (!targetDigit)
                {
                    continue;              // 1,3,5,7
                }
                initState.AddTransitionDefaultParam(staticBitActiveState, AnimatorConditionMode.Equals, i,
                                                    bitActionSwitchGroup.variableName);
                conditions.Add(new AnimatorCondition
                {
                    mode      = AnimatorConditionMode.NotEqual,
                    threshold = i,
                    parameter = bitActionSwitchGroup.variableName
                });
            }

            initState.AddTransitionDefaultParam(staticBitInactiveState, conditions.ToArray());
        }
        public static void Create(AnimatorStateMachine stateMachine, BitActionSwitchGroup bitActionSwitchGroup,
                                  int groupIndex)
        {
            stateMachine.entryPosition    = Style.EntryPosition;
            stateMachine.anyStatePosition = Style.AnyStatePosition;
            stateMachine.exitPosition     = Style.ExitPosition;

            var initState = CreateInitState(stateMachine, bitActionSwitchGroup.bitActionSwitchItems, groupIndex);

            stateMachine.defaultState = initState;

            var loadBitStartState = stateMachine.AddStateDefaultParam("Load Bit Start", Style.LoadBitStartStatePosition);

            loadBitStartState.motion = GlobalClips.ShortEmptyClip;
            var loadBitDriver = loadBitStartState.AddStateMachineBehaviour <VRCAvatarParameterDriver>();

            loadBitDriver.parameters.Add(new VRC_AvatarParameterDriver.Parameter
            {
                name  = ActionSwitchParameters.InitializedParameterName,
                value = 0.0f
            });

            var effectStartState = stateMachine.AddStateDefaultParam("Effect State Start", Style.EffectStartStatePosition);

            effectStartState.motion = GlobalClips.ShortEmptyClip;

            loadBitStartState.AddTransitionDefaultParam(effectStartState, new[]
            {
                new AnimatorCondition
                {
                    mode      = AnimatorConditionMode.NotEqual,
                    threshold = 0.0f,
                    parameter = ActionSwitchParameters.ObjectNumParameterName
                },
                new AnimatorCondition
                {
                    mode      = AnimatorConditionMode.If,
                    threshold = 0.0f,
                    parameter = ActionSwitchParameters.VRCIsLocalParameterName
                }
            });

            var endState = stateMachine.AddStateDefaultParam("End", Style.EndStatePosition);

            var bitCalculatorStateMachine = BitCalculatorStateMachine.CreateStateMachine(stateMachine, Style.BitCalculatorStatePosition, bitActionSwitchGroup, loadBitStartState, endState, groupIndex);

            for (var i = 0; i < bitActionSwitchGroup.bitActionSwitchItems.Count; i++)
            {
                var position = Style.ObjectSwitchStatePosition;
                position.x -= 250 * i;
                var objectSwitchStateMachine = ObjectSwitchStateMachine.CreateStateMachine(stateMachine, position, i,
                                                                                           bitActionSwitchGroup, bitCalculatorStateMachine, groupIndex);
                effectStartState.AddTransitionDefaultParam(objectSwitchStateMachine.defaultState,
                                                           AnimatorConditionMode.Equals, i + 1 + groupIndex * 9, ActionSwitchParameters.ObjectNumParameterName);
            }

            var initToLoad = initState.AddTransitionDefaultParam(loadBitStartState, false);

            initToLoad.hasExitTime = true;

            endState.AddTransitionDefaultParam(loadBitStartState, AnimatorConditionMode.If, 0.0f, ActionSwitchParameters.ThroughTransitionParameterName);
        }