private void ParseNoteProperties(IXmlNode node, Note note, string noteId)
{
bool isBended = false;
BendPoint bendOrigin = null;
int? bendMiddleValue = null;
int? bendMiddleOffset1 = null;
int? bendMiddleOffset2 = null;
BendPoint bendDestination = null;
node.IterateChildren(c =>
{
if (c.NodeType == XmlNodeType.Element)
{
switch (c.LocalName)
{
case "Property":
var name = c.GetAttribute("name");
switch (name)
{
case "String":
note.String = Std.ParseInt(GetValue(FindChildElement(c, "String"))) + 1;
break;
case "Fret":
note.Fret = Std.ParseInt(GetValue(FindChildElement(c, "Fret")));
break;
case "Element":
note.Element = Std.ParseInt(GetValue(FindChildElement(c, "Element")));
break;
case "Variation":
note.Variation = Std.ParseInt(GetValue(FindChildElement(c, "Variation")));
break;
case "Tapped":
_tappedNotes[noteId] = true;
break;
case "HarmonicType":
var htype = FindChildElement(c, "HType");
if (htype != null)
{
switch (GetValue(htype))
{
case "NoHarmonic":
note.HarmonicType = HarmonicType.None;
break;
case "Natural":
note.HarmonicType = HarmonicType.Natural;
break;
case "Artificial":
note.HarmonicType = HarmonicType.Artificial;
break;
case "Pinch":
note.HarmonicType = HarmonicType.Pinch;
break;
case "Tap":
note.HarmonicType = HarmonicType.Tap;
break;
case "Semi":
note.HarmonicType = HarmonicType.Semi;
break;
case "Feedback":
note.HarmonicType = HarmonicType.Feedback;
break;
}
}
break;
case "HarmonicFret":
var hfret = FindChildElement(c, "HFret");
if (hfret != null)
{
note.HarmonicValue = Std.ParseFloat(GetValue(hfret));
}
break;
case "Muted":
if (FindChildElement(c, "Enable") != null)
note.IsDead = true;
break;
case "PalmMuted":
if (FindChildElement(c, "Enable") != null)
note.IsPalmMute = true;
break;
// case "Element":
// case "Variation":
// case "Tone":
case "Octave":
note.Octave = Std.ParseInt(GetValue(FindChildElement(c, "Number"))) - 1;
break;
case "Tone":
note.Tone = Std.ParseInt(GetValue(FindChildElement(c, "Step")));
break;
case "Bended":
isBended = true;
break;
case "BendOriginValue":
if (bendOrigin == null) bendOrigin = new BendPoint();
bendOrigin.Value = ToBendValue(Std.ParseFloat(GetValue(FindChildElement(c, "Float"))));
break;
case "BendOriginOffset":
if (bendOrigin == null) bendOrigin = new BendPoint();
bendOrigin.Offset = ToBendOffset(Std.ParseFloat(GetValue(FindChildElement(c, "Float"))));
break;
case "BendMiddleValue":
bendMiddleValue = ToBendValue(Std.ParseFloat(GetValue(FindChildElement(c, "Float"))));
break;
case "BendMiddleOffset1":
bendMiddleOffset1 = ToBendOffset(Std.ParseFloat(GetValue(FindChildElement(c, "Float"))));
break;
case "BendMiddleOffset2":
bendMiddleOffset2 = ToBendOffset(Std.ParseFloat(GetValue(FindChildElement(c, "Float"))));
break;
case "BendDestinationValue":
if (bendDestination == null) bendDestination = new BendPoint(BendPoint.MaxPosition);
// NOTE: If we directly cast the expression of value to (int) it is 3 instead of 4, strange compiler
// optimizations happening here:
// (int)(Std.ParseFloat(GetValue(FindChildElement(c, "Float")))* BendPointValueFactor) => (int)(100f * 0.04f) => 3
// (Std.ParseFloat(GetValue(FindChildElement(c, "Float")))* BendPointValueFactor) => (100f * 0.04f) => 4.0
bendDestination.Value = ToBendValue(Std.ParseFloat(GetValue(FindChildElement(c, "Float"))));
break;
case "BendDestinationOffset":
if (bendDestination == null) bendDestination = new BendPoint();
bendDestination.Offset = ToBendOffset(Std.ParseFloat(GetValue(FindChildElement(c, "Float"))));
break;
case "HopoOrigin":
if (FindChildElement(c, "Enable") != null)
note.IsHammerPullOrigin = true;
break;
case "HopoDestination":
// NOTE: gets automatically calculated
// if (FindChildElement(node, "Enable") != null)
// note.isHammerPullDestination = true;
break;
case "Slide":
var slideFlags = Std.ParseInt(GetValue(FindChildElement(c, "Flags")));
if ((slideFlags & 0x01) != 0)
note.SlideType = SlideType.Shift;
if ((slideFlags & 0x02) != 0)
note.SlideType = SlideType.Legato;
if ((slideFlags & 0x04) != 0)
note.SlideType = SlideType.OutDown;
if ((slideFlags & 0x08) != 0)
note.SlideType = SlideType.OutUp;
if ((slideFlags & 0x10) != 0)
note.SlideType = SlideType.IntoFromBelow;
if ((slideFlags & 0x20) != 0)
note.SlideType = SlideType.IntoFromAbove;
break;
}
break;
}
}
});
if (isBended)
{
if (bendOrigin == null) bendOrigin = new BendPoint();
if (bendDestination == null) bendDestination = new BendPoint(BendPoint.MaxPosition);
note.AddBendPoint(bendOrigin);
if (bendMiddleOffset1 != null && bendMiddleValue != null)
{
note.AddBendPoint(new BendPoint(bendMiddleOffset1.Value, bendMiddleValue.Value));
}
if (bendMiddleOffset2 != null && bendMiddleValue != null)
{
note.AddBendPoint(new BendPoint(bendMiddleOffset2.Value, bendMiddleValue.Value));
}
if (bendMiddleOffset1 == null && bendMiddleOffset2 == null && bendMiddleValue != null)
{
note.AddBendPoint(new BendPoint(BendPoint.MaxPosition / 2, bendMiddleValue.Value));
}
note.AddBendPoint(bendDestination);
}
}