#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 //-----------------------------------------------------------------------------