示例#1
0
    // アニメーション 再生/変更
    private void ChangeAnimation(AnimationPattern pattern)
    {
        if (scriptRoot == null)
        {
            return;
        }

        // 再生する回数を指定します
        int timesPlay = 0;
        // 再生開始時のframeoffset(今回は0で固定)
        int frameOffset = 0;
        // アニメーションの再生速度を指定します
        float rateTime = 1;

        if (scriptRoot != null)
        {
            switch (pattern)
            {
            case AnimationPattern.Menace:
                timesPlay = 1;
                break;

            case AnimationPattern.Wait:
                timesPlay = 1;
                break;

            default:
                break;
            }
            scriptRoot.AnimationPlay(-1, (int)pattern, timesPlay, frameOffset, rateTime);
        }
    }
示例#2
0
            public void PlayAnimation()
            {
                AnimationPattern animationPattern = animationPatterns[animationPatternIndex];
                List <AnimationPatternSignal> animationPatternSignals = animationPattern.GetAnimationPatternSignals();

                float animationSpeedModifier = 1;

                if (framesGiven > 0)
                {
                    animationSpeedModifier = animationPattern.GetTotalFrames() / framesGiven;
                }

                int i = 0;

                foreach (AnimationPatternSignal signal in animationPatternSignals)
                {
                    if (i == 0)
                    {
                        overworldObjectCoordinator.animationQueue.Enqueue(Animate(signal.GetSpriteIndex(),
                                                                                  SECONDS_PER_FRAME * signal.GetStartFrame() * animationSpeedModifier));
                    }
                    else
                    {
                        int frameDifference = GetFrameDifference(signal, animationPatternSignals[i - 1]);

                        overworldObjectCoordinator.animationQueue.Enqueue(Animate(signal.GetSpriteIndex(),
                                                                                  SECONDS_PER_FRAME * frameDifference * animationSpeedModifier));
                    }
                    i++;
                }
            }
    // アニメーション 再生/変更
    private void AnimationChange(AnimationPattern pattern)
    {
        Script_SpriteStudio6_Root scriptRoot = null;    // SpriteStudio Anime を操作するためのクラス
        int iTimesPlaey = 0;

        if (m_goCharacter == null)
        {
            return;
        }

        scriptRoot = Script_SpriteStudio6_Root.Parts.RootGet(m_goCharacter);
        if (scriptRoot != null)
        {
            switch (pattern)
            {
            case AnimationPattern.Wait:
                iTimesPlaey = 0;        // ループ再生
                break;

            case AnimationPattern.Attack:
                iTimesPlaey = 1;        // 1回だけ再生
                break;

            case AnimationPattern.Run:
                iTimesPlaey = 0;        // ループ再生
                break;

            default:
                break;
            }
            scriptRoot.AnimationPlay(-1, (int)pattern, iTimesPlaey);
        }
    }
示例#4
0
        public void OnInitStorables(VAMLaunch plugin)
        {
            _minPosition = new JSONStorableFloat("oscSourceMinPosition", 10.0f, 0.0f, 99.0f);
            plugin.RegisterFloat(_minPosition);
            _maxPosition = new JSONStorableFloat("oscSourceMaxPosition", 80.0f, 0.0f, 99.0f);
            plugin.RegisterFloat(_maxPosition);
            _speed = new JSONStorableFloat("oscSourceSpeed", 30.0f, 20.0f, 80.0f);
            plugin.RegisterFloat(_speed);
            _animationOffset = new JSONStorableFloat("oscAnimationOffset", 0.0f, 0.0f, 0.5f);
            plugin.RegisterFloat(_animationOffset);

            _targetAnimationAtomChooser = new JSONStorableStringChooser("oscSourceTargetAnimationAtom",
                                                                        GetTargetAnimationAtomChoices(), "", "Target Animation Pattern",
                                                                        (name) =>
            {
                _animationAtomController = null;
                _targetAnimationPattern  = null;

                if (string.IsNullOrEmpty(name))
                {
                    return;
                }

                var atom = SuperController.singleton.GetAtomByUid(name);
                if (atom && atom.animationPatterns.Length > 0)
                {
                    _animationAtomController = atom.freeControllers[0];
                    _targetAnimationPattern  = atom.animationPatterns[0];
                }
            });
            plugin.RegisterStringChooser(_targetAnimationAtomChooser);
        }
示例#5
0
    // アニメーション 再生/変更
    private void ChangeAnimation(AnimationPattern pattern)
    {
        // アニメーションが生成されていなければreturn
        if (scriptRoot == null)
        {
            return;
        }

        // 再生回数を指定します
        int timesPlay = 0;

        if (scriptRoot != null)
        {
            switch (pattern)
            {
            case AnimationPattern.Move:
                timesPlay = 0;        // ループ再生
                break;

            case AnimationPattern.Attack:
                timesPlay = 1;        // 1回だけ再生
                break;

            default:
                break;
            }
            scriptRoot.AnimationPlay(-1, (int)pattern, timesPlay);
        }
    }
示例#6
0
        public void Apply()
        {
            for (int i = 0; i < montageJSON.Count; i++)
            {
                JSONClass atomJSON  = montageJSON[i].AsObject;
                Atom      foundAtom = SuperController.singleton.GetAtomByUid(atomJSON["id"]);

                if (foundAtom.GetStorableByID("AnimationPattern") != null)
                {
                    AnimationPattern ap = foundAtom.GetStorableByID("AnimationPattern") as AnimationPattern;
                    ap.SyncStepNames();
                    ap.autoSyncStepNamesJSON.SetVal(false);
                }

                if (foundAtom == null)
                {
                    SuperController.LogError("Montage referenced an atom that doesn't exist " + atomJSON["id"]);
                    return;
                }

                if (atomJSON["id"].Value.Contains("Doll Control"))
                {
                    continue;
                }

                foundAtom.PreRestore();
                foundAtom.RestoreTransform(atomJSON);
                foundAtom.Restore(atomJSON, restorePhysical: true, restoreAppearance: false, restoreCore: false, presetAtoms: montageJSON);
                foundAtom.LateRestore(atomJSON, restorePhysical: true, restoreAppearance: false, restoreCore: false);
                foundAtom.PostRestore();
                SuperController.singleton.PauseSimulation(5, "Loading Montage");
            }
        }
    // アニメーション再生/変更
    private void AnimationChange(AnimationPattern pattern)
    {
        if (!_goCharacter)
        {
            return;
        }

        var timesPlay  = 0;
        var scriptRoot = Script_SpriteStudio6_Root.Parts.RootGet(_goCharacter);

        if (!scriptRoot)
        {
            return;
        }
        switch (pattern)
        {
        case AnimationPattern.Wait:
            timesPlay = 0; // ループ再生
            break;

        case AnimationPattern.Stretch:
            timesPlay = 1; // 1回だけ再生
            break;

        case AnimationPattern.Walk:
            timesPlay = 0; // ループ再生
            break;

        default:
            break;
        }
        scriptRoot.AnimationPlay(-1, (int)pattern, timesPlay);
    }
 protected void AnimationChooserCallback(string s)
 {
     _animation = Controller.GetAtoms()
                  .SelectMany(a => a.GetComponentsInChildren <AnimationPattern>())
                  .FirstOrDefault(c => c.uid == s);
     AnimationChooser.valNoCallback = _animation == null ? "None" : s;
 }
示例#9
0
        public void NextThruster()
        {
            AnimationPattern ap = dm.thrustController.ap;

            if (ap == null)
            {
                return;
            }

            Atom         apAtom = ap.containingAtom;
            MoveProducer mp     = apAtom.GetStorableByID("AnimatedObject") as MoveProducer;

            Atom otherPerson = DollmasterPlugin.GetSomeoneElse(mp.receiver.containingAtom);

            if (otherPerson == null)
            {
                return;
            }

            Atom otherOtherPerson = DollmasterPlugin.GetSomeoneElse(otherPerson);

            if (otherOtherPerson == null)
            {
                return;
            }

            dm.thrustController.ConfigureAPSteps(otherPerson, otherOtherPerson);
        }
示例#10
0
        public Node(UI ui, AnimationPattern ap)
        {
            this.ap = ap;
            this.ui = ui;

            connectButton    = ui.CreateButton("Connect", 100, 50);
            disconnectButton = ui.CreateButton("Disconnect All", 100, 50);
            disconnectButton.transform.SetParent(connectButton.transform);
            disconnectButton.transform.Translate(0, -0.08f, 0);

            UIDynamicButton playButton = ui.CreateButton("Play", 100, 50);

            playButton.transform.SetParent(connectButton.transform);
            playButton.transform.Translate(0, -0.16f, 0);

            playButton.button.onClick.AddListener(() =>
            {
                ap.SetBoolParamValue("on", true);

                if (ap.GetBoolParamValue("pause") == true)
                {
                    playButton.label = "Stop";
                    ap.ResetAnimation();
                }
                else
                {
                    playButton.label = "Play";
                    ap.SetBoolParamValue("on", false);
                }

                ap.TogglePause();
            });
        }
示例#11
0
        public void GenerateThrustAtoms()
        {
            dm.StartCoroutine(CreateAtom("AnimationPattern", "Thrust AP", (apAtom) =>
            {
                AnimationPattern ap = apAtom.GetStorableByID("AnimationPattern") as AnimationPattern;
                this.ap             = ap;

                ap.autoSyncStepNamesJSON.SetVal(false);

                thrustAtomChooser.SetVal(apAtom.name);

                if (ap.steps.Length >= 2)
                {
                    return;
                }

                ConfigureAPSteps(atom);

                UISetupState(apAtom);

                ap.SyncStepNames();
                ap.containingAtom.hidden   = true;
                ap.hideCurveUnlessSelected = true;
                ap.HideAllSteps();
            }, true));
        }
示例#12
0
    // アニメーション 再生/変更
    private void ChangeAnimation(AnimationPattern pattern)
    {
        if (scriptRoot == null)
        {
            return;
        }

        int timesPlay = 0;

        if (scriptRoot != null)
        {
            switch (pattern)
            {
            case AnimationPattern.Walk:
                timesPlay = 0;        // ループ再生
                break;

            case AnimationPattern.Attack:
                timesPlay = 1;        // 1回だけ再生
                break;

            default:
                break;
            }
            scriptRoot.AnimationPlay(-1, (int)pattern, timesPlay);
        }
    }
示例#13
0
 private void AnimChooserCallback(string s)
 {
     for (var i = 0; i < _animTotal; i++)
     {
         _atomUpdate          = SuperController.singleton.GetAtomByUid(_animChooser[i].val);
         _animUpdate          = _atomUpdate.GetStorableByID("AnimationPattern") as AnimationPattern;
         _animAtoms[i]        = _atomUpdate;
         _animationPattern[i] = _animUpdate;
     }
 }
示例#14
0
        public void OnInitStorables(VAMLaunch plugin)
        {
            _minPosition = new JSONStorableFloat("patternSourceMinPosition", 10.0f, 0.0f, 99.0f);
            plugin.RegisterFloat(_minPosition);
            _maxPosition = new JSONStorableFloat("patternSourceMaxPosition", 80.0f, 0.0f, 99.0f);
            plugin.RegisterFloat(_maxPosition);

            _targetAnimationAtomChooser = new JSONStorableStringChooser("patternSourceTargetAnimationAtom",
                                                                        GetTargetAnimationAtomChoices(), "", "Target Animation Pattern",
                                                                        (name) =>
            {
                _animationAtomController = null;
                _targetAnimationPattern  = null;

                if (string.IsNullOrEmpty(name))
                {
                    return;
                }

                var atom = SuperController.singleton.GetAtomByUid(name);
                if (atom && atom.animationPatterns.Length > 0)
                {
                    _animationAtomController = atom.freeControllers[0];
                    _targetAnimationPattern  = atom.animationPatterns[0];
                    _patternTime             = _targetAnimationPattern.GetFloatJSONParam("currentTime");
                    _patternSpeed            = _targetAnimationPattern.GetFloatJSONParam("speed");
                }
            });
            plugin.RegisterStringChooser(_targetAnimationAtomChooser);

            _samplePlaneChooser = new JSONStorableStringChooser("patternSourceSamplePlane", _samplePlaneChoices, "",
                                                                "Sample Plane", (name) =>
            {
                for (int i = 0; i < _samplePlaneChoices.Count; i++)
                {
                    if (_samplePlaneChoices[i] == name)
                    {
                        _samplePlaneIndex = i;
                        break;
                    }
                }
            });
            plugin.RegisterStringChooser(_samplePlaneChooser);
            if (string.IsNullOrEmpty(_samplePlaneChooser.val))
            {
                _samplePlaneChooser.SetVal("Y");
            }

            _includeMidPoints = new JSONStorableBool("patternSourceIncludeMidPoints", false);
            plugin.RegisterBool(_includeMidPoints);
            _invertPosition = new JSONStorableBool("patternSourceInvertPosition", false);
            plugin.RegisterBool(_invertPosition);
            _useLocalSpace = new JSONStorableBool("patternSourceUseLocalSpace", false);
            plugin.RegisterBool(_useLocalSpace);
        }
    void                    DrawAnimation(int index)
    {
        if (index < 0 || index >= this.animation.animations.Count)
        {
            return;
        }
        EditorGUILayout.Space();
        GUILayout.BeginHorizontal();
        {
            EditorGUI.BeginChangeCheck();
            AnimationPattern newPattern   = EditorGUILayout.ObjectField(this.animation.animations[index].pattern, typeof(AnimationPattern), false, GUILayout.MinWidth(100)) as AnimationPattern;
            AnimationFX      newAnimation = EditorGUILayout.ObjectField(this.animation.animations[index].animation, typeof(AnimationFX), false, GUILayout.MinWidth(100)) as AnimationFX;
            float            newLife      = EditorGUILayout.FloatField(this.animation.animations[index].life, GUILayout.MinWidth(15));
            float            newDelay     = EditorGUILayout.FloatField(this.animation.animations[index].delay, GUILayout.MinWidth(15));
            if (newLife < 0)
            {
                newLife = 0;
            }
            if (newDelay < 0)
            {
                newDelay = 0;
            }

            if (EditorGUI.EndChangeCheck())
            {
                Undo.RecordObject(this.animation, "Undo Inspector (Complex Animation)");

                this.animation.animations[index].pattern   = newPattern;
                this.animation.animations[index].animation = newAnimation;
                this.animation.animations[index].delay     = newDelay;
                this.animation.animations[index].life      = newLife;
                EditorUtility.SetDirty(this.animation);
            }

            /*
             * if (GUILayout.Button("Preview"))
             * {
             *  if (this.animation.animations[index].pattern)
             *      Debug.Log("Preview of pattern " + this.animation.animations[index].pattern.patternName);
             *  else
             *      Debug.LogWarning("Pattern is missing");
             * }
             */
            if (GUILayout.Button("X"))
            {
                Undo.RecordObject(this.animation, "Undo Inspector (Complex Animation)");
                this.animation.animations.RemoveAt(index);
                EditorUtility.SetDirty(this.animation);
            }
        }
        GUILayout.EndHorizontal();
    }
示例#16
0
        public override void Init()
        {
            try
            {
                ui = new UI(this, 0.001f);
                ui.canvas.transform.SetParent(containingAtom.mainController.transform, false);
                ui.canvas.transform.localPosition = new Vector3(0, -0.15f, 0);

                thrustValue = new JSONStorableFloat("thrust", 0, 0, SLIDER_MAX, true, true);
                RegisterFloat(thrustValue);

                UIDynamicSlider thrustSlider = ui.CreateSlider("Thrust Control", 300, 120);
                thrustSlider.valueFormat = "n0";
                thrustValue.slider       = thrustSlider.slider;

                thrustSlider.slider.onValueChanged.AddListener((float value) =>
                {
                    if (ap != null)
                    {
                        float speed = Remap(thrustValue.val, 0, SLIDER_MAX, 0, maxSpeed.val);
                        ap.SetFloatParamValue("speed", speed);
                    }
                });

                apName = new JSONStorableString("apName", "");
                RegisterString(apName);

                CreateButton("Select Animation Pattern").button.onClick.AddListener(() =>
                {
                    SuperController.singleton.SelectModeAtom((atom) =>
                    {
                        if (atom.GetStorableByID("AnimationPattern") == null)
                        {
                            SuperController.LogError("You must select an animation pattern.");
                            return;
                        }

                        apName.SetVal(atom.name);
                        ap = atom.GetStorableByID("AnimationPattern") as AnimationPattern;
                    });
                });

                maxSpeed = new JSONStorableFloat("maxSpeed", 4, 0, 10, false, true);
                RegisterFloat(maxSpeed);
                CreateSlider(maxSpeed, true);
            }
            catch (Exception e)
            {
                SuperController.LogError("Exception caught: " + e);
            }
        }
示例#17
0
        private void GenerateMotionPointsFromPattern(AnimationPattern pattern, ref List <MotionPoint> points,
                                                     out float outMinY, out float outMaxY)
        {
            outMinY = float.MaxValue;
            outMaxY = float.MinValue;

            points.Clear();
            for (int i = 0; i < pattern.steps.Length; i++)
            {
                MotionPoint point;

                point.Time     = pattern.steps[i].timeStep;
                point.Position = pattern.steps[i].point.position;

                if (_useLocalSpace.val)
                {
                    point.Position = pattern.transform.InverseTransformPoint(point.Position);
                }

                points.Add(point);

                outMaxY = GetMaxPosition(outMaxY, point.Position);
                outMinY = GetMinPosition(outMinY, point.Position);

                if (_includeMidPoints.val)
                {
                    point.Time = pattern.steps[i].timeStep +
                                 pattern.steps[(i + 1) % pattern.steps.Length].transitionToTime * 0.5f;
                    point.Position = pattern.GetPositionFromPoint(i, 0.5f);

                    if (_useLocalSpace.val)
                    {
                        point.Position = pattern.transform.InverseTransformPoint(point.Position);
                    }

                    points.Add(point);

                    outMaxY = GetMaxPosition(outMaxY, point.Position);
                    outMinY = GetMinPosition(outMinY, point.Position);
                }
            }
        }
示例#18
0
        void Start()
        {
            if (apName.val != apName.defaultVal)
            {
                Atom atom = GetAtomById(apName.val);
                if (atom == null)
                {
                    SuperController.LogError("atom named " + apName + " not found");
                    return;
                }

                AnimationPattern foundAP = atom.GetStorableByID("AnimationPattern") as AnimationPattern;
                if (foundAP == null)
                {
                    SuperController.LogError("atom " + apName + " is not an animation pattern");
                    return;
                }

                ap = foundAP;
            }
        }
示例#19
0
        public void UISetupState(Atom apAtom)
        {
            if (apAtom == null)
            {
                selectButton.gameObject.SetActive(true);
                createButton.gameObject.SetActive(true);
                slider.gameObject.SetActive(false);
            }
            else
            {
                ap = apAtom.GetStorableByID("AnimationPattern") as AnimationPattern;
                if (ap == null)
                {
                    return;
                }

                ap.InitUI();
                AttachCustomSlider();
                selectButton.gameObject.SetActive(false);
                createButton.gameObject.SetActive(false);
                slider.gameObject.SetActive(true);
            }
        }
示例#20
0
    public override void Init()
    {
        try
        {
            _pattern = containingAtom.GetComponentInChildren <AnimationPattern>();
            if (_pattern == null)
            {
                throw new Exception("The Director plugin can only be applied on AnimationPattern.");
            }
            _possessor                  = SuperController.singleton.centerCameraTarget.transform.GetComponent <Possessor>();
            _currentTimeJSON            = _pattern.GetFloatJSONParam("currentTime");
            _speedJSON                  = _pattern.GetFloatJSONParam("speed");
            _camExposureJSON            = GameObject.FindObjectOfType <SkyshopLightController>()?.GetFloatJSONParam("camExposure");
            _navigationHologridRenderer = SuperController.singleton.navigationHologrid.gameObject.GetComponent <MeshRenderer>();

            InitControls();
            UpdateActivation();
        }
        catch (Exception e)
        {
            SuperController.LogError("Failed to initialize plugin: " + e);
        }
    }
示例#21
0
        public ThrustController(DollmasterPlugin dm) : base(dm)
        {
            thrustEnabled = new JSONStorableBool("thrustEnabled", true);
            dm.RegisterBool(thrustEnabled);
            UIDynamicToggle moduleEnableToggle = dm.CreateToggle(thrustEnabled);

            moduleEnableToggle.label           = "Enable Thrusting";
            moduleEnableToggle.backgroundColor = Color.green;

            thrustAtomChooser = new JSONStorableStringChooser("thrustTarget", GetAnimationPatternNames(), "", "Thrust Control", (string name) =>
            {
                RestoreOriginalSlider();

                ap = null;

                UISetupState(SuperController.singleton.GetAtomByUid(name));
            });
            thrustAtomChooser.storeType = JSONStorableParam.StoreType.Full;
            dm.RegisterStringChooser(thrustAtomChooser);
            UIDynamicPopup popup = dm.CreatePopup(thrustAtomChooser);

            popup.popup.onOpenPopupHandlers += () =>
            {
                thrustAtomChooser.choices = GetAnimationPatternNames();
            };

            slider = dm.ui.CreateSlider("Thrust Speed", 300, 120);
            slider.transform.Translate(0, 0.15f, 0, Space.Self);

            slider.slider.onValueChanged.AddListener((float v) =>
            {
                if (ap == null)
                {
                    return;
                }

                JSONStorableFloat speedStore = ap.GetFloatJSONParam("speed");
                if (speedStore.slider != slider.slider)
                {
                    AttachCustomSlider();
                }
            });

            Image img = slider.GetComponentInChildren <Image>();

            img.color = new Color(0.4f, 0.2f, 0.245f, 1.0f);
            slider.labelText.color = new Color(1, 1, 1);

            slider.gameObject.SetActive(false);

            createButton = dm.ui.CreateButton("Generate Animation Pattern or...", 400, 120);
            createButton.transform.Translate(0, 0.15f, 0, Space.Self);
            createButton.buttonColor = new Color(0.4f, 0.2f, 0.245f, 1.0f);
            createButton.textColor   = new Color(1, 1, 1);

            createButton.button.onClick.AddListener(() =>
            {
                dm.StartCoroutine(CreateAtom("AnimationPattern", "Thrust AP", (apAtom) =>
                {
                    AnimationPattern ap = apAtom.GetStorableByID("AnimationPattern") as AnimationPattern;

                    ap.autoSyncStepNamesJSON.SetVal(false);

                    thrustAtomChooser.SetVal(apAtom.name);

                    if (ap.steps.Length >= 2)
                    {
                        return;
                    }

                    FreeControllerV3 hipControl = atom.GetStorableByID("hipControl") as FreeControllerV3;
                    apAtom.mainController.transform.SetPositionAndRotation(hipControl.transform.position, hipControl.transform.rotation);
                    apAtom.SelectAtomParent(atom);

                    //ap.animatedTransform = hipControl.transform;

                    MoveProducer mp = apAtom.GetStorableByID("AnimatedObject") as MoveProducer;
                    mp.SetReceiverByName(atom.name + ":hipControl");

                    AnimationStep stepA = ap.CreateStepAtPosition(0);
                    stepA.containingAtom.ClearParentAtom();
                    stepA.containingAtom.mainController.transform.position = apAtom.mainController.transform.position;
                    stepA.containingAtom.mainController.transform.rotation = apAtom.mainController.transform.rotation;
                    //stepA.containingAtom.SetParentAtom(apAtom.name);

                    AnimationStep stepB = ap.CreateStepAtPosition(1);
                    stepB.containingAtom.ClearParentAtom();
                    FreeControllerV3 abdomen2Control = atom.GetStorableByID("abdomen2Control") as FreeControllerV3;

                    stepB.containingAtom.mainController.transform.position = abdomen2Control.transform.position;
                    stepB.containingAtom.mainController.transform.rotation = apAtom.mainController.transform.rotation;

                    apAtom.mainController.transform.Translate(0, 0, -0.2f, Space.Self);

                    stepA.containingAtom.mainController.currentPositionState = FreeControllerV3.PositionState.ParentLink;
                    stepA.containingAtom.mainController.currentRotationState = FreeControllerV3.RotationState.ParentLink;
                    Rigidbody rba = SuperController.singleton.RigidbodyNameToRigidbody(apAtom.name + ":control");
                    stepA.containingAtom.mainController.SelectLinkToRigidbody(rba, FreeControllerV3.SelectLinkState.PositionAndRotation);

                    stepB.containingAtom.mainController.currentPositionState = FreeControllerV3.PositionState.ParentLink;
                    stepB.containingAtom.mainController.currentRotationState = FreeControllerV3.RotationState.ParentLink;
                    Rigidbody rbb = SuperController.singleton.RigidbodyNameToRigidbody(apAtom.name + ":control");
                    stepB.containingAtom.mainController.SelectLinkToRigidbody(rbb, FreeControllerV3.SelectLinkState.PositionAndRotation);

                    UISetupState(apAtom);

                    ap.SyncStepNames();
                }, true));
            });

            selectButton = dm.ui.CreateButton("Select Animation Pattern To Control", 400, 120);
            selectButton.transform.Translate(0.52f, 0.15f, 0, Space.Self);
            selectButton.buttonColor = new Color(0.4f, 0.2f, 0.245f, 1.0f);
            selectButton.textColor   = new Color(1, 1, 1);

            selectButton.button.onClick.AddListener(() =>
            {
                SuperController.singleton.SelectModeAtom((atom) =>
                {
                    if (atom == null)
                    {
                        return;
                    }

                    if (atom.GetStorableByID("AnimationPattern") == null)
                    {
                        SuperController.LogError("Select an Animation Pattern");
                        return;
                    }

                    AnimationPattern ap = atom.GetStorableByID("AnimationPattern") as AnimationPattern;
                    ap.SyncStepNames();
                    ap.autoSyncStepNamesJSON.SetVal(false);

                    thrustAtomChooser.SetVal(atom.uid);
                });
            });

            dm.CreateSpacer();
        }
示例#22
0
 public void                     Instantiation(AnimationPattern pattern, AnimationFX fx)
 {
     this.pattern = pattern;
     this.fx      = fx;
 }
示例#23
0
        public override void Init()
        {
            try
            {
                if (containingAtom == null)
                {
                    return;
                }


                PATH_WHEN_LOADED = SuperController.singleton.currentLoadDir;
                SuperController.singleton.currentSaveDir = PATH_WHEN_LOADED;

                uiVisible = new JSONStorableBool("uiVisible", false, (bool on) =>
                {
                    ui.canvas.enabled    = on;
                    keyUI.canvas.enabled = on;
                });
                RegisterBool(uiVisible);


                #region Animation Pattern Init
                animationPattern = containingAtom.GetStorableByID("AnimationPattern") as AnimationPattern;
                if (animationPattern == null)
                {
                    SuperController.LogError("You must add this plugin to an AnimationPattern");
                    return;
                }
                animationPattern.Pause();
                animationPattern.containingAtom.GetStorableByID("scale").SetFloatParamValue("scale", 0);
                #endregion


                CreatePeopleChooser((atom) =>
                {
                    if (atom == null)
                    {
                        return;
                    }
                    person = atom;
                });

                saveStore = new JSONStorableString("keyframes", "");
                RegisterString(saveStore);

                #region World UI
                float UISCALE = 0.001f;
                ui = new UI(this, UISCALE);
                ui.canvas.transform.SetParent(animationPattern.containingAtom.mainController.transform, false);

                UIDynamicToggle  onToggle   = ui.CreateToggle("On", 120, 60);
                JSONStorableBool onStorable = animationPattern.GetBoolJSONParam("on");
                onStorable.toggleAlt             = onToggle.toggle;
                onToggle.transform.localPosition = new Vector3(-575 + 35, 160, 0);

                UIDynamicToggle  loopToggle   = ui.CreateToggle("Loop", 140, 60);
                JSONStorableBool loopStorable = animationPattern.GetBoolJSONParam("loop");
                loopStorable.toggleAlt             = loopToggle.toggle;
                loopToggle.transform.localPosition = new Vector3(-575 + 180, 160, 0);

                UIDynamicButton doneEditingButton = ui.CreateButton("Done Editing", 200, 60);
                doneEditingButton.transform.localPosition = new Vector3(-575 + 75, -300, 0);
                doneEditingButton.buttonColor             = new Color(0.45f, 0.8f, 0.3f);
                doneEditingButton.textColor = new Color(1, 1, 1);
                doneEditingButton.button.onClick.AddListener(() =>
                {
                    uiVisible.SetVal(false);
                    ClearEditingKey();
                    if (SuperController.singleton.GetSelectedAtom() == animationPattern.containingAtom)
                    {
                        SuperController.singleton.ClearSelection();
                    }
                });

                timeSlider = ui.CreateSlider("Time", 500, 110);
                timeSlider.transform.localPosition = new Vector3(-350, 55, 0);
                timeSlider.slider.maxValue         = animationPattern.GetTotalTime();

                time           = animationPattern.GetFloatJSONParam("currentTime");
                time.sliderAlt = timeSlider.slider;

                UIDynamicButton playButton = ui.CreateButton("▶", 50, 60);
                playButton.transform.localPosition = new Vector3(-575, -30, 0);
                playButton.button.onClick.AddListener(() =>
                {
                    ClearEditingKey();
                    if (animationPattern.GetCurrentTimeCounter() == animationPattern.GetTotalTime())
                    {
                        animationPattern.ResetAndPlay();
                    }
                    else
                    {
                        animationPattern.Play();
                    }
                });

                UIDynamicButton pauseButton = ui.CreateButton("||", 50, 60);
                pauseButton.transform.localPosition = new Vector3(-525, -30, 0);
                pauseButton.button.onClick.AddListener(() =>
                {
                    ClearEditingKey();
                    animationPattern.Pause();
                });

                UIDynamicButton rewindButton = ui.CreateButton("«", 50, 60);
                rewindButton.transform.localPosition = new Vector3(-475, -30, 0);
                rewindButton.button.onClick.AddListener(() =>
                {
                    ClearEditingKey();
                    animationPattern.ResetAnimation();
                });

                UIDynamicButton addKeyButton = ui.CreateButton("+Key", 100, 60);
                addKeyButton.textColor               = new Color(0.984f, 0.917f, 0.972f);
                addKeyButton.buttonColor             = new Color(0.474f, 0.023f, 0.4f);
                addKeyButton.transform.localPosition = new Vector3(-550, -200, 0);
                addKeyButton.button.onClick.AddListener(AddKey);

                UIDynamicButton insertKeyButton = ui.CreateButton("Insert Key", 140, 60);
                insertKeyButton.textColor               = new Color(0.984f, 0.917f, 0.972f);
                insertKeyButton.buttonColor             = new Color(0.474f, 0.023f, 0.4f);
                insertKeyButton.transform.localPosition = new Vector3(-420, -200, 0);
                insertKeyButton.button.onClick.AddListener(InsertKey);

                UIDynamicButton nextKeyButton = ui.CreateButton("Next Key", 140, 60);
                nextKeyButton.transform.localPosition = new Vector3(-390, -100, 0);
                nextKeyButton.button.onClick.AddListener(() =>
                {
                    if (keyframes.Count <= 0)
                    {
                        return;
                    }

                    int index     = keyframes.IndexOf(GetNearestKeyToTime(time.val));
                    int nextIndex = index + 1;
                    if (nextIndex >= keyframes.Count)
                    {
                        nextIndex = 0;
                    }

                    SuperController.singleton.SelectController(keyframes[nextIndex].step.containingAtom.mainController);
                });

                UIDynamicButton previousKeyButton = ui.CreateButton("Prev Key", 140, 60);
                previousKeyButton.transform.localPosition = new Vector3(-530, -100, 0);
                previousKeyButton.button.onClick.AddListener(() =>
                {
                    if (keyframes.Count <= 0)
                    {
                        return;
                    }

                    int index     = keyframes.IndexOf(GetNearestKeyToTime(time.val));
                    int prevIndex = index - 1;

                    if (prevIndex < 0)
                    {
                        prevIndex = keyframes.Count - 1;
                    }

                    SuperController.singleton.SelectController(keyframes[prevIndex].step.containingAtom.mainController);
                });



                #endregion

                #region Keyframe UI
                keyUI          = new UI(this, UISCALE * 0.8f);
                undoPoseButton = keyUI.CreateButton("Undo", 300, 90);
                undoPoseButton.buttonText.fontSize     = 40;
                undoPoseButton.transform.localPosition = new Vector3(0, 120, 0);
                undoPoseButton.textColor   = new Color(1, 1, 1);
                undoPoseButton.buttonColor = new Color(0.650f, 0.027f, 0.027f);
                undoPoseButton.button.onClick.AddListener(() =>
                {
                    if (editingKeyframe == null)
                    {
                        return;
                    }

                    editingKeyframe.pose = lastPose;
                    SetToPose(lastPose, true);
                });

                setDurationSlider = keyUI.CreateSlider("Duration To Key", 500, 110);
                setDurationSlider.defaultButtonEnabled    = true;
                setDurationSlider.quickButtonsEnabled     = true;
                setDurationSlider.rangeAdjustEnabled      = true;
                setDurationSlider.transform.localPosition = new Vector3(0, -270, 0);

                tweenSelection = keyUI.CreatePopup("Tween", 500, 110);
                tweenSelection.transform.localPosition = new Vector3(0, -350, 0);

                UIDynamicButton copyPoseButton = keyUI.CreateButton("Copy Pose", 200, 60);
                copyPoseButton.transform.localPosition = new Vector3(-150, -170, 0);
                copyPoseButton.button.onClick.AddListener(() =>
                {
                    if (editingKeyframe == null)
                    {
                        return;
                    }

                    copiedPose = editingKeyframe.pose;
                });

                UIDynamicButton pastePoseButton = keyUI.CreateButton("Paste Pose", 200, 60);
                pastePoseButton.transform.localPosition = new Vector3(50, -170, 0);
                pastePoseButton.button.onClick.AddListener(() =>
                {
                    if (editingKeyframe == null)
                    {
                        return;
                    }

                    if (copiedPose == null)
                    {
                        return;
                    }

                    editingKeyframe.pose = copiedPose;
                    SetToPose(editingKeyframe.pose, true);
                });

                UIDynamicButton copyControllerButton = keyUI.CreateButton("Copy Control", 200, 60);
                copyControllerButton.transform.localPosition = new Vector3(-150, -120, 0);
                copyControllerButton.button.onClick.AddListener(() =>
                {
                    if (editingKeyframe == null)
                    {
                        return;
                    }

                    FreeControllerV3 selectedController = SuperController.singleton.GetSelectedController();
                    if (selectedController == null)
                    {
                        return;
                    }

                    copiedPosition = selectedController.transform.position;
                    copiedRotation = selectedController.transform.rotation;
                });

                UIDynamicButton pasteControllerButton = keyUI.CreateButton("Paste Control", 200, 60);
                pasteControllerButton.transform.localPosition = new Vector3(50, -120, 0);
                pasteControllerButton.button.onClick.AddListener(() =>
                {
                    if (editingKeyframe == null)
                    {
                        return;
                    }

                    FreeControllerV3 selectedController = SuperController.singleton.GetSelectedController();
                    if (selectedController == null)
                    {
                        return;
                    }

                    selectedController.transform.position = copiedPosition;
                    selectedController.transform.rotation = copiedRotation;
                });

                #endregion

                #region Plugin (Debug) UI
                #region Experimental Save and Load Pose
                UIDynamicButton loadPoseButton = CreateButton("Load Pose");
                loadPoseButton.transform.localPosition = new Vector3(-520, -150, 0);
                loadPoseButton.button.onClick.AddListener(() =>
                {
                    if (person == null)
                    {
                        return;
                    }

                    Vector3 position    = person.mainController.transform.position;
                    Quaternion rotation = person.mainController.transform.rotation;

                    person.LoadPhysicalPresetDialog();

                    person.mainController.transform.SetPositionAndRotation(position, rotation);
                });

                UIDynamicButton savePoseButton = CreateButton("Save Pose");
                savePoseButton.transform.localPosition = new Vector3(-360, -150, 0);
                savePoseButton.button.onClick.AddListener(() =>
                {
                    if (person == null)
                    {
                        return;
                    }

                    person.SavePresetDialog(true, false);
                });
                #endregion
                #endregion

                timeSlider.slider.onValueChanged.AddListener((value) =>
                {
                });

                UIDynamicToggle snapToggle = ui.CreateToggle("Snap To Keyframe", 340, 60);
                snapToggle.transform.localPosition = new Vector3(-270, -30);

                EventTrigger       timeSliderET = timeSlider.slider.gameObject.AddComponent <EventTrigger>();
                EventTrigger.Entry entry        = new EventTrigger.Entry();
                entry.eventID = EventTriggerType.Drag;
                entry.callback.AddListener((data) =>
                {
                    if (keyframes.Count == 0)
                    {
                        return;
                    }

                    if (snapToggle.toggle.isOn)
                    {
                        Keyframe nearestToTime = null;
                        keyframes.ForEach((key) =>
                        {
                            float timeDelta = Mathf.Abs(key.step.timeStep - time.val);
                            if (timeDelta <= 0.01f && nearestToTime == null)
                            {
                                nearestToTime = key;
                            }
                        });

                        if (nearestToTime != null)
                        {
                            SuperController.singleton.SelectController(nearestToTime.step.containingAtom.mainController);
                        }
                        else
                        {
                            SuperController.singleton.ClearSelection();
                            ClearEditingKey();
                        }
                    }
                    else
                    {
                        ClearEditingKey();
                    }
                });
                timeSliderET.triggers.Add(entry);

                Transform thickTimelineTransform = new GameObject().transform;
                thickTimelineTransform.SetParent(animationPattern.containingAtom.mainController.transform, false);
                thickTimeline = thickTimelineTransform.gameObject.AddComponent <LineRenderer>();
                thickTimeline.positionCount     = 0;
                thickTimeline.startWidth        = 0.02f;
                thickTimeline.endWidth          = 0.02f;
                thickTimeline.material          = animationPattern.rootLineDrawerMaterial;
                thickTimeline.material.color    = new Color(0.15f, 0.66f, 0.0f);
                thickTimeline.useWorldSpace     = false;
                thickTimeline.numCornerVertices = 6;
                thickTimeline.alignment         = LineAlignment.View;

                updateKeyframeLoop = StartCoroutine(UpdateEditingKeyframeLoop());

                lookAtCamera = new JSONStorableBool("UILookAtCamera", true, (bool on) =>
                {
                    ui.lookAtCamera    = on;
                    keyUI.lookAtCamera = on;
                });
                RegisterBool(lookAtCamera);
                CreateToggle(lookAtCamera);

                person.freeControllers.ToList().ForEach((fc) =>
                {
                    JSONStorableBool animateControl = new JSONStorableBool(fc.name, true);
                    RegisterBool(animateControl);
                    CreateToggle(animateControl, true);
                });

                CreateButton("Reverse Animation").button.onClick.AddListener(() =>
                {
                    List <AnimationStep> reversedSteps = animationPattern.steps.ToList();
                    reversedSteps.Reverse();

                    animationPattern.steps = reversedSteps.ToArray();
                    animationPattern.RecalculateTimeSteps();

                    keyframes.Reverse();
                });

                maxKeyframesPerRow = new JSONStorableFloat("max keyframes per row", 6, (float value) =>
                {
                }, 2, 20, true);
                CreateSlider(maxKeyframesPerRow);
                RegisterFloat(maxKeyframesPerRow);
            }
            catch (Exception e)
            {
                SuperController.LogError("Exception caught: " + e);
            }
        }
示例#24
0
        public ThrustController(DollmasterPlugin dm) : base(dm)
        {
            thrustEnabled = new JSONStorableBool("thrustEnabled", true);
            dm.RegisterBool(thrustEnabled);
            UIDynamicToggle moduleEnableToggle = dm.CreateToggle(thrustEnabled);

            moduleEnableToggle.label           = "Enable Thrusting";
            moduleEnableToggle.backgroundColor = Color.green;

            thrustAtomChooser = new JSONStorableStringChooser("thrustTarget", GetAnimationPatternNames(), "", "Thrust Control", (string name) =>
            {
                RestoreOriginalSlider();

                ap = null;

                UISetupState(SuperController.singleton.GetAtomByUid(name));
            });
            thrustAtomChooser.storeType = JSONStorableParam.StoreType.Full;
            dm.RegisterStringChooser(thrustAtomChooser);
            UIDynamicPopup popup = dm.CreatePopup(thrustAtomChooser);

            popup.popup.onOpenPopupHandlers += () =>
            {
                thrustAtomChooser.choices = GetAnimationPatternNames();
            };

            slider = dm.ui.CreateSlider("Thrust Speed", 300, 120);
            slider.transform.Translate(0, 0.15f, 0, Space.Self);

            slider.slider.onValueChanged.AddListener((float v) =>
            {
                if (ap == null)
                {
                    return;
                }

                JSONStorableFloat speedStore = ap.GetFloatJSONParam("speed");
                if (speedStore.slider != slider.slider)
                {
                    AttachCustomSlider();
                }
            });

            Image img = slider.GetComponentInChildren <Image>();

            img.color = new Color(0.4f, 0.2f, 0.245f, 1.0f);
            slider.labelText.color = new Color(1, 1, 1);

            slider.gameObject.SetActive(false);

            createButton = dm.ui.CreateButton("Generate Animation Pattern or...", 400, 120);
            createButton.transform.Translate(0, 0.15f, 0, Space.Self);
            createButton.buttonColor = new Color(0.4f, 0.2f, 0.245f, 1.0f);
            createButton.textColor   = new Color(1, 1, 1);

            createButton.button.onClick.AddListener(GenerateThrustAtoms);

            selectButton = dm.ui.CreateButton("Select Animation Pattern To Control", 400, 120);
            selectButton.transform.Translate(0.52f, 0.15f, 0, Space.Self);
            selectButton.buttonColor = new Color(0.4f, 0.2f, 0.245f, 1.0f);
            selectButton.textColor   = new Color(1, 1, 1);

            selectButton.button.onClick.AddListener(() =>
            {
                SuperController.singleton.SelectModeAtom((atom) =>
                {
                    if (atom == null)
                    {
                        return;
                    }

                    if (atom.GetStorableByID("AnimationPattern") == null)
                    {
                        SuperController.LogError("Select an Animation Pattern");
                        return;
                    }

                    AnimationPattern ap = atom.GetStorableByID("AnimationPattern") as AnimationPattern;
                    ap.SyncStepNames();
                    ap.autoSyncStepNamesJSON.SetVal(false);

                    thrustAtomChooser.SetVal(atom.uid);
                });
            });

            dm.CreateSpacer();

            GenerateThrustAtoms();
        }
示例#25
0
    // アニメーション 再生/変更
    private void ChangeAnimation(AnimationPattern pattern)
    {
        // アニメーションが生成されていなければreturn
        if (scriptRoot == null)
        {
            return;
        }

        // 再生する回数を指定します
        int timesPlay = 0;
        // 再生開始時のframeoffset(今回は0(初めから)で固定)
        int frameOffset = 0;
        // アニメーションの再生速度を指定します(1で標準)
        float rateTime = 1;

        // アニメーション生成済みなら受け取ったAnimationPatternごとに変数を設定
        if (scriptRoot != null)
        {
            switch (pattern)
            {
            case AnimationPattern.Wait:
                timesPlay = 0;        // ループ再生 ;
                break;

            case AnimationPattern.Walk:
                timesPlay = 0;        // ループ再生
                rateTime  = 1.5f;     // 再生速度を1.5倍にします
                break;

            case AnimationPattern.Jump:
                timesPlay = 1;        // 1回だけ再生
                break;

            case AnimationPattern.Push:
                timesPlay = 0;        // ループ再生
                break;

            case AnimationPattern.Pull:
                timesPlay = 0;        // ループ再生
                break;

            case AnimationPattern.Climb:
                timesPlay = 0;        // ループ再生
                rateTime  = 1.8f;     // 再生速度を1.8倍にします
                break;

            case AnimationPattern.Down:
                timesPlay = 0;        // ループ再生
                rateTime  = 1.8f;     // 再生速度を1.8倍にします
                break;

            case AnimationPattern.Death:
                timesPlay = 1;        // 1回だけ再生
                break;

            default:
                break;
            }
            // 設定した値を使用してアニメーションを再生する
            scriptRoot.AnimationPlay(-1, (int)pattern, timesPlay, frameOffset, rateTime);
        }
    }
示例#26
0
        IEnumerator Load(JSONClass saveObject)
        {
            yield return(new WaitForSeconds(2.0f));

            JSONArray savedNodes       = saveObject["nodes"].AsArray;
            JSONArray savedTransitions = saveObject["transitions"].AsArray;

            for (int i = 0; i < savedNodes.Count; i++)
            {
                Atom a = sc.GetAtomByUid(savedNodes[i]["atom"].Value);
                if (a == null)
                {
                    SuperController.LogError("Animation graph could not find the atom named " + savedNodes[i]["atom"].Value);
                    continue;
                }

                AnimationPattern ap = a.GetStorableByID("AnimationPattern") as AnimationPattern;
                if (ap == null)
                {
                    SuperController.LogError(a.name + " is not an animation pattern");
                    continue;
                }

                CreateNode(ap);
            }

            if (nodes.Count > 0)
            {
                root = nodes[0];
            }

            for (int i = 0; i < savedTransitions.Count; i++)
            {
                JSONClass transitionData = savedTransitions[i].AsObject;
                string    startName      = transitionData["start"].Value;
                string    endName        = transitionData["end"].Value;

                Atom a = sc.GetAtomByUid(startName);
                Atom b = sc.GetAtomByUid(endName);

                if (a == null)
                {
                    SuperController.LogError(startName + " atom was not found");
                    continue;
                }

                if (b == null)
                {
                    SuperController.LogError(endName + " atom was not found");
                    continue;
                }


                Transition t = CreateTransition(a, b);

                if (t != null)
                {
                    Node nodeA = FindNodeFromAtom(a);
                    if (nodeA != null)
                    {
                        nodeA.transitions.Add(t);
                    }
                }
            }
        }
示例#27
0
        public override void Init()
        {
            try
            {
                sc = SuperController.singleton;

                ui = new UI(this, 0.001f);
                ui.canvas.transform.SetParent(containingAtom.mainController.transform, false);

                UIDynamicButton entrySelector = ui.CreateButton("Select Entry");
                entrySelector.transform.Translate(0, 0.1f, 0);
                entrySelector.button.onClick.AddListener(() =>
                {
                    sc.SelectModeAtom((atom) =>
                    {
                        AnimationPattern ap = atom.GetStorableByID("AnimationPattern") as AnimationPattern;
                        if (ap == null)
                        {
                            SuperController.LogError("Only Animation Patterns can be selected.");
                            return;
                        }

                        root = CreateNode(ap);
                        CreateTransition(containingAtom, root.atom);

                        active = root;

                        entrySelector.gameObject.SetActive(false);
                        PerformSave();
                    });
                });

                UIDynamicButton playButton = ui.CreateButton("Test Start", 80, 60);
                playButton.transform.Translate(0, -0.2f, 0);
                playButton.button.onClick.AddListener(() =>
                {
                    if (root == null)
                    {
                        return;
                    }

                    active = root;
                    active.Start();
                });

                UIDynamicButton nextButton = ui.CreateButton("Test Next", 80, 60);
                nextButton.transform.Translate(0, -0.3f, 0);
                nextButton.button.onClick.AddListener(() =>
                {
                    if (active == null)
                    {
                        return;
                    }

                    Transition transition = active.GetRandomTransition();
                    if (transition != null)
                    {
                        Node nextNode = GetEndNodeFromTransition(transition);
                        if (nextNode != null)
                        {
                            active.Stop();
                            nextNode.Start();
                            active = nextNode;
                        }
                    }
                });

                UIDynamicButton doneEditingButton = ui.CreateButton("Done Editing", 80, 60);
                doneEditingButton.transform.Translate(0, -0.6f, 0);
                doneEditingButton.button.onClick.AddListener(() =>
                {
                    ui.canvas.enabled = false;
                    if (sc.GetSelectedAtom() == containingAtom)
                    {
                        sc.ClearSelection();
                    }
                });

                saveString = new JSONStorableString("graph", "");
                RegisterString(saveString);

                playNextWhenReady = new JSONStorableAction("play next if ready", () =>
                {
                    if (active == null)
                    {
                        return;
                    }

                    if (started == false)
                    {
                        active.Start();
                        started = true;
                        return;
                    }

                    if (active.ap.loop == false)
                    {
                        if (active.ap.GetCurrentTimeCounter() < active.ap.GetTotalTime())
                        {
                            return;
                        }
                    }

                    Transition transition = active.GetRandomTransition();
                    if (transition != null)
                    {
                        Node nextNode = GetEndNodeFromTransition(transition);
                        if (nextNode != null)
                        {
                            active.Stop();
                            nextNode.Start();
                            active = nextNode;
                        }
                    }
                });

                RegisterAction(playNextWhenReady);
            }
            catch (Exception e)
            {
                SuperController.LogError("Exception caught: " + e);
            }
        }
示例#28
0
        Node CreateNode(AnimationPattern ap)
        {
            Node foundNode = nodes.Find((other) =>
            {
                return(other.ap == ap);
            });

            if (foundNode != null)
            {
                sc.SelectController(containingAtom.mainController);
                return(foundNode);
            }

            Node node = new Node(ui, ap);

            //ap.containingAtom.SetOn(false);
            ap.SetBoolParamValue("on", false);
            ap.Pause();
            ap.ResetAnimation();

            lineMaterial = ap.rootLineDrawerMaterial;

            if (nodes.Contains(node) == false)
            {
                nodes.Add(node);
            }

            node.connectButton.button.onClick.AddListener(() =>
            {
                sc.SelectModeAtom((atom) =>
                {
                    if (atom == ap.containingAtom)
                    {
                        SuperController.LogError("Can't make a connection to itself.");
                        return;
                    }
                    AnimationPattern childAP = atom.GetStorableByID("AnimationPattern") as AnimationPattern;
                    if (childAP == null)
                    {
                        SuperController.LogError("Only Animation Patterns can be selected.");
                        return;
                    }

                    Node childNode        = CreateNode(childAP);
                    Transition transition = CreateTransition(node.atom, childNode.atom);
                    if (transition != null)
                    {
                        node.transitions.Add(transition);
                        PerformSave();
                    }
                });
            });

            node.disconnectButton.button.onClick.AddListener(() =>
            {
                node.transitions.ForEach((t) =>
                {
                    t.OnDestroy();
                    transitions.Remove(t);
                });

                node.transitions.Clear();
            });

            sc.SelectController(containingAtom.mainController);

            return(node);
        }