void Awake()
        {
            increaseButton.AddListener(EventTriggerType.PointerUp, e => _operateSpinButtonObservable.OnNext(0));
            decreaseButton.AddListener(EventTriggerType.PointerUp, e => _operateSpinButtonObservable.OnNext(0));
            increaseButton.AddListener(EventTriggerType.PointerDown, e => _operateSpinButtonObservable.OnNext(valueStep));
            decreaseButton.AddListener(EventTriggerType.PointerDown, e => _operateSpinButtonObservable.OnNext(-valueStep));

            var property = GetReactiveProperty();

            property.Subscribe(x => inputField.text = x.ToString());
            //float temp = 0f;
            var updateValueFromInputFieldStream = inputField.OnValueChangedAsObservable()
                                                  //.Where(x => Regex.IsMatch(x, @"^[0-9]+$"))
                                                  .Select(x => {
                var temp = 0f;
                if (float.TryParse(x, out temp))
                {
                    return(temp);
                }
                return(property.Value);
            });

            var updateValueFromSpinButtonStream = _operateSpinButtonObservable
                                                  //.Throttle(TimeSpan.FromMilliseconds(longPressTriggerMilliseconds))
                                                  //.Where(delta => Math.Abs(delta) > float.Epsilon)
                                                  //.SelectMany(delta => Observable.Interval(TimeSpan.FromMilliseconds(continuousPressIntervalMilliseconds))
                                                  //    .TakeUntil(_operateSpinButtonObservable.Where(d => Math.Abs(d) <= float.Epsilon))
                                                  //    .Select(_ => delta))
                                                  //.Merge(_operateSpinButtonObservable.Where(d => Math.Abs(d) > float.Epsilon))
                                                  .Select(delta => property.Value + delta);

            var isUndoRedoAction = false;

            Observable.Merge(
                updateValueFromSpinButtonStream,
                updateValueFromInputFieldStream)
            .Select(x => Mathf.Clamp(x, minValue, maxValue))
            .DistinctUntilChanged()
            .Where(_ => isUndoRedoAction ? (isUndoRedoAction = false) : true)
            .Select(x => new { current = x, prev = property.Value })
            .Subscribe(x => EditCommandManager.Do(
                           new Command(
                               () => property.Value = x.current,
                               () => { isUndoRedoAction = true; property.Value = x.prev; },
                               () => { isUndoRedoAction = true; property.Value = x.current; })))
            .AddTo(this);
        }
Пример #2
0
        IEnumerator LoadMusic(string fileName)
        {
            using (var _unityWebRequest = UnityWebRequestMultimedia.GetAudioClip(Path.Combine(MusicSelector.DirectoryPath.Value, fileName), AudioType.WAV)){
                yield return(_unityWebRequest.SendWebRequest());

                EditCommandManager.Clear();
                ResetEditor();

                AudioClip clip = null;

                if (_unityWebRequest.isHttpError || _unityWebRequest.isNetworkError)
                {
                    Debug.Log(_unityWebRequest.error.ToString());
                }
                else
                {
                    clip = DownloadHandlerAudioClip.GetContent(_unityWebRequest);
                    Audio.Source.clip = clip;

                    EditData.Name.Value = fileName;
                    LoadEditData();
                    Audio.OnLoad.OnNext(Unit.Default);
                }
            }

            /*
             * using (var www = new WWW("file:///" + Path.Combine(MusicSelector.DirectoryPath.Value, fileName)))
             * {
             *  yield return www;
             *
             *  EditCommandManager.Clear();
             *  ResetEditor();
             *  Audio.Source.clip = www.GetAudioClip();
             *
             *  if (Audio.Source.clip == null)
             *  {
             *      // TODO: 読み込み失敗時の処理
             *  }
             *  else
             *  {
             *      EditData.Name.Value = fileName;
             *      LoadEditData();
             *      Audio.OnLoad.OnNext(Unit.Default);
             *  }
             * }
             */
        }
        void Init()
        {
            var handlerOnMouseDownObservable = new Subject <Vector3>();

            handleImage.AddListener(
                EventTriggerType.PointerDown,
                (e) =>
            {
                handlerOnMouseDownObservable.OnNext(Vector3.right * ConvertUtils.SamplesToCanvasPositionX(CurrentSamples.Value));
            });

            var operateHandleObservable = this.UpdateAsObservable()
                                          .SkipUntil(handlerOnMouseDownObservable)
                                          .TakeWhile(_ => !Input.GetMouseButtonUp(0))
                                          .RepeatSafe()
                                          .Select(_ => ConvertUtils.ScreenToCanvasPosition(Input.mousePosition))
                                          .Select(canvasPos => ConvertUtils.CanvasPositionXToSamples(canvasPos.x))
                                          .Select(samples => Mathf.Clamp(samples, 0, Audio.Source.clip.samples))
                                          .DistinctUntilChanged();

            operateHandleObservable.Subscribe(samples => CurrentSamples.Value = samples);

            operateHandleObservable.Buffer(this.UpdateAsObservable().Where(_ => Input.GetMouseButtonUp(0)))
            .Where(b => 2 <= b.Count)
            .Select(x => new { current = x.Last(), prev = x.First() })
            .Subscribe(x => EditCommandManager.Do(
                           new Command(
                               () => CurrentSamples.Value = x.current,
                               () => CurrentSamples.Value = x.prev)));

            Observable.Merge(
                CurrentSamples.AsUnitObservable(),
                NoteCanvas.OffsetX.AsUnitObservable(),
                Audio.SmoothedTimeSamples.AsUnitObservable(),
                NoteCanvas.Width.AsUnitObservable(),
                EditData.OffsetSamples.AsUnitObservable())
            .Select(_ => CurrentSamples.Value)
            .Subscribe(x =>
            {
                var pos = lineRectTransform.localPosition;
                pos.x   = ConvertUtils.SamplesToCanvasPositionX(x);
                lineRectTransform.localPosition = pos;
            });
        }
Пример #4
0
        IEnumerator LoadMusic(string fileName)
        {
            using (var www = new WWW("file:///" + Path.Combine(MusicSelector.DirectoryPath.Value, fileName)))
            {
                yield return(www);

                EditCommandManager.Clear();
                ResetEditor();
                Audio.Source.clip = www.GetAudioClip();

                if (Audio.Source.clip == null)
                {
                    // TODO: 読み込み失敗時の処理
                }
                else
                {
                    EditData.Name.Value = fileName;
                    LoadEditData();
                    Audio.OnLoad.OnNext(Unit.Default);
                }
            }
        }
Пример #5
0
        void Init()
        {
            var operateCanvasScaleObservable = canvasEvents.MouseScrollWheelObservable
                                               .Where(_ => KeyInput.CtrlKey())
                                               .Merge(this.UpdateAsObservable().Where(_ => Input.GetKey(KeyCode.UpArrow)).Select(_ => 0.05f))
                                               .Merge(this.UpdateAsObservable().Where(_ => Input.GetKey(KeyCode.DownArrow)).Select(_ => - 0.05f))
                                               .Select(delta => NoteCanvas.Width.Value * (1 + delta))
                                               .Select(x => x / (Audio.Source.clip.samples / 100f))
                                               .Select(x => Mathf.Clamp(x, 0.1f, 2f))
                                               .Merge(canvasWidthScaleController.OnValueChangedAsObservable()
                                                      .DistinctUntilChanged())
                                               .DistinctUntilChanged()
                                               .Select(x => Audio.Source.clip.samples / 100f * x);

            operateCanvasScaleObservable.Subscribe(x => NoteCanvas.Width.Value = x);

            operateCanvasScaleObservable.Buffer(operateCanvasScaleObservable.ThrottleFrame(2))
            .Where(b => 2 <= b.Count)
            .Select(x => new { current = x.Last(), prev = x.First() })
            .Subscribe(x => EditCommandManager.Do(
                           new Command(
                               () => NoteCanvas.Width.Value = x.current,
                               () => NoteCanvas.Width.Value = x.prev)));
        }
Пример #6
0
        void Awake()
        {
            // Initialize canvas offset x
            Audio.OnLoad.Subscribe(_ => NoteCanvas.OffsetX.Value = -Screen.width * 0.45f * NoteCanvas.ScaleFactor.Value);

            var operateCanvasOffsetXObservable = this.UpdateAsObservable()
                                                 .SkipUntil(canvasEvents.VerticalLineOnMouseDownObservable)
                                                 .TakeWhile(_ => !Input.GetMouseButtonUp(0))
                                                 .Select(_ => Input.mousePosition.x)
                                                 .Buffer(2, 1).Where(b => 2 <= b.Count)
                                                 .RepeatSafe()
                                                 .Select(b => (b[1] - b[0]) * NoteCanvas.ScaleFactor.Value)
                                                 .Select(x => x + NoteCanvas.OffsetX.Value)
                                                 .Select(x => new { x, max = Screen.width * 0.5f * 0.95f * NoteCanvas.ScaleFactor.Value })
                                                 .Select(v => Mathf.Clamp(v.x, -v.max, v.max))
                                                 .DistinctUntilChanged();

            operateCanvasOffsetXObservable.Subscribe(x => NoteCanvas.OffsetX.Value = x);

            operateCanvasOffsetXObservable.Buffer(this.UpdateAsObservable().Where(_ => Input.GetMouseButtonUp(0)))
            .Where(b => 2 <= b.Count)
            .Select(x => new { current = x.Last(), prev = x.First() })
            .Subscribe(x => EditCommandManager.Do(
                           new Command(
                               () => NoteCanvas.OffsetX.Value = x.current,
                               () => NoteCanvas.OffsetX.Value = x.prev)));

            NoteCanvas.OffsetX.Subscribe(x =>
            {
                var pos  = verticalLineRect.localPosition;
                var pos2 = waveformRenderImage.localPosition;
                pos.x    = pos2.x = x;
                verticalLineRect.localPosition    = pos;
                waveformRenderImage.localPosition = pos2;
            });
        }
Пример #7
0
        void Init()
        {
            var closestNoteAreaOnMouseDownObservable = canvasEvents.NotesRegionOnMouseDownObservable
                                                       .Where(_ => !KeyInput.CtrlKey())
                                                       .Where(_ => !Input.GetMouseButtonDown(1))
                                                       .Where(_ => 0 <= NoteCanvas.ClosestNotePosition.Value.num);

            closestNoteAreaOnMouseDownObservable
            .Where(_ => EditState.NoteType.Value == NoteTypes.Single)
            .Where(_ => !KeyInput.ShiftKey())
            .Merge(closestNoteAreaOnMouseDownObservable
                   .Where(_ => EditState.NoteType.Value == NoteTypes.Long))
            .Subscribe(_ =>
            {
                if (EditData.Notes.ContainsKey(NoteCanvas.ClosestNotePosition.Value))
                {
                    EditData.Notes[NoteCanvas.ClosestNotePosition.Value].OnClickObservable.OnNext(Unit.Default);
                }
                else
                {
                    RequestForEditNote.OnNext(
                        new Note(
                            NoteCanvas.ClosestNotePosition.Value,
                            EditState.NoteType.Value,
                            NotePosition.None,
                            EditState.LongNoteTailPosition.Value));
                }
            });


            // Start editing of long note
            closestNoteAreaOnMouseDownObservable
            .Where(_ => EditState.NoteType.Value == NoteTypes.Single)
            .Where(_ => KeyInput.ShiftKey())
            .Do(_ => EditState.NoteType.Value = NoteTypes.Long)
            .Subscribe(_ => RequestForAddNote.OnNext(
                           new Note(
                               NoteCanvas.ClosestNotePosition.Value,
                               NoteTypes.Long,
                               NotePosition.None,
                               NotePosition.None)));


            // Finish editing long note by press-escape or right-click
            this.UpdateAsObservable()
            .Where(_ => EditState.NoteType.Value == NoteTypes.Long)
            .Where(_ => Input.GetKeyDown(KeyCode.Escape) || Input.GetMouseButtonDown(1))
            .Subscribe(_ => EditState.NoteType.Value = NoteTypes.Single);

            var finishEditLongNoteObservable = EditState.NoteType.Where(editType => editType == NoteTypes.Single);

            finishEditLongNoteObservable.Subscribe(_ => EditState.LongNoteTailPosition.Value = NotePosition.None);


            RequestForRemoveNote.Buffer(RequestForRemoveNote.ThrottleFrame(1))
            .Select(b => b.OrderBy(note => note.position.ToSamples(Audio.Source.clip.frequency, EditData.BPM.Value)).ToList())
            .Subscribe(notes => EditCommandManager.Do(
                           new Command(
                               () => notes.ForEach(RemoveNote),
                               () => notes.ForEach(AddNote))));

            RequestForAddNote.Buffer(RequestForAddNote.ThrottleFrame(1))
            .Select(b => b.OrderBy(note => note.position.ToSamples(Audio.Source.clip.frequency, EditData.BPM.Value)).ToList())
            .Subscribe(notes => EditCommandManager.Do(
                           new Command(
                               () => notes.ForEach(AddNote),
                               () => notes.ForEach(RemoveNote))));

            RequestForChangeNoteStatus.Select(note => new { current = note, prev = EditData.Notes[note.position].note })
            .Buffer(RequestForChangeNoteStatus.ThrottleFrame(1))
            .Select(b => b.OrderBy(note => note.current.position.ToSamples(Audio.Source.clip.frequency, EditData.BPM.Value)).ToList())
            .Subscribe(notes => EditCommandManager.Do(
                           new Command(
                               () => notes.ForEach(x => ChangeNoteStates(x.current)),
                               () => notes.ForEach(x => ChangeNoteStates(x.prev)))));


            RequestForEditNote.Subscribe(note =>
            {
                if (note.type == NoteTypes.Single)
                {
                    (EditData.Notes.ContainsKey(note.position)
                        ? RequestForRemoveNote
                        : RequestForAddNote)
                    .OnNext(note);
                }
                else if (note.type == NoteTypes.Long)
                {
                    if (!EditData.Notes.ContainsKey(note.position))
                    {
                        RequestForAddNote.OnNext(note);
                        return;
                    }

                    var noteObject = EditData.Notes[note.position];
                    (noteObject.note.type == NoteTypes.Long
                        ? RequestForRemoveNote
                        : RequestForChangeNoteStatus)
                    .OnNext(noteObject.note);
                }
            });
        }
        void Init()
        {
            this.UpdateAsObservable()
            .Where(_ => Audio.Source.clip != null)
            .Select(_ => Audio.Source.clip.samples)
            .Subscribe(samples => playbackPositionController.maxValue = samples);

            // Input -> Audio timesamples -> Model timesamples -> UI

            // Input (arrow key)
            var operateArrowKeyObservable = Observable.Merge(
                this.UpdateAsObservable().Where(_ => Input.GetKey(KeyCode.RightArrow)).Select(_ => 7),
                this.UpdateAsObservable().Where(_ => Input.GetKey(KeyCode.LeftArrow)).Select(_ => - 7))
                                            .Select(delta => delta * (KeyInput.CtrlKey() ? 5 : 1))
                                            .Select(delta => delta
                                                    / NoteCanvas.Width.Value
                                                    * NoteCanvas.ScaleFactor.Value
                                                    * Audio.Source.clip.samples)
                                            .Select(delta => Audio.Source.timeSamples + delta);

            operateArrowKeyObservable.Where(_ => Audio.IsPlaying.Value)
            .Do(_ => Audio.IsPlaying.Value = false)
            .Subscribe(_ => EditState.IsOperatingPlaybackPositionDuringPlay.Value = true);

            operateArrowKeyObservable.Where(_ => EditState.IsOperatingPlaybackPositionDuringPlay.Value)
            .Throttle(TimeSpan.FromMilliseconds(50))
            .Do(_ => Audio.IsPlaying.Value = true)
            .Subscribe(_ => EditState.IsOperatingPlaybackPositionDuringPlay.Value = false);

            // Input (scroll pad)
            var operateScrollPadObservable = this.UpdateAsObservable()
                                             .SkipUntil(canvasEvents.WaveformRegionOnMouseDownObservable
                                                        .Where(_ => !Input.GetMouseButtonDown(1)))
                                             .TakeWhile(_ => !Input.GetMouseButtonUp(0))
                                             .Select(_ => Input.mousePosition.x)
                                             .Buffer(2, 1).Where(b => 2 <= b.Count)
                                             .RepeatSafe()
                                             .Select(b => (b[0] - b[1])
                                                     / NoteCanvas.Width.Value
                                                     * NoteCanvas.ScaleFactor.Value
                                                     * Audio.Source.clip.samples)
                                             .Select(delta => Audio.Source.timeSamples + delta);

            canvasEvents.WaveformRegionOnMouseDownObservable
            .Where(_ => Audio.IsPlaying.Value)
            .Do(_ => Audio.IsPlaying.Value = false)
            .Subscribe(_ => EditState.IsOperatingPlaybackPositionDuringPlay.Value = true);

            this.UpdateAsObservable()
            .Where(_ => EditState.IsOperatingPlaybackPositionDuringPlay.Value)
            .Where(_ => Input.GetMouseButtonUp(0))
            .Do(_ => Audio.IsPlaying.Value = true)
            .Subscribe(_ => EditState.IsOperatingPlaybackPositionDuringPlay.Value = false);

            // Input (mouse scroll wheel)
            var operateMouseScrollWheelObservable = canvasEvents.MouseScrollWheelObservable
                                                    .Where(_ => !KeyInput.CtrlKey())
                                                    .Select(delta => Audio.Source.clip.samples / 100f * -delta)
                                                    .Select(deltaSamples => Audio.Source.timeSamples + deltaSamples);

            operateMouseScrollWheelObservable.Where(_ => Audio.IsPlaying.Value)
            .Do(_ => EditState.IsOperatingPlaybackPositionDuringPlay.Value = true)
            .Subscribe(_ => Audio.IsPlaying.Value = false);

            operateMouseScrollWheelObservable.Throttle(TimeSpan.FromMilliseconds(350))
            .Where(_ => EditState.IsOperatingPlaybackPositionDuringPlay.Value)
            .Do(_ => EditState.IsOperatingPlaybackPositionDuringPlay.Value = false)
            .Subscribe(_ => Audio.IsPlaying.Value = true);

            var isRedoUndoAction = false;

            // Input (slider)
            var operatePlayPositionSliderObservable = playbackPositionController.OnValueChangedAsObservable()
                                                      .DistinctUntilChanged();


            // Input -> Audio timesamples
            var operatePlaybackPositionObservable = Observable.Merge(
                operateArrowKeyObservable,
                operateScrollPadObservable,
                operateMouseScrollWheelObservable,
                operatePlayPositionSliderObservable)
                                                    .Select(timeSamples => Mathf.FloorToInt(timeSamples))
                                                    .Select(timeSamples => Mathf.Clamp(timeSamples, 0, Audio.Source.clip.samples - 1));

            operatePlaybackPositionObservable.Subscribe(timeSamples => Audio.Source.timeSamples = timeSamples);

            operatePlaybackPositionObservable.Buffer(operatePlaybackPositionObservable.ThrottleFrame(10))
            .Where(_ => isRedoUndoAction ? (isRedoUndoAction = false) : true)
            .Where(b => 2 <= b.Count)
            .Select(x => new { current = x.Last(), prev = x.First() })
            .Subscribe(x => EditCommandManager.Do(
                           new Command(
                               () => Audio.TimeSamples.Value = x.current,
                               () => { isRedoUndoAction = true; Audio.TimeSamples.Value = x.prev; },
                               () => { isRedoUndoAction = true; Audio.TimeSamples.Value = x.current; })));


            // Audio timesamples -> Model timesamples
            Audio.Source.ObserveEveryValueChanged(audio => audio.timeSamples)
            .DistinctUntilChanged()
            .Subscribe(timeSamples => Audio.TimeSamples.Value = timeSamples);

            this.UpdateAsObservable()
            .Where(_ => Audio.Source.clip != null)
            .Where(_ => Audio.Source.timeSamples > Audio.Source.clip.samples - 1)
            .Subscribe(_ => Audio.IsPlaying.Value = false);


            // Model timesamples -> UI(slider)
            Audio.TimeSamples.Subscribe(timeSamples => playbackPositionController.value = timeSamples);

            // Model timesamples -> UI(text)
            Audio.TimeSamples.Select(_ => TimeSpan.FromSeconds(Audio.Source.time).ToString().Substring(3, 5))
            .DistinctUntilChanged()
            .Select(elapsedTime =>
                    elapsedTime + " / "
                    + TimeSpan.FromSeconds(Audio.Source.clip.samples / (float)Audio.Source.clip.frequency).ToString().Substring(3, 5))
            .SubscribeToText(playbackTimeDisplayText);
        }