template<class T = int> struct slider_point
{
slider_point(){}
slider_point(T x, T y): X(x), Y(y){}
~slider_point(){}
T X;
T Y;
};
template<class T = int> struct slider_values
{
slider_values(){}
slider_values(slider_point<T> min_values, slider_point<T> max_values, slider_point<T> default_values)
:minimum(min_values),maximum(max_values),default(default_values),current(default_values)
{}
~slider_values(){}
slider_point<T> minimum;
slider_point<T> maximum;
slider_point<T> default;
slider_point<T> current;
};
struct slider_box
{
slider_box(){}
~slider_box(){}
slider_box(slider_point<float> position, slider_point<float> size, DWORD color_inner, DWORD color_outline):
pos(position), size(size), color_inner(color_inner), color_outline(color_outline)
{}
slider_point<float> pos;
slider_point<float> size;
DWORD color_inner;
DWORD color_outline;
void draw()
{
return render->D3DBoxBorder(pos.X,pos.Y,size.X,size.Y,color_outline,color_inner);
}
};
struct slider_button
{
slider_button(){}
slider_button(slider_point<float> size, slider_point<float> pos, button_color _appearance = default_appearance, button_color _highlight = default_highlighted, button_color _mousedown = default_mousedown)
: size(size), pos(pos), appearance(_appearance), highlight(_highlight), mousedown(_mousedown)
{}
~slider_button(){}
button_color appearance;
button_color highlight;
button_color mousedown;
slider_point<float> size;
slider_point<float> pos;
bool IsPointOnThis(slider_point<float> point)
{
return IsPointInArea(point.X,point.Y,pos.X,pos.Y,size.X,size.Y);
}
bool IsMouseOnThis()
{
return IsPointOnThis(slider_point<float>((float)cursorPos.x,(float)cursorPos.y));
}
void SetPos(slider_point<float> point)
{
pos = point;
}
void SetCenter(slider_point<float> point)
{
pos.X = (point.X - (size.X/2.0f));
pos.Y = (point.Y - (size.Y/2.0f));
}
void SetTopLeft(slider_point<float> point)
{
pos = point;
}
void SetTopRight(slider_point<float> point)
{
pos.Y = point.Y;
pos.X = point.X-size.X;
}
void SetBottomLeft(slider_point<float> point)
{
pos.X = point.X;
pos.Y = point.Y-size.Y;
}
void SetBottomRight(slider_point<float> point)
{
pos.X = point.X-size.X;
pos.Y = point.Y-size.Y;
}
float GetLeft()
{
return pos.X;
}
float GetRight()
{
return pos.X+size.X;
}
float GetTop()
{
return pos.Y;
}
float GetBottom()
{
return pos.Y+size.Y;
}
slider_point<float> GetCenter()
{
return slider_point<float>(pos.X+(size.X/2.0f),pos.Y+(size.Y/2.0f));
}
void draw()
{
if(!IsPointInArea(cursorPos.x,cursorPos.y,pos.X,pos.Y,size.X,size.Y))
return render->D3DBoxBorder(pos.X,pos.Y,size.X,size.Y,appearance.border,appearance.button);
if(Keys(VK_LBUTTON).Down)
return render->D3DBoxBorder(pos.X,pos.Y,size.X,size.Y,mousedown.border,mousedown.button);
return render->D3DBoxBorder(pos.X,pos.Y,size.X,size.Y,highlight.border,highlight.button);
}
};
//not only left/right or up/down, but also both at once!
template<class T = int> class slider
{
private:
slider_values<T> data;
bool Dragging;
slider_point<float> DragMouseStart;
slider_point<float> DragSliderStart;
public:
bool Show;
bool LockXMovement;
bool LockYMovement;
slider_box box;
slider_button sliding;
slider(){Show = true;Dragging=false;}
slider(slider_point<float> pos, slider_point<float> size, slider_point<T> minimum, slider_point<T> maximum, slider_point<T> default, slider_point<float> slider_size, DWORD _color_inner, DWORD _color_outline, bool LockX = false, bool LockY = false, button_color _appearance = default_appearance, button_color _highlighted = default_highlighted, button_color _mousedown = default_mousedown)
: data(minimum,maximum,default),LockXMovement(LockX),LockYMovement(LockY),box(pos,size,_color_inner,_color_outline), sliding(slider_size,pos,_appearance,_highlighted,_mousedown)
{
Dragging = false;
if(sliding.size.Y > box.size.Y)
{
sliding.size.Y = box.size.Y;
LockYMovement = true;
}
if(sliding.size.X > box.size.X)
{
sliding.size.X = box.size.X;
LockXMovement = true;
}
sliding.SetCenter( slider_point<float>( pos.X+( (float)(((float)(default.X-minimum.X))/((float)(maximum.X-minimum.X))) *size.X), pos.Y+( (float)(((float)(default.Y-minimum.Y))/((float)(maximum.Y-minimum.Y))) *size.Y)));
if(sliding.pos.X < box.pos.X)
sliding.pos = slider_point<float>( box.pos.X , sliding.pos.Y );
if(sliding.GetRight() > (box.pos.X + box.size.X))
sliding.SetTopRight(slider_point<float>( box.pos.X+box.size.X , sliding.pos.Y ));
if(sliding.pos.Y < box.pos.Y)
sliding.pos = slider_point<float>( sliding.pos.X , box.pos.Y );
if(sliding.GetBottom() > (box.pos.Y+box.size.Y))
sliding.SetBottomLeft(slider_point<float>( sliding.pos.X , box.pos.Y+box.size.Y ));
Show = true;
}
slider_values<T> GetValue()
{
return data.current;
}
void Process()
{
if(Dragging)
{
if(Keys(VK_LBUTTON).Up)
{
Dragging = false;
}
if(!LockXMovement)
{
float mousepos = (float)cursorPos.x;
sliding.pos = slider_point<float>( DragSliderStart.X+(mousepos-DragMouseStart.X) , sliding.pos.Y );
if(sliding.pos.X < box.pos.X)
sliding.pos = slider_point<float>( box.pos.X , sliding.pos.Y );
if(sliding.GetRight() > (box.pos.X+box.size.X))
sliding.SetTopRight(slider_point<float>( box.pos.X+box.size.X , sliding.pos.Y ));
data.current.X = data.minimum.X + (T)((float)(data.maximum.X-data.minimum.X) * ((sliding.pos.X-box.pos.X)/(box.size.X-sliding.size.X)));
}
if(!LockYMovement)
{
float mousepos = (float)cursorPos.y;
sliding.pos = slider_point<float>( sliding.pos.X , DragSliderStart.Y+(mousepos-DragMouseStart.Y) );
if(sliding.pos.Y < box.pos.Y)
sliding.pos = slider_point<float>( sliding.pos.X , box.pos.Y );
if(sliding.GetBottom() > (box.pos.Y+box.size.Y))
sliding.SetBottomLeft(slider_point<float>( sliding.pos.X , box.pos.Y+box.size.Y ));
data.current.Y = data.minimum.Y + (T)((float)(data.maximum.Y-data.minimum.Y) * ((sliding.pos.Y-box.pos.Y)/(box.size.Y-sliding.size.Y)));
}
DirectXFont::Access(4)->Print(0.0f,50.0f,0xFF00FF00,string_format("[%04d,%04d]",(int)data.current.X,(int)data.current.Y).c_str());
}else
if(Keys(VK_LBUTTON).Pressed)
{
if(sliding.IsMouseOnThis())
{
Dragging = true;
DragMouseStart.X = (float)cursorPos.x;
DragMouseStart.Y = (float)cursorPos.y;
DragSliderStart = sliding.pos;
}
}
box.draw();
sliding.draw();
}
~slider()
{
}
};
dGVtcGxhdGU8Y2xhc3MgVCA9IGludD4gc3RydWN0IHNsaWRlcl9wb2ludAp7CiAgICBzbGlkZXJfcG9pbnQoKXt9CglzbGlkZXJfcG9pbnQoVCB4LCBUIHkpOiBYKHgpLCBZKHkpe30KCX5zbGlkZXJfcG9pbnQoKXt9CglUIFg7CglUIFk7Cn07Cgp0ZW1wbGF0ZTxjbGFzcyBUID0gaW50PiBzdHJ1Y3Qgc2xpZGVyX3ZhbHVlcwp7CglzbGlkZXJfdmFsdWVzKCl7fQoJc2xpZGVyX3ZhbHVlcyhzbGlkZXJfcG9pbnQ8VD4gbWluX3ZhbHVlcywgc2xpZGVyX3BvaW50PFQ+IG1heF92YWx1ZXMsIHNsaWRlcl9wb2ludDxUPiBkZWZhdWx0X3ZhbHVlcykKCQk6bWluaW11bShtaW5fdmFsdWVzKSxtYXhpbXVtKG1heF92YWx1ZXMpLGRlZmF1bHQoZGVmYXVsdF92YWx1ZXMpLGN1cnJlbnQoZGVmYXVsdF92YWx1ZXMpCgl7fQoJfnNsaWRlcl92YWx1ZXMoKXt9CglzbGlkZXJfcG9pbnQ8VD4gbWluaW11bTsKCXNsaWRlcl9wb2ludDxUPiBtYXhpbXVtOwoJc2xpZGVyX3BvaW50PFQ+IGRlZmF1bHQ7CglzbGlkZXJfcG9pbnQ8VD4gY3VycmVudDsKfTsKCnN0cnVjdCBzbGlkZXJfYm94CnsKCXNsaWRlcl9ib3goKXt9Cgl+c2xpZGVyX2JveCgpe30KCXNsaWRlcl9ib3goc2xpZGVyX3BvaW50PGZsb2F0PiBwb3NpdGlvbiwgc2xpZGVyX3BvaW50PGZsb2F0PiBzaXplLCBEV09SRCBjb2xvcl9pbm5lciwgRFdPUkQgY29sb3Jfb3V0bGluZSk6CgkJcG9zKHBvc2l0aW9uKSwgc2l6ZShzaXplKSwgY29sb3JfaW5uZXIoY29sb3JfaW5uZXIpLCBjb2xvcl9vdXRsaW5lKGNvbG9yX291dGxpbmUpCgl7fQoJc2xpZGVyX3BvaW50PGZsb2F0PiBwb3M7CglzbGlkZXJfcG9pbnQ8ZmxvYXQ+IHNpemU7CglEV09SRCBjb2xvcl9pbm5lcjsKCURXT1JEIGNvbG9yX291dGxpbmU7Cgl2b2lkIGRyYXcoKQoJewoJCXJldHVybiByZW5kZXItPkQzREJveEJvcmRlcihwb3MuWCxwb3MuWSxzaXplLlgsc2l6ZS5ZLGNvbG9yX291dGxpbmUsY29sb3JfaW5uZXIpOwoJfQp9OwoKc3RydWN0IHNsaWRlcl9idXR0b24KewoJc2xpZGVyX2J1dHRvbigpe30KCXNsaWRlcl9idXR0b24oc2xpZGVyX3BvaW50PGZsb2F0PiBzaXplLCBzbGlkZXJfcG9pbnQ8ZmxvYXQ+IHBvcywgYnV0dG9uX2NvbG9yIF9hcHBlYXJhbmNlID0gZGVmYXVsdF9hcHBlYXJhbmNlLCBidXR0b25fY29sb3IgX2hpZ2hsaWdodCA9IGRlZmF1bHRfaGlnaGxpZ2h0ZWQsIGJ1dHRvbl9jb2xvciBfbW91c2Vkb3duID0gZGVmYXVsdF9tb3VzZWRvd24pCgkJOiBzaXplKHNpemUpLCBwb3MocG9zKSwgYXBwZWFyYW5jZShfYXBwZWFyYW5jZSksIGhpZ2hsaWdodChfaGlnaGxpZ2h0KSwgbW91c2Vkb3duKF9tb3VzZWRvd24pCgl7fQoJfnNsaWRlcl9idXR0b24oKXt9CglidXR0b25fY29sb3IgYXBwZWFyYW5jZTsKCWJ1dHRvbl9jb2xvciBoaWdobGlnaHQ7CglidXR0b25fY29sb3IgbW91c2Vkb3duOwoJc2xpZGVyX3BvaW50PGZsb2F0PiBzaXplOwoJc2xpZGVyX3BvaW50PGZsb2F0PiBwb3M7Cglib29sIElzUG9pbnRPblRoaXMoc2xpZGVyX3BvaW50PGZsb2F0PiBwb2ludCkKCXsKCQlyZXR1cm4gSXNQb2ludEluQXJlYShwb2ludC5YLHBvaW50LlkscG9zLlgscG9zLlksc2l6ZS5YLHNpemUuWSk7Cgl9Cglib29sIElzTW91c2VPblRoaXMoKQoJewoJCXJldHVybiBJc1BvaW50T25UaGlzKHNsaWRlcl9wb2ludDxmbG9hdD4oKGZsb2F0KWN1cnNvclBvcy54LChmbG9hdCljdXJzb3JQb3MueSkpOwoJfQoJdm9pZCBTZXRQb3Moc2xpZGVyX3BvaW50PGZsb2F0PiBwb2ludCkKCXsKCQlwb3MgPSBwb2ludDsKCX0KCXZvaWQgU2V0Q2VudGVyKHNsaWRlcl9wb2ludDxmbG9hdD4gcG9pbnQpCgl7CgkJcG9zLlggPSAocG9pbnQuWCAtIChzaXplLlgvMi4wZikpOwoJCXBvcy5ZID0gKHBvaW50LlkgLSAoc2l6ZS5ZLzIuMGYpKTsKCX0KCXZvaWQgU2V0VG9wTGVmdChzbGlkZXJfcG9pbnQ8ZmxvYXQ+IHBvaW50KQoJewoJCXBvcyA9IHBvaW50OwoJfQoJdm9pZCBTZXRUb3BSaWdodChzbGlkZXJfcG9pbnQ8ZmxvYXQ+IHBvaW50KQoJewoJCXBvcy5ZID0gcG9pbnQuWTsKCQlwb3MuWCA9IHBvaW50Llgtc2l6ZS5YOwoJfQoJdm9pZCBTZXRCb3R0b21MZWZ0KHNsaWRlcl9wb2ludDxmbG9hdD4gcG9pbnQpCgl7CgkJcG9zLlggPSBwb2ludC5YOwoJCXBvcy5ZID0gcG9pbnQuWS1zaXplLlk7Cgl9Cgl2b2lkIFNldEJvdHRvbVJpZ2h0KHNsaWRlcl9wb2ludDxmbG9hdD4gcG9pbnQpCgl7CgkJcG9zLlggPSBwb2ludC5YLXNpemUuWDsKCQlwb3MuWSA9IHBvaW50Llktc2l6ZS5ZOwoJfQoJZmxvYXQgR2V0TGVmdCgpCgl7CgkJcmV0dXJuIHBvcy5YOwoJfQoJZmxvYXQgR2V0UmlnaHQoKQoJewoJCXJldHVybiBwb3MuWCtzaXplLlg7Cgl9CglmbG9hdCBHZXRUb3AoKQoJewoJCXJldHVybiBwb3MuWTsKCX0KCWZsb2F0IEdldEJvdHRvbSgpCgl7CgkJcmV0dXJuIHBvcy5ZK3NpemUuWTsKCX0KCXNsaWRlcl9wb2ludDxmbG9hdD4gR2V0Q2VudGVyKCkKCXsKCQlyZXR1cm4gc2xpZGVyX3BvaW50PGZsb2F0Pihwb3MuWCsoc2l6ZS5YLzIuMGYpLHBvcy5ZKyhzaXplLlkvMi4wZikpOwoJfQoJdm9pZCBkcmF3KCkKCXsKCQlpZighSXNQb2ludEluQXJlYShjdXJzb3JQb3MueCxjdXJzb3JQb3MueSxwb3MuWCxwb3MuWSxzaXplLlgsc2l6ZS5ZKSkKCQkJcmV0dXJuIHJlbmRlci0+RDNEQm94Qm9yZGVyKHBvcy5YLHBvcy5ZLHNpemUuWCxzaXplLlksYXBwZWFyYW5jZS5ib3JkZXIsYXBwZWFyYW5jZS5idXR0b24pOwoJCWlmKEtleXMoVktfTEJVVFRPTikuRG93bikKCQkJcmV0dXJuIHJlbmRlci0+RDNEQm94Qm9yZGVyKHBvcy5YLHBvcy5ZLHNpemUuWCxzaXplLlksbW91c2Vkb3duLmJvcmRlcixtb3VzZWRvd24uYnV0dG9uKTsKCQlyZXR1cm4gIHJlbmRlci0+RDNEQm94Qm9yZGVyKHBvcy5YLHBvcy5ZLHNpemUuWCxzaXplLlksaGlnaGxpZ2h0LmJvcmRlcixoaWdobGlnaHQuYnV0dG9uKTsKCX0KfTsKCi8vbm90IG9ubHkgbGVmdC9yaWdodCBvciB1cC9kb3duLCBidXQgYWxzbyBib3RoIGF0IG9uY2UhCnRlbXBsYXRlPGNsYXNzIFQgPSBpbnQ+IGNsYXNzIHNsaWRlcgp7CnByaXZhdGU6CglzbGlkZXJfdmFsdWVzPFQ+IGRhdGE7Cglib29sIERyYWdnaW5nOwkKCXNsaWRlcl9wb2ludDxmbG9hdD4gRHJhZ01vdXNlU3RhcnQ7CglzbGlkZXJfcG9pbnQ8ZmxvYXQ+IERyYWdTbGlkZXJTdGFydDsKcHVibGljOgoJYm9vbCBTaG93OwoJYm9vbCBMb2NrWE1vdmVtZW50OwoJYm9vbCBMb2NrWU1vdmVtZW50OwoJc2xpZGVyX2JveCBib3g7CglzbGlkZXJfYnV0dG9uIHNsaWRpbmc7CglzbGlkZXIoKXtTaG93ID0gdHJ1ZTtEcmFnZ2luZz1mYWxzZTt9CglzbGlkZXIoc2xpZGVyX3BvaW50PGZsb2F0PiBwb3MsIHNsaWRlcl9wb2ludDxmbG9hdD4gc2l6ZSwgc2xpZGVyX3BvaW50PFQ+IG1pbmltdW0sIHNsaWRlcl9wb2ludDxUPiBtYXhpbXVtLCBzbGlkZXJfcG9pbnQ8VD4gZGVmYXVsdCwgc2xpZGVyX3BvaW50PGZsb2F0PiBzbGlkZXJfc2l6ZSwgRFdPUkQgX2NvbG9yX2lubmVyLCBEV09SRCBfY29sb3Jfb3V0bGluZSwgYm9vbCBMb2NrWCA9IGZhbHNlLCBib29sIExvY2tZID0gZmFsc2UsIGJ1dHRvbl9jb2xvciBfYXBwZWFyYW5jZSA9IGRlZmF1bHRfYXBwZWFyYW5jZSwgYnV0dG9uX2NvbG9yIF9oaWdobGlnaHRlZCA9IGRlZmF1bHRfaGlnaGxpZ2h0ZWQsIGJ1dHRvbl9jb2xvciBfbW91c2Vkb3duID0gZGVmYXVsdF9tb3VzZWRvd24pCgkJOiBkYXRhKG1pbmltdW0sbWF4aW11bSxkZWZhdWx0KSxMb2NrWE1vdmVtZW50KExvY2tYKSxMb2NrWU1vdmVtZW50KExvY2tZKSxib3gocG9zLHNpemUsX2NvbG9yX2lubmVyLF9jb2xvcl9vdXRsaW5lKSwgc2xpZGluZyhzbGlkZXJfc2l6ZSxwb3MsX2FwcGVhcmFuY2UsX2hpZ2hsaWdodGVkLF9tb3VzZWRvd24pCgl7CgkJRHJhZ2dpbmcgPSBmYWxzZTsKCQlpZihzbGlkaW5nLnNpemUuWSA+IGJveC5zaXplLlkpCgkJewoJCQlzbGlkaW5nLnNpemUuWSA9IGJveC5zaXplLlk7CgkJCUxvY2tZTW92ZW1lbnQgPSB0cnVlOwoJCX0KCQlpZihzbGlkaW5nLnNpemUuWCA+IGJveC5zaXplLlgpCgkJewoJCQlzbGlkaW5nLnNpemUuWCA9IGJveC5zaXplLlg7CgkJCUxvY2tYTW92ZW1lbnQgPSB0cnVlOwoJCX0KCQkKCQkJCgkJc2xpZGluZy5TZXRDZW50ZXIoIHNsaWRlcl9wb2ludDxmbG9hdD4oIHBvcy5YKyggKGZsb2F0KSgoKGZsb2F0KShkZWZhdWx0LlgtbWluaW11bS5YKSkvKChmbG9hdCkobWF4aW11bS5YLW1pbmltdW0uWCkpKSAqc2l6ZS5YKSwgcG9zLlkrKCAoZmxvYXQpKCgoZmxvYXQpKGRlZmF1bHQuWS1taW5pbXVtLlkpKS8oKGZsb2F0KShtYXhpbXVtLlktbWluaW11bS5ZKSkpICpzaXplLlkpKSk7CgkJaWYoc2xpZGluZy5wb3MuWCA8IGJveC5wb3MuWCkKCQkJc2xpZGluZy5wb3MgPSBzbGlkZXJfcG9pbnQ8ZmxvYXQ+KCBib3gucG9zLlggLCBzbGlkaW5nLnBvcy5ZICk7CgkJaWYoc2xpZGluZy5HZXRSaWdodCgpID4gKGJveC5wb3MuWCArIGJveC5zaXplLlgpKQoJCQlzbGlkaW5nLlNldFRvcFJpZ2h0KHNsaWRlcl9wb2ludDxmbG9hdD4oIGJveC5wb3MuWCtib3guc2l6ZS5YICwgc2xpZGluZy5wb3MuWSApKTsKCQlpZihzbGlkaW5nLnBvcy5ZIDwgYm94LnBvcy5ZKQoJCQlzbGlkaW5nLnBvcyA9IHNsaWRlcl9wb2ludDxmbG9hdD4oIHNsaWRpbmcucG9zLlggLCBib3gucG9zLlkgKTsKCQlpZihzbGlkaW5nLkdldEJvdHRvbSgpID4gKGJveC5wb3MuWStib3guc2l6ZS5ZKSkKCQkJc2xpZGluZy5TZXRCb3R0b21MZWZ0KHNsaWRlcl9wb2ludDxmbG9hdD4oIHNsaWRpbmcucG9zLlggLCBib3gucG9zLlkrYm94LnNpemUuWSApKTsKCQlTaG93ID0gdHJ1ZTsKCX0KCXNsaWRlcl92YWx1ZXM8VD4gR2V0VmFsdWUoKQoJewoJCXJldHVybiBkYXRhLmN1cnJlbnQ7Cgl9Cgl2b2lkIFByb2Nlc3MoKQoJewoJCWlmKERyYWdnaW5nKQoJCXsKCQkJaWYoS2V5cyhWS19MQlVUVE9OKS5VcCkKCQkJewoJCQkJRHJhZ2dpbmcgPSBmYWxzZTsKCQkJfQoJCQlpZighTG9ja1hNb3ZlbWVudCkKCQkJewoJCQkJZmxvYXQgbW91c2Vwb3MgPSAoZmxvYXQpY3Vyc29yUG9zLng7CgkJCQlzbGlkaW5nLnBvcyA9IHNsaWRlcl9wb2ludDxmbG9hdD4oIERyYWdTbGlkZXJTdGFydC5YKyhtb3VzZXBvcy1EcmFnTW91c2VTdGFydC5YKSAsIHNsaWRpbmcucG9zLlkgKTsKCQkJCWlmKHNsaWRpbmcucG9zLlggPCBib3gucG9zLlgpCgkJCQkJc2xpZGluZy5wb3MgPSBzbGlkZXJfcG9pbnQ8ZmxvYXQ+KCBib3gucG9zLlggLCBzbGlkaW5nLnBvcy5ZICk7CgkJCQlpZihzbGlkaW5nLkdldFJpZ2h0KCkgPiAoYm94LnBvcy5YK2JveC5zaXplLlgpKQoJCQkJCXNsaWRpbmcuU2V0VG9wUmlnaHQoc2xpZGVyX3BvaW50PGZsb2F0PiggYm94LnBvcy5YK2JveC5zaXplLlggLCBzbGlkaW5nLnBvcy5ZICkpOwoJCQkJZGF0YS5jdXJyZW50LlggPSBkYXRhLm1pbmltdW0uWCArIChUKSgoZmxvYXQpKGRhdGEubWF4aW11bS5YLWRhdGEubWluaW11bS5YKSAqICgoc2xpZGluZy5wb3MuWC1ib3gucG9zLlgpLyhib3guc2l6ZS5YLXNsaWRpbmcuc2l6ZS5YKSkpOwoJCQl9CgkJCWlmKCFMb2NrWU1vdmVtZW50KQoJCQl7CgkJCQlmbG9hdCBtb3VzZXBvcyA9IChmbG9hdCljdXJzb3JQb3MueTsKCQkJCXNsaWRpbmcucG9zID0gc2xpZGVyX3BvaW50PGZsb2F0Piggc2xpZGluZy5wb3MuWCAsIERyYWdTbGlkZXJTdGFydC5ZKyhtb3VzZXBvcy1EcmFnTW91c2VTdGFydC5ZKSApOwoJCQkJaWYoc2xpZGluZy5wb3MuWSA8IGJveC5wb3MuWSkKCQkJCQlzbGlkaW5nLnBvcyA9IHNsaWRlcl9wb2ludDxmbG9hdD4oIHNsaWRpbmcucG9zLlggLCBib3gucG9zLlkgKTsKCQkJCWlmKHNsaWRpbmcuR2V0Qm90dG9tKCkgPiAoYm94LnBvcy5ZK2JveC5zaXplLlkpKQoJCQkJCXNsaWRpbmcuU2V0Qm90dG9tTGVmdChzbGlkZXJfcG9pbnQ8ZmxvYXQ+KCBzbGlkaW5nLnBvcy5YICwgYm94LnBvcy5ZK2JveC5zaXplLlkgKSk7CgkJCQlkYXRhLmN1cnJlbnQuWSA9IGRhdGEubWluaW11bS5ZICsgKFQpKChmbG9hdCkoZGF0YS5tYXhpbXVtLlktZGF0YS5taW5pbXVtLlkpICogKChzbGlkaW5nLnBvcy5ZLWJveC5wb3MuWSkvKGJveC5zaXplLlktc2xpZGluZy5zaXplLlkpKSk7CgkJCX0KCQkJRGlyZWN0WEZvbnQ6OkFjY2Vzcyg0KS0+UHJpbnQoMC4wZiw1MC4wZiwweEZGMDBGRjAwLHN0cmluZ19mb3JtYXQoIlslMDRkLCUwNGRdIiwoaW50KWRhdGEuY3VycmVudC5YLChpbnQpZGF0YS5jdXJyZW50LlkpLmNfc3RyKCkpOwoJCX1lbHNlCgkJaWYoS2V5cyhWS19MQlVUVE9OKS5QcmVzc2VkKQoJCXsKCQkJaWYoc2xpZGluZy5Jc01vdXNlT25UaGlzKCkpCgkJCXsKCQkJCURyYWdnaW5nID0gdHJ1ZTsKCQkJCURyYWdNb3VzZVN0YXJ0LlggPSAoZmxvYXQpY3Vyc29yUG9zLng7CgkJCQlEcmFnTW91c2VTdGFydC5ZID0gKGZsb2F0KWN1cnNvclBvcy55OwoJCQkJRHJhZ1NsaWRlclN0YXJ0ID0gc2xpZGluZy5wb3M7CgkJCX0KCQl9CgkJYm94LmRyYXcoKTsKCQlzbGlkaW5nLmRyYXcoKTsKCX0KCX5zbGlkZXIoKQoJewoKCX0KfTsK