#ifdef WIN32
#define NOMINMAX
#endif
#include "ext/Selector.h"
#include "tgl.h"
//#include "drawutil.h"
#include "tmathutil.h"
using namespace ToonzExt;
//-----------------------------------------------------------------------------
namespace
{
const GLfloat s_normalColor[] = {250.0 / 255.0, 127 / 255.0, 240 / 255.0};
const GLfloat s_highlightedColor[] = {150.0 / 255.0, 255.0 / 255.0, 140.0 / 255.0};
const double s_sqrt_2 = sqrt(2.0);
const double s_radius = 5.0;
const double s_over_size = 10;
const double s_length = 15;
const double s_square_size = 5;
const double s_arrow_ratio = 2.5;
void drawArrow(const TPointD &from,
const TPointD &direction,
double length,
const TPointD &arrowDirection = TPointD(0.0, -1.0),
double arrowLength = 0.0)
{
if (length <= 0 ||
arrowLength < 0)
return;
if (arrowLength == 0.0)
arrowLength = 0.2 * length;
TPointD
pnt(from),
myDir = normalize(direction);
TPointD
myArrowDirection(arrowDirection);
if (arrowDirection.y <= 0.0)
myArrowDirection = normalize(TPointD(-0.5, 0.8));
if (direction * TPointD(1, 0) <= 0.0)
myArrowDirection.x = -myArrowDirection.x;
myDir = myDir * length;
myArrowDirection = myArrowDirection * arrowLength;
glBegin(GL_LINES);
tglVertex(pnt);
pnt += myDir;
tglVertex(pnt);
glEnd();
glBegin(GL_TRIANGLES);
TPointD
up = myDir + myArrowDirection;
tglVertex(from + up);
//tglVertex(pnt);
tglVertex(pnt);
myArrowDirection.y = -myArrowDirection.y;
TPointD
down = myDir + myArrowDirection;
tglVertex(from + down);
glEnd();
}
}
//-----------------------------------------------------------------------------
Selector::Selector(double stroke_length,
double min_val,
double max_val)
{
original_stroke_length_ = stroke_length;
range_ = TPointD(min_val, max_val);
isVisible_ = false;
pixel_size_ = 1.0;
w_ = 0.5;
this->init();
}
//-----------------------------------------------------------------------------
void Selector::init()
{
strokeRef_ = 0;
signum_ = 1.0;
isSelected_ = NONE;
}
//-----------------------------------------------------------------------------
Selector::~Selector()
{
}
//-----------------------------------------------------------------------------
TPointD
Selector::getUp() const
{
if (!strokeRef_)
return TPointD();
TThickPoint
pnt = strokeRef_->getPoint(w_);
TPointD
p = convert(pnt),
p1;
TPointD
v0,
v1,
v = normalize(rotate90(strokeRef_->getSpeed(w_)));
const double delta = TConsts::epsilon;
if (w_ - delta >= 0.0)
v0 = rotate90(strokeRef_->getSpeed(w_ - delta));
else
v0 = rotate90(strokeRef_->getSpeed(0));
if (w_ + delta <= 1.0)
v1 = rotate90(strokeRef_->getSpeed(w_ + delta));
else
v1 = rotate90(strokeRef_->getSpeed(1.0));
if (!isAlmostZero(v * v0) ||
!isAlmostZero(v * v1))
v = normalize(v1 + v0);
return v;
}
//-----------------------------------------------------------------------------
void Selector::draw(Designer *designer)
{
if (!strokeRef_ ||
!isVisible_)
return;
pixel_size_ = designer ? sqrt(designer->getPixelSize2()) : 1.0;
TPointD
v = this->getUp(),
n = normalize(rotate90(v));
TThickPoint
pnt = strokeRef_->getThickPoint(w_);
height_ = (pnt.thick + s_over_size) * pixel_size_;
TPointD
p(pnt.x, pnt.y),
up = p + v * height_,
down = p - v * height_;
glColor3fv(s_normalColor);
glBegin(GL_LINES);
tglVertex(down);
tglVertex(up);
glEnd();
if (isSelected_ == POSITION)
glColor3fv(s_highlightedColor);
else
glColor3fv(s_normalColor);
double
radius = s_radius * pixel_size_;
if (isSelected_ == POSITION)
tglDrawDisk(up + v * radius,
radius);
tglDrawCircle(up + v * radius,
radius);
if (isSelected_ == LENGTH)
glColor3fv(s_highlightedColor);
else
glColor3fv(s_normalColor);
{
// the circle center is in
TPointD
down = -this->getUp(),
center = pnt + down * (height_);
const double
length = s_square_size * 0.5 * pixel_size_;
TPointD
// offset(length, 0.0),
offset(length,
length),
bottom_left = center - offset,
top_rigth = center + offset;
TRectD
rectangle(bottom_left,
top_rigth);
if (isSelected_ == LENGTH)
tglFillRect(rectangle);
tglDrawRect(rectangle);
}
/*
TPointD
arrowDirection(-0.5,0.8);
if( signum_ < 0.0 )
arrowDirection.x = -arrowDirection.x;
const double
length = s_length * pixel_size_,
arrow_length = length/s_arrow_ratio;
drawArrow(down,
TPointD(1,0),
length,
arrowDirection,
arrow_length);
drawArrow(down,
TPointD(-1,0),
length,
arrowDirection,
arrow_length);
*/
// draw stroke related information
if (designer &&
this->isSelected())
designer->draw(this);
#if 0 //def _DEBUG
{
TThickPoint
pnt = strokeRef_->getThickPoint(w_);
TPointD
up = this->getUp(),
down = -up;
double
radius = s_radius * pixel_size_;
// the circle center is in
TPointD
center = pnt + up * ( height_ + radius);
glColor3d(1.0,0.0,1.0);
tglDrawCircle(center,radius+pixel_size_);
// one pixel of tolerance
center = pnt + down * ( height_ );
const double
length = s_length * pixel_size_;
TPointD
offset(length, 0.0),
bottom_left = center - offset,
top_rigth = center + offset;
TRectD
rectangle(bottom_left,
top_rigth);
rectangle = rectangle.enlarge( 2.0* pixel_size_);
tglDrawRect(rectangle);
}
#endif
}
//-----------------------------------------------------------------------------
void Selector::mouseDown(const TPointD &pos)
{
click_ =
curr_ =
pos;
if (!strokeRef_)
return;
stroke_length_ =
original_stroke_length_;
prev_ = curr_;
}
//-----------------------------------------------------------------------------
void Selector::mouseUp(const TPointD &pos)
{
curr_ = pos;
if (!strokeRef_)
return;
original_stroke_length_ =
stroke_length_;
prev_ = curr_;
}
//-----------------------------------------------------------------------------
void Selector::mouseMove(const TPointD &pos)
{
curr_ = pos;
if (!strokeRef_)
return;
isSelected_ = this->getSelection(pos);
prev_ = curr_;
}
//-----------------------------------------------------------------------------
void Selector::mouseDrag(const TPointD &pos)
{
curr_ = pos;
if (!strokeRef_)
return;
double
val = original_stroke_length_;
const double
stroke_length = strokeRef_->getLength();
double
max_val = std::min(stroke_length, range_.y);
TPointD
v = curr_ - prev_;
signum_ = 1.0;
switch (isSelected_) {
case POSITION:
w_ = strokeRef_->getW(pos);
break;
case LENGTH:
signum_ = v * TPointD(1.0, 0.0) < 0.0 ? -1.0 : 1.0;
val = original_stroke_length_ + signum_ * pixel_size_ * norm(v);
stroke_length_ = std::max(std::min(max_val, val), range_.x);
break;
default:
assert(false);
}
prev_ = curr_;
}
//-----------------------------------------------------------------------------
void Selector::setStroke(const TStroke *ref)
{
//if(strokeRef_ &&
// strokeRef_ != ref )
// w_=strokeRef_->getParameterAtLength( strokeRef_->getLength()*0.5);
//else
// w_=0.5;
this->init();
strokeRef_ = ref;
}
//-----------------------------------------------------------------------------
Selector::Selection
Selector::getSelection(const TPointD &pos)
{
if (!strokeRef_ ||
!isVisible_)
return NONE;
TThickPoint
pnt = strokeRef_->getThickPoint(w_);
TPointD
up = this->getUp(),
down = -up;
double
radius = s_radius * pixel_size_;
// the circle center is in
TPointD
center = pnt + up * (height_ + radius);
// one pixel of tolerance
if (tdistance2(center, pos) <= sq(radius + pixel_size_))
return POSITION;
center = pnt + down * (height_);
// const double length = s_length * pixel_size_;
const double length = s_square_size * 0.5 * pixel_size_;
TPointD
// offset(length, 0.0),
offset(length,
length),
bottom_left = center - offset,
top_rigth = center + offset;
TRectD
rectangle(bottom_left,
top_rigth);
rectangle = rectangle.enlarge(2.0 * pixel_size_);
if (rectangle.contains(pos))
return LENGTH;
return NONE;
}
//-----------------------------------------------------------------------------
double
Selector::getLength() const
{
return stroke_length_;
}
//-----------------------------------------------------------------------------
void Selector::setLength(double length)
{
stroke_length_ =
original_stroke_length_ = length;
}
//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------