private void NodeMouseDown(MouseEventArgs e, clsXYPC xypc) { //* inactive: //* left: add node (max 4), else replace //* right: replace node //* replace node that would make semitone or tone, else use COF //* active //* remove node from chord //* //* Active[0][] = current chord (from NoteMap) //* ActiveBoolChord[] = new chord List <int> chord = clsCF.clsEv.ConvBoolArrayToListInt(Active[0]); ActiveBoolChord = Active[0].ToArray(); if (Active[0][xypc.PC]) //remove hit node from current chord { ActiveBoolChord[xypc.PC] = false; } else //not active { if (chord.Count > 3 || e.Button == MouseButtons.Right) { RemoveWeakestNode(xypc); } ActiveBoolChord[xypc.PC] = true; } int[] newchord = clsCF.clsEv.ConvBoolArrayToListInt(ActiveBoolChord).ToArray(); ShowPlayChord(newchord); }
private void NodeMouseDown(MouseEventArgs e, clsXYPC xypc) { //* inactive: //* left: add node (max 4), else replace //* right: replace node //* replace node that would make semitone or tone, else use COF //* active //* remove node from chord //* bool[] boolchord = (e.Button == MouseButtons.Left) ? ActiveBoolChordCF : NextBoolChordCF; List <int> chord = clsCF.clsEv.ConvBoolArrayToListInt(boolchord); ActiveBoolChordMouse = boolchord.ToArray(); if (boolchord[xypc.PC]) //remove hit node from current chord { ActiveBoolChordMouse[xypc.PC] = false; } else //not active { if (chord.Count > 3 || e.Clicks == 2) { RemoveWeakestNode(xypc); } ActiveBoolChordMouse[xypc.PC] = true; } int[] newchord = clsCF.clsEv.ConvBoolArrayToListInt(ActiveBoolChordMouse).ToArray(); SetPlayChord(newchord); }
private void ShowBullsEyes(Graphics xgr, SizeF size) { //EmergingBoolChord = new bool[12]; //* show bullseye countdown using nudLookAhead //int lookahead = (int)nudLookAhead.Value; if (LookAhead == 0) { return; } clsMTime.clsBBT bbt = P.F.CurrentBBT.Copy(); //int qi = bbt.Ticks / P.F.TicksPerQI; //bool[] currentchord = P.F.CF.NoteMap[qi]; bool[] currentchord = ActiveBoolChordCF; for (int i = 0; i < LookAhead; i++) { bbt.NextBeat(); if (bbt.Ticks >= P.F.MaxBBT.Ticks) { break; } int qi = bbt.Ticks / P.F.TicksPerQI; //bool[] newchord = P.F.CF.NoteMap[qi]; bool[] newchord = P.F.CF.NoteMap.GetBoolChord(qi, eKBTrans.Add); if (newchord.SequenceEqual(currentchord)) { continue; } if (!picPC_indMouseDown) { int innerradius = (i == 0) ? Radius : ((2 * LookAhead - 1 - i) * Radius) / (2 * LookAhead); int innerdiameter = 2 * innerradius; SizeF innersize = new SizeF(innerdiameter, innerdiameter); for (int y = 0; y < XYPC.Count; y++) { for (int x = 0; x < XYPC[y].Count; x++) { clsXYPC xypc = XYPC[y][x]; //* compare without kbtrans applied //int pc = (xypc.PC - P.frmSC.Play.TransposeKB).Mod12(); PointF innerloc = new PointF(xypc.XPos - innerradius, xypc.YPos - innerradius); RectangleF innerrectf = new RectangleF(innerloc, innersize); if (currentchord[xypc.PC] && !newchord[xypc.PC]) //pc only in current chord { xgr.FillEllipse(P.ColorsTonnetz["Old Active Node"].Br, innerrectf); } else if (!currentchord[xypc.PC] && newchord[xypc.PC]) //pc only in new chord { xgr.FillEllipse(P.ColorsTonnetz["New Active Node"].Br, innerrectf); } } } break; } } }
internal void CreateNodes() { Space = HalfSpace * 2; int pc = 0; int y = 0; int ypos = HalfSpace; XYPC.Clear(); DictXYPC.Clear(); //* initialize PC and DictPC int xpos = HalfSpace; while (ypos < picPC.Height - HalfSpace) { List <clsXYPC> listx = new List <clsXYPC>(); int x = 0; while (xpos < picPC.Width - HalfSpace) { clsXYPC xypc = new clsXYPC(x, y, xpos, ypos, pc); listx.Add(xypc); x++; xpos += Space; pc = (pc + 7).Mod12(); //circle of fifths if (!DictXYPC.ContainsKey(pc)) { DictXYPC.Add(pc, xypc); } } XYPC.Add(listx); x = 0; if (y % 2 == 0) { xpos = Space; pc = (listx[0].PC + 3).Mod12(); //minor sixth } else { xpos = HalfSpace; //starting position pc = (listx[0].PC + 8).Mod12(); //minor third } y++; ypos += Space; } //* set key Key = (P.F.MTime == null) ? new clsKey(0, "major", 0) : P.F.Keys[P.F.CurrentBBT.Ticks]; bool[] scalenotes = (Key.Major) ? NoteName.MajScaleNotes : NoteName.MinScaleNotesDown; ScaleNotes = new bool[12]; for (int i = 0; i < 12; i++) { ScaleNotes[(i + Key.KBTrans_KeyNote).Mod12()] = scalenotes[i]; } picPC.Refresh(); }
private void ShowNodes(Graphics xgr, SizeF size) { for (int y = 0; y < XYPC.Count; y++) { for (int x = 0; x < XYPC[y].Count; x++) { clsXYPC xypc = XYPC[y][x]; PointF loc = new PointF(xypc.XPos - Radius, xypc.YPos - Radius); ShowNode(xgr, xypc.PC, loc, size); } } }
private void RemoveWeakestNode(clsXYPC xypc) { //* remove from ActiveBoolChord if (RemoveNodeDiff(xypc, 1)) { return; } if (RemoveNodeDiff(xypc, 2)) { return; } RemoveNodeDia(); }
private void ShowName(Graphics xgr, SizeF size, StringFormat fmt, int y, int x) { int pc = XYPC[y][x].PC; string sf = NoteName.GetNoteNameOrSolfa(pc, P.F.Keys[P.F.CurrentBBT.Ticks]); Font font = (ScaleNotes[pc]) ? DiatonicFont : ChromaticFont; Brush fontbrush = (ScaleNotes[pc]) ? DiatonicFontBrush : ChromaticFontBrush; clsXYPC xypc = XYPC[y][x]; PointF loc = new PointF(xypc.XPos - Radius, xypc.YPos - Radius); RectangleF rectf = new RectangleF(loc, size); //xgr.DrawRectangle(new Pen(Color.Green, 3), loc.X, loc.Y, size.Width, size.Height); xgr.DrawString(sf, font, fontbrush, rectf, fmt); }
private void ShowNodeTxt(Graphics xgr, SizeF size, StringFormat fmt, int y, int x) { clsXYPC xypc = XYPC[y][x]; int pc = xypc.PC; int pcsf = (pc - P.frmSC.Play.TransposeKB).Mod12(); //int pcshow = (P.frmSC.optShowSolfa.Checked) ? pcsf : pc; //* kbtrans applied to key by GetNoteNameOrSolfa string txt = NoteName.GetNoteNameOrSolfa(pc, P.F.Keys[P.F.CurrentBBT.Ticks, kbtrans: true]); Font font = (ScaleNotes[pc]) ? DiatonicFont : ChromaticFont; Brush fontbrush = (ScaleNotes[pc]) ? P.ColorsTonnetz["Diatonic Note"].Br : P.ColorsTonnetz["Chromatic Note"].Br; PointF loc = new PointF(xypc.XPos - Radius, xypc.YPos - Radius); RectangleF rectf = new RectangleF(loc, size); //xgr.DrawRectangle(new Pen(Color.Green, 3), loc.X, loc.Y, size.Width, size.Height); xgr.DrawString(txt, font, fontbrush, rectf, fmt); }
private bool RemoveNodeDiff(clsXYPC xypc, int indiff) { //* remove first node that where diff <= indiff for (int i = 0; i < 12; i++) { if (!ActiveBoolChord[i]) { continue; } int diff = (i - xypc.PC).Mod12(); if (diff == indiff) //first semitone { ActiveBoolChord[i] = false; return(true); } } return(false); }
private void picPC_MouseDown(object sender, MouseEventArgs e) { picPC_indMouseDown = true; List <int> keylist = new List <int>(); List <clsXYPC> valuelist = new List <clsXYPC>(); //* get distance from any node where diffx and diffy <= Space int distancesquared; foreach (List <clsXYPC> list in XYPC) { foreach (clsXYPC xypc in list) { int diffx = Math.Abs(xypc.XPos - e.X); int diffy = Math.Abs(xypc.YPos - e.Y); if (diffx <= Space && diffy <= Space) { distancesquared = diffx * diffx + diffy * diffy; if (distancesquared < RadiusSquared) //inside node - add to chord { NodeMouseDown(e, xypc); return; } keylist.Add(distancesquared); valuelist.Add(xypc); } } } //* sort nearest nodes by distance from mouse click if (keylist.Count < 3) { return; //too near edge? } int[] keyarray = keylist.ToArray(); //distancesquared clsXYPC[] valuearray = valuelist.ToArray(); Array.Sort(keyarray, valuearray); //* find nearest 3 nodes (triangle - maj, min chords) clsXYPC[] chxypc = new clsXYPC[3]; for (int i = 0; i < 3; i++) { int pc = valuearray[i].PC; chxypc[i] = valuearray[i]; } //* check if triangle and find apex int y0 = chxypc[0].YPos; //nearest from mouseclick int y1 = chxypc[1].YPos; int y2 = chxypc[2].YPos; //furthest from mouseclick int apex = -1; if (y0 == y1 && y2 != y0) { apex = 2; } else if (y0 == y2 && y1 != y0) { apex = 1; } else if (y1 == y2 && y0 != y1) { apex = 0; } else { return; //not triangle } int[] chord = null; //if (e.Button == MouseButtons.Right) { //dim, aug if (e.Clicks == 2) //dim, aug //* get nearest non-apex node { int near = (apex == 0) ? 1 : 0; //nearest index List <int> chlist = new List <int>(4); chlist.Add(chxypc[apex].PC); chlist.Add(chxypc[near].PC); //2 nodes on nearest diagonal int diff = (chlist[1] - chlist[0]).Mod12(); if (diff > 6) { diff = 12 - diff; } if (diff != 3 && diff != 4) { return; //not dim or aug chord (should not happen) } //* add notes to make dim or aug chord int pc = chlist[1]; do { pc = (pc + diff).Mod12(); } while (chlist.Contains(pc)); chlist.Add(pc); if (diff == 3) //mi3 -> dim7 chord { do { pc = (pc + diff).Mod12(); } while (chlist.Contains(pc)); chlist.Add(pc); } chord = chlist.ToArray(); //} else if (e.Button == MouseButtons.Left) { //maj, min } else if (e.Clicks == 1) //maj, min { chord = new int[] { chxypc[0].PC, chxypc[1].PC, chxypc[2].PC }; } else { //LogicError.Throw(eLogicError.X143); return; } if (chord != null) { for (int i = 0; i < chord.Length; i++) { int pc = chord[i]; ActiveBoolChordMouse[pc] = true; //kbtrans applied } SetPlayChord(chord); } }
internal void CreateNodes() { //* always start at C (fixed keyboard allows for modulation) //* change solfa during modulation or kbtrans //* XYPC.PC = displayed PC - same as frmSC Space = HalfSpace * 2; //int pc = (Key == null) ? 0 : Key.KeyNote; int pc = 0; //C int y = 0; int ypos = HalfSpace; XYPC.Clear(); DictXYPC.Clear(); //* initialize PC and DictPC int xpos = HalfSpace; while (ypos < picPC.Height - HalfSpace) { List <clsXYPC> listx = new List <clsXYPC>(); int x = 0; while (xpos < picPC.Width - HalfSpace) { clsXYPC xypc = new clsXYPC(x, y, xpos, ypos, pc); listx.Add(xypc); x++; xpos += Space; pc = (pc + 7).Mod12(); //circle of fifths if (!DictXYPC.ContainsKey(pc)) { DictXYPC.Add(pc, xypc); } } XYPC.Add(listx); x = 0; if (y % 2 == 0) { xpos = Space; pc = (listx[0].PC + 3).Mod12(); //minor sixth } else { xpos = HalfSpace; //starting position pc = (listx[0].PC + 8).Mod12(); //minor third } y++; ypos += Space; } //* set key Key = (P.F.MTime == null) ? new clsKeyTicks(0, "major", 0) : P.F.Keys[P.F.CurrentBBT.Ticks, kbtrans : true]; bool[] scalenotes = (Key.Major) ? NoteName.MajScaleNotes : NoteName.MinScaleNotesDown; ScaleNotes = new bool[12]; for (int i = 0; i < 12; i++) { //ScaleNotes[(i + Key.KBTrans_KeyNote).Mod12()] = scalenotes[i]; ScaleNotes[(i + Key.KeyNote).Mod12()] = scalenotes[i]; } picPC.Refresh(); }
private void ShowBullsEyes(Graphics xgr, SizeF size) { //* show bullseye countdown using nudLookAhead clsMTime.clsBBT bbt = P.F.CurrentBBT.Copy(); int qi = bbt.Ticks / P.F.TicksPerQI; bool[] currentchord = P.F.CF.NoteMap[qi]; int lookahead = (int)nudLookAhead.Value; for (int i = 0; i < lookahead; i++) { bbt.NextBeat(); if (bbt.Ticks >= P.F.MaxTicks) { break; } qi = bbt.Ticks / P.F.TicksPerQI; bool[] chord = P.F.CF.NoteMap[qi]; if (chord.SequenceEqual(currentchord)) { continue; } if (chord.SequenceEqual(NullBoolChord)) { continue; } //* draw bullseyes int outerradius = Radius + lookahead * (int)nudBeatWidth.Value; int outerdiameter = 2 * outerradius; for (int y = 0; y < XYPC.Count; y++) { for (int x = 0; x < XYPC[y].Count; x++) { clsXYPC xypc = XYPC[y][x]; if (!chord[xypc.PC]) { continue; //only show if in new chord } int innerradius = Radius + i * (int)nudBeatWidth.Value; int innerdiameter = innerradius * 2; PointF outerloc = new PointF(xypc.XPos - outerradius, xypc.YPos - outerradius); SizeF outersize = new SizeF(outerdiameter, outerdiameter); RectangleF outerrectf = new RectangleF(outerloc, outersize); PointF innerloc = new PointF(xypc.XPos - innerradius, xypc.YPos - innerradius); SizeF innersize = new SizeF(innerdiameter, innerdiameter); RectangleF innerrectf = new RectangleF(innerloc, innersize); GraphicsPath path = new GraphicsPath(); path.AddEllipse(innerrectf); Region region = new Region(path); xgr.ExcludeClip(region); xgr.FillEllipse(BullsEyeBrush, outerrectf); xgr.ResetClip(); } } break; } }