Blob Blame Raw


#ifdef _WIN32
#define NOMINMAX
#endif

#include "ext/OverallDesigner.h"
//#include "ext/StrokeParametricDeformer.h"
#include "ext/StrokeDeformation.h"
#include "ext/SmoothDeformation.h"
#include "ext/CornerDeformation.h"
#include "ext/StraightCornerDeformation.h"
#include "ext/Selector.h"
#include "ext/ContextStatus.h"

#include "tcurves.h"

#include <tstroke.h>
#include <tgl.h>
#include <tgeometry.h>
#include <drawutil.h>
#include <sstream>

/*
#ifdef  _DEBUG
#undef  _DEBUG
#define RESTORE_DEBUG
#endif
//*/

//-----------------------------------------------------------------------------

namespace
{
void extglDrawText(const TPointD &p,
				   const std::string &s,
				   void *character = GLUT_BITMAP_TIMES_ROMAN_10)
{
	glPushMatrix();
	glTranslated(p.x, p.y, 0);
	if (character <= GLUT_STROKE_MONO_ROMAN) {
		double factor = 0.07;
		glScaled(factor, factor, factor);
		for (int i = 0; i < (int)s.size(); i++)
			glutStrokeCharacter(character, s[i]);
	} else
		for (int i = 0; i < (int)s.size(); i++)
			glutBitmapCharacter(character, s[i]);

	glPopMatrix();
}

//---------------------------------------------------------------------------

void drawSign(const TPointD &p,
			  const TPointD &v,
			  double size)
{
	if (size == 0.0)
		return;
	size = fabs(size);

	TPointD v90 = rotate90(v);
	TPointD v270 = rotate270(v);

	glBegin(GL_LINES);
	glVertex2d(p.x, p.y);
	v90 = normalize(v90);
	v90 = v90 * size;
	v90 = p + v90;
	glVertex2d(v90.x, v90.y);
	glEnd();
	glBegin(GL_LINES);
	glVertex2d(p.x, p.y);
	v270 = normalize(v270);
	v270 = v270 * size;
	v270 = p + v270;
	glVertex2d(v270.x, v270.y);
	glEnd();
}

//---------------------------------------------------------------------------

void drawCross(const TPointD &p,
			   double size)
{
	TPointD
		v1 = TPointD(1, 1);
	TPointD
		v2 = TPointD(1, -1);

	drawSign(p, v1, size);
	drawSign(p, v2, size);
}

//---------------------------------------------------------------------------

/**
   * Try to verify if it is possible to call
   * some method of this stroke.
   */
bool isValid(const TStroke *s)
{
	if (!s)
		return false;
	const int
		cpCount = s->getControlPointCount();
	int
		i;
	for (i = 0;
		 i < cpCount;
		 ++i)
		s->getControlPoint(i);
	const int
		chunkCount = s->getChunkCount();
	for (i = 0;
		 i < chunkCount;
		 ++i)
		s->getChunk(i);
	return true;
}

//---------------------------------------------------------------------------

void showCP(const TStroke *s,
			double pixelSize)
{
	if (!s)
		return;

	// show control points
	const int
		countCP = s->getControlPointCount();
	TThickPoint
		p1;

	for (int i = 0;
		 i < countCP;
		 ++i) {
		p1 = s->getControlPoint(i);
		if (i & 1)
			glColor3d(1.0, 0.0, 0.0);
		else
			glColor3d(1.0, 1.0, 0.0);

		drawCross(convert(p1),
				  p1.thick * pixelSize);
		tglDrawCircle(convert(p1),
					  p1.thick * pixelSize);
	}
}

//---------------------------------------------------------------------------

void drawStrokeCenterLine(const TStroke *stroke,
						  double pixelSize,
						  const ToonzExt::Interval &vals)
{
	double
		from = vals.first,
		to = vals.second;

	if (!stroke ||
		pixelSize < 0.0)
		return;

	from = std::max(std::min(from, 1.0), 0.0);
	to = std::max(std::min(to, 1.0), 0.0);

	if (from < to) {
		drawStrokeCenterline(*stroke,
							 pixelSize,
							 from,
							 to);
	} else {
		drawStrokeCenterline(*stroke,
							 pixelSize,
							 from,
							 1.0);
		drawStrokeCenterline(*stroke,
							 pixelSize,
							 0.0,
							 to);
	}
	tglDrawDisk(stroke->getPoint(from),
				5.0 * pixelSize);
	tglDrawDisk(stroke->getPoint(to),
				5.0 * pixelSize);

#ifdef _DEBUG
	glColor3d(1.0, 0.0, 0.0);
	tglDrawDisk(stroke->getPoint(0.0),
				9.0 * pixelSize);
#endif
}

//---------------------------------------------------------------------------

void showCorners(const TStroke *s,
				 int cornerSize,
				 double pixelSize)
{
	if (!s)
		return;

	const TPointD
		offset(20, 20);

	// show corners
	vector<double>
		corners;

	ToonzExt::cornersDetector(s,
							  cornerSize,
							  corners);
	if (corners.empty())
		return;

	int
		i,
		size = corners.size();

	glColor3d(0.8, 1.0, 0.3);
	// find interval with corner like extremes
	for (i = 0;
		 i < size;
		 ++i) {
		double
			tmp = corners[i];
		TPointD
			pnt = s->getPoint(tmp);
		double
			large = 5.0;
		drawCross(pnt,
				  large * pixelSize);

		glColor3d(0.7, 0.7, 0.7);
		std::ostringstream oss;
		oss << "[" << tmp << "]";
		extglDrawText(TPointD(pnt.x, pnt.y) + offset, oss.str());
	}

	corners.clear();

	ToonzExt::straightCornersDetector(s,
									  corners);
	if (corners.empty())
		return;

	size = corners.size();
	glColor3d(0.8, 1.0, 0.3);
	// find interval with corner like extremes
	for (i = 0;
		 i < size;
		 ++i) {
		double
			tmp = corners[i];
		TPointD
			pnt = s->getPoint(tmp);
		double
			large = 5.0;
		drawCross(pnt,
				  large * pixelSize);

		glColor3d(0.7, 0.2, 0.2);
		std::ostringstream oss;
		oss << "[" << tmp << "]";
		extglDrawText(TPointD(pnt.x, pnt.y) - offset, oss.str());
	}
}
}

//-----------------------------------------------------------------------------

ToonzExt::OverallDesigner::OverallDesigner(int x,
										   int y)
	: x_(x), y_(y)
{
	pixelSize_ = sqrt(this->getPixelSize2());
	scale_ = pixelSize_ != 0.0 ? pixelSize_ : 1.0;
}

//-----------------------------------------------------------------------------

ToonzExt::OverallDesigner::~OverallDesigner()
{
}

//-----------------------------------------------------------------------------

void ToonzExt::OverallDesigner::draw(ToonzExt::SmoothDeformation *sd)
{
#ifdef _DEBUG
	glPushMatrix();
	{
		this->setPosition();
		TCubic c;
		c.setP0(TPointD(0.0, 0.0));
		c.setP1(TPointD(4.0, 12.0));
		c.setP2(TPointD(12.0, 12.0));
		c.setP3(TPointD(16.0, 0.0));
		glColor3d(1.0, 0.0, 1.0);
		tglDraw(c, 100, GL_LINE);
	}
	glPopMatrix();
#endif
}

//-----------------------------------------------------------------------------

void ToonzExt::OverallDesigner::draw(ToonzExt::CornerDeformation *sd)
{
#ifdef _DEBUG
	glPushMatrix();
	{
		this->setPosition();
		TCubic c;
		c.setP0(TPointD(0.0, 0.0));
		c.setP1(TPointD(0.0, 12.0));
		c.setP2(TPointD(6.0, 12.0));
		c.setP3(TPointD(12.0, 12.0));
		glColor3d(1.0, 0.0, 1.0);
		tglDraw(c, 100, GL_LINE);
		c.setP0(TPointD(12.0, 12.0));
		c.setP1(TPointD(6.0, 8.0));
		c.setP2(TPointD(6.0, 4.0));
		c.setP3(TPointD(12.0, 0.0));
		tglDraw(c, 100, GL_LINE);
	}
	glPopMatrix();
#endif
}

//-----------------------------------------------------------------------------

void ToonzExt::OverallDesigner::draw(ToonzExt::StraightCornerDeformation *sd)
{
#ifdef _DEBUG
	glPushMatrix();
	{
		this->setPosition();
		glColor3d(0.0, 1.0, 1.0);
		glBegin(GL_LINE_STRIP);
		tglVertex(TPointD(0.0, 0.0));
		tglVertex(TPointD(8.0, 12.0));
		tglVertex(TPointD(16.0, 0.0));
		glEnd();
	}
	glPopMatrix();
#endif
}

//-----------------------------------------------------------------------------

void ToonzExt::OverallDesigner::draw(ToonzExt::StrokeDeformation *sd)
{
	if (sd) {
		const TStroke *
			s;

		//glColor3d(1.0,0.0,1.0);
		s = sd->getCopiedStroke();
		if (s) {
			const ContextStatus *
				status = sd->getStatus();
			double
				w = 0.0,
				pixelSize = 1.0;

			if (status) {
				w = status->w_;
				pixelSize = status->pixelSize_ < 0 ? 1.0 : status->pixelSize_;
			}
#ifdef _DEBUG
			drawCross(s->getPoint(0),
					  2 * pixelSize);

			tglDrawCircle(s->getPoint(w), 8 * pixelSize);
			drawCross(s->getPoint(w), 8 * pixelSize);
#endif
			ToonzExt::Interval
				ex = sd->getExtremes();
			drawStrokeCenterLine(s,
								 pixelSize_,
								 ex);
			if (status) {
#ifdef _DEBUG
				glColor3d(0, 0, 0);
				showCorners(s,
							status->cornerSize_,
							pixelSize);

				glColor3d(0, 0, 0);
				TPointD
					offset = normalize(TPointD(1.0, 1.0)) * 20.0;
				std::ostringstream oss;
				oss << "(" << this->x_
					<< "," << this->y_
					<< ")\n{" << w
					<< ",{" << sd->getExtremes().first
					<< "," << sd->getExtremes().second
					<< "}}";
				extglDrawText(TPointD(x_, y_) + offset, oss.str());

				glColor3d(0.5, 1.0, 0.5);
				showCP(s,
					   pixelSize);
#endif
			}
		}

		/*
    glColor3d(1.0,1.0,0.0);
    s = sd->getStroke();
    if(s)
    {
      drawCross( s->getPoint(0),
                 4);

      drawStrokeCenterLine(s,
                           pixelSize_,
                           ToonzExt::Interval(0,1));
    }
    */

		s = sd->getTransformedStroke();

		glColor3d(1.0, 0.0, 0.0);
		if (s) {
#ifdef _DEBUG
			isValid(s);
#endif
			drawStrokeCenterline(*s,
								 pixelSize_);
		}

#ifdef _DEBUG
		{
			const TStroke
				*c = sd->getCopiedStroke(),
				*s = sd->getStroke();
			if (c && s) {
				//glColor3d(1,1,0);
				//tglDrawDisk(s->getPoint(0.0),
				//            5*pixelSize_);

				int count = std::min(c->getControlPointCount(),
									 s->getControlPointCount());
				for (int i = 0;
					 i < count;
					 ++i) {
					TThickPoint
						ccp = c->getControlPoint(i);
					TThickPoint
						scp = s->getControlPoint(i);
				}
			}
		}
#endif
	}
}

//-----------------------------------------------------------------------------

void ToonzExt::OverallDesigner::setPosition()
{
	TPointD
		offset(1, -1);
	offset = normalize(offset) * (20.0 * scale_);
	glTranslated(x_ + offset.x,
				 y_ + offset.y,
				 0.0);
	glScalef(scale_,
			 scale_,
			 scale_);
}

//-----------------------------------------------------------------------------

void ToonzExt::OverallDesigner::draw(ToonzExt::Selector *selector)
{
	if (!selector)
		return;

	const TStroke *
		ref = selector->getStroke();

	if (!ref)
		return;

	double
		length_at_w = ref->getLength(selector->getW()),
		emi_selector_length = selector->getLength() * 0.5,
		stroke_length = ref->getLength();

	ToonzExt::Interval
		interval;

	if (ref->isSelfLoop()) {
		interval.first = length_at_w - emi_selector_length;
		if (interval.first < 0.0)
			interval.first = stroke_length + interval.first;

		interval.first = ref->getParameterAtLength(interval.first);

		interval.second = length_at_w + emi_selector_length;
		if (interval.second > stroke_length)
			interval.second = interval.second - stroke_length;

		interval.second = ref->getParameterAtLength(interval.second);
	} else {
		interval.first = ref->getParameterAtLength(std::max(0.0, length_at_w - emi_selector_length));
		interval.second = ref->getParameterAtLength(std::min(stroke_length, length_at_w + emi_selector_length));
	}

	float
		prev_line_width = 1.0;

	glGetFloatv(GL_LINE_WIDTH,
				&prev_line_width);

	glLineWidth(2.0);
	drawStrokeCenterLine(ref,
						 pixelSize_,
						 interval);
	glLineWidth(prev_line_width);
}

//-----------------------------------------------------------------------------
//  End Of File
//-----------------------------------------------------------------------------
/*
#ifdef  RESTORE_DEBUG
#undef  RESTORE_DEBUG
#define _DEBUG  1
#endif
//*/