| #include "ext/Selector.h" |
| #include "tgl.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); |
| 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); |
| |
| { |
| |
| TPointD |
| down = -this->getUp(), |
| center = pnt + down * (height_); |
| const double |
| length = s_square_size * 0.5 * pixel_size_; |
| |
| TPointD |
| |
| offset(length, |
| length), |
| bottom_left = center - offset, |
| top_rigth = center + offset; |
| |
| TRectD |
| rectangle(bottom_left, |
| top_rigth); |
| |
| if (isSelected_ == LENGTH) |
| tglFillRect(rectangle); |
| |
| tglDrawRect(rectangle); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 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_; |
| |
| |
| TPointD |
| center = pnt + up * ( height_ + radius); |
| |
| glColor3d(1.0,0.0,1.0); |
| tglDrawCircle(center,radius+pixel_size_); |
| |
| |
| 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) |
| { |
| |
| |
| |
| |
| |
| 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_; |
| |
| |
| TPointD |
| center = pnt + up * (height_ + radius); |
| |
| |
| if (tdistance2(center, pos) <= sq(radius + pixel_size_)) |
| return POSITION; |
| |
| center = pnt + down * (height_); |
| |
| |
| const double length = s_square_size * 0.5 * pixel_size_; |
| |
| TPointD |
| |
| 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; |
| } |
| |
| |
| |
| |