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