/** * @brief Loads a todocnote into the display panel * @param[in] aNote The todocnote to display * @param[in] aNoteIndex The index of the todocnote in the overall Song. */ public void LoadNote(Music.CombinedNote aNote, int aNoteIndex) { // Set the note being represented. mNote = aNote; mNoteIndex = aNoteIndex; // Update the length panel. UpdateLengthPanel(); // Update the offset panel. UpdateOffsetPanel(); // Update the pitches UpdatePitches(); // Update the drums UpdateDrums(); // Display the buttons if (mNoteIndex != 0) { mMoveLeftButton.gameObject.SetActive(true); mMoveLeftButton.onClick.AddListener(OnMoveLeftButtonClicked); } if (mNoteIndex != mSongCreationHandler.GetNumNotes() - 1) { mMoveRightButton.gameObject.SetActive(true); mMoveRightButton.onClick.AddListener(OnMoveRightButtonClicked); } }
/*************************************************************************//** * @} * @defgroup SongPubFunc Public Functions * @ingroup DocSong * Functions that allow other classes to interact with the Song. * @{ *****************************************************************************/ /** * @brief Adds a @link Music::CombinedNote note@endlink to the Song. * @param[in] aNewNote The @link Music::CombinedNote note@endlink to add. */ public void AddNote(Music.CombinedNote aNewNote) { // Update the number of musical notes in the Song if needed. if (aNewNote.NumPitches > 0) { mNumMusicalNotes++; for (int i = 0; i < aNewNote.NumPitches; i++) { // Update the highest pitch. if (aNewNote.MusicalNote.Pitches[i] != Music.PITCH.REST && mHighestPitch < aNewNote.MusicalNote.Pitches[i]) { mHighestPitch = aNewNote.MusicalNote.Pitches[i]; } // Update the lowest pitch. if (aNewNote.MusicalNote.Pitches[i] != Music.PITCH.REST && mLowestPitch > aNewNote.MusicalNote.Pitches[i]) { mLowestPitch = aNewNote.MusicalNote.Pitches[i]; } } } // Update the number of notes with drum hits in the Song if needed. if (aNewNote.NumDrums > 0) { mNumDrumNotes++; } // Add the note to the list. mNotes.Add(aNewNote); // Update the Song type. UpdateSongType(); }
/*************************************************************************//** * @} * @defgroup SC_MDPPubFunc Public Functions * @ingroup DocSC_MDP * Functions for other classes to interact with the SC_MeasureDisplayPanel. * @{ *****************************************************************************/ /** * @brief Adds a @link Music::CombinedNote note@endlink to the @link SC_MeasureDisplayPanel::mNotes list of notes managed by this panel@endlink. * @param[in] aNote The todoc note to add to the measure. * @param[in] aNoteIndex The index of the @link Music::CombinedNote note@endlink in the overall Song. * * This function also creates the @link DocSC_NDP SC_NoteDisplayPanel object@endlink for the @link Music::CombinedNote note@endlink. */ public void AddNote(Music.CombinedNote aNote, int aNoteIndex) { // Calculate the percentage used up in the measure. float newPercentage = mPercentageUsed + Music.GetNoteLengthRelativeToMeasure(aNote.OffsetFromPrevNote, Music.TIME_SIGNATURE_4_4()); // If there is no more room in the measure for this note, then send it back to the parent. if (newPercentage >= 1f) { mParent.HandleFullMeasure(newPercentage - mPercentageUsed, aNote); } // If there is more room, then create the new panel and add it to this measure. else { // Update the percentage used. mPercentageUsed = newPercentage; // Create a SC_NoteDisplayPanel GameObject clone = null; clone = Instantiate(Resources.Load <GameObject>(NOTE_DISPLAY_PANEL_PATH)); Assert.IsNotNull(clone, "Could not load SC_NoteDisplayPanel prefab!"); // Set the values for the note's transform. clone.transform.SetParent(transform.parent); // Initialize the cloned panel. SC_NoteDisplayPanel newPanel = clone.AddComponent <SC_NoteDisplayPanel>(); newPanel.LoadNote(aNote, aNoteIndex); // Add the panel to the list. mNotes.Add(newPanel); } }
/*************************************************************************//** * @} * @defgroup SC_NDCHandlers Event Handlers * @ingroup DocSC_NDC * Functions that are called by the SC_NoteDisplayContainer to handle events. * @{ *****************************************************************************/ /** * @brief Handler for when a @link DocSC_MDP measure@endlink fills up. * @param[in] aSpillover How much did the new note exceed the limit of the @link DocSC_MDP measure@endlink. * @param[in] aNote The todocnote that was attempted to be added to the todocmeasure. * * This function creates a new @link DocSC_MDP measure@endlink and puts * @link SC_NoteDisplayContainer::AddNote the note@endlink that couldn't be added to the last * @link DocSC_MDP measure@endlink into the new one. */ public void HandleFullMeasure(float aSpillover, Music.CombinedNote aNote) { // Create a new measure toggle. GameObject clone = Instantiate(Resources.Load <GameObject>(MEASURE_PANEL_PREFAB_PATH)); Assert.IsNotNull(clone, "Could not load the MeasurePanel prefab!"); // Add the measure panel to the list. mMeasures.Add(clone.AddComponent <SC_MeasureDisplayPanel>()); // Increase the current measure. mCurrentMeasure++; // Set the values for the new measure toggle. mMeasures[mCurrentMeasure].transform.GetChild(0).GetChild(1).GetComponent <Text>().text = "Measure " + (mCurrentMeasure + 1).ToString(); mMeasures[mCurrentMeasure].transform.SetParent(transform); mMeasures[mCurrentMeasure].SetParentContainer(this); mMeasures[mCurrentMeasure].SetToggle(true); // Handle Spillover from the previous measure. mMeasures[mCurrentMeasure].SetPercentageUsed(0f - aSpillover); // Add the note to the new measure. mMeasures[mCurrentMeasure].AddNote(aNote, mNumNotes); // Make only the new measure be shown. HandleMeasureToggled(mMeasures[mCurrentMeasure]); }
/** * @brief Creates a new note in the song. * * Gets the currently selected values from the modules in the scene uses them * to @link Music::CreateNote create@endlink a new @link Music::CombinedNote note@endlink. * * The function won't do anything if no @link SongCreationManager::mPitchSelector pitches@endlink * or @link SongCreationManager::mDrumSelector drums@endlink are selected. * * @see SongCreationManager::mNewNoteButton */ public void OnCreateNote(Music.CombinedNote aNote) { // Add the note to the song. mSong.AddNote(aNote); // Add the note to the note display. mNoteDisplay.AddNote(aNote); }
/** * @brief Saves the Song to a file * * This function adds the song to the @link VirtualInstrumentManager::SongManager Song Manager@endlink and also saves the Song. * to a file. * * @see Song::WriteSongToFile */ public void OnSaveSong() { // Special handling to make drum loops loop properly. The first hit has an initial offset // equal to the length used to create the last note. if (mSong.GetSongType() == Song.SongType.DrumLoop) { Music.CombinedNote firstNote = mSong.GetAllNotes()[0]; mSong.ReplaceNote(firstNote, 0); } mVIM.SongManager.AddSong(mSong); mSong.WriteSongToFile(); }
/** * @brief Replaces a note at a given index. * @param[in] aNote The note that will be put into the Song at the given index. * @param[in] aIndex The index of the place to insert the note. */ public void ReplaceNote(Music.CombinedNote aNote, int aIndex) { Assert.IsTrue(aIndex < mNotes.Count, "Tried to replace a note at the index " + aIndex.ToString() + " for a Song with only " + mNotes.Count.ToString() + " notes in it!"); // Get the replaced note. Music.CombinedNote replacedNote = mNotes[aIndex]; // Replace the note. mNotes[aIndex] = aNote; // Account for changes in the number of musical notes and drum notes in the Song. if (replacedNote.NumPitches > 0 && aNote.NumPitches == 0) { mNumMusicalNotes--; } else if (replacedNote.NumPitches == 0 && aNote.NumPitches > 0) { mNumMusicalNotes++; } if (replacedNote.NumDrums > 0 && aNote.NumDrums == 0) { mNumDrumNotes--; } else if (replacedNote.NumDrums == 0 && aNote.NumDrums > 0) { mNumDrumNotes++; } // See if we need to update the highest/lowest pitch. if (replacedNote.NumPitches > 0 && mNumMusicalNotes > 0) { // See if we need to set a new highest/lowest pitch. foreach (Music.PITCH pitch in replacedNote.MusicalNote.Pitches) { if (pitch != Music.PITCH.REST && pitch == mHighestPitch) { mHighestPitch = Music.PITCH.C0; SearchForHighestPitch(); } if (pitch != Music.PITCH.REST && pitch == mLowestPitch) { mLowestPitch = Music.PITCH.B9; SearchForLowestPitch(); } } } // Update the Song type. UpdateSongType(); }
/** * @brief Moves a todocnote earlier in the Song. * @param[in] aNotePanel The panel that triggered the event. */ public void HandleMoveNoteRight(SC_NoteDisplayPanel aNotePanel) { // Get the note to move and the note that was previously to the left. Music.CombinedNote noteToMove = aNotePanel.GetNote(); int noteToMoveIndex = aNotePanel.GetNoteIndex(); Music.CombinedNote noteToRight = mSong.GetNote(noteToMoveIndex + 1); // Swap the notes. mSong.ReplaceNote(noteToMove, noteToMoveIndex + 1); mSong.ReplaceNote(noteToRight, noteToMoveIndex); // Reload the song. OnLoadSong(mSong); }
/*************************************************************************//** * @} * @defgroup SC_NDiaPubFunc Public Functions * @ingroup DocSC_NDia * These are functions that allow for interaction between the SC_NoteDialog and other classes. * @{ *****************************************************************************/ /** * @brief Loads a @link Music::CombinedNote note@endlink into the SC_NoteDialog * @param[in] aNote The @link Music::CombinedNote note@endlink to load. */ public void LoadNoteIntoDialog(Music.CombinedNote aNote) { Music.MelodyNote melody = aNote.MusicalNote; Music.PercussionNote percussion = aNote.Drums; // Add display panels. if (melody.NumPitches > 0) { // Add each pitch in the note. int index = 0; foreach (Music.PITCH pitch in melody.Pitches) { GameObject clone = Instantiate(Resources.Load <GameObject>(PDDP_PREFAB_PATH)); clone.transform.SetParent(mMelodyDisplay); SC_PitchDrumDisplayPanel panel = clone.AddComponent <SC_PitchDrumDisplayPanel>(); panel.InitializeAsPitchDisplay(melody.Pitches[index], melody.Lengths[index], melody.Velocities[index]); panel.SetParentContainer(this); mPitches.Add(panel); index++; clone = null; } } // Add each drum in the note. if (percussion.NumHits > 0) { int index = 0; foreach (Music.DRUM drum in percussion.Hits) { GameObject clone = Instantiate(Resources.Load <GameObject>(PDDP_PREFAB_PATH)); clone.transform.SetParent(mPercussionDisplay); SC_PitchDrumDisplayPanel panel = clone.AddComponent <SC_PitchDrumDisplayPanel>(); panel.InitializeAsDrumDisplay(percussion.Hits[index], percussion.Velocities[index]); panel.SetParentContainer(this); mDrums.Add(panel); index++; clone = null; } } // Set the offset panel. mOffsetPanel.SetSelected(aNote.OffsetFromPrevNote); // Set the Done button UpdateDoneButton(); }
/** * @brief Removes a note from the Song. * @param[in] aIndex The index of the note to remove. */ public void RemoveNote(int aIndex) { Assert.IsTrue(aIndex < mNotes.Count, "Tried to remove a note at the index " + aIndex.ToString() + " from a Song with only " + mNotes.Count.ToString() + " notes in it!"); // Get the note to be removed. Music.CombinedNote removedNote = mNotes[aIndex]; // Remove the note. mNotes.RemoveAt(aIndex); // Update information about the pitches in the Song.. if (removedNote.MusicalNote.Pitches != null) { // Decrease the number of musical notes. mNumMusicalNotes--; // See if we need to set a new highest/lowest pitch. foreach (Music.PITCH pitch in removedNote.MusicalNote.Pitches) { if (pitch != Music.PITCH.REST && pitch == mHighestPitch) { mHighestPitch = Music.PITCH.C0; SearchForHighestPitch(); } if (pitch != Music.PITCH.REST && pitch == mLowestPitch) { mLowestPitch = Music.PITCH.B9; SearchForLowestPitch(); } } } // Update information about the drums in the Song. if (removedNote.Drums.Hits != null) { mNumDrumNotes--; } // Update the Song type. UpdateSongType(); // Clean up. GC.Collect(); Resources.UnloadUnusedAssets(); }
/** * @brief Handles the Add Note button being clicked by loading a @link DocSC_NDia Note Dialog@endlink. */ public void OnNewNoteButtonClicked() { // Load the dialog. GameObject dialogObj = Instantiate(Resources.Load <GameObject>(NOTE_DIALOG_PATH)); dialogObj.transform.SetParent(transform, true); SC_NoteDialog dialog = dialogObj.transform.GetChild(0).GetComponent <SC_NoteDialog>(); // Get the initial offset for the note dialog. Music.NoteLength dialogOffset = new Music.NoteLength(Music.NOTE_LENGTH_BASE.NONE); if (mSong.GetNumNotes() > 0) { // Get the last note to find the initial offset. int lastNoteIndex = mSong.GetNumNotes() - 1; Music.CombinedNote lastNote = mSong.GetNote(lastNoteIndex); // If there are pitches in the last note, then set the dialog's offset to // be the shortest length of all of the pitches in the last note. if (lastNote.NumPitches > 0) { Music.NoteLength shortestLength = lastNote.MusicalNote.Lengths[0]; for (int i = 1; i < lastNote.NumPitches; i++) { if (lastNote.MusicalNote.Lengths[i] < shortestLength) { shortestLength = lastNote.MusicalNote.Lengths[i]; } } dialogOffset = shortestLength; } // If there are not pitches in the last note, then set it to // the last note's offset. else { dialogOffset = lastNote.OffsetFromPrevNote; } } dialog.SetDefaultOffset(dialogOffset); dialog.NoteDialogFinished.AddListener(OnCreateNote); }
/** * @brief Handles the done button being clicked. */ private void OnDoneButtonClicked() { // Set up the pitches. int numPitches = mPitches.Count; Music.PITCH[] pitches = null; int[] pitchVelocities = null; Music.NoteLength[] lengths = null; // If there are pitches, then get them from the panels. if (numPitches != 0) { // Get all of the pitches, velocities, and lengths. pitches = new Music.PITCH[numPitches]; pitchVelocities = new int[numPitches]; lengths = new Music.NoteLength[numPitches]; int index = 0; foreach (SC_PitchDrumDisplayPanel pitch in mPitches) { pitches[index] = pitch.GetPitch(); pitchVelocities[index] = pitch.GetNoteVelocity(); lengths[index] = pitch.GetLengthOfPitch(); index++; } } // Create the melody note. Music.MelodyNote melody = new Music.MelodyNote(pitchVelocities, lengths, pitches); // Set up the drums. int numDrums = mDrums.Count; Music.DRUM[] drums = null; int[] drumVelocities = null; // If there are drums, then get them from the panels. if (numDrums != 0) { // Get all of the drums and their velocities. drums = new Music.DRUM[numDrums]; drumVelocities = new int[numDrums]; int index = 0; foreach (SC_PitchDrumDisplayPanel drum in mDrums) { drums[index] = drum.GetDrum(); drumVelocities[index] = drum.GetNoteVelocity(); index++; } } // Create the percussion note. Music.PercussionNote percussion = new Music.PercussionNote(drumVelocities, drums); // Get the offset of the note. Music.NoteLength offset = mOffsetPanel.GetSelected(); // Create the note. Music.CombinedNote note = new Music.CombinedNote(melody, percussion, offset); // Invoke the event which signals the dialog being finished. NoteDialogFinished.Invoke(note); // Self-destruct. DestroyImmediate(transform.parent.gameObject, false); }
/*************************************************************************//** * @} * @defgroup SC_NDCPubFunc Public Functions * @ingroup DocSC_NDC * Functions for other classes to interact with the SC_NoteDisplayContainer. * @{ *****************************************************************************/ /** * @brief Adds a @link Music::CombinedNote note@endlink to the @link DocSC_MDP current measure@endlink. * @param[in] aNote The todocnote to add. * * This function just updates the index of the @link Music::CombinedNote note@endlink in the song * and @link SC_MeasureDisplayPanel::AddNote sends it to the current measure@endlink for it to handle adding it. */ public void AddNote(Music.CombinedNote aNote) { mMeasures[mCurrentMeasure].AddNote(aNote, mNumNotes); mNumNotes++; }
/** * @brief Modifies a @link Music::CombinedNote note@endlink in the Song. * * @see Song::ReplaceNote */ public void OnModifyNote(Music.CombinedNote aNote) { mSong.ReplaceNote(aNote, mEditIndex); OnLoadSong(mSong); }