private void btnTrackApply_Click(object sender, EventArgs e)
 {
     //fill object properties on the form
     txtDefault.Text   = _objects[dropObjects.SelectedIndex].def[dropParamPath.SelectedIndex];
     dropLeafStep.Text = _objects[dropObjects.SelectedIndex].step[dropParamPath.SelectedIndex];
     txtTrait.Text     = _objects[dropObjects.SelectedIndex].trait_type[dropParamPath.SelectedIndex];
     //enable track highlighting tools
     btnTrackColorDialog.Enabled  = true;
     NUD_TrackDoubleclick.Enabled = true;
     NUD_TrackHighlight.Enabled   = true;
     //add track to list and populate with values
     _tracks[_selecttrack] = new Sequencer_Object()
     {
         obj_name        = _objects[dropObjects.SelectedIndex].obj_name[dropParamPath.SelectedIndex],
         friendly_type   = _objects[dropObjects.SelectedIndex].obj_displayname,
         param_path      = _objects[dropObjects.SelectedIndex].param_path[dropParamPath.SelectedIndex],
         friendly_param  = _objects[dropObjects.SelectedIndex].param_displayname[dropParamPath.SelectedIndex],
         _default        = float.Parse(_objects[dropObjects.SelectedIndex].def[dropParamPath.SelectedIndex]),
         step            = _objects[dropObjects.SelectedIndex].step[dropParamPath.SelectedIndex],
         trait_type      = _objects[dropObjects.SelectedIndex].trait_type[dropParamPath.SelectedIndex],
         highlight_color = "-8355585",
         highlight_value = 1,
         footer          = _objects[dropObjects.SelectedIndex].footer[dropParamPath.SelectedIndex]
     };
     //if lane is not middle, edit the param_path and friendly_param to match
     if (_tracks[_selecttrack].param_path.Contains(".ent"))
     {
         _tracks[_selecttrack].param_path      = _tracks[_selecttrack].param_path.Replace(".ent", _tracklane[dropTrackLane.SelectedIndex]);
         _tracks[_selecttrack].friendly_param += ", " + dropTrackLane.Text;
     }
     //change row header to reflect what the track is
     ChangeTrackName();
 }
        private void btnTrackDown_Click(object sender, EventArgs e)
        {
            DataGridView dgv = trackEditor;

            try {
                int totalRows = dgv.Rows.Count;
                // get index of the row for the selected cell
                int rowIndex = dgv.SelectedCells[0].OwningRow.Index;
                if (rowIndex == totalRows - 1)
                {
                    return;
                }
                //move track in list
                Sequencer_Object selectedTrack = _tracks[rowIndex];
                _tracks.Remove(selectedTrack);
                _tracks.Insert(rowIndex + 1, selectedTrack);
                // get index of the column for the selected cell
                int             colIndex    = dgv.SelectedCells[0].OwningColumn.Index;
                DataGridViewRow selectedRow = dgv.Rows[rowIndex];
                dgv.Rows.Remove(selectedRow);
                dgv.Rows.Insert(rowIndex + 1, selectedRow);
                dgv.ClearSelection();
                dgv.Rows[rowIndex + 1].Cells[colIndex].Selected = true;
                //sets flag that leaf has unsaved changes
                SaveLeaf(false);
            }
            catch { }
        }
        ///Update DGV from _tracks
        public void LoadLeaf(dynamic _load /*List<string> _load*/)
        {
            if ((string)_load["obj_type"] != "SequinLeaf")
            {
                MessageBox.Show("This does not appear to be a leaf file!");
                return;
            }

            lblTrackFileName.Text = $@"Leaf Editor - {_load["obj_name"]}";
            //clear existing tracks
            _tracks.Clear();
            //set beat_cnt and time_sig
            numericUpDown_LeafLength.Value = (int)_load["beat_cnt"];
            var _time_sig = (string)_load["time_sig"] ?? "4/4";

            dropTimeSig.SelectedIndex = dropTimeSig.FindStringExact(_time_sig);
            //each object in the seq_objs[] list becomes a track
            foreach (var seq_obj in _load["seq_objs"])
            {
                Sequencer_Object _s = new Sequencer_Object()
                {
                    obj_name    = seq_obj["obj_name"],
                    trait_type  = seq_obj["trait_type"],
                    data_points = seq_obj["data_points"],
                    step        = seq_obj["step"],
                    _default    = seq_obj["default"],
                    footer      = seq_obj["footer"]
                };
                //if the leaf has definitions for these, add them. If not, set to defaults
                _s.param_path      = seq_obj.ContainsKey("param_path_hash") ? $"0x{(string)seq_obj["param_path_hash"]}" : (string)seq_obj["param_path"];
                _s.highlight_color = seq_obj.ContainsKey("editor_data") ? (string)seq_obj["editor_data"][0] : "-8355585";
                _s.highlight_value = seq_obj.ContainsKey("editor_data") ? (float)seq_obj["editor_data"][1] : 1;
                //iterate over every _object to find where a param_path is located
                //this was the best way to do this I could come up with
                foreach (Object_Params _obj in _objects)
                {
                    //replace .z01 .z02 .a01 .a02 with .ent, so that it's found in the param list
                    var reg_param = Regex.Replace(_s.param_path, "[.].*", ".ent");
                    //if found, set the friendly names
                    for (int x = 0; x < _obj.param_path.Count; x++)
                    {
                        if (_obj.param_path[x] == reg_param && _obj.obj_name[x] == _s.obj_name.Replace((string)_load["obj_name"], "leafname"))
                        {
                            //_s.friendly_param = _obj.param_displayname[_obj.param_path.IndexOf(reg_param)];
                            _s.friendly_param = _obj.param_displayname[x];
                            _s.friendly_type  = _obj.obj_displayname;
                            break;
                        }
                    }
                }
                //if an object can be multi-lane, it will be an .ent. Check for "." to detect this
                if (_s.param_path.Contains("."))
                {
                    //get the index of the lane from _tracklane to get the item from dropTrackLane, and append that to the friendly_param
                    _s.friendly_param += $", {dropTrackLane.Items[_tracklane.IndexOf($".{_s.param_path.Split('.')[1]}")]}";
                }

                //finally, add the completed seq_obj to tracks
                _tracks.Add(_s);
            }
            //clear the DGV and prep for new data points
            trackEditor.Rows.Clear();
            trackEditor.RowCount = _tracks.Count;
            //foreach row, import data points associated with it
            foreach (DataGridViewRow r in trackEditor.Rows)
            {
                if (_tracks[r.Index].friendly_param.Length > 1)
                {
                    r.HeaderCell.Value = _tracks[r.Index].friendly_type + " (" + _tracks[r.Index].friendly_param + ")";
                    //pass _griddata per row to be imported to the DGV
                    TrackRawImport(r, _tracks[r.Index].data_points);
                }
            }
            //enable a bunch of elements now that a leaf is loaded.
            dropObjects.Enabled          = true;
            dropParamPath.Enabled        = true;
            btnTrackColorDialog.Enabled  = true;
            NUD_TrackDoubleclick.Enabled = true;
            NUD_TrackHighlight.Enabled   = true;
            btnTrackDelete.Enabled       = _tracks.Count > 0;
            btnTrackUp.Enabled           = _tracks.Count > 1;
            btnTrackDown.Enabled         = _tracks.Count > 1;
            SaveLeaf(true);
        }