예제 #1
0
 public UmlNote GetOrCreateNote(NoteLocation location)
 {
     if (!_notes.TryGetValue(location, out var note))
     {
         _notes[location] = note = new UmlNote();
     }
     return(note);
 }
예제 #2
0
 //-------------------------------------------------------------------------------------------------------------------------------
 // Handle the drag  drop and resize location of the notes
 //-------------------------------------------------------------------------------------------------------------------------------
 private void inApp_LocationChanged(object sender, EventArgs e)
 {
     foreach (var note in Notes)
     {
         if (note.InApplication != null)
         {
             NoteLocation ln = adjustLocation(note);
             note.Left = ln.X;
             note.Top  = ln.Y;
         }
     }
 }
예제 #3
0
        public bool BeginPlaySong(Song s, bool pal, int startNote)
        {
            song                    = s;
            famitrackerTempo        = song.UsesFamiTrackerTempo;
            famitrackerSpeed        = song.FamitrackerSpeed;
            palPlayback             = pal;
            playPosition            = startNote;
            playLocation            = new NoteLocation(0, 0);
            frameNumber             = 0;
            famitrackerTempoCounter = 0;
            channelStates           = CreateChannelStates(this, song.Project, apuIndex, song.Project.ExpansionNumN163Channels, palPlayback);

            NesApu.InitAndReset(apuIndex, sampleRate, palPlayback, tndMode, song.Project.ExpansionAudioMask, song.Project.ExpansionNumN163Channels, dmcCallback);

            ResetFamiStudioTempo();
            UpdateChannelsMuting();

            //Debug.WriteLine($"START SEEKING!!");

            if (startNote != 0)
            {
                seeking = true;
                NesApu.StartSeeking(apuIndex);

                AdvanceChannels();
                UpdateChannels();
                UpdateTempo();

                while (playLocation.ToAbsoluteNoteIndex(song) < startNote - 1)
                {
                    if (!PlaySongFrameInternal(true))
                    {
                        break;
                    }
                }

                NesApu.StopSeeking(apuIndex);
                seeking = false;
            }
            else
            {
                AdvanceChannels();
                UpdateChannels();
                UpdateTempo();
            }

            playPosition = playLocation.ToAbsoluteNoteIndex(song);
            UpdateBeat();

            EndFrame();

            return(true);
        }
예제 #4
0
        public UmlNote AddNote(NoteLocation location, string noteText, IUmlFill background = null)
        {
            noteText = noteText?.Trim();
            if (string.IsNullOrEmpty(noteText))
            {
                return(null);
            }
            var note = GetOrCreateNote(location);

            if (background != null)
            {
                note.Background = background;
            }
            note.Text += "\n" + noteText;
            return(note);
        }
예제 #5
0
 //-------------------------------------------------------------------------------------------------------------------------------
 // check if the specified location (X, Y) is already used by another note
 //-------------------------------------------------------------------------------------------------------------------------------
 private bool isLocationAlreadyUsed(NoteLocation location, UINotifier note)
 {
     foreach (var p in Notes)
     {
         if (p.Left == location.X &&
             p.Top == location.Y)
         {
             if (note.InApplication != null &&
                 p.ID == note.ID)
             {
                 return(false);
             }
             return(true);
         }
     }
     return(false);
 }
예제 #6
0
        //-------------------------------------------------------------------------------------------------------------------------------
        // Find a valid position for the note into the note area:
        // 1. Inside the Screen (support multiple screens)
        // 2. Inside the father application (if specified)
        //-------------------------------------------------------------------------------------------------------------------------------
        private NoteLocation adjustLocation(UINotifier note)
        {
            Rectangle notesArea;
            int       nColumn = 0, xShift = 25;                                               // Custom note overlay
            //  x_Shift     = Width + 5;                                         // Full visible note (no overlay)
            bool add = false;

            if (InApplication != null && InApplication.WindowState == FormWindowState.Normal)        // Get the available notes area, based on the type of note location
            {
                notesArea = InApplication.Bounds;
            }
            else
            {
                notesArea = new Rectangle(Screen.GetWorkingArea(note).Left,
                                          Screen.GetWorkingArea(note).Top,
                                          Screen.GetWorkingArea(note).Width,
                                          Screen.GetWorkingArea(note).Height);
            }

            int nMaxRows    = notesArea.Height / Height;                             // Max number of rows in the available space
            int nMaxColumns = notesArea.Width / xShift;                              // Max number of columns in the available space

            noteLocation = new NoteLocation(notesArea.Width +                        // Initial Position X
                                            notesArea.Left -
                                            Width,
                                            notesArea.Height +                        // Initial Position Y
                                            notesArea.Top -
                                            Height);

            while (nMaxRows > 0 && !add)                                              // Check the latest available position (no overlap)
            {
                for (int nRow = 1; nRow <= nMaxRows; nRow++)
                {
                    noteLocation.Y = notesArea.Height +
                                     notesArea.Top -
                                     Height * nRow;

                    if (!isLocationAlreadyUsed(noteLocation, note))
                    {
                        add = true; break;
                    }

                    if (nRow == nMaxRows)                                            // X shift if no more column space
                    {
                        nColumn++;
                        nRow = 0;

                        noteLocation.X = notesArea.Width +
                                         notesArea.Left -
                                         Width - xShift * nColumn;
                    }

                    if (nColumn >= nMaxColumns)                                      // Last exit condition: the screen is full of note
                    {
                        add = true; break;
                    }
                }
            }

            noteLocation.initialLocation = new Point(noteLocation.X,                  // Init the initial Location, for drag & drop
                                                     noteLocation.Y);
            return(noteLocation);
        }
예제 #7
0
        //-------------------------------------------------------------------------------------------------------------------------------
        // Create the Note and handle its location
        //-------------------------------------------------------------------------------------------------------------------------------
        private void setNotifier(string description, UINotifierType noteType, string title, bool isUpdate = false)
        {
            Title           = title;
            Description     = description;
            _uiNotifierType = noteType;

            noteTitle.Text   = title;                             // Fill the UINotifier data title
            noteContent.Text = description;                       // Fill the UINotifier data description
            noteDate.Text    = DateTime.Now + "";                 // Fill the UINotifier data Timestamp

            #region ADJUST COLORS

            switch (noteType)
            {
            case UINotifierType.ERROR:
                icon.Symbol      = 61527;
                icon.SymbolColor = UIStyles.Red.ButtonFillColor;
                LeaveColor       = UIStyles.Red.ButtonFillColor;
                HoverColor       = UIStyles.Red.ButtonFillHoverColor;
                break;

            case UINotifierType.INFO:
                icon.Symbol      = 61530;
                icon.SymbolColor = UIStyles.Blue.ButtonFillColor;
                LeaveColor       = UIStyles.Blue.ButtonFillColor;
                HoverColor       = UIStyles.Blue.ButtonFillHoverColor;
                break;

            case UINotifierType.WARNING:
                icon.Symbol      = 61553;
                icon.SymbolColor = UIStyles.Orange.ButtonFillColor;
                LeaveColor       = UIStyles.Orange.ButtonFillColor;
                HoverColor       = UIStyles.Orange.ButtonFillHoverColor;
                break;

            case UINotifierType.OK:
                icon.Symbol      = 61528;
                icon.SymbolColor = UIStyles.Green.ButtonFillColor;
                LeaveColor       = UIStyles.Green.ButtonFillColor;
                HoverColor       = UIStyles.Green.ButtonFillHoverColor;
                break;
            }

            buttonClose.BackColor = LeaveColor;                              // Init colors
            buttonMenu.BackColor  = LeaveColor;
            noteTitle.BackColor   = LeaveColor;

            buttonClose.MouseHover += (s, e) =>                    // Mouse hover
            {
                buttonClose.BackColor = HoverColor;
                buttonMenu.BackColor  = HoverColor;
                noteTitle.BackColor   = HoverColor;
            };
            buttonMenu.MouseHover += (s, e) =>
            {
                buttonMenu.BackColor  = HoverColor;
                buttonClose.BackColor = HoverColor;
                noteTitle.BackColor   = HoverColor;
            }; noteTitle.MouseHover += (s, e) =>
            {
                buttonMenu.BackColor  = HoverColor;
                buttonClose.BackColor = HoverColor;
                noteTitle.BackColor   = HoverColor;
            };

            buttonClose.MouseLeave += (s, e) =>                    // Mouse leave
            {
                buttonClose.BackColor = LeaveColor;
                buttonMenu.BackColor  = LeaveColor;
                noteTitle.BackColor   = LeaveColor;
            };
            buttonMenu.MouseLeave += (s, e) =>
            {
                buttonMenu.BackColor  = LeaveColor;
                buttonClose.BackColor = LeaveColor;
                noteTitle.BackColor   = LeaveColor;
            };
            noteTitle.MouseLeave += (s, e) =>
            {
                buttonMenu.BackColor  = LeaveColor;
                buttonClose.BackColor = LeaveColor;
                noteTitle.BackColor   = LeaveColor;
            };

            #endregion ADJUST COLORS

            #region DIALOG NOTE

            if (IsDialog)
            {
                Button ok_button = new Button();                     // Dialog note comes with a simple Ok button
                ok_button.FlatStyle = FlatStyle.Flat;
                ok_button.BackColor = LeaveColor;
                ok_button.ForeColor = Color.White;
                Size = new Size(Size.Width,              // Resize the note to contain the button
                                Size.Height + 50);
                ok_button.Size     = new Size(120, 40);
                ok_button.Location = new Point(Size.Width / 2 - ok_button.Size.Width / 2,
                                               Size.Height - 50);
                ok_button.Text   = UILocalize.OK;
                ok_button.Click += onOkButtonClick;
                Controls.Add(ok_button);

                noteDate.Location = new Point(noteDate.Location.X,    // Shift down the date location
                                              noteDate.Location.Y + 44);

                noteLocation = new NoteLocation(Left, Top);      // Default Center Location
            }

            #endregion DIALOG NOTE

            #region NOTE LOCATION

            if (!IsDialog && !isUpdate)
            {
                NoteLocation location = adjustLocation(this);          // Set the note location

                Left = location.X;                                     // UINotifier position X
                Top  = location.Y;                                     // UINotifier position Y
            }

            #endregion NOTE LOCATION
        }
예제 #8
0
        public void Advance(Song song, NoteLocation location, ref int famitrackerSpeed)
        {
            // When advancing row, if there was a delayed note, play it immediately. That's how FamiTracker does it.
            if (delayedNote != null)
            {
                PlayNote(delayedNote, delayedNoteSlidePitch, delayedNoteSlideStep);
                delayedNote        = null;
                delayedNoteCounter = 0;
            }

            var channel = song.GetChannelByType(channelType);
            var pattern = channel.PatternInstances[location.PatternIndex];

            if (pattern == null)
            {
                return;
            }

            pattern.Notes.TryGetValue(location.NoteIndex, out var newNote);

            var needClone = true;

            // Generate a release note if the release counter reaches zero.
            if (releaseCounter > 0 && --releaseCounter == 0 && (newNote == null || !newNote.IsMusicalOrStop))
            {
                newNote       = newNote == null ? new Note() : newNote.Clone();
                newNote.Value = Note.NoteRelease;
                needClone     = false;
            }

            // Generate a stop note if the stop counter reaches zero.
            if (durationCounter > 0 && --durationCounter == 0 && (newNote == null || !newNote.IsMusicalOrStop))
            {
                newNote       = newNote == null ? new Note() : newNote.Clone();
                newNote.Value = Note.NoteStop;
                needClone     = false;
            }

            if (newNote != null)
            {
                // We dont delay speed effects. This is not what FamiTracker does, but I dont care.
                // There is a special place in hell for people who delay speed effect.
                if (newNote.HasSpeed)
                {
                    famitrackerSpeed = newNote.Speed;
                }

                // Slide params needs to be computed right away since we wont have access to the play position/channel later.
                int noteSlidePitch = 0;
                int noteSlideStep  = 0;

                if (newNote.IsMusical)
                {
                    if (newNote.IsSlideNote)
                    {
                        channel.ComputeSlideNoteParams(newNote, location, famitrackerSpeed, noteTable, palPlayback, true, out noteSlidePitch, out noteSlideStep, out _);
                    }

                    if (newNote.HasRelease)
                    {
                        releaseCounter = newNote.Release;
                    }

                    durationCounter = newNote.Duration;
                }

                // Store note for later if delayed.
                if (newNote.HasNoteDelay)
                {
                    delayedNote           = newNote;
                    delayedNoteCounter    = newNote.NoteDelay + 1;
                    delayedNoteSlidePitch = noteSlidePitch;
                    delayedNoteSlideStep  = noteSlideStep;
                    return;
                }

                PlayNote(newNote, noteSlidePitch, noteSlideStep, needClone);
            }
        }
예제 #9
0
        private void CreateSlideNotes(Song s, Dictionary <Pattern, RowFxData[, ]> patternFxData)
        {
            var processedPatterns = new HashSet <Pattern>();

            // Convert slide notes + portamento to our format.
            foreach (var c in s.Channels)
            {
                if (!c.SupportsSlideNotes)
                {
                    continue;
                }

                var songSpeed          = s.FamitrackerSpeed;
                var lastNoteInstrument = (Instrument)null;
                var lastNoteArpeggio   = (Arpeggio)null;
                var lastNoteValue      = (byte)Note.NoteInvalid;
                var portamentoSpeed    = 0;
                var slideSpeed         = 0;
                var slideShift         = c.IsN163WaveChannel ? 2 : 0;
                var slideSign          = c.IsN163WaveChannel || c.IsFdsWaveChannel || c.IsVrc7FmChannel ? -1 : 1; // Inverted channels.

                for (int p = 0; p < s.Length; p++)
                {
                    var pattern = c.PatternInstances[p];

                    if (pattern == null)
                    {
                        continue;
                    }

                    var patternLen = s.GetPatternLength(p);

                    for (var it = pattern.GetDenseNoteIterator(0, patternLen); !it.Done; it.Next())
                    {
                        var location = new NoteLocation(p, it.CurrentTime);
                        var note     = it.CurrentNote;

                        // Look for speed changes.
                        s.ApplySpeedEffectAt(location, ref songSpeed);

                        if (!patternFxData.ContainsKey(pattern) || processedPatterns.Contains(pattern))
                        {
                            continue;
                        }

                        var fxData      = patternFxData[pattern];
                        var slideTarget = 0;

                        for (int i = 0; i < fxData.GetLength(1); i++)
                        {
                            var fx = fxData[location.NoteIndex, i];

                            if (fx.param != 0)
                            {
                                // When the effect it turned on, we need to add a note.
                                if ((fx.fx == Effect_PortaUp ||
                                     fx.fx == Effect_PortaDown ||
                                     fx.fx == Effect_SlideUp ||
                                     fx.fx == Effect_SlideDown) &&
                                    lastNoteValue >= Note.MusicalNoteMin &&
                                    lastNoteValue <= Note.MusicalNoteMax && (note == null || !note.IsValid))
                                {
                                    if (note == null)
                                    {
                                        note = pattern.GetOrCreateNoteAt(location.NoteIndex);
                                        it.Resync();
                                    }

                                    note.Value      = lastNoteValue;
                                    note.Instrument = lastNoteInstrument;
                                    note.Arpeggio   = lastNoteArpeggio;
                                    note.HasAttack  = false;
                                }
                            }

                            if (fx.fx == Effect_PortaUp)
                            {
                                // If we have a Qxx/Rxx on the same row as a 1xx/2xx, things get weird.
                                if (slideTarget == 0)
                                {
                                    slideSpeed = (-fx.param * slideSign) << slideShift;
                                }
                            }
                            if (fx.fx == Effect_PortaDown)
                            {
                                // If we have a Qxx/Rxx on the same row as a 1xx/2xx, things get weird.
                                if (slideTarget == 0)
                                {
                                    slideSpeed = (fx.param * slideSign) << slideShift;
                                }
                            }
                            if (fx.fx == Effect_Portamento)
                            {
                                portamentoSpeed = fx.param;
                            }
                            if (fx.fx == Effect_SlideUp && note != null && note.IsMusical)
                            {
                                slideTarget = Utils.Clamp(note.Value + (fx.param & 0xf), Note.MusicalNoteMin, Note.MusicalNoteMax);
                                slideSpeed  = (-((fx.param >> 4) * 2 + 1)) << slideShift;
                            }
                            if (fx.fx == Effect_SlideDown && note != null && note.IsMusical)
                            {
                                slideTarget = Utils.Clamp(note.Value - (fx.param & 0xf), Note.MusicalNoteMin, Note.MusicalNoteMax);
                                slideSpeed  = (((fx.param >> 4) * 2 + 1)) << slideShift;
                            }
                        }

                        // Create a slide note.
                        if (note != null && !note.IsSlideNote)
                        {
                            if (note.IsMusical)
                            {
                                var slideSource = note.Value;
                                var noteTable   = NesApu.GetNoteTableForChannelType(c.Type, s.Project.PalMode, s.Project.ExpansionNumChannels);
                                var pitchLimit  = NesApu.GetPitchLimitForChannelType(c.Type);

                                // If we have a new note with auto-portamento enabled, we need to
                                // swap the notes since our slide notes work backward compared to
                                // FamiTracker.
                                if (portamentoSpeed != 0)
                                {
                                    // Ignore notes with no attack since we created them to handle a previous slide.
                                    if (note.HasAttack && lastNoteValue >= Note.MusicalNoteMin && lastNoteValue <= Note.MusicalNoteMax)
                                    {
                                        slideSpeed  = portamentoSpeed;
                                        slideTarget = note.Value;
                                        slideSource = lastNoteValue;
                                        note.Value  = lastNoteValue;
                                    }
                                }

                                // Our implementation of VRC7 pitches is quite different from FamiTracker.
                                // Compensate for larger pitches in higher octaves by shifting. We cant shift by
                                // a large amount because the period is 9-bit and FamiTracker is restricted to
                                // this for slides (octave never changes).
                                var octaveSlideShift = c.IsVrc7FmChannel && note.Value >= 12 ? 1 : 0;

                                // 3xx/Qxy/Rxy : We know which note we are sliding to and the speed, but we
                                //               don't know how many frames it will take to get there.
                                if (slideTarget != 0)
                                {
                                    // Advance in the song until we have the correct number of frames.
                                    var numFrames = Math.Max(1, Math.Abs((noteTable[slideSource] - noteTable[slideTarget]) / (slideSpeed << octaveSlideShift)));
                                    note.SlideNoteTarget = (byte)slideTarget;

                                    // TODO: Here we consider if the start note has a delay, but ignore the end note. It might have one too.
                                    var nextLocation = location;
                                    s.AdvanceNumberOfFrames(ref nextLocation, numFrames, note.HasNoteDelay ? -note.NoteDelay : 0, songSpeed, s.Project.PalMode);

                                    // Still to see if there is a note between the current one and the
                                    // next note, this could append if you add a note before the slide
                                    // is supposed to finish.
                                    if (FindNextSlideEffect(c, location, out var nextLocation2, patternFxData))
                                    {
                                        nextLocation = NoteLocation.Min(nextLocation, nextLocation2);

                                        // If the slide is interrupted by another slide effect, we will not reach
                                        // the final target, but rather some intermediate note. Let's do our best
                                        // to interpolate and figure out the best note.
                                        var numFramesUntilNextSlide = s.CountFramesBetween(location, nextLocation, songSpeed, s.Project.PalMode);
                                        var ratio             = Utils.Clamp(numFramesUntilNextSlide / numFrames, 0.0f, 1.0f);
                                        var intermediatePitch = (int)Math.Round(Utils.Lerp(noteTable[slideSource], noteTable[slideTarget], ratio));

                                        slideTarget          = FindBestMatchingNote(noteTable, intermediatePitch, Math.Sign(slideSpeed));
                                        note.SlideNoteTarget = (byte)slideTarget;
                                    }

                                    if (nextLocation.PatternIndex < s.Length)
                                    {
                                        // Add an extra note with no attack to stop the slide.
                                        var nextPattern = c.PatternInstances[nextLocation.PatternIndex];
                                        if (!nextPattern.Notes.TryGetValue(nextLocation.NoteIndex, out var nextNote) || !nextNote.IsValid)
                                        {
                                            nextNote            = nextPattern.GetOrCreateNoteAt(nextLocation.NoteIndex);
                                            nextNote.Instrument = note.Instrument;
                                            nextNote.Value      = (byte)slideTarget;
                                            nextNote.HasAttack  = false;
                                            it.Resync();
                                        }
                                        else if (nextNote != null && nextNote.IsRelease)
                                        {
                                            Log.LogMessage(LogSeverity.Warning, $"A slide note ends on a release note. This is currently unsupported and will require manual correction. {GetPatternString(nextPattern, nextLocation.NoteIndex)}");
                                        }
                                    }

                                    // 3xx, Qxx and Rxx stops when its done.
                                    slideSpeed = 0;
                                }

                                // 1xx/2xy : We know the speed at which we are sliding, but need to figure out what makes it stop.
                                else if (slideSpeed != 0 && FindNextSlideEffect(c, location, out var nextLocation, patternFxData))
                                {
                                    // See how many frames until the slide stops.
                                    var numFrames = (int)Math.Round(s.CountFramesBetween(location, nextLocation, songSpeed, s.Project.PalMode));

                                    // TODO: Here we consider if the start note has a delay, but ignore the end note. It might have one too.
                                    numFrames = Math.Max(1, numFrames - (note.HasNoteDelay ? note.NoteDelay : 0));

                                    // Compute the pitch delta and find the closest target note.
                                    var newNotePitch = Utils.Clamp(noteTable[slideSource] + numFrames * (slideSpeed << octaveSlideShift), 0, pitchLimit);
                                    var newNote      = FindBestMatchingNote(noteTable, newNotePitch, Math.Sign(slideSpeed));

                                    note.SlideNoteTarget = (byte)newNote;

                                    // If the FX was turned off, we need to add an extra note.
                                    var nextPattern = c.PatternInstances[nextLocation.PatternIndex];
                                    if (!nextPattern.Notes.TryGetValue(nextLocation.NoteIndex, out var nextNote) || !nextNote.IsValid)
                                    {
                                        nextNote            = nextPattern.GetOrCreateNoteAt(nextLocation.NoteIndex);
                                        nextNote.Instrument = note.Instrument;
                                        nextNote.Value      = (byte)newNote;
                                        nextNote.HasAttack  = false;
                                        it.Resync();
                                    }
                                    else if (nextNote != null && nextNote.IsRelease)
                                    {
                                        Log.LogMessage(LogSeverity.Warning, $"A slide note ends on a release note. This is currently unsupported and will require manual correction. {GetPatternString(nextPattern, nextLocation.NoteIndex)}");
                                    }
                                }
                            }
                        }

                        if (note != null && (note.IsMusical || note.IsStop))
                        {
                            lastNoteValue      = note.IsSlideNote ? note.SlideNoteTarget : note.Value;
                            lastNoteInstrument = note.Instrument;
                            lastNoteArpeggio   = note.Arpeggio;
                        }
                    }

                    processedPatterns.Add(pattern);
                }
            }
        }
예제 #10
0
        private bool FindNextSlideEffect(Channel channel, NoteLocation location, out NoteLocation nextLocation, Dictionary <Pattern, RowFxData[, ]> patternFxData)
        {
            nextLocation = NoteLocation.Invalid;

            var pattern = channel.PatternInstances[location.PatternIndex];

            if (pattern == null || !patternFxData.ContainsKey(pattern))
            {
                return(false);
            }

            var patternLen = channel.Song.GetPatternLength(location.PatternIndex);
            var fxData     = patternFxData[pattern];

            for (var it = pattern.GetDenseNoteIterator(location.NoteIndex + 1, patternLen); !it.Done; it.Next())
            {
                var time = it.CurrentTime;
                var note = it.CurrentNote;

                var fxChanged = false;
                for (int i = 0; i < fxData.GetLength(1); i++)
                {
                    var fx = fxData[time, i];

                    if (fx.fx == Effect_PortaUp ||
                        fx.fx == Effect_PortaDown ||
                        fx.fx == Effect_Portamento ||
                        fx.fx == Effect_SlideUp ||
                        fx.fx == Effect_SlideDown)
                    {
                        fxChanged = true;
                        break;
                    }
                }

                if (note != null && note.IsValid || fxChanged)
                {
                    nextLocation.PatternIndex = location.PatternIndex;
                    nextLocation.NoteIndex    = time;
                    return(true);
                }
            }

            for (int p = location.PatternIndex + 1; p < channel.Song.Length; p++)
            {
                pattern    = channel.PatternInstances[p];
                patternLen = channel.Song.GetPatternLength(p);

                if (pattern != null && patternFxData.ContainsKey(pattern))
                {
                    fxData = patternFxData[pattern];

                    for (var it = pattern.GetDenseNoteIterator(0, patternLen); !it.Done; it.Next())
                    {
                        var time = it.CurrentTime;
                        var note = it.CurrentNote;

                        var fxChanged = false;
                        for (int i = 0; i < fxData.GetLength(1); i++)
                        {
                            var fx = fxData[time, i];

                            if (fx.fx == Effect_PortaUp ||
                                fx.fx == Effect_PortaDown ||
                                fx.fx == Effect_Portamento ||
                                fx.fx == Effect_SlideUp ||
                                fx.fx == Effect_SlideDown)
                            {
                                fxChanged = true;
                                break;
                            }
                        }

                        if (note != null && note.IsValid || fxChanged)
                        {
                            nextLocation.PatternIndex = p;
                            nextLocation.NoteIndex    = time;
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
예제 #11
0
        //-------------------------------------------------------------------------------------------------------------------------------
        //                                  Create the Note and handle its location
        //-------------------------------------------------------------------------------------------------------------------------------
        private void setNotifier(string description,
                                 Type noteType,
                                 string title,
                                 bool isUpdate = false)
        {
            this.title       = title;
            this.description = description;
            this.type        = noteType;

            noteTitle.Text   = title;                                   // Fill the Notifier data title
            noteContent.Text = description;                             // Fill the Notifier data description
            noteDate.Text    = DateTime.Now + "";                       // Fill the Notifier data Timestamp

            #region ADJUST COLORS
            switch (noteType)
            {
            case Type.ERROR:
                icon.Image = global::Notify.Properties.Resources.ko;
                Leave      = Color.FromArgb(200, 60, 70);
                Hover      = Color.FromArgb(240, 80, 90);
                break;

            case Type.INFO:
                icon.Image = global::Notify.Properties.Resources.info;
                Leave      = Color.FromArgb(90, 140, 230);
                Hover      = Color.FromArgb(110, 160, 250);
                break;

            case Type.WARNING:
                icon.Image = global::Notify.Properties.Resources.warning;
                Leave      = Color.FromArgb(200, 200, 80);
                Hover      = Color.FromArgb(220, 220, 80);
                break;

            case Type.OK:
                icon.Image = global::Notify.Properties.Resources.ok;
                Leave      = Color.FromArgb(80, 200, 130);
                Hover      = Color.FromArgb(80, 240, 130);
                break;
            }

            buttonClose.BackColor = Leave;                              // Init colors
            buttonMenu.BackColor  = Leave;
            noteTitle.BackColor   = Leave;

            this.buttonClose.MouseHover += (s, e) =>                    // Mouse hover
            {
                this.buttonClose.BackColor = Hover;
                this.buttonMenu.BackColor  = Hover;
                this.noteTitle.BackColor   = Hover;
            };
            this.buttonMenu.MouseHover += (s, e) =>
            {
                this.buttonMenu.BackColor  = Hover;
                this.buttonClose.BackColor = Hover;
                this.noteTitle.BackColor   = Hover;
            }; this.noteTitle.MouseHover += (s, e) =>
            {
                this.buttonMenu.BackColor  = Hover;
                this.buttonClose.BackColor = Hover;
                this.noteTitle.BackColor   = Hover;
            };

            this.buttonClose.MouseLeave += (s, e) =>                    // Mouse leave
            {
                this.buttonClose.BackColor = Leave;
                this.buttonMenu.BackColor  = Leave;
                this.noteTitle.BackColor   = Leave;
            };
            this.buttonMenu.MouseLeave += (s, e) =>
            {
                this.buttonMenu.BackColor  = Leave;
                this.buttonClose.BackColor = Leave;
                this.noteTitle.BackColor   = Leave;
            };
            this.noteTitle.MouseLeave += (s, e) =>
            {
                this.buttonMenu.BackColor  = Leave;
                this.buttonClose.BackColor = Leave;
                this.noteTitle.BackColor   = Leave;
            };
            #endregion

            #region DIALOG NOTE
            if (isDialog)
            {
                Button ok_button = new Button();                        // Dialog note comes with a simple Ok button
                ok_button.FlatStyle = FlatStyle.Flat;
                ok_button.BackColor = Leave;
                ok_button.ForeColor = Color.White;
                Size = new Size(Size.Width,                             // Resize the note to contain the button
                                Size.Height + 50);
                ok_button.Size     = new Size(120, 40);
                ok_button.Location = new Point(Size.Width / 2 - ok_button.Size.Width / 2,
                                               Size.Height - 50);
                ok_button.Text   = DialogResult.OK.ToString();
                ok_button.Click += onOkButtonClick;
                Controls.Add(ok_button);

                noteDate.Location = new Point(noteDate.Location.X,      // Shift down the date location
                                              noteDate.Location.Y + 44);


                noteLocation = new NoteLocation(Left, Top);             // Default Center Location
            }
            #endregion

            #region NOTE LOCATION
            if (!isDialog && !isUpdate)
            {
                NoteLocation location = adjustLocation(this);           // Set the note location

                Left = location.X;                                      // Notifier position X
                Top  = location.Y;                                      // Notifier position Y
            }
            #endregion
        }
예제 #12
0
        private void RenderTimecode(RenderGraphics g)
        {
            var frame            = App.CurrentFrame;
            var famitrackerTempo = App.Project != null && App.Project.UsesFamiTrackerTempo;

            var zeroSizeX  = g.MeasureString("0", ThemeBase.FontHuge);
            var colonSizeX = g.MeasureString(":", ThemeBase.FontHuge);

            var timeCodeSizeY = Height - timecodePosY * 2;
            var textColor     = App.IsRecording ? theme.DarkRedFillBrush : theme.LightGreyFillBrush2;

            g.FillAndDrawRectangle(timecodePosX, timecodePosY, timecodePosX + timecodeSizeX, Height - timecodePosY, theme.BlackBrush, theme.LightGreyFillBrush2);

            if (Settings.TimeFormat == 0 || famitrackerTempo) // MM:SS:mmm cant be used with FamiTracker tempo.
            {
                var location = NoteLocation.FromAbsoluteNoteIndex(App.Song, frame);

                var numPatternDigits = Utils.NumDecimalDigits(App.Song.Length - 1);
                var numNoteDigits    = Utils.NumDecimalDigits(App.Song.GetPatternLength(location.PatternIndex) - 1);

                var patternString = location.PatternIndex.ToString("D" + numPatternDigits);
                var noteString    = location.NoteIndex.ToString("D" + numNoteDigits);

                var charPosX = timecodePosX + timecodeSizeX / 2 - ((numPatternDigits + numNoteDigits) * zeroSizeX + colonSizeX) / 2;

                for (int i = 0; i < numPatternDigits; i++, charPosX += zeroSizeX)
                {
                    g.DrawText(patternString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, textColor, zeroSizeX);
                }

                g.DrawText(":", ThemeBase.FontHuge, charPosX, 2, textColor, colonSizeX);
                charPosX += colonSizeX;

                for (int i = 0; i < numNoteDigits; i++, charPosX += zeroSizeX)
                {
                    g.DrawText(noteString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, textColor, zeroSizeX);
                }
            }
            else
            {
                TimeSpan time = App.CurrentTime;

                var minutesString      = time.Minutes.ToString("D2");
                var secondsString      = time.Seconds.ToString("D2");
                var millisecondsString = time.Milliseconds.ToString("D3");

                // 00:00:000
                var charPosX = timecodePosX + timecodeSizeX / 2 - (7 * zeroSizeX + 2 * colonSizeX) / 2;

                for (int i = 0; i < 2; i++, charPosX += zeroSizeX)
                {
                    g.DrawText(minutesString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, textColor, zeroSizeX);
                }
                g.DrawText(":", ThemeBase.FontHuge, charPosX, 2, textColor, colonSizeX);
                charPosX += colonSizeX;
                for (int i = 0; i < 2; i++, charPosX += zeroSizeX)
                {
                    g.DrawText(secondsString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, textColor, zeroSizeX);
                }
                g.DrawText(":", ThemeBase.FontHuge, charPosX, 2, textColor, colonSizeX);
                charPosX += colonSizeX;
                for (int i = 0; i < 3; i++, charPosX += zeroSizeX)
                {
                    g.DrawText(millisecondsString[i].ToString(), ThemeBase.FontHuge, charPosX, 2, textColor, zeroSizeX);
                }
            }
        }
예제 #13
0
        public void ShowNotes()
        {
            string line = NoteDuration + " " + NoteLocation.ToString() + " " + RawNote + " " + octave + " " + intensity + " " + pan;

            Trace.WriteLine(line);
        }